@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.
Files changed (78) 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/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 +2 -2
  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 +4 -15
  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 -8
  23. package/dist/custom/api/dashboardApi.ts +6 -9
  24. package/dist/custom/model/dashboard.types.d.ts +38 -32
  25. package/dist/custom/model/dashboard.types.js +2 -155
  26. package/dist/custom/model/dashboard.types.ts +60 -275
  27. package/dist/custom/model/dashboardTopics.d.ts +2 -0
  28. package/dist/custom/model/dashboardTopics.js +8 -0
  29. package/dist/custom/model/dashboardTopics.ts +5 -0
  30. package/dist/custom/queries/useDashboardConfig.d.ts +96 -96
  31. package/dist/custom/queries/useWidgetData.d.ts +96 -96
  32. package/dist/custom/runtime/DashboardGroup.vue +2 -2
  33. package/dist/custom/runtime/DashboardPage.vue +17 -7
  34. package/dist/custom/runtime/DashboardRuntime.vue +20 -8
  35. package/dist/custom/runtime/WidgetRenderer.vue +1 -2
  36. package/dist/custom/runtime/WidgetShell.vue +3 -3
  37. package/dist/custom/skills/adminforth-dashboard/SKILL.md +2 -2
  38. package/dist/custom/widgets/{gauge-card/GaugeCardWidget.vue → GaugeCardWidget.vue} +63 -61
  39. package/dist/custom/widgets/{kpi-card/KpiCardWidget.vue → KpiCardWidget.vue} +35 -33
  40. package/dist/custom/widgets/{pivot-table/PivotTableWidget.vue → PivotTableWidget.vue} +71 -68
  41. package/dist/custom/widgets/{table/TableWidget.vue → TableWidget.vue} +5 -5
  42. package/dist/custom/widgets/chart/{bar/BarChart.vue → BarChart.vue} +2 -2
  43. package/dist/custom/widgets/chart/ChartWidget.vue +4 -15
  44. package/{custom/widgets/chart/funnel → dist/custom/widgets/chart}/FunnelChart.vue +80 -78
  45. package/{custom/widgets/chart/line → dist/custom/widgets/chart}/LineChart.vue +2 -2
  46. package/dist/custom/widgets/chart/{pie/PieChart.vue → PieChart.vue} +2 -2
  47. package/{custom/widgets/chart/stacked-bar → dist/custom/widgets/chart}/StackedBarChart.vue +97 -95
  48. package/dist/custom/widgets/chart/chart.types.d.ts +0 -2
  49. package/dist/custom/widgets/chart/chart.types.js +0 -23
  50. package/dist/custom/widgets/chart/chart.types.ts +0 -28
  51. package/dist/endpoint/dashboard.d.ts +2 -3
  52. package/dist/endpoint/dashboard.js +12 -32
  53. package/dist/endpoint/groups.d.ts +2 -21
  54. package/dist/endpoint/groups.js +18 -16
  55. package/dist/endpoint/widgets.d.ts +0 -3
  56. package/dist/endpoint/widgets.js +27 -74
  57. package/dist/index.js +1 -3
  58. package/dist/schema/api.d.ts +2090 -511
  59. package/dist/schema/api.js +18 -15
  60. package/dist/schema/widget.d.ts +1003 -250
  61. package/dist/schema/widget.js +102 -46
  62. package/dist/services/dashboardConfigService.d.ts +0 -10
  63. package/dist/services/dashboardConfigService.js +6 -21
  64. package/dist/services/widgetDataService.js +226 -196
  65. package/endpoint/dashboard.ts +13 -46
  66. package/endpoint/groups.ts +25 -42
  67. package/endpoint/widgets.ts +36 -95
  68. package/index.ts +0 -3
  69. package/package.json +3 -3
  70. package/schema/api.ts +19 -15
  71. package/schema/widget.ts +113 -52
  72. package/services/dashboardConfigService.ts +6 -25
  73. package/services/widgetDataService.ts +304 -229
  74. package/custom/widgets/chart/histogram/HistogramChart.vue +0 -21
  75. package/dist/custom/widgets/chart/histogram/HistogramChart.vue +0 -21
  76. package/dist/services/widgetConfigValidator.d.ts +0 -8
  77. package/dist/services/widgetConfigValidator.js +0 -27
  78. 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, DashboardVariables, 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,10 +25,6 @@ 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
