@adminforth/dashboard 1.5.0 → 1.7.0

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.
Files changed (58) hide show
  1. package/custom/api/dashboardApi.ts +137 -1
  2. package/custom/model/dashboard.types.ts +32 -22
  3. package/custom/package.json +1 -0
  4. package/custom/pnpm-lock.yaml +31 -0
  5. package/custom/runtime/DashboardRuntime.vue +9 -15
  6. package/custom/runtime/YamlConfigEditor.vue +109 -0
  7. package/custom/skills/adminforth-dashboard/SKILL.md +66 -10
  8. package/custom/widgets/KpiCardWidget.vue +172 -9
  9. package/custom/widgets/chart/ChartWidget.vue +5 -5
  10. package/custom/widgets/registry.ts +4 -4
  11. package/dist/custom/api/dashboardApi.d.ts +46 -1
  12. package/dist/custom/api/dashboardApi.js +90 -0
  13. package/dist/custom/api/dashboardApi.ts +137 -1
  14. package/dist/custom/model/dashboard.types.d.ts +30 -14
  15. package/dist/custom/model/dashboard.types.js +2 -2
  16. package/dist/custom/model/dashboard.types.ts +32 -22
  17. package/dist/custom/package.json +1 -0
  18. package/dist/custom/pnpm-lock.yaml +31 -0
  19. package/dist/custom/queries/useDashboardConfig.d.ts +106 -104
  20. package/dist/custom/queries/useWidgetData.d.ts +106 -104
  21. package/dist/custom/runtime/DashboardRuntime.vue +9 -15
  22. package/dist/custom/runtime/YamlConfigEditor.vue +109 -0
  23. package/dist/custom/skills/adminforth-dashboard/SKILL.md +66 -10
  24. package/dist/custom/widgets/KpiCardWidget.vue +172 -9
  25. package/dist/custom/widgets/chart/ChartWidget.vue +5 -5
  26. package/dist/custom/widgets/registry.js +4 -4
  27. package/dist/custom/widgets/registry.ts +4 -4
  28. package/dist/endpoint/widgets.js +99 -14
  29. package/dist/schema/api.d.ts +11426 -1634
  30. package/dist/schema/api.js +118 -21
  31. package/dist/schema/widget.d.ts +425 -1980
  32. package/dist/schema/widget.js +13 -374
  33. package/dist/schema/widgets/charts.d.ts +1689 -0
  34. package/dist/schema/widgets/charts.js +92 -0
  35. package/dist/schema/widgets/common.d.ts +275 -0
  36. package/dist/schema/widgets/common.js +171 -0
  37. package/dist/schema/widgets/gauge-card.d.ts +172 -0
  38. package/dist/schema/widgets/gauge-card.js +28 -0
  39. package/dist/schema/widgets/kpi-card.d.ts +212 -0
  40. package/dist/schema/widgets/kpi-card.js +43 -0
  41. package/dist/schema/widgets/pivot-table.d.ts +196 -0
  42. package/dist/schema/widgets/pivot-table.js +17 -0
  43. package/dist/schema/widgets/table.d.ts +130 -0
  44. package/dist/schema/widgets/table.js +12 -0
  45. package/dist/services/widgetDataService.js +96 -2
  46. package/endpoint/widgets.ts +173 -26
  47. package/package.json +1 -1
  48. package/schema/api.ts +148 -22
  49. package/schema/widget.ts +43 -425
  50. package/schema/widgets/charts.ts +113 -0
  51. package/schema/widgets/common.ts +194 -0
  52. package/schema/widgets/gauge-card.ts +34 -0
  53. package/schema/widgets/kpi-card.ts +49 -0
  54. package/schema/widgets/pivot-table.ts +24 -0
  55. package/schema/widgets/table.ts +18 -0
  56. package/services/widgetDataService.ts +129 -3
  57. package/shims-vue.d.ts +11 -0
  58. package/tsconfig.json +3 -1
@@ -16,14 +16,68 @@
16
16
 
17
17
  <div
18
18
  v-else
19
- class="grid gap-1"
19
+ class="grid gap-3"
20
20
  >
