@adminforth/dashboard 1.4.0 → 1.4.2

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 (86) hide show
  1. package/README.md +23 -4
  2. package/custom/api/dashboardApi.ts +6 -9
  3. package/custom/model/dashboard.types.ts +60 -275
  4. package/custom/model/dashboardTopics.ts +5 -0
  5. package/custom/package.json +1 -0
  6. package/custom/runtime/DashboardGroup.vue +2 -2
  7. package/custom/runtime/DashboardPage.vue +17 -7
  8. package/custom/runtime/DashboardRuntime.vue +20 -8
  9. package/custom/runtime/WidgetRenderer.vue +1 -2
  10. package/custom/runtime/WidgetShell.vue +3 -3
  11. package/custom/skills/adminforth-dashboard/SKILL.md +2 -2
  12. package/custom/widgets/{gauge-card/GaugeCardWidget.vue → GaugeCardWidget.vue} +63 -61
  13. package/custom/widgets/{kpi-card/KpiCardWidget.vue → KpiCardWidget.vue} +35 -33
  14. package/custom/widgets/{pivot-table/PivotTableWidget.vue → PivotTableWidget.vue} +71 -68
  15. package/custom/widgets/{table/TableWidget.vue → TableWidget.vue} +5 -5
  16. package/custom/widgets/chart/{bar/BarChart.vue → BarChart.vue} +2 -2
  17. package/custom/widgets/chart/ChartWidget.vue +4 -15
  18. package/{dist/custom/widgets/chart/funnel → custom/widgets/chart}/FunnelChart.vue +80 -78
  19. package/{dist/custom/widgets/chart/line → custom/widgets/chart}/LineChart.vue +2 -2
  20. package/custom/widgets/chart/{pie/PieChart.vue → PieChart.vue} +2 -2
  21. package/{dist/custom/widgets/chart/stacked-bar → custom/widgets/chart}/StackedBarChart.vue +97 -95
  22. package/custom/widgets/chart/chart.types.ts +0 -28
  23. package/dist/custom/api/dashboardApi.d.ts +4 -8
  24. package/dist/custom/api/dashboardApi.js +2 -6
  25. package/dist/custom/api/dashboardApi.ts +6 -9
  26. package/dist/custom/composables/useElementSize.js +7 -10
  27. package/dist/custom/model/dashboard.types.d.ts +38 -32
  28. package/dist/custom/model/dashboard.types.js +4 -161
  29. package/dist/custom/model/dashboard.types.ts +60 -275
  30. package/dist/custom/model/dashboardTopics.d.ts +2 -0
  31. package/dist/custom/model/dashboardTopics.js +4 -0
  32. package/dist/custom/model/dashboardTopics.ts +5 -0
  33. package/dist/custom/package.json +1 -0
  34. package/dist/custom/queries/useDashboardConfig.d.ts +96 -96
  35. package/dist/custom/queries/useDashboardConfig.js +9 -12
  36. package/dist/custom/queries/useWidgetData.d.ts +96 -96
  37. package/dist/custom/queries/useWidgetData.js +9 -12
  38. package/dist/custom/runtime/DashboardGroup.vue +2 -2
  39. package/dist/custom/runtime/DashboardPage.vue +17 -7
  40. package/dist/custom/runtime/DashboardRuntime.vue +20 -8
  41. package/dist/custom/runtime/WidgetRenderer.vue +1 -2
  42. package/dist/custom/runtime/WidgetShell.vue +3 -3
  43. package/dist/custom/skills/adminforth-dashboard/SKILL.md +2 -2
  44. package/dist/custom/widgets/{gauge-card/GaugeCardWidget.vue → GaugeCardWidget.vue} +63 -61
  45. package/dist/custom/widgets/{kpi-card/KpiCardWidget.vue → KpiCardWidget.vue} +35 -33
  46. package/dist/custom/widgets/{pivot-table/PivotTableWidget.vue → PivotTableWidget.vue} +71 -68
  47. package/dist/custom/widgets/{table/TableWidget.vue → TableWidget.vue} +5 -5
  48. package/dist/custom/widgets/chart/{bar/BarChart.vue → BarChart.vue} +2 -2
  49. package/dist/custom/widgets/chart/ChartWidget.vue +4 -15
  50. package/{custom/widgets/chart/funnel → dist/custom/widgets/chart}/FunnelChart.vue +80 -78
  51. package/{custom/widgets/chart/line → dist/custom/widgets/chart}/LineChart.vue +2 -2
  52. package/dist/custom/widgets/chart/{pie/PieChart.vue → PieChart.vue} +2 -2
  53. package/{custom/widgets/chart/stacked-bar → dist/custom/widgets/chart}/StackedBarChart.vue +97 -95
  54. package/dist/custom/widgets/chart/chart.types.d.ts +0 -2
  55. package/dist/custom/widgets/chart/chart.types.js +1 -25
  56. package/dist/custom/widgets/chart/chart.types.ts +0 -28
  57. package/dist/custom/widgets/chart/chart.utils.js +6 -14
  58. package/dist/custom/widgets/registry.js +14 -22
  59. package/dist/endpoint/dashboard.d.ts +2 -3
  60. package/dist/endpoint/dashboard.js +12 -32
  61. package/dist/endpoint/groups.d.ts +2 -21
  62. package/dist/endpoint/groups.js +18 -16
  63. package/dist/endpoint/widgets.d.ts +0 -3
  64. package/dist/endpoint/widgets.js +27 -74
  65. package/dist/index.js +1 -3
  66. package/dist/schema/api.d.ts +2090 -511
  67. package/dist/schema/api.js +18 -15
  68. package/dist/schema/widget.d.ts +1003 -250
  69. package/dist/schema/widget.js +102 -46
  70. package/dist/services/dashboardConfigService.d.ts +0 -10
  71. package/dist/services/dashboardConfigService.js +6 -21
  72. package/dist/services/widgetDataService.js +226 -196
  73. package/endpoint/dashboard.ts +13 -46
  74. package/endpoint/groups.ts +25 -42
  75. package/endpoint/widgets.ts +36 -95
  76. package/index.ts +0 -3
  77. package/package.json +3 -3
  78. package/schema/api.ts +19 -15
  79. package/schema/widget.ts +113 -52
  80. package/services/dashboardConfigService.ts +6 -25
  81. package/services/widgetDataService.ts +304 -229
  82. package/custom/widgets/chart/histogram/HistogramChart.vue +0 -21
  83. package/dist/custom/widgets/chart/histogram/HistogramChart.vue +0 -21
  84. package/dist/services/widgetConfigValidator.d.ts +0 -8
  85. package/dist/services/widgetConfigValidator.js +0 -27
  86. package/services/widgetConfigValidator.ts +0 -61