30
  options?: {
@@ -38,39 +34,6 @@ type WidgetEndpointsContext = {
38
34
  ) => Promise<unknown>;
39
35
  };
40
36
 
41
- function formatWidgetConfigValidationErrors(error: { issues: { path: PropertyKey[], message: string }[] }) {
42
- return error.issues.map((issue) => ({
43
- field: issue.path.length ? formatWidgetConfigFieldPath(issue.path.map(String).join('.')) : 'config',
44
- message: issue.message,
45
- }));
46
- }
47
-
48
- function formatWidgetConfigApiValidationErrors(errors: DashboardWidgetConfigValidationError[]) {
49
- return errors.map((error) => ({
50
- ...error,
51
- field: formatWidgetConfigFieldPath(error.field),
52
- }));
53
- }
54
-
55
- function formatWidgetConfigFieldPath(field: string) {
56
- const fieldAliases = new Map([
57
- ['minWidth', 'min_width'],
58
- ['maxWidth', 'max_width'],
59
- ['groupBy', 'group_by'],
60
- ['orderBy', 'order_by'],
61
- ['pageSize', 'page_size'],
62
- ['timeSeries', 'time_series'],
63
- ['valueField', 'value_field'],
64
- ['targetValue', 'target_value'],
65
- ['targetField', 'target_field'],
66
- ]);
67
-
68
- return field
69
- .split('.')
70
- .map((segment) => fieldAliases.get(segment) ?? segment)
71
- .join('.');
72
- }
73
-
74
37
  export function registerWidgetEndpoints(
75
38
  server: IHttpServer,
76
39
  ctx: WidgetEndpointsContext,
@@ -87,9 +50,7 @@ export function registerWidgetEndpoints(
87
50
  return { error: 'Dashboard edit is not allowed' };
88
51
  }
89
52
 
90
- const slug = String(body?.slug || 'default');
91
- const groupId = String(body?.groupId || '');
92
- const dashboard = await ctx.getDashboardRecord(slug);
53
+ const dashboard = await ctx.getDashboardRecord(body.slug);
93
54
 
94
55
  if (!dashboard) {
95
56
  response.setStatus(404);
@@ -97,17 +58,17 @@ export function registerWidgetEndpoints(
97
58
  }
98
59
 
99
60
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
100
- const group = config.groups.find((item) => item.id === groupId);
61
+ const group = config.groups.find((item) => item.id === body.groupId);
101
62
 
102
63
  if (!group) {
103
64
  response.setStatus(404);
104
65
  return { error: 'Dashboard group not found' };
105
66
  }
106
67
 
107
- 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;
108
69
  const widget: DashboardWidgetConfig = {
109
70
  id: `widget_${randomUUID()}`,
110
- group_id: groupId,
71
+ group_id: body.groupId,
111
72
  label: 'New widget',
112
73
  size: 'small',
113
74
  order: nextOrder,
@@ -133,10 +94,7 @@ export function registerWidgetEndpoints(
133
94
  return { error: 'Dashboard edit is not allowed' };
134
95
  }
135
96
 
136
- const slug = String(body?.slug || 'default');
137
- const widgetId = String(body?.widgetId || '');
138
- const direction = body?.direction === 'down' ? 'down' : 'up';
139
- const dashboard = await ctx.getDashboardRecord(slug);
97
+ const dashboard = await ctx.getDashboardRecord(body.slug);
140
98
 
141
99
  if (!dashboard) {
142
100
  response.setStatus(404);
@@ -144,7 +102,7 @@ export function registerWidgetEndpoints(
144
102
  }
145
103
 
146
104
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
147
- const widget = config.widgets.find((item) => item.id === widgetId);
105
+ const widget = config.widgets.find((item) => item.id === body.widgetId);
148
106
 
149
107
  if (!widget) {
150
108
  response.setStatus(404);
@@ -154,11 +112,17 @@ export function registerWidgetEndpoints(
154
112
  const sortedWidgets = config.widgets
155
113
  .filter((item) => item.group_id === widget.group_id)
156
114
  .sort((a, b) => a.order - b.order);
157
- const currentIndex = sortedWidgets.findIndex((item) => item.id === widgetId);
158
- 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;
159
117
 
160
118
  if (targetIndex < 0 || targetIndex >= sortedWidgets.length) {
161
- 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
+ };
162
126
  }
163
127
 
164
128
  const reorderedWidgets = [...sortedWidgets];
@@ -188,9 +152,7 @@ export function registerWidgetEndpoints(
188
152
  return { error: 'Dashboard edit is not allowed' };
189
153
  }
190
154
 
191
- const slug = String(body?.slug || 'default');
192
- const widgetId = String(body?.widgetId || '');
193
- const dashboard = await ctx.getDashboardRecord(slug);
155
+ const dashboard = await ctx.getDashboardRecord(body.slug);
194
156
 
195
157
  if (!dashboard) {
196
158
  response.setStatus(404);
@@ -198,7 +160,7 @@ export function registerWidgetEndpoints(
198
160
  }
199
161
 
200
162
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
201
- const nextWidgets = config.widgets.filter((item) => item.id !== widgetId);
163
+ const nextWidgets = config.widgets.filter((item) => item.id !== body.widgetId);
202
164
 
203
165
  if (nextWidgets.length === config.widgets.length) {
204
166
  response.setStatus(404);
@@ -224,9 +186,7 @@ export function registerWidgetEndpoints(
224
186
  return { error: 'Dashboard edit is not allowed' };
225
187
  }
226
188
 
227
- const slug = String(body?.slug || 'default');
228
- const widgetId = String(body?.widgetId || '');
229
- const dashboard = await ctx.getDashboardRecord(slug);
189
+ const dashboard = await ctx.getDashboardRecord(body.slug);
230
190
 
231
191
  if (!dashboard) {
232
192
  response.setStatus(404);
@@ -234,43 +194,26 @@ export function registerWidgetEndpoints(
234
194
  }
235
195
 
236
196
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
237
- const widget = config.widgets.find((item) => item.id === widgetId);
197
+ const widget = config.widgets.find((item) => item.id === body.widgetId);
238
198
 
239
199
  if (!widget) {
240
200
  response.setStatus(404);
241
201
  return { error: 'Dashboard widget not found' };
242
202
  }
243
203
 
244
- const parsedWidgetConfig = StoredWidgetConfigSchema.safeParse(normalizeDashboardWidgetConfig(body.config));
204
+ const typedWidgetConfig = body.config as EditableDashboardWidgetConfig;
245
205
 
246
- if (!parsedWidgetConfig.success) {
247
- response.setStatus(422);
248
- return {
249
- error: 'Invalid widget config',
250
- validationErrors: formatWidgetConfigValidationErrors(parsedWidgetConfig.error),
251
- };
252
- }
253
-
254
- const typedWidgetConfig = parsedWidgetConfig.data as DashboardWidgetConfig;
255
- const apiValidationErrors = ctx.validateDashboardWidgetApiConfig(typedWidgetConfig);
256
-
257
- if (apiValidationErrors.length) {
258
- response.setStatus(422);
259
- return {
260
- error: 'Invalid widget config',
261
- validationErrors: formatWidgetConfigApiValidationErrors(apiValidationErrors),
262
- };
263
- }
206
+ const nextWidget: DashboardWidgetConfig = {
207
+ ...typedWidgetConfig,
208
+ id: widget.id,
209
+ group_id: widget.group_id,
210
+ order: widget.order,
211
+ };
264
212
 
265
213
  return ctx.persistDashboardConfig(dashboard, {
266
214
  ...config,
267
- widgets: config.widgets.map((item) => item.id === widgetId
268
- ? {
269
- ...typedWidgetConfig,
270
- id: widget.id,
271
- group_id: widget.group_id,
272
- order: widget.order,
273
- }
215
+ widgets: config.widgets.map((item) => item.id === body.widgetId
216
+ ? nextWidget
274
217
  : item),
275
218
  });
276
219
  },
@@ -283,9 +226,7 @@ export function registerWidgetEndpoints(
283
226
  request_schema: WidgetDataRequestSchema,
284
227
  response_schema: DashboardWidgetDataResponseSchema,
285
228
  handler: async ({ body, response }) => {
286
- const slug = String(body?.slug || 'default');
287
- const widgetId = String(body?.widgetId || '');
288
- const dashboard = await ctx.getDashboardRecord(slug);
229
+ const dashboard = await ctx.getDashboardRecord(body.slug);
289
230
 
290
231
  if (!dashboard) {
291
232
  response.setStatus(404);
@@ -293,7 +234,7 @@ export function registerWidgetEndpoints(
293
234
  }
294
235
 
295
236
  const config = ctx.parseStoredDashboardConfig(dashboard.config);
296
- const widget = config.widgets.find((item) => item.id === widgetId);
237
+ const widget = config.widgets.find((item) => item.id === body.widgetId);
297
238
 
298
239
  if (!widget) {
299
240
  response.setStatus(404);
@@ -303,7 +244,7 @@ export function registerWidgetEndpoints(
303
244
  return {
304
245
  widget,
305
246
  data: await ctx.getWidgetData(widget, {
306
- pagination: body?.pagination,
247
+ pagination: body.pagination,
307
248
  variables: widget.variables,
308
249
  }),
309
250
  };
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.4.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,38 +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
51
  }).strict()
52
52
 
53
53
  export const SetDashboardConfigRequestZodSchema = z.object({
54
- slug: z.string().optional(),
55
- config: z.record(z.string(), z.unknown()),
54
+ slug: z.string(),
55
+ config: DashboardConfigZodSchema,
56
56
  }).strict()
57
57
 
58
58
  export const GroupIdRequestZodSchema = z.object({
59
- slug: z.string().optional(),
59
+ slug: z.string(),
60
60
  groupId: z.string(),
61
61
  }).strict()
62
62
 
63
63
  export const MoveGroupRequestZodSchema = z.object({
64
- slug: z.string().optional(),
64
+ slug: z.string(),
65
65
  groupId: z.string(),
66
66
  direction: z.enum(['up', 'down']),
67
67
  }).strict()
68
68
 
69
+ export const EditableDashboardGroupConfigZodSchema = z.object({
70
+ label: z.string(),
71
+ }).strict()
72
+
69
73
  export const SetGroupConfigRequestZodSchema = z.object({
70
- slug: z.string().optional(),
74
+ slug: z.string(),
71
75
  groupId: z.string(),
72
- config: DashboardGroupZodSchema,
76
+ config: EditableDashboardGroupConfigZodSchema,
73
77
  }).strict()
74
78
 
75
79
  export const WidgetIdRequestZodSchema = z.object({
76
- slug: z.string().optional(),
80
+ slug: z.string(),
77
81
  widgetId: z.string(),
78
82
  }).strict()
79
83
 
80
84
  export const WidgetDataRequestZodSchema = z.object({
81
- slug: z.string().optional(),
85
+ slug: z.string(),
82
86
  widgetId: z.string(),
83
87
  pagination: z.object({
84
88
  page: z.number().int().positive(),
@@ -87,15 +91,15 @@ export const WidgetDataRequestZodSchema = z.object({
87
91
  }).strict()
88
92
 
89
93
  export const MoveWidgetRequestZodSchema = z.object({
90
- slug: z.string().optional(),
94
+ slug: z.string(),
91
95
  widgetId: z.string(),
92
96
  direction: z.enum(['up', 'down']),
93
97
  }).strict()
94
98
 
95
99
  export const SetWidgetConfigRequestZodSchema = z.object({
96
- slug: z.string().optional(),
100
+ slug: z.string(),
97
101
  widgetId: z.string(),
98
- config: z.record(z.string(), z.unknown()),
102
+ config: EditableDashboardWidgetConfigSchema,
99
103
  }).strict()
100
104
 
101
105
  export const DashboardErrorResponseSchema = toAdminForthJsonSchema(DashboardErrorResponseZodSchema)