21
- <div class="text-3xl font-bold text-lightNavbarText dark:text-darkNavbarText">
22
- {{ formattedValue }}
23
- </div>
24
- <div class="text-sm text-lightListTableText dark:text-darkListTableText">
25
- {{ label }}
21
+ <div class="grid gap-1">
22
+ <div class="text-3xl font-bold text-lightNavbarText dark:text-darkNavbarText">
23
+ {{ formattedValue }}
24
+ </div>
25
+ <div class="flex flex-wrap items-center gap-2 text-sm text-lightListTableText dark:text-darkListTableText">
26
+ <span>{{ label }}</span>
27
+ <span
28
+ v-if="comparison"
29
+ class="rounded px-1.5 py-0.5 text-xs font-medium"
30
+ :class="comparisonClass"
31
+ :title="comparison.tooltip"
32
+ >
33
+ {{ comparison.label }}
34
+ </span>
35
+ </div>
26
36
  </div>
37
+ <svg
38
+ v-if="sparklinePoints"
39
+ class="h-12 w-full overflow-visible"
40
+ viewBox="0 0 100 32"
41
+ preserveAspectRatio="none"
42
+ aria-hidden="true"
43
+ >
44
+ <defs v-if="usesSparklineGradient">
45
+ <linearGradient
46
+ :id="sparklineGradientId"
47
+ x1="0"
48
+ y1="0"
49
+ x2="0"
50
+ y2="1"
51
+ >
52
+ <stop
53
+ offset="0%"
54
+ stop-color="currentColor"
55
+ stop-opacity="0.24"
56
+ />
57
+ <stop
58
+ offset="100%"
59
+ stop-color="currentColor"
60
+ stop-opacity="0"
61
+ />
62
+ </linearGradient>
63
+ </defs>
64
+ <polygon
65
+ v-if="usesSparklineGradient"
66
+ class="text-lightPrimary dark:text-darkPrimary"
67
+ :points="sparklineFillPoints"
68
+ :fill="`url(#${sparklineGradientId})`"
69
+ />
70
+ <polyline
71
+ class="text-lightPrimary dark:text-darkPrimary"
72
+ :points="sparklinePoints"
73
+ fill="none"
74
+ stroke="currentColor"
75
+ stroke-width="2"
76
+ stroke-linecap="round"
77
+ stroke-linejoin="round"
78
+ vector-effect="non-scaling-stroke"
79
+ />
80
+ </svg>
27
81
  </div>
28
82
  </div>
29
83
  </template>
