@adminforth/dashboard 1.3.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.
Files changed (80) hide show
  1. package/README.md +103 -15
  2. package/custom/api/dashboardApi.ts +9 -8
  3. package/custom/model/dashboard.types.ts +63 -270
  4. package/custom/model/dashboardTopics.ts +5 -0
  5. package/custom/runtime/DashboardGroup.vue +2 -2
  6. package/custom/runtime/DashboardPage.vue +17 -7
  7. package/custom/runtime/DashboardRuntime.vue +20 -8
  8. package/custom/runtime/WidgetRenderer.vue +1 -2
  9. package/custom/runtime/WidgetShell.vue +3 -3
  10. package/custom/skills/adminforth-dashboard/SKILL.md +110 -3
  11. package/custom/widgets/{gauge-card/GaugeCardWidget.vue → GaugeCardWidget.vue} +63 -61
  12. package/custom/widgets/{kpi-card/KpiCardWidget.vue → KpiCardWidget.vue} +35 -33
  13. package/custom/widgets/{pivot-table/PivotTableWidget.vue → PivotTableWidget.vue} +71 -68
  14. package/custom/widgets/{table/TableWidget.vue → TableWidget.vue} +5 -5
  15. package/custom/widgets/chart/{bar/BarChart.vue → BarChart.vue} +2 -2
  16. package/custom/widgets/chart/ChartWidget.vue +24 -18
  17. package/{dist/custom/widgets/chart/funnel → custom/widgets/chart}/FunnelChart.vue +80 -78
  18. package/{dist/custom/widgets/chart/line → custom/widgets/chart}/LineChart.vue +2 -2
  19. package/custom/widgets/chart/{pie/PieChart.vue → PieChart.vue} +2 -2
  20. package/{dist/custom/widgets/chart/stacked-bar → custom/widgets/chart}/StackedBarChart.vue +97 -95
  21. package/custom/widgets/chart/chart.types.ts +0 -28
  22. package/dist/custom/api/dashboardApi.d.ts +4 -7
  23. package/dist/custom/api/dashboardApi.js +5 -0
  24. package/dist/custom/api/dashboardApi.ts +9 -8
  25. package/dist/custom/model/dashboard.types.d.ts +40 -31
  26. package/dist/custom/model/dashboard.types.js +13 -152
  27. package/dist/custom/model/dashboard.types.ts +63 -270
  28. package/dist/custom/model/dashboardTopics.d.ts +2 -0
  29. package/dist/custom/model/dashboardTopics.js +8 -0
  30. package/dist/custom/model/dashboardTopics.ts +5 -0
  31. package/dist/custom/queries/useDashboardConfig.d.ts +116 -96
  32. package/dist/custom/queries/useWidgetData.d.ts +116 -96
  33. package/dist/custom/runtime/DashboardGroup.vue +2 -2
  34. package/dist/custom/runtime/DashboardPage.vue +17 -7
  35. package/dist/custom/runtime/DashboardRuntime.vue +20 -8
  36. package/dist/custom/runtime/WidgetRenderer.vue +1 -2
  37. package/dist/custom/runtime/WidgetShell.vue +3 -3
  38. package/dist/custom/skills/adminforth-dashboard/SKILL.md +110 -3
  39. package/dist/custom/widgets/{gauge-card/GaugeCardWidget.vue → GaugeCardWidget.vue} +63 -61
  40. package/dist/custom/widgets/{kpi-card/KpiCardWidget.vue → KpiCardWidget.vue} +35 -33
  41. package/dist/custom/widgets/{pivot-table/PivotTableWidget.vue → PivotTableWidget.vue} +71 -68
  42. package/dist/custom/widgets/{table/TableWidget.vue → TableWidget.vue} +5 -5
  43. package/dist/custom/widgets/chart/{bar/BarChart.vue → BarChart.vue} +2 -2
  44. package/dist/custom/widgets/chart/ChartWidget.vue +24 -18
  45. package/{custom/widgets/chart/funnel → dist/custom/widgets/chart}/FunnelChart.vue +80 -78
  46. package/{custom/widgets/chart/line → dist/custom/widgets/chart}/LineChart.vue +2 -2
  47. package/dist/custom/widgets/chart/{pie/PieChart.vue → PieChart.vue} +2 -2
  48. package/{custom/widgets/chart/stacked-bar → dist/custom/widgets/chart}/StackedBarChart.vue +97 -95
  49. package/dist/custom/widgets/chart/chart.types.d.ts +0 -2
  50. package/dist/custom/widgets/chart/chart.types.js +0 -23
  51. package/dist/custom/widgets/chart/chart.types.ts +0 -28
  52. package/dist/endpoint/dashboard.d.ts +6 -2
  53. package/dist/endpoint/dashboard.js +29 -5
  54. package/dist/endpoint/groups.d.ts +2 -21
  55. package/dist/endpoint/groups.js +18 -16
  56. package/dist/endpoint/widgets.d.ts +2 -4
  57. package/dist/endpoint/widgets.js +28 -74
  58. package/dist/index.js +1 -3
  59. package/dist/schema/api.d.ts +2172 -500
  60. package/dist/schema/api.js +21 -13
  61. package/dist/schema/widget.d.ts +1076 -263
  62. package/dist/schema/widget.js +108 -49
  63. package/dist/services/dashboardConfigService.d.ts +0 -10
  64. package/dist/services/dashboardConfigService.js +6 -21
  65. package/dist/services/widgetDataService.d.ts +2 -1
  66. package/dist/services/widgetDataService.js +266 -206
  67. package/endpoint/dashboard.ts +47 -7
  68. package/endpoint/groups.ts +25 -42
  69. package/endpoint/widgets.ts +41 -96
  70. package/index.ts +0 -3
  71. package/package.json +3 -3
  72. package/schema/api.ts +23 -13
  73. package/schema/widget.ts +119 -55
  74. package/services/dashboardConfigService.ts +6 -25
  75. package/services/widgetDataService.ts +350 -237
  76. package/custom/widgets/chart/histogram/HistogramChart.vue +0 -21
  77. package/dist/custom/widgets/chart/histogram/HistogramChart.vue +0 -21
  78. package/dist/services/widgetConfigValidator.d.ts +0 -8
  79. package/dist/services/widgetConfigValidator.js +0 -27
  80. package/services/widgetConfigValidator.ts +0 -61