@@ -28,6 +28,14 @@ const FieldRefSchema = z.union([
28
28
  format: ValueFormatSchema,
29
29
  }).strict(),
30
30
  ]);
31
+ const JsonValueSchema = z.lazy(() => z.union([
32
+ z.string(),
33
+ z.number(),
34
+ z.boolean(),
35
+ z.null(),
36
+ z.array(JsonValueSchema),
37
+ z.record(z.string(), JsonValueSchema),
38
+ ]));
31
39
  const FilterExpressionSchema = z.lazy(() => z.union([
32
40
  z.array(FilterExpressionSchema),
33
41
  z.object({
@@ -38,16 +46,16 @@ const FilterExpressionSchema = z.lazy(() => z.union([
38
46
  }).strict(),
39
47
  z.object({
40
48
  field: z.string(),
41
- eq: z.unknown().optional(),
42
- neq: z.unknown().optional(),
43
- gt: z.unknown().optional(),
44
- gte: z.unknown().optional(),
45
- lt: z.unknown().optional(),
46
- lte: z.unknown().optional(),
47
- in: z.array(z.unknown()).optional(),
48
- not_in: z.array(z.unknown()).optional(),
49
- like: z.unknown().optional(),
50
- ilike: z.unknown().optional(),
49
+ eq: JsonValueSchema.optional(),
50
+ neq: JsonValueSchema.optional(),
51
+ gt: JsonValueSchema.optional(),
52
+ gte: JsonValueSchema.optional(),
53
+ lt: JsonValueSchema.optional(),
54
+ lte: JsonValueSchema.optional(),
55
+ in: z.array(JsonValueSchema).optional(),
56
+ not_in: z.array(JsonValueSchema).optional(),
57
+ like: JsonValueSchema.optional(),
58
+ ilike: JsonValueSchema.optional(),
51
59
  }).strict(),
52
60
  ]));
53
61
  const QueryAggregateOperationSchema = z.enum([
@@ -62,7 +70,7 @@ const QueryAggregateOperationSchema = z.enum([
62
70
  const QueryFieldSelectItemSchema = z.object({
63
71
  field: z.string(),
64
72
  as: z.string().optional(),
65
- grain: z.enum(['hour', 'day', 'week', 'month', 'quarter', 'year']).optional(),
73
+ grain: z.enum(['day', 'week', 'month', 'year']).optional(),
66
74
  }).strict();
67
75
  const QueryAggregateSelectItemSchema = z.object({
68
76
  agg: QueryAggregateOperationSchema,
@@ -72,7 +80,7 @@ const QueryAggregateSelectItemSchema = z.object({
72
80
  }).strict().superRefine((item, ctx) => {
73
81
  if (!['count'].includes(item.agg) && !item.field) {
74
82
  ctx.addIssue({
75
- code: z.ZodIssueCode.custom,
83
+ code: 'custom',
76
84
  path: ['field'],
77
85
  message: `field is required for ${item.agg}`,
78
86
  });
@@ -92,7 +100,7 @@ const QueryGroupByItemSchema = z.union([
92
100
  z.object({
93
101
  field: z.string(),
94
102
  as: z.string().optional(),
95
- grain: z.enum(['hour', 'day', 'week', 'month', 'quarter', 'year']).optional(),
103
+ grain: z.enum(['day', 'week', 'month', 'year']).optional(),
96
104
  timezone: z.string().optional(),
97
105
  }).strict(),
98
106
  ]);
@@ -102,13 +110,13 @@ const QueryOrderByItemSchema = z.object({
102
110
  }).strict();
103
111
  const TimeSeriesConfigSchema = z.object({
104
112
  field: z.string(),
105
- grain: z.enum(['hour', 'day', 'week', 'month', 'quarter', 'year']),
113
+ grain: z.enum(['day', 'week', 'month', 'year']),
106
114
  timezone: z.string().optional(),
107
115
  }).strict();
108
116
  const PeriodConfigSchema = z.object({
109
117
  field: z.string(),
110
- gte: z.unknown().optional(),
111
- lt: z.unknown().optional(),
118
+ gte: JsonValueSchema.optional(),
119
+ lt: JsonValueSchema.optional(),
112
120
  }).strict();
113
121
  const BucketConfigSchema = z.object({
114
122
  field: z.string(),
@@ -122,17 +130,17 @@ const QueryCalcItemSchema = z.object({
122
130
  calc: z.string(),
123
131
  as: z.string(),
124
132
  }).strict();
125
- const FormattingConfigSchema = z.record(z.string(), z.unknown());
126
- const VariablesConfigSchema = z.record(z.string(), z.unknown());
133
+ const FormattingConfigSchema = z.record(z.string(), JsonValueSchema);
134
+ const VariablesConfigSchema = z.record(z.string(), JsonValueSchema);
127
135
  export const QueryConfigSchema = z.object({
128
136
  resource: z.string(),
129
137
  select: z.array(QuerySelectItemSchema).optional(),
130
138
  filters: FilterExpressionSchema.optional(),
131
- groupBy: z.array(QueryGroupByItemSchema).optional(),
132
- orderBy: z.array(QueryOrderByItemSchema).optional(),
139
+ group_by: z.array(QueryGroupByItemSchema).optional(),
140
+ order_by: z.array(QueryOrderByItemSchema).optional(),
133
141
  limit: z.number().int().positive().optional(),
134
142
  offset: z.number().int().nonnegative().optional(),
135
- timeSeries: TimeSeriesConfigSchema.optional(),
143
+ time_series: TimeSeriesConfigSchema.optional(),
136
144
  period: PeriodConfigSchema.optional(),
137
145
  bucket: BucketConfigSchema.optional(),
138
146
  calcs: z.array(QueryCalcItemSchema).optional(),
@@ -148,26 +156,28 @@ export const FunnelQueryConfigSchema = z.object({
148
156
  steps: z.array(FunnelQueryStepSchema).min(1),
149
157
  calcs: z.array(QueryCalcItemSchema).optional(),
150
158
  }).strict();
151
- const WidgetBaseSchema = z.object({
152
- id: z.string().optional(),
153
- group_id: z.string().optional(),
159
+ const EditableWidgetBaseSchema = z.object({
154
160
  label: z.string().optional(),
155
161
  variables: VariablesConfigSchema.optional(),
156
162
  size: DashboardWidgetSizeSchema.optional(),
157
163
  width: z.number().positive('Width must be greater than 0').optional(),
158
164
  height: z.number().positive('Height must be greater than 0').optional(),
159
- minWidth: z.number().nonnegative('Min width must be a non-negative number').optional(),
160
- maxWidth: z.number().nonnegative('Max width must be a non-negative number').nullable().optional(),
161
- order: z.number().optional(),
165
+ min_width: z.number().nonnegative('Min width must be a non-negative number').optional(),
166
+ max_width: z.number().nonnegative('Max width must be a non-negative number').nullable().optional(),
167
+ }).strict();
168
+ const StoredWidgetBaseSchema = EditableWidgetBaseSchema.extend({
169
+ id: z.string(),
170
+ group_id: z.string(),
171
+ order: z.number(),
162
172
  });
163
173
  const TableViewConfigSchema = z.object({
164
174
  columns: z.array(FieldRefSchema).optional(),
165
175
  pagination: z.boolean().optional(),
166
- pageSize: z.number().int().positive().optional(),
176
+ page_size: z.number().int().positive().optional(),
167
177
  }).strict();
168
178
  const ChartBaseSchema = z.object({
169
179
  title: z.string().optional(),
170
- });
180
+ }).strict();
171
181
  const ChartBucketSchema = z.object({
172
182
  label: z.string().min(1, 'Bucket label is required'),
173
183
  min: z.number().optional(),
@@ -237,8 +247,8 @@ const KpiCardViewConfigSchema = z.object({
237
247
  text: z.string().optional(),
238
248
  field: z.string().optional(),
239
249
  }).strict().optional(),
240
- comparison: z.unknown().optional(),
241
- sparkline: z.unknown().optional(),
250
+ comparison: JsonValueSchema.optional(),
251
+ sparkline: JsonValueSchema.optional(),
242
252
  }).strict();
243
253
  const GaugeCardViewConfigSchema = z.object({
244
254
  title: z.string().optional(),
@@ -254,9 +264,9 @@ const GaugeCardViewConfigSchema = z.object({
254
264
  label: z.string().optional(),
255
265
  }).strict().optional(),
256
266
  progress: z.object({
257
- valueField: z.string(),
258
- targetValue: z.number().optional(),
259
- targetField: z.string().optional(),
267
+ value_field: z.string(),
268
+ target_value: z.number().optional(),
269
+ target_field: z.string().optional(),
260
270
  format: ValueFormatSchema,
261
271
  }).strict().optional(),
262
272
  color: z.string().optional(),
@@ -271,15 +281,38 @@ const PivotTableViewConfigSchema = z.object({
271
281
  aggregation: z.enum(['sum', 'count', 'avg', 'min', 'max']).optional(),
272
282
  }).strict()).min(1),
273
283
  }).strict();
274
- export const EmptyWidgetConfigSchema = WidgetBaseSchema.extend({
284
+ const EditableEmptyWidgetConfigSchema = EditableWidgetBaseSchema.extend({
275
285
  target: z.literal('empty'),
276
286
  });
277
- const TableWidgetConfigSchema = WidgetBaseSchema.extend({
287
+ export const EmptyWidgetConfigSchema = StoredWidgetBaseSchema.extend({
288
+ target: z.literal('empty'),
289
+ });
290
+ const EditableTableWidgetConfigSchema = EditableWidgetBaseSchema.extend({
291
+ target: z.literal('table'),
292
+ table: TableViewConfigSchema.optional(),
293
+ query: QueryConfigSchema,
294
+ });
295
+ const TableWidgetConfigSchema = StoredWidgetBaseSchema.extend({
278
296
  target: z.literal('table'),
279
297
  table: TableViewConfigSchema.optional(),
280
298
  query: QueryConfigSchema,
281
299
  });
282
- const ChartWidgetTargetConfigSchema = WidgetBaseSchema.extend({
300
+ const EditableChartWidgetTargetConfigSchema = EditableWidgetBaseSchema.extend({
301
+ target: z.literal('chart'),
302
+ chart: ChartConfigSchema,
303
+ query: z.union([QueryConfigSchema, FunnelQueryConfigSchema]),
304
+ }).superRefine((widget, ctx) => {
305
+ const isFunnelChart = widget.chart.type === 'funnel';
306
+ const isFunnelQuery = 'steps' in widget.query;
307
+ if (isFunnelChart && !isFunnelQuery) {
308
+ ctx.addIssue({
309
+ code: 'custom',
310
+ path: ['query'],
311
+ message: 'Funnel charts must use steps query',
312
+ });
313
+ }
314
+ });
315
+ const ChartWidgetTargetConfigSchema = StoredWidgetBaseSchema.extend({
283
316
  target: z.literal('chart'),
284
317
  chart: ChartConfigSchema,
285
318
  query: z.union([QueryConfigSchema, FunnelQueryConfigSchema]),
@@ -288,33 +321,56 @@ const ChartWidgetTargetConfigSchema = WidgetBaseSchema.extend({
288
321
  const isFunnelQuery = 'steps' in widget.query;
289
322
  if (isFunnelChart && !isFunnelQuery) {
290
323
  ctx.addIssue({
291
- code: z.ZodIssueCode.custom,
324
+ code: 'custom',
292
325
  path: ['query'],
293
326
  message: 'Funnel charts must use steps query',
294
327
  });
295
328
  }
296
329
  });
297
- const KpiCardWidgetConfigSchema = WidgetBaseSchema.extend({
330
+ const EditableKpiCardWidgetConfigSchema = EditableWidgetBaseSchema.extend({
298
331
  target: z.literal('kpi_card'),
299
332
  card: KpiCardViewConfigSchema,
300
333
  query: QueryConfigSchema,
301
334
  });
302
- const GaugeCardWidgetConfigSchema = WidgetBaseSchema.extend({
335
+ const KpiCardWidgetConfigSchema = StoredWidgetBaseSchema.extend({
336
+ target: z.literal('kpi_card'),
337
+ card: KpiCardViewConfigSchema,
338
+ query: QueryConfigSchema,
339
+ });
340
+ const EditableGaugeCardWidgetConfigSchema = EditableWidgetBaseSchema.extend({
341
+ target: z.literal('gauge_card'),
342
+ card: GaugeCardViewConfigSchema,
343
+ query: QueryConfigSchema,
344
+ });
345
+ const GaugeCardWidgetConfigSchema = StoredWidgetBaseSchema.extend({
303
346
  target: z.literal('gauge_card'),
304
347
  card: GaugeCardViewConfigSchema,
305
348
  query: QueryConfigSchema,
306
349
  });
307
- const PivotTableWidgetConfigSchema = WidgetBaseSchema.extend({
350
+ const EditablePivotTableWidgetConfigSchema = EditableWidgetBaseSchema.extend({
308
351
  target: z.literal('pivot_table'),
309
352
  pivot: PivotTableViewConfigSchema,
310
353
  query: QueryConfigSchema,
311
354
  });
355
+ const PivotTableWidgetConfigSchema = StoredWidgetBaseSchema.extend({
356
+ target: z.literal('pivot_table'),
357
+ pivot: PivotTableViewConfigSchema,
358
+ query: QueryConfigSchema,
359
+ });
360
+ export const EditableDashboardWidgetConfigSchema = z.discriminatedUnion('target', [
361
+ EditableEmptyWidgetConfigSchema,
362
+ EditableTableWidgetConfigSchema,
363
+ EditableChartWidgetTargetConfigSchema,
364
+ EditableKpiCardWidgetConfigSchema,
365
+ EditableGaugeCardWidgetConfigSchema,
366
+ EditablePivotTableWidgetConfigSchema,
367
+ ]);
312
368
  export const WidgetConfigSchema = z.discriminatedUnion('target', [
313
- TableWidgetConfigSchema,
314
- ChartWidgetTargetConfigSchema,
315
- KpiCardWidgetConfigSchema,
316
- GaugeCardWidgetConfigSchema,
317
- PivotTableWidgetConfigSchema,
369
+ EditableTableWidgetConfigSchema,
370
+ EditableChartWidgetTargetConfigSchema,
371
+ EditableKpiCardWidgetConfigSchema,
372
+ EditableGaugeCardWidgetConfigSchema,
373
+ EditablePivotTableWidgetConfigSchema,
318
374
  ]);
319
375
  export const StoredWidgetConfigSchema = z.discriminatedUnion('target', [
320
376
  EmptyWidgetConfigSchema,
@@ -8,13 +8,6 @@ export type DashboardRecord = {
8
8
  config: unknown;
9
9
  };
10
10
  export declare function parseStoredDashboardConfig(config: unknown): DashboardConfig;
11
- export declare function buildDashboardResponse(dashboard: DashboardRecord): {
12
- id: string;
13
- slug: string;
14
- label: string;
15
- revision: number;
16
- config: DashboardConfig;
17
- };
18
11
  export type PersistedDashboardResponse = {
19
12
  id: string;
20
13
  slug: string;
@@ -22,14 +15,11 @@ export type PersistedDashboardResponse = {
22
15
  revision: number;
23
16
  config: DashboardConfig;
24
17
  };
25
- export declare function dashboardConfigUpdatedTopic(slug: string): string;
26
- export declare function normalizeDashboardOrder(config: DashboardConfig): DashboardConfig;
27
18
  export declare function getDashboardRecord(adminforth: IAdminForth, dashboardConfigsResourceId: string, slug: string): Promise<DashboardRecord | null>;
28
19
  export declare function persistDashboardConfig(adminforth: IAdminForth, dashboardConfigsResourceId: string, dashboard: DashboardRecord, config: DashboardConfig): Promise<PersistedDashboardResponse>;
29
20
  export type DashboardConfigService = {
30
21
  getDashboardRecord: (slug: string) => Promise<DashboardRecord | null>;
31
22
  parseStoredDashboardConfig: typeof parseStoredDashboardConfig;
32
23
  persistDashboardConfig: (dashboard: DashboardRecord, config: DashboardConfig) => Promise<PersistedDashboardResponse>;
33
- buildDashboardResponse: typeof buildDashboardResponse;
34
24
  };
35
25
  export declare function createDashboardConfigService(adminforth: IAdminForth, dashboardConfigsResourceId: string): DashboardConfigService;
@@ -8,27 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { Filters } from 'adminforth';
11
- import { normalizeDashboardConfig } from '../custom/model/dashboard.types.js';
12
- const DASHBOARD_CONFIG_UPDATED_TOPIC_PREFIX = '/opentopic/dashboard-config-updated';
11
+ import { getDashboardConfigUpdatedTopic } from '../custom/model/dashboardTopics.js';
12
+ import { DashboardConfigZodSchema } from '../schema/api.js';
13
13
  export function parseStoredDashboardConfig(config) {
14
- if (typeof config === 'string') {
15
- return normalizeDashboardConfig(JSON.parse(config));
16
- }
17
- return normalizeDashboardConfig(config);
18
- }
19
- export function buildDashboardResponse(dashboard) {
20
- return {
21
- id: dashboard.id,
22
- slug: dashboard.slug,
23
- label: dashboard.label,
24
- revision: dashboard.revision,
25
- config: parseStoredDashboardConfig(dashboard.config),
26
- };
27
- }
28
- export function dashboardConfigUpdatedTopic(slug) {
29
- return `${DASHBOARD_CONFIG_UPDATED_TOPIC_PREFIX}/${slug}`;
14
+ const parsedConfig = typeof config === 'string' ? JSON.parse(config) : config;
15
+ return DashboardConfigZodSchema.parse(parsedConfig);
30
16
  }
31
- export function normalizeDashboardOrder(config) {
17
+ function normalizeDashboardOrder(config) {
32
18
  var _a;
33
19
  const widgetsByGroupId = new Map();
34
20
  for (const widget of config.widgets) {
@@ -55,7 +41,7 @@ export function persistDashboardConfig(adminforth, dashboardConfigsResourceId, d
55
41
  config: normalizedConfig,
56
42
  revision: dashboard.revision + 1,
57
43
  });
58
- yield adminforth.websocket.publish(dashboardConfigUpdatedTopic(dashboard.slug), {
44
+ yield adminforth.websocket.publish(getDashboardConfigUpdatedTopic(dashboard.slug), {
59
45
  id: dashboard.id,
60
46
  slug: dashboard.slug,
61
47
  revision: dashboard.revision + 1,
@@ -74,6 +60,5 @@ export function createDashboardConfigService(adminforth, dashboardConfigsResourc
74
60
  getDashboardRecord: (slug) => getDashboardRecord(adminforth, dashboardConfigsResourceId, slug),
75
61
  parseStoredDashboardConfig,
76
62
  persistDashboardConfig: (dashboard, config) => persistDashboardConfig(adminforth, dashboardConfigsResourceId, dashboard, config),
77
- buildDashboardResponse,
78
63
  };
79
64
  }