@@ -61,11 +115,120 @@ watch(
61
115
  const kpiConfig = computed(() => props.widget.target === 'kpi_card' ? props.widget.card : undefined)
62
116
  const widgetData = computed(() => data.value?.data as DashboardWidgetTableData | null)
63
117
  const columns = computed(() => widgetData.value?.columns ?? [])
64
- const firstRow = computed(() => widgetData.value?.rows[0] ?? {})
118
+ const firstRow = computed(() => widgetData.value?.values ?? widgetData.value?.rows[0] ?? {})
65
119
  const valueField = computed(() => kpiConfig.value?.value.field || columns.value[0])
66
120
  const value = computed(() => toFiniteNumber(firstRow.value[valueField.value]))
67
121
  const label = computed(() => kpiConfig.value?.subtitle?.field
68
- ? String(firstRow.value[kpiConfig.value.subtitle.field])
122
+ ? [kpiConfig.value.subtitle.text, formatValue(firstRow.value[kpiConfig.value.subtitle.field], kpiConfig.value.value.format)]
123
+ .filter(Boolean)
124
+ .join(': ')
69
125
  : kpiConfig.value?.subtitle?.text ?? kpiConfig.value?.title ?? props.widget.label)
70
- const formattedValue = computed(() => `${kpiConfig.value?.value.prefix ?? ''}${formatChartValue(value.value)}${kpiConfig.value?.value.suffix ?? ''}`)
126
+ const formattedValue = computed(() => `${kpiConfig.value?.value.prefix ?? ''}${formatValue(value.value, kpiConfig.value?.value.format)}${kpiConfig.value?.value.suffix ?? ''}`)
127
+ const comparisonValue = computed(() => toFiniteNumber(kpiConfig.value?.comparison?.field
128
+ ? firstRow.value[kpiConfig.value.comparison.field]
129
+ : undefined))
130
+ const comparison = computed(() => {
131
+ const config = kpiConfig.value?.comparison
132
+
133
+ if (!config) {
134
+ return null
135
+ }
136
+
137
+ const template = config.compact?.template ?? '{sign}{value}'
138
+ const tooltipTemplate = config.tooltip?.template
139
+ const valueText = formatValue(Math.abs(comparisonValue.value), config.format, { signed: false, compactTemplate: true })
140
+ const sign = comparisonValue.value > 0 ? '+' : comparisonValue.value < 0 ? '-' : ''
141
+
142
+ return {
143
+ value: comparisonValue.value,
144
+ label: config.compact?.show === false ? valueText : applyTemplate(template, sign, valueText),
145
+ tooltip: tooltipTemplate
146
+ ? applyTemplate(tooltipTemplate, sign, valueText)
147
+ : config.tooltip?.label,
148
+ positiveIsGood: config.positive_is_good ?? true,
149
+ }
150
+ })
151
+ const comparisonClass = computed(() => {
152
+ if (!comparison.value || comparison.value.value === 0) {
153
+ return 'bg-lightListBorder text-lightListTableText dark:bg-darkListBorder dark:text-darkListTableText'
154
+ }
155
+
156
+ const isGood = comparison.value.positiveIsGood
157
+ ? comparison.value.value > 0
158
+ : comparison.value.value < 0
159
+
160
+ return isGood
161
+ ? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300'
162
+ : 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300'
163
+ })
164
+ const sparklineRows = computed(() => widgetData.value?.rows ?? [])
165
+ const sparklineConfig = computed(() => kpiConfig.value?.sparkline)
166
+ const sparklineGradientId = computed(() => `kpi-sparkline-${props.widget.id}`)
167
+ const usesSparklineGradient = computed(() => sparklineConfig.value?.fill?.type === 'gradient')
168
+ const sparklineCoordinates = computed(() => {
169
+ const field = sparklineConfig.value?.field
170
+
171
+ if (!field || sparklineRows.value.length < 2) {
172
+ return []
173
+ }
174
+
175
+ const values = sparklineRows.value.map((row) => toFiniteNumber(row[field]))
176
+ const min = Math.min(...values)
177
+ const max = Math.max(...values)
178
+ const range = max - min || 1
179
+
180
+ return values.map((item, index) => ({
181
+ x: (index / Math.max(values.length - 1, 1)) * 100,
182
+ y: 30 - ((item - min) / range) * 28,
183
+ }))
184
+ })
185
+ const sparklinePoints = computed(() => sparklineCoordinates.value.length
186
+ ? sparklineCoordinates.value.map((point) => `${point.x},${point.y}`).join(' ')
187
+ : '')
188
+ const sparklineFillPoints = computed(() => sparklineCoordinates.value.length
189
+ ? `0,32 ${sparklinePoints.value} 100,32`
190
+ : '')
191
+
192
+ function applyTemplate(template: string, sign: string, value: string) {
193
+ return template
194
+ .replaceAll('{sign}', sign)
195
+ .replaceAll('{value}', value)
196
+ }
197
+
198
+ function formatValue(
199
+ rawValue: unknown,
200
+ format = 'number',
201
+ options: { signed?: boolean, compactTemplate?: boolean } = {},
202
+ ) {
203
+ const numericValue = toFiniteNumber(rawValue)
204
+ const sign = options.signed && numericValue > 0 ? '+' : ''
205
+ const absoluteValue = options.signed ? Math.abs(numericValue) : numericValue
206
+
207
+ if (format === 'integer') {
208
+ return `${sign}${formatChartValue(absoluteValue, { maximumFractionDigits: 0 })}`
209
+ }
210
+
211
+ if (format === 'compact_number') {
212
+ return `${sign}${formatChartValue(absoluteValue, { notation: 'compact', maximumFractionDigits: 1 })}`
213
+ }
214
+
215
+ if (format === 'currency' || format === 'currency_delta') {
216
+ return `${sign}${formatChartValue(absoluteValue, {
217
+ style: 'currency',
218
+ currency: 'USD',
219
+ maximumFractionDigits: 2,
220
+ })}`
221
+ }
222
+
223
+ if (format === 'percent' || format === 'percent_delta') {
224
+ const value = formatChartValue(absoluteValue, { maximumFractionDigits: 1 })
225
+ return options.compactTemplate ? value : `${sign}${value}%`
226
+ }
227
+
228
+ if (format === 'number_delta') {
229
+ return `${sign}${formatChartValue(absoluteValue, { maximumFractionDigits: 2 })}`
230
+ }
231
+
232
+ return `${sign}${formatChartValue(absoluteValue, { maximumFractionDigits: 2 })}`
233
+ }
71
234
  </script>
@@ -83,11 +83,11 @@
83
83
  import { computed, watch } from 'vue'
84
84
  import { useWidgetData } from '../../queries/useWidgetData.js'
85
85
  import type { ChartDashboardWidgetConfig, DashboardWidgetTableData } from '../../model/dashboard.types.js'
86
- import BarChart from './bar/BarChart.vue'
87
- import FunnelChart from './funnel/FunnelChart.vue'
88
- import LineChart from './line/LineChart.vue'
89
- import PieChart from './pie/PieChart.vue'
90
- import StackedBarChart from './stacked-bar/StackedBarChart.vue'
86
+ import BarChart from './BarChart.vue'
87
+ import FunnelChart from './FunnelChart.vue'
88
+ import LineChart from './LineChart.vue'
89
+ import PieChart from './PieChart.vue'
90
+ import StackedBarChart from './StackedBarChart.vue'
91
91
  import { toFiniteNumber } from './chart.utils.js'
92
92
 
93
93
  const DEFAULT_WIDGET_HEIGHT = 500
@@ -1,10 +1,10 @@
1
1
  import type { Component } from 'vue'
2
2
  import type { DashboardWidgetTarget } from '../model/dashboard.types.js'
3
3
  import ChartWidget from './chart/ChartWidget.vue'
4
- import GaugeCardWidget from './gauge-card/GaugeCardWidget.vue'
5
- import KpiCardWidget from './kpi-card/KpiCardWidget.vue'
6
- import PivotTableWidget from './pivot-table/PivotTableWidget.vue'
7
- import TableWidget from './table/TableWidget.vue'
4
+ import GaugeCardWidget from './GaugeCardWidget.vue'
5
+ import KpiCardWidget from './KpiCardWidget.vue'
6
+ import PivotTableWidget from './PivotTableWidget.vue'
7
+ import TableWidget from './TableWidget.vue'
8
8
 
9
9
  export type DashboardWidgetType = DashboardWidgetTarget
10
10
 
@@ -1,4 +1,4 @@
1
- import type { DashboardConfig, EditableDashboardGroupConfig, DashboardGroupMoveDirection, DashboardWidgetConfig, DashboardWidgetConfigValidationError, DashboardWidgetMoveDirection } from '../model/dashboard.types.js';
1
+ import type { DashboardConfig, EditableDashboardGroupConfig, DashboardGroupMoveDirection, ChartDashboardWidgetConfig, DashboardWidgetConfig, DashboardWidgetConfigValidationError, DashboardWidgetMoveDirection, GaugeCardWidgetConfig, KpiCardWidgetConfig, PivotTableWidgetConfig, TableWidgetConfig } from '../model/dashboard.types.js';
2
2
  export type DashboardResponse = {
3
3
  id: string;
4
4
  slug: string;
@@ -16,6 +16,41 @@ export type DashboardWidgetDataRequest = {
16
16
  pageSize: number;
17
17
  };
18
18
  };
19
+ export type ConfigurableTableWidgetConfig = Omit<TableWidgetConfig, 'id' | 'group_id' | 'order'>;
20
+ export type ConfigurableKpiCardWidgetConfig = Omit<KpiCardWidgetConfig, 'id' | 'group_id' | 'order'>;
21
+ export type ConfigurableGaugeCardWidgetConfig = Omit<GaugeCardWidgetConfig, 'id' | 'group_id' | 'order'>;
22
+ export type ConfigurableChartWidgetConfig = Omit<ChartDashboardWidgetConfig, 'id' | 'group_id' | 'order'>;
23
+ export type ConfigurableLineChartWidgetConfig = ConfigurableChartWidgetConfig & {
24
+ chart: {
25
+ type: 'line';
26
+ };
27
+ };
28
+ export type ConfigurableBarChartWidgetConfig = ConfigurableChartWidgetConfig & {
29
+ chart: {
30
+ type: 'bar';
31
+ };
32
+ };
33
+ export type ConfigurableStackedBarChartWidgetConfig = ConfigurableChartWidgetConfig & {
34
+ chart: {
35
+ type: 'stacked_bar';
36
+ };
37
+ };
38
+ export type ConfigurablePieChartWidgetConfig = ConfigurableChartWidgetConfig & {
39
+ chart: {
40
+ type: 'pie';
41
+ };
42
+ };
43
+ export type ConfigurableHistogramChartWidgetConfig = ConfigurableChartWidgetConfig & {
44
+ chart: {
45
+ type: 'histogram';
46
+ };
47
+ };
48
+ export type ConfigurableFunnelChartWidgetConfig = ConfigurableChartWidgetConfig & {
49
+ chart: {
50
+ type: 'funnel';
51
+ };
52
+ };
53
+ export type ConfigurablePivotTableWidgetConfig = Omit<PivotTableWidgetConfig, 'id' | 'group_id' | 'order'>;
19
54
  export declare class DashboardApiError extends Error {
20
55
  validationErrors: DashboardWidgetConfigValidationError[];
21
56
  constructor(message: string, validationErrors?: DashboardWidgetConfigValidationError[]);
@@ -30,5 +65,15 @@ export declare const dashboardApi: {
30
65
  moveDashboardWidget(slug: string, widgetId: string, direction: DashboardWidgetMoveDirection): Promise<DashboardResponse>;
31
66
  removeDashboardWidget(slug: string, widgetId: string): Promise<DashboardResponse>;
32
67
  setWidgetConfig(slug: string, widgetId: string, config: unknown): Promise<DashboardResponse>;
68
+ configureTableWidget(slug: string, widgetId: string, config: ConfigurableTableWidgetConfig): Promise<DashboardResponse>;
69
+ configureKpiCardWidget(slug: string, widgetId: string, config: ConfigurableKpiCardWidgetConfig): Promise<DashboardResponse>;
70
+ configureGaugeCardWidget(slug: string, widgetId: string, config: ConfigurableGaugeCardWidgetConfig): Promise<DashboardResponse>;
71
+ configureLineChartWidget(slug: string, widgetId: string, config: ConfigurableLineChartWidgetConfig): Promise<DashboardResponse>;
72
+ configureBarChartWidget(slug: string, widgetId: string, config: ConfigurableBarChartWidgetConfig): Promise<DashboardResponse>;
73
+ configureStackedBarChartWidget(slug: string, widgetId: string, config: ConfigurableStackedBarChartWidgetConfig): Promise<DashboardResponse>;
74
+ configurePieChartWidget(slug: string, widgetId: string, config: ConfigurablePieChartWidgetConfig): Promise<DashboardResponse>;
75
+ configureHistogramChartWidget(slug: string, widgetId: string, config: ConfigurableHistogramChartWidgetConfig): Promise<DashboardResponse>;
76
+ configureFunnelChartWidget(slug: string, widgetId: string, config: ConfigurableFunnelChartWidgetConfig): Promise<DashboardResponse>;
77
+ configurePivotTableWidget(slug: string, widgetId: string, config: ConfigurablePivotTableWidgetConfig): Promise<DashboardResponse>;
33
78
  getDashboardWidgetData(slug: string, widgetId: string, request?: DashboardWidgetDataRequest): Promise<DashboardWidgetDataResponse>;
34
79
  };
@@ -164,6 +164,96 @@ export const dashboardApi = {
164
164
  });
165
165
  });