@@ -2,6 +2,7 @@ import type { AdminUser, IHttpServer } from 'adminforth';
2
2
  import { randomUUID } from 'crypto';
3
3
  import type {
4
4
  DashboardConfig,
5
+ EditableDashboardGroupConfig,
5
6
  DashboardGroupConfig,
6
7
  } from '../custom/model/dashboard.types.js';
7
8
  import {
@@ -11,14 +12,7 @@ import {
11
12
  SetGroupConfigRequestSchema,
12
13
  SlugRequestSchema,
13
14
  } from '../schema/api.js';
14
-
15
- type DashboardRecord = {
16
- id: string;
17
- slug: string;
18
- label: string;
19
- revision: number;
20
- config: unknown;
21
- };
15
+ import type { DashboardRecord, PersistedDashboardResponse } from '../services/dashboardConfigService.js';
22
16
 
23
17
  type GroupEndpointsContext = {
24
18
  canEditDashboard: (adminUser: AdminUser) => boolean;
@@ -27,20 +21,7 @@ type GroupEndpointsContext = {
27
21
  persistDashboardConfig: (
28
22
  dashboard: DashboardRecord,
29
23
  config: DashboardConfig,
30
- ) => Promise<{
31
- id: string;
32
- slug: string;
33
- label: string;
34
- revision: number;
35
- config: DashboardConfig;
36
- }>;
37
- buildDashboardResponse: (dashboard: DashboardRecord) => {
38
- id: string;
39
- slug: string;
40
- label: string;
41
- revision: number;
42
- config: DashboardConfig;
43
- };
24
+ ) => Promise<PersistedDashboardResponse>;
44
25
  };
45
26
 
46
27
  export function registerGroupEndpoints(
@@ -59,8 +40,7 @@ export function registerGroupEndpoints(
59
40
  return { error: 'Dashboard edit is not allowed' };
60
41
  }
61
42
 
62
- const slug = String(body?.slug || 'default');
63
- const dashboard = await ctx.getDashboardRecord(slug);
43
+ const dashboard = await ctx.getDashboardRecord(body.slug);
64
44
 
65
45
  if (!dashboard) {
66
46
  response.setStatus(404);
@@ -95,9 +75,8 @@ export function registerGroupEndpoints(
95
75
  return { error: 'Dashboard edit is not allowed' };
96
76
  }
97
77
 
98
- const slug = String(body?.slug || 'default');
99
- const groupId = String(body?.groupId || '');
100
- const dashboard = await ctx.getDashboardRecord(slug);
78
+ const groupId = body.groupId;
79
+ const dashboard = await ctx.getDashboardRecord(body.slug);
101
80
 
102
81
  if (!dashboard) {
103
82
  response.setStatus(404);
@@ -112,14 +91,16 @@ export function registerGroupEndpoints(
112
91
  return { error: 'Dashboard group not found' };
113
92
  }
114
93
 
94
+ const nextGroup: DashboardGroupConfig = {
95
+ ...(body.config as EditableDashboardGroupConfig),
96
+ id: group.id,
97
+ order: group.order,
98
+ };
99
+
115
100
  return ctx.persistDashboardConfig(dashboard, {
116
101
  ...config,
117
102
  groups: config.groups.map((item) => item.id === groupId
118
- ? {
119
- ...(body.config as DashboardGroupConfig),
120
- id: group.id,
121
- order: group.order,
122
- }
103
+ ? nextGroup
123
104
  : item),
124
105
  });
125
106
  },
@@ -137,10 +118,7 @@ export function registerGroupEndpoints(
137
118
  return { error: 'Dashboard edit is not allowed' };
138
119
  }
139
120
 
140
- const slug = String(body?.slug || 'default');
141
- const groupId = String(body?.groupId || '');
142
- const direction = body?.direction === 'down' ? 'down' : 'up';
143
- const dashboard = await ctx.getDashboardRecord(slug);
121
+ const dashboard = await ctx.getDashboardRecord(body.slug);
144
122
 
145
123
  if (!dashboard) {
146
124
  response.setStatus(404);
@@ -149,17 +127,23 @@ export function registerGroupEndpoints(
149
127
 
150
128
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
151
129
  const sortedGroups = [...config.groups].sort((a, b) => a.order - b.order);
152
- const currentIndex = sortedGroups.findIndex((group) => group.id === groupId);
130
+ const currentIndex = sortedGroups.findIndex((group) => group.id === body.groupId);
153
131
 
154
132
  if (currentIndex === -1) {
155
133
  response.setStatus(404);
156
134
  return { error: 'Dashboard group not found' };
157
135
  }
158
136
 
159
- const targetIndex = direction === 'up' ? currentIndex - 1 : currentIndex + 1;
137
+ const targetIndex = body.direction === 'up' ? currentIndex - 1 : currentIndex + 1;
160
138
 
161
139
  if (targetIndex < 0 || targetIndex >= sortedGroups.length) {
162
- return ctx.buildDashboardResponse(dashboard);
140
+ return {
141
+ id: dashboard.id,
142
+ slug: dashboard.slug,
143
+ label: dashboard.label,
144
+ revision: dashboard.revision,
145
+ config: ctx.parseStoredDashboardConfig(dashboard.config),
146
+ };
163
147
  }
164
148
 
165
149
  const reorderedGroups = [...sortedGroups];
@@ -185,9 +169,8 @@ export function registerGroupEndpoints(
185
169
  return { error: 'Dashboard edit is not allowed' };
186
170
  }
187
171
 
188
- const slug = String(body?.slug || 'default');
189
- const groupId = String(body?.groupId || '');
190
- const dashboard = await ctx.getDashboardRecord(slug);
172
+ const groupId = body.groupId;
173
+ const dashboard = await ctx.getDashboardRecord(body.slug);
191
174
 
192
175
  if (!dashboard) {
193
176
  response.setStatus(404);
@@ -1,9 +1,11 @@
1
1
  import type { AdminUser, IHttpServer } from 'adminforth';
2
2
  import { randomUUID } from 'crypto';
3
- import {
4
- normalizeDashboardWidgetConfig,
3
+ import type {
4
+ DashboardConfig,
5
+ DashboardVariables,
6
+ DashboardWidgetConfig,
7
+ EditableDashboardWidgetConfig,
5
8
  } from '../custom/model/dashboard.types.js';
6
- import type { DashboardConfig, DashboardWidgetConfig } from '../custom/model/dashboard.types.js';
7
9
  import {
8
10
  DashboardApiResponseSchema,
9
11
  DashboardWidgetDataResponseSchema,
@@ -13,8 +15,6 @@ import {
13
15
  WidgetDataRequestSchema,
14
16
  WidgetIdRequestSchema,
15
17
  } from '../schema/api.js';
16
- import { StoredWidgetConfigSchema } from '../schema/widget.js';
17
- import type { DashboardWidgetConfigValidationError } from '../schema/widget.js';
18
18
  import type { DashboardRecord, PersistedDashboardResponse } from '../services/dashboardConfigService.js';
19
19
 
20
20
  type WidgetEndpointsContext = {
@@ -25,49 +25,15 @@ type WidgetEndpointsContext = {
25
25
  dashboard: DashboardRecord,
26
26
  config: DashboardConfig,
27
27
  ) => Promise<PersistedDashboardResponse>;
28
- buildDashboardResponse: (dashboard: DashboardRecord) => PersistedDashboardResponse;
29
- validateDashboardWidgetApiConfig: (
30
- widget: DashboardWidgetConfig,
31
- ) => DashboardWidgetConfigValidationError[];
32
28
  getWidgetData: (
33
29
  widget: DashboardWidgetConfig,
34
- options?: { pagination?: { page: number, pageSize: number } },
30
+ options?: {
31
+ pagination?: { page: number, pageSize: number },
32
+ variables?: DashboardVariables,
33
+ },
35
34
  ) => Promise<unknown>;
36
35
  };
37
36
 
38
- function formatWidgetConfigValidationErrors(error: { issues: { path: PropertyKey[], message: string }[] }) {
39
- return error.issues.map((issue) => ({
40
- field: issue.path.length ? formatWidgetConfigFieldPath(issue.path.map(String).join('.')) : 'config',
41
- message: issue.message,
42
- }));
43
- }
44
-
45
- function formatWidgetConfigApiValidationErrors(errors: DashboardWidgetConfigValidationError[]) {
46
- return errors.map((error) => ({
47
- ...error,
48
- field: formatWidgetConfigFieldPath(error.field),
49
- }));
50
- }
51
-
52
- function formatWidgetConfigFieldPath(field: string) {
53
- const fieldAliases = new Map([
54
- ['minWidth', 'min_width'],
55
- ['maxWidth', 'max_width'],
56
- ['groupBy', 'group_by'],
57
- ['orderBy', 'order_by'],
58
- ['pageSize', 'page_size'],
59
- ['timeSeries', 'time_series'],
60
- ['valueField', 'value_field'],
61
- ['targetValue', 'target_value'],
62
- ['targetField', 'target_field'],
63
- ]);
64
-
65
- return field
66
- .split('.')
67
- .map((segment) => fieldAliases.get(segment) ?? segment)
68
- .join('.');
69
- }
70
-
71
37
  export function registerWidgetEndpoints(
72
38
  server: IHttpServer,
73
39
  ctx: WidgetEndpointsContext,
@@ -84,9 +50,7 @@ export function registerWidgetEndpoints(
84
50
  return { error: 'Dashboard edit is not allowed' };
85
51
  }
86
52
 
87
- const slug = String(body?.slug || 'default');
88
- const groupId = String(body?.groupId || '');
89
- const dashboard = await ctx.getDashboardRecord(slug);
53
+ const dashboard = await ctx.getDashboardRecord(body.slug);
90
54
 
91
55
  if (!dashboard) {
92
56
  response.setStatus(404);
@@ -94,17 +58,17 @@ export function registerWidgetEndpoints(
94
58
  }
95
59
 
96
60
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
97
- const group = config.groups.find((item) => item.id === groupId);
61
+ const group = config.groups.find((item) => item.id === body.groupId);
98
62
 
99
63
  if (!group) {
100
64
  response.setStatus(404);
101
65
  return { error: 'Dashboard group not found' };
102
66
  }
103
67
 
104
- const nextOrder = config.widgets.filter((item) => item.group_id === groupId).length + 1;
68
+ const nextOrder = config.widgets.filter((item) => item.group_id === body.groupId).length + 1;
105
69
  const widget: DashboardWidgetConfig = {
106
70
  id: `widget_${randomUUID()}`,
107
- group_id: groupId,
71
+ group_id: body.groupId,
108
72
  label: 'New widget',
109
73
  size: 'small',
110
74
  order: nextOrder,
@@ -130,10 +94,7 @@ export function registerWidgetEndpoints(
130
94
  return { error: 'Dashboard edit is not allowed' };
131
95
  }
132
96
 
133
- const slug = String(body?.slug || 'default');
134
- const widgetId = String(body?.widgetId || '');
135
- const direction = body?.direction === 'down' ? 'down' : 'up';
136
- const dashboard = await ctx.getDashboardRecord(slug);
97
+ const dashboard = await ctx.getDashboardRecord(body.slug);
137
98
 
138
99
  if (!dashboard) {
139
100
  response.setStatus(404);
@@ -141,7 +102,7 @@ export function registerWidgetEndpoints(
141
102
  }
142
103
 
143
104
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
144
- const widget = config.widgets.find((item) => item.id === widgetId);
105
+ const widget = config.widgets.find((item) => item.id === body.widgetId);
145
106
 
146
107
  if (!widget) {
147
108
  response.setStatus(404);
@@ -151,11 +112,17 @@ export function registerWidgetEndpoints(
151
112
  const sortedWidgets = config.widgets
152
113
  .filter((item) => item.group_id === widget.group_id)
153
114
  .sort((a, b) => a.order - b.order);
154
- const currentIndex = sortedWidgets.findIndex((item) => item.id === widgetId);
155
- const targetIndex = direction === 'up' ? currentIndex - 1 : currentIndex + 1;
115
+ const currentIndex = sortedWidgets.findIndex((item) => item.id === body.widgetId);
116
+ const targetIndex = body.direction === 'up' ? currentIndex - 1 : currentIndex + 1;
156
117
 
157
118
  if (targetIndex < 0 || targetIndex >= sortedWidgets.length) {
158
- return ctx.buildDashboardResponse(dashboard);
119
+ return {
120
+ id: dashboard.id,
121
+ slug: dashboard.slug,
122
+ label: dashboard.label,
123
+ revision: dashboard.revision,
124
+ config: ctx.parseStoredDashboardConfig(dashboard.config),
125
+ };
159
126
  }
160
127
 
161
128
  const reorderedWidgets = [...sortedWidgets];
@@ -185,9 +152,7 @@ export function registerWidgetEndpoints(
185
152
  return { error: 'Dashboard edit is not allowed' };
186
153
  }
187
154
 
188
- const slug = String(body?.slug || 'default');
189
- const widgetId = String(body?.widgetId || '');
190
- const dashboard = await ctx.getDashboardRecord(slug);
155
+ const dashboard = await ctx.getDashboardRecord(body.slug);
191
156
 
192
157
  if (!dashboard) {
193
158
  response.setStatus(404);
@@ -195,7 +160,7 @@ export function registerWidgetEndpoints(
195
160
  }
196
161
 
197
162
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
198
- const nextWidgets = config.widgets.filter((item) => item.id !== widgetId);
163
+ const nextWidgets = config.widgets.filter((item) => item.id !== body.widgetId);
199
164
 
200
165
  if (nextWidgets.length === config.widgets.length) {
201
166
  response.setStatus(404);
@@ -221,9 +186,7 @@ export function registerWidgetEndpoints(
221
186
  return { error: 'Dashboard edit is not allowed' };
222
187
  }
223
188
 
224
- const slug = String(body?.slug || 'default');
225
- const widgetId = String(body?.widgetId || '');
226
- const dashboard = await ctx.getDashboardRecord(slug);
189
+ const dashboard = await ctx.getDashboardRecord(body.slug);
227
190
 
228
191
  if (!dashboard) {
229
192
  response.setStatus(404);
@@ -231,43 +194,26 @@ export function registerWidgetEndpoints(
231
194
  }
232
195
 
233
196
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
234
- const widget = config.widgets.find((item) => item.id === widgetId);
197
+ const widget = config.widgets.find((item) => item.id === body.widgetId);
235
198
 
236
199
  if (!widget) {
237
200
  response.setStatus(404);
238
201
  return { error: 'Dashboard widget not found' };
239
202
  }
240
203
 
241
- const parsedWidgetConfig = StoredWidgetConfigSchema.safeParse(normalizeDashboardWidgetConfig(body.config));
242
-
243
- if (!parsedWidgetConfig.success) {
244
- response.setStatus(422);
245
- return {
246
- error: 'Invalid widget config',
247
- validationErrors: formatWidgetConfigValidationErrors(parsedWidgetConfig.error),
248
- };
249
- }
250
-
251
- const typedWidgetConfig = parsedWidgetConfig.data as DashboardWidgetConfig;
252
- const apiValidationErrors = ctx.validateDashboardWidgetApiConfig(typedWidgetConfig);
204
+ const typedWidgetConfig = body.config as EditableDashboardWidgetConfig;
253
205
 
254
- if (apiValidationErrors.length) {
255
- response.setStatus(422);
256
- return {
257
- error: 'Invalid widget config',
258
- validationErrors: formatWidgetConfigApiValidationErrors(apiValidationErrors),
259
- };
260
- }
206
+ const nextWidget: DashboardWidgetConfig = {
207
+ ...typedWidgetConfig,
208
+ id: widget.id,
209
+ group_id: widget.group_id,
210
+ order: widget.order,
211
+ };
261
212
 
262
213
  return ctx.persistDashboardConfig(dashboard, {
263
214
  ...config,
264
- widgets: config.widgets.map((item) => item.id === widgetId
265
- ? {
266
- ...typedWidgetConfig,
267
- id: widget.id,
268
- group_id: widget.group_id,
269
- order: widget.order,
270
- }
215
+ widgets: config.widgets.map((item) => item.id === body.widgetId
216
+ ? nextWidget
271
217
  : item),
272
218
  });
273
219
  },
@@ -280,9 +226,7 @@ export function registerWidgetEndpoints(
280
226
  request_schema: WidgetDataRequestSchema,
281
227
  response_schema: DashboardWidgetDataResponseSchema,
282
228
  handler: async ({ body, response }) => {
283
- const slug = String(body?.slug || 'default');
284
- const widgetId = String(body?.widgetId || '');
285
- const dashboard = await ctx.getDashboardRecord(slug);
229
+ const dashboard = await ctx.getDashboardRecord(body.slug);
286
230
 
287
231
  if (!dashboard) {
288
232
  response.setStatus(404);
@@ -290,7 +234,7 @@ export function registerWidgetEndpoints(
290
234
  }
291
235
 
292
236
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
293
- const widget = config.widgets.find((item) => item.id === widgetId);
237
+ const widget = config.widgets.find((item) => item.id === body.widgetId);
294
238
 
295
239
  if (!widget) {
296
240
  response.setStatus(404);
@@ -300,7 +244,8 @@ export function registerWidgetEndpoints(
300
244
  return {
301
245
  widget,
302
246
  data: await ctx.getWidgetData(widget, {
303
- pagination: body?.pagination,
247
+ pagination: body.pagination,
248
+ variables: widget.variables,
304
249
  }),
305
250
  };
306
251
  },
package/index.ts CHANGED
@@ -8,7 +8,6 @@ import { registerGroupEndpoints } from "./endpoint/groups.js";
8
8
  import { registerWidgetEndpoints } from './endpoint/widgets.js';
9
9
  import { createDashboardConfigService } from "./services/dashboardConfigService.js";
10
10
  import { createWidgetDataService } from "./services/widgetDataService.js";
11
- import { createWidgetConfigValidatorService } from "./services/widgetConfigValidator.js";
12
11
 
13
12
  const DEFAULT_DASHBOARD_CONFIG = {
14
13
  version: 1,
@@ -119,7 +118,6 @@ export default class DashboardPlugin extends AdminForthPlugin {
119
118
  this.options.dashboardConfigsResourceId,
120
119
  );
121
120
  const widgetDataService = createWidgetDataService(this.adminforth);
122
- const widgetConfigValidatorService = createWidgetConfigValidatorService(this.adminforth);
123
121
 
124
122
  const ctx = {
125
123
  adminforth: this.adminforth,
@@ -127,7 +125,6 @@ export default class DashboardPlugin extends AdminForthPlugin {
127
125
  canEditDashboard,
128
126
  ...dashboardConfigService,
129
127
  ...widgetDataService,
130
- ...widgetConfigValidatorService,
131
128
  };
132
129
 
133
130
  registerDashboardEndpoints(server, ctx);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/dashboard",
3
- "version": "1.3.0",
3
+ "version": "1.4.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -9,7 +9,7 @@
9
9
  "access": "public"
10
10
  },
11
11
  "scripts": {
12
- "build": "tsc && rsync -av --exclude 'node_modules' custom dist/",
12
+ "build": "rm -rf dist && tsc && rsync -av --exclude 'node_modules' custom dist/",
13
13
  "typecheck": "tsc --noEmit"
14
14
  },
15
15
  "keywords": [
@@ -21,7 +21,7 @@
21
21
  "description": "Dashboard plugin for AdminForth",
22
22
  "devDependencies": {
23
23
  "@types/node": "latest",
24
- "adminforth": "^2.60.0",
24
+ "adminforth": "2.61.0-next.9",
25
25
  "semantic-release": "^24.2.1",
26
26
  "semantic-release-slack-bot": "^4.0.2",
27
27
  "typescript": "^5.7.3",
package/schema/api.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { toJSONSchema, z } from 'zod'
2
- import { StoredWidgetConfigSchema, WidgetConfigSchema } from './widget.js'
2
+ import { EditableDashboardWidgetConfigSchema, StoredWidgetConfigSchema } from './widget.js'
3
3
 
4
4
  function toAdminForthJsonSchema(schema: z.ZodType) {
5
5
  return toJSONSchema(schema, { target: 'draft-7' })
@@ -17,13 +17,13 @@ export const DashboardGroupZodSchema = z.object({
17
17
  id: z.string(),
18
18
  label: z.string(),
19
19
  order: z.number(),
20
- })
20
+ }).strict()
21
21
 
22
22
  export const DashboardConfigZodSchema = z.object({
23
23
  version: z.number(),
24
24
  groups: z.array(DashboardGroupZodSchema),
25
25
  widgets: z.array(StoredWidgetConfigSchema),
26
- })
26
+ }).strict()
27
27
 
28
28
  export const DashboardResponseZodSchema = z.object({
29
29
  id: z.string(),
@@ -47,33 +47,42 @@ export const DashboardWidgetDataResponseZodSchema = z.union([
47
47
  ])
48
48
 
49
49
  export const SlugRequestZodSchema = z.object({
50
- slug: z.string().optional(),
50
+ slug: z.string(),
51
+ }).strict()
52
+
53
+ export const SetDashboardConfigRequestZodSchema = z.object({
54
+ slug: z.string(),
55
+ config: DashboardConfigZodSchema,
51
56
  }).strict()
52
57
 
53
58
  export const GroupIdRequestZodSchema = z.object({
54
- slug: z.string().optional(),
59
+ slug: z.string(),
55
60
  groupId: z.string(),
56
61
  }).strict()
57
62
 
58
63
  export const MoveGroupRequestZodSchema = z.object({
59
- slug: z.string().optional(),
64
+ slug: z.string(),
60
65
  groupId: z.string(),
61
66
  direction: z.enum(['up', 'down']),
62
67
  }).strict()
63
68
 
69
+ export const EditableDashboardGroupConfigZodSchema = z.object({
70
+ label: z.string(),
71
+ }).strict()
72
+
64
73
  export const SetGroupConfigRequestZodSchema = z.object({
65
- slug: z.string().optional(),
74
+ slug: z.string(),
66
75
  groupId: z.string(),
67
- config: DashboardGroupZodSchema,
76
+ config: EditableDashboardGroupConfigZodSchema,
68
77
  }).strict()
69
78
 
70
79
  export const WidgetIdRequestZodSchema = z.object({
71
- slug: z.string().optional(),
80
+ slug: z.string(),
72
81
  widgetId: z.string(),
73
82
  }).strict()
74
83
 
75
84
  export const WidgetDataRequestZodSchema = z.object({
76
- slug: z.string().optional(),
85
+ slug: z.string(),
77
86
  widgetId: z.string(),
78
87
  pagination: z.object({
79
88
  page: z.number().int().positive(),
@@ -82,15 +91,15 @@ export const WidgetDataRequestZodSchema = z.object({
82
91
  }).strict()
83
92
 
84
93
  export const MoveWidgetRequestZodSchema = z.object({
85
- slug: z.string().optional(),
94
+ slug: z.string(),
86
95
  widgetId: z.string(),
87
96
  direction: z.enum(['up', 'down']),
88
97
  }).strict()
89
98
 
90
99
  export const SetWidgetConfigRequestZodSchema = z.object({
91
- slug: z.string().optional(),
100
+ slug: z.string(),
92
101
  widgetId: z.string(),
93
- config: z.record(z.string(), z.unknown()),
102
+ config: EditableDashboardWidgetConfigSchema,
94
103
  }).strict()
95
104
 
96
105
  export const DashboardErrorResponseSchema = toAdminForthJsonSchema(DashboardErrorResponseZodSchema)
@@ -100,6 +109,7 @@ export const DashboardResponseSchema = toAdminForthJsonSchema(DashboardResponseZ
100
109
  export const DashboardApiResponseSchema = toAdminForthJsonSchema(DashboardApiResponseZodSchema)
101
110
  export const DashboardWidgetDataResponseSchema = toAdminForthJsonSchema(DashboardWidgetDataResponseZodSchema)
102
111
  export const SlugRequestSchema = toAdminForthJsonSchema(SlugRequestZodSchema)
112
+ export const SetDashboardConfigRequestSchema = toAdminForthJsonSchema(SetDashboardConfigRequestZodSchema)
103
113
  export const GroupIdRequestSchema = toAdminForthJsonSchema(GroupIdRequestZodSchema)
104
114
  export const MoveGroupRequestSchema = toAdminForthJsonSchema(MoveGroupRequestZodSchema)
105
115
  export const SetGroupConfigRequestSchema = toAdminForthJsonSchema(SetGroupConfigRequestZodSchema)