166
166
  },
167
+ configureTableWidget(slug, widgetId, config) {
168
+ return __awaiter(this, void 0, void 0, function* () {
169
+ return callDashboardApi('/adminapi/v1/dashboard/configure_table_widget', {
170
+ slug,
171
+ widgetId,
172
+ config,
173
+ });
174
+ });
175
+ },
176
+ configureKpiCardWidget(slug, widgetId, config) {
177
+ return __awaiter(this, void 0, void 0, function* () {
178
+ return callDashboardApi('/adminapi/v1/dashboard/configure_kpi_card_widget', {
179
+ slug,
180
+ widgetId,
181
+ config,
182
+ });
183
+ });
184
+ },
185
+ configureGaugeCardWidget(slug, widgetId, config) {
186
+ return __awaiter(this, void 0, void 0, function* () {
187
+ return callDashboardApi('/adminapi/v1/dashboard/configure_gauge_card_widget', {
188
+ slug,
189
+ widgetId,
190
+ config,
191
+ });
192
+ });
193
+ },
194
+ configureLineChartWidget(slug, widgetId, config) {
195
+ return __awaiter(this, void 0, void 0, function* () {
196
+ return callDashboardApi('/adminapi/v1/dashboard/configure_line_chart_widget', {
197
+ slug,
198
+ widgetId,
199
+ config,
200
+ });
201
+ });
202
+ },
203
+ configureBarChartWidget(slug, widgetId, config) {
204
+ return __awaiter(this, void 0, void 0, function* () {
205
+ return callDashboardApi('/adminapi/v1/dashboard/configure_bar_chart_widget', {
206
+ slug,
207
+ widgetId,
208
+ config,
209
+ });
210
+ });
211
+ },
212
+ configureStackedBarChartWidget(slug, widgetId, config) {
213
+ return __awaiter(this, void 0, void 0, function* () {
214
+ return callDashboardApi('/adminapi/v1/dashboard/configure_stacked_bar_chart_widget', {
215
+ slug,
216
+ widgetId,
217
+ config,
218
+ });
219
+ });
220
+ },
221
+ configurePieChartWidget(slug, widgetId, config) {
222
+ return __awaiter(this, void 0, void 0, function* () {
223
+ return callDashboardApi('/adminapi/v1/dashboard/configure_pie_chart_widget', {
224
+ slug,
225
+ widgetId,
226
+ config,
227
+ });
228
+ });
229
+ },
230
+ configureHistogramChartWidget(slug, widgetId, config) {
231
+ return __awaiter(this, void 0, void 0, function* () {
232
+ return callDashboardApi('/adminapi/v1/dashboard/configure_histogram_chart_widget', {
233
+ slug,
234
+ widgetId,
235
+ config,
236
+ });
237
+ });
238
+ },
239
+ configureFunnelChartWidget(slug, widgetId, config) {
240
+ return __awaiter(this, void 0, void 0, function* () {
241
+ return callDashboardApi('/adminapi/v1/dashboard/configure_funnel_chart_widget', {
242
+ slug,
243
+ widgetId,
244
+ config,
245
+ });
246
+ });
247
+ },
248
+ configurePivotTableWidget(slug, widgetId, config) {
249
+ return __awaiter(this, void 0, void 0, function* () {
250
+ return callDashboardApi('/adminapi/v1/dashboard/configure_pivot_table_widget', {
251
+ slug,
252
+ widgetId,
253
+ config,
254
+ });
255
+ });
256
+ },
167
257
  getDashboardWidgetData(slug_1, widgetId_1) {
168
258
  return __awaiter(this, arguments, void 0, function* (slug, widgetId, request = {}) {
169
259
  return callDashboardWidgetDataApi('/adminapi/v1/dashboard/get_dashboard_widget_data', Object.assign({ slug,
@@ -1,11 +1,15 @@
1
1
  import type {
2
2
  DashboardConfig,
3
3
  EditableDashboardGroupConfig,
4
- EditableDashboardWidgetConfig,
5
4
  DashboardGroupMoveDirection,
5
+ ChartDashboardWidgetConfig,
6
6
  DashboardWidgetConfig,
7
7
  DashboardWidgetConfigValidationError,
8
8
  DashboardWidgetMoveDirection,
9
+ GaugeCardWidgetConfig,
10
+ KpiCardWidgetConfig,
11
+ PivotTableWidgetConfig,
12
+ TableWidgetConfig,
9
13
  } from '../model/dashboard.types.js'
10
14
 
11
15
  export type DashboardResponse = {
@@ -28,6 +32,18 @@ export type DashboardWidgetDataRequest = {
28
32
  }
29
33
  }
30
34
 
35
+ export type ConfigurableTableWidgetConfig = Omit<TableWidgetConfig, 'id' | 'group_id' | 'order'>
36
+ export type ConfigurableKpiCardWidgetConfig = Omit<KpiCardWidgetConfig, 'id' | 'group_id' | 'order'>
37
+ export type ConfigurableGaugeCardWidgetConfig = Omit<GaugeCardWidgetConfig, 'id' | 'group_id' | 'order'>
38
+ export type ConfigurableChartWidgetConfig = Omit<ChartDashboardWidgetConfig, 'id' | 'group_id' | 'order'>
39
+ export type ConfigurableLineChartWidgetConfig = ConfigurableChartWidgetConfig & { chart: { type: 'line' } }
40
+ export type ConfigurableBarChartWidgetConfig = ConfigurableChartWidgetConfig & { chart: { type: 'bar' } }
41
+ export type ConfigurableStackedBarChartWidgetConfig = ConfigurableChartWidgetConfig & { chart: { type: 'stacked_bar' } }
42
+ export type ConfigurablePieChartWidgetConfig = ConfigurableChartWidgetConfig & { chart: { type: 'pie' } }
43
+ export type ConfigurableHistogramChartWidgetConfig = ConfigurableChartWidgetConfig & { chart: { type: 'histogram' } }
44
+ export type ConfigurableFunnelChartWidgetConfig = ConfigurableChartWidgetConfig & { chart: { type: 'funnel' } }
45
+ export type ConfigurablePivotTableWidgetConfig = Omit<PivotTableWidgetConfig, 'id' | 'group_id' | 'order'>
46
+
31
47
  export class DashboardApiError extends Error {
32
48
  validationErrors: DashboardWidgetConfigValidationError[]
33
49
 
@@ -205,6 +221,126 @@ export const dashboardApi = {
205
221
  })
206
222
  },
207
223
 
224
+ async configureTableWidget(
225
+ slug: string,
226
+ widgetId: string,
227
+ config: ConfigurableTableWidgetConfig,
228
+ ): Promise<DashboardResponse> {
229
+ return callDashboardApi('/adminapi/v1/dashboard/configure_table_widget', {
230
+ slug,
231
+ widgetId,
232
+ config,
233
+ })
234
+ },
235
+
236
+ async configureKpiCardWidget(
237
+ slug: string,
238
+ widgetId: string,
239
+ config: ConfigurableKpiCardWidgetConfig,
240
+ ): Promise<DashboardResponse> {
241
+ return callDashboardApi('/adminapi/v1/dashboard/configure_kpi_card_widget', {
242
+ slug,
243
+ widgetId,
244
+ config,
245
+ })
246
+ },
247
+
248
+ async configureGaugeCardWidget(
249
+ slug: string,
250
+ widgetId: string,
251
+ config: ConfigurableGaugeCardWidgetConfig,
252
+ ): Promise<DashboardResponse> {
253
+ return callDashboardApi('/adminapi/v1/dashboard/configure_gauge_card_widget', {
254
+ slug,
255
+ widgetId,
256
+ config,
257
+ })
258
+ },
259
+
260
+ async configureLineChartWidget(
261
+ slug: string,
262
+ widgetId: string,
263
+ config: ConfigurableLineChartWidgetConfig,
264
+ ): Promise<DashboardResponse> {
265
+ return callDashboardApi('/adminapi/v1/dashboard/configure_line_chart_widget', {
266
+ slug,
267
+ widgetId,
268
+ config,
269
+ })
270
+ },
271
+
272
+ async configureBarChartWidget(
273
+ slug: string,
274
+ widgetId: string,
275
+ config: ConfigurableBarChartWidgetConfig,
276
+ ): Promise<DashboardResponse> {
277
+ return callDashboardApi('/adminapi/v1/dashboard/configure_bar_chart_widget', {
278
+ slug,
279
+ widgetId,
280
+ config,
281
+ })
282
+ },
283
+
284
+ async configureStackedBarChartWidget(
285
+ slug: string,
286
+ widgetId: string,
287
+ config: ConfigurableStackedBarChartWidgetConfig,
288
+ ): Promise<DashboardResponse> {
289
+ return callDashboardApi('/adminapi/v1/dashboard/configure_stacked_bar_chart_widget', {
290
+ slug,
291
+ widgetId,
292
+ config,
293
+ })
294
+ },
295
+
296
+ async configurePieChartWidget(
297
+ slug: string,
298
+ widgetId: string,
299
+ config: ConfigurablePieChartWidgetConfig,
300
+ ): Promise<DashboardResponse> {
301
+ return callDashboardApi('/adminapi/v1/dashboard/configure_pie_chart_widget', {
302
+ slug,
303
+ widgetId,
304
+ config,
305
+ })
306
+ },
307
+
308
+ async configureHistogramChartWidget(
309
+ slug: string,
310
+ widgetId: string,
311
+ config: ConfigurableHistogramChartWidgetConfig,
312
+ ): Promise<DashboardResponse> {
313
+ return callDashboardApi('/adminapi/v1/dashboard/configure_histogram_chart_widget', {
314
+ slug,
315
+ widgetId,
316
+ config,
317
+ })
318
+ },
319
+
320
+ async configureFunnelChartWidget(
321
+ slug: string,
322
+ widgetId: string,
323
+ config: ConfigurableFunnelChartWidgetConfig,
324
+ ): Promise<DashboardResponse> {
325
+ return callDashboardApi('/adminapi/v1/dashboard/configure_funnel_chart_widget', {
326
+ slug,
327
+ widgetId,
328
+ config,
329
+ })
330
+ },
331
+
332
+ async configurePivotTableWidget(
333
+ slug: string,
334
+ widgetId: string,
335
+ config: ConfigurablePivotTableWidgetConfig,
336
+ ): Promise<DashboardResponse> {
337
+ return callDashboardApi('/adminapi/v1/dashboard/configure_pivot_table_widget', {
338
+ slug,
339
+ widgetId,
340
+ config,
341
+ })
342
+ },
343
+
208
344
  async getDashboardWidgetData(
209
345
  slug: string,
210
346
  widgetId: string,
@@ -24,7 +24,7 @@ export type DashboardWidgetConfigValidationError = {
24
24
  };
25
25
  export type QueryAggregateOperation = 'sum' | 'count' | 'count_distinct' | 'avg' | 'min' | 'max' | 'median';
26
26
  export type TimeGrain = 'day' | 'week' | 'month' | 'year';
27
- export type ValueFormat = 'number' | 'compact_number' | 'currency' | 'percent' | 'percent_delta' | 'number_delta' | 'currency_delta';
27
+ export type ValueFormat = 'number' | 'integer' | 'compact_number' | 'currency' | 'percent' | 'percent_delta' | 'number_delta' | 'currency_delta';
28
28
  export type WidgetLayout = {
29
29
  size?: DashboardWidgetSize;
30
30
  width?: number;
@@ -90,21 +90,17 @@ export type QueryOrderByItem = {
90
90
  export type QueryConfig = {
91
91
  resource: string;
92
92
  select?: QuerySelectItem[];
93
+ sparkline?: {
94
+ field: string;
95
+ grain: TimeGrain;
96
+ as: string;
97
+ fill_missing?: Record<string, JsonValue>;
98
+ };
93
99
  filters?: FilterExpression;
94
100
  group_by?: QueryGroupByItem[];
95
101
  order_by?: QueryOrderByItem[];
96
102
  limit?: number;
97
103
  offset?: number;
98
- time_series?: {
99
- field: string;
100
- grain: TimeGrain;
101
- timezone?: string;
102
- };
103
- period?: {
104
- field: string;
105
- gte?: JsonValue;
106
- lt?: JsonValue;
107
- };
108
104
  bucket?: {
109
105
  field: string;
110
106
  buckets: Array<{
@@ -148,8 +144,29 @@ export type KpiCardViewConfig = {
148
144
  text?: string;
149
145
  field?: string;
150
146
  };
151
- comparison?: JsonValue;
152
- sparkline?: JsonValue;
147
+ comparison?: {
148
+ field: string;
149
+ format?: ValueFormat;
150
+ positive_is_good?: boolean;
151
+ compact?: {
152
+ show?: boolean;
153
+ template?: string;
154
+ };
155
+ tooltip?: {
156
+ label?: string;
157
+ template?: string;
158
+ };
159
+ };
160
+ sparkline?: {
161
+ type?: 'line';
162
+ field: string;
163
+ x: string;
164
+ show_axes?: boolean;
165
+ show_labels?: boolean;
166
+ fill?: {
167
+ type?: 'gradient' | 'solid';
168
+ };
169
+ };
153
170
  };
154
171
  export type GaugeCardViewConfig = {
155
172
  title?: string;
@@ -211,7 +228,6 @@ export type PivotTableWidgetConfig = WidgetBaseConfig & {
211
228
  query: QueryConfig;
212
229
  };
213
230
  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'>;
215
231
  export type DashboardWidgetTableData = {
216
232
  kind?: 'table';
217
233
  columns: string[];
@@ -10,8 +10,8 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  export function serializeDashboardWidgetConfigForEditor(widget) {
13
- const { id: _id, group_id: _groupId, order: _order } = widget, editableWidget = __rest(widget, ["id", "group_id", "order"]);
14
- return editableWidget;
13
+ const { id: _id, group_id: _groupId, order: _order } = widget, editableWidgetConfig = __rest(widget, ["id", "group_id", "order"]);
14
+ return editableWidgetConfig;
15
15
  }
16
16
  export function getFieldRefField(value) {
17
17
  return typeof value === 'string' ? value : value === null || value === void 0 ? void 0 : value.field;