@adminforth/dashboard 1.10.0 → 1.11.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.
@@ -22,26 +22,320 @@ Dashboard root, groups, and widgets are different entities.
22
22
 
23
23
  ## Tool routing
24
24
 
25
+ - Get dashboard slugs: dashboard_get_slugs
25
26
  - Read dashboard: dashboard_get_config
26
27
  - Add group: dashboard_add_dashboard_group
27
28
  - Rename group: dashboard_set_dashboard_group_config
28
29
  - Add widget slot: dashboard_add_dashboard_widget
29
- - Configure table widget: dashboard_configure_table_widget
30
- - Configure KPI card widget: dashboard_configure_kpi_card_widget
31
- - Configure gauge card widget: dashboard_configure_gauge_card_widget
32
- - Configure line chart widget: dashboard_configure_line_chart_widget
33
- - Configure bar chart widget: dashboard_configure_bar_chart_widget
34
- - Configure stacked bar chart widget: dashboard_configure_stacked_bar_chart_widget
35
- - Configure pie chart widget: dashboard_configure_pie_chart_widget
36
- - Configure histogram chart widget: dashboard_configure_histogram_chart_widget
37
- - Configure funnel chart widget: dashboard_configure_funnel_chart_widget
38
- - Configure pivot table widget: dashboard_configure_pivot_table_widget
30
+ - Configure widget:
31
+ - table: dashboard_configure_table_widget
32
+ - kpi_card: dashboard_configure_kpi_card_widget
33
+ - gauge_card: dashboard_configure_gauge_card_widget
34
+ - pivot_table: dashboard_configure_pivot_table_widget
35
+ - line_chart: dashboard_configure_line_chart_widget
36
+ - bar_chart: dashboard_configure_bar_chart_widget
37
+ - stacked_bar_chart: dashboard_configure_stacked_bar_chart_widget
38
+ - pie_chart: dashboard_configure_pie_chart_widget
39
+ - histogram_chart: dashboard_configure_histogram_chart_widget
40
+ - funnel_chart: dashboard_configure_funnel_chart_widget
39
41
  - Move/remove widget/group: matching move/remove tool
40
42
  - Load widget data: dashboard_get_dashboard_widget_data
41
43
 
42
44
  If a known dashboard tool schema is missing, call fetch_tool_schema for that exact tool.
43
45
  If fetch_tool_schema returns but the intended tool is still not callable, stop and report a tool-routing error. Do not substitute another mutation tool.
44
46
 
47
+ ## Configure schema examples
48
+
49
+ These examples show the expected shape only. Do not copy them one-to-one: adapt resource names, fields, aggregations, labels, filters, formats, and calculations to the actual dashboard request and available resource columns.
50
+
51
+ Important:
52
+ - `config.target` is the widget target, never a resource path.
53
+ - Never use values like `/resource/llm_usage` in `config.target`.
54
+ - Put the data resource in `config.query.resource`, for example `query.resource: "llm_usage"`.
55
+ - For chart widgets, `config.target` is always `chart`; the concrete chart kind is `config.chart.type`.
56
+ - `query.calcs[].calc` is an expression over already selected fields/aliases, not raw SQL. Do not use SQL syntax such as `CASE WHEN`.
57
+
58
+ Example `dashboard_configure_table_widget` config:
59
+
60
+ ```yaml
61
+ target: table
62
+ label: Recent usage
63
+ size: wide
64
+ table:
65
+ columns:
66
+ - field: used_at
67
+ label: Date
68
+ - field: model
69
+ label: Model
70
+ - field: total_tokens
71
+ label: Tokens
72
+ format: integer
73
+ pagination: true
74
+ page_size: 20
75
+ query:
76
+ resource: llm_usage
77
+ select:
78
+ - field: used_at
79
+ - field: model
80
+ - field: total_tokens
81
+ order_by:
82
+ - field: used_at
83
+ direction: desc
84
+ ```
85
+
86
+ Example `dashboard_configure_kpi_card_widget` config:
87
+
88
+ ```yaml
89
+ target: kpi_card
90
+ label: Total spend
91
+ size: medium
92
+ card:
93
+ title: Total spend
94
+ value:
95
+ field: spend
96
+ format: currency
97
+ query:
98
+ resource: llm_usage
99
+ select:
100
+ - agg: sum
101
+ field: cost
102
+ as: spend
103
+ ```
104
+
105
+ Example `dashboard_configure_gauge_card_widget` config:
106
+
107
+ ```yaml
108
+ target: gauge_card
109
+ label: Budget usage
110
+ size: medium
111
+ card:
112
+ title: Budget usage
113
+ value:
114
+ field: spend
115
+ format: currency
116
+ progress:
117
+ value_field: spend
118
+ target_value: 1000
119
+ format: percent
120
+ query:
121
+ resource: llm_usage
122
+ select:
123
+ - agg: sum
124
+ field: cost
125
+ as: spend
126
+ ```
127
+
128
+ Example `dashboard_configure_pivot_table_widget` config:
129
+
130
+ ```yaml
131
+ target: pivot_table
132
+ label: Spend by model and purpose
133
+ size: wide
134
+ pivot:
135
+ rows:
136
+ - field: model
137
+ label: Model
138
+ columns:
139
+ - field: purpose
140
+ label: Purpose
141
+ values:
142
+ - field: spend
143
+ label: Spend
144
+ format: currency
145
+ aggregation: sum
146
+ query:
147
+ resource: llm_usage
148
+ select:
149
+ - field: model
150
+ - field: purpose
151
+ - agg: sum
152
+ field: cost
153
+ as: spend
154
+ group_by:
155
+ - model
156
+ - purpose
157
+ ```
158
+
159
+ Example `dashboard_configure_line_chart_widget` config:
160
+
161
+ ```yaml
162
+ target: chart
163
+ label: Daily spend
164
+ size: wide
165
+ chart:
166
+ type: line
167
+ x:
168
+ field: day
169
+ label: Day
170
+ y:
171
+ - field: spend
172
+ label: Spend
173
+ format: currency
174
+ query:
175
+ resource: llm_usage
176
+ select:
177
+ - field: used_at
178
+ grain: day
179
+ as: day
180
+ - agg: sum
181
+ field: cost
182
+ as: spend
183
+ group_by:
184
+ - field: used_at
185
+ grain: day
186
+ as: day
187
+ order_by:
188
+ - field: day
189
+ direction: asc
190
+ ```
191
+
192
+ Example `dashboard_configure_bar_chart_widget` config:
193
+
194
+ ```yaml
195
+ target: chart
196
+ label: Spend by model
197
+ size: wide
198
+ chart:
199
+ type: bar
200
+ x:
201
+ field: model
202
+ label: Model
203
+ y:
204
+ field: spend
205
+ label: Spend
206
+ format: currency
207
+ query:
208
+ resource: llm_usage
209
+ select:
210
+ - field: model
211
+ - agg: sum
212
+ field: cost
213
+ as: spend
214
+ group_by:
215
+ - model
216
+ ```
217
+
218
+ Example `dashboard_configure_stacked_bar_chart_widget` config:
219
+
220
+ ```yaml
221
+ target: chart
222
+ label: Daily spend by purpose
223
+ size: wide
224
+ chart:
225
+ type: stacked_bar
226
+ x:
227
+ field: day
228
+ label: Day
229
+ y:
230
+ field: spend
231
+ label: Spend
232
+ format: currency
233
+ series:
234
+ field: purpose
235
+ label: Purpose
236
+ query:
237
+ resource: llm_usage
238
+ select:
239
+ - field: used_at
240
+ grain: day
241
+ as: day
242
+ - field: purpose
243
+ - agg: sum
244
+ field: cost
245
+ as: spend
246
+ group_by:
247
+ - field: used_at
248
+ grain: day
249
+ as: day
250
+ - purpose
251
+ order_by:
252
+ - field: day
253
+ direction: asc
254
+ ```
255
+
256
+ Example `dashboard_configure_pie_chart_widget` config:
257
+
258
+ ```yaml
259
+ target: chart
260
+ label: Spend share by model
261
+ size: medium
262
+ chart:
263
+ type: pie
264
+ label:
265
+ field: model
266
+ label: Model
267
+ value:
268
+ field: spend
269
+ label: Spend
270
+ format: currency
271
+ query:
272
+ resource: llm_usage
273
+ select:
274
+ - field: model
275
+ - agg: sum
276
+ field: cost
277
+ as: spend
278
+ group_by:
279
+ - model
280
+ ```
281
+
282
+ Example `dashboard_configure_histogram_chart_widget` config:
283
+
284
+ ```yaml
285
+ target: chart
286
+ label: Request size distribution
287
+ size: wide
288
+ chart:
289
+ type: histogram
290
+ x:
291
+ field: total_tokens
292
+ label: Tokens
293
+ y:
294
+ field: requests
295
+ label: Requests
296
+ query:
297
+ resource: llm_usage
298
+ select:
299
+ - field: total_tokens
300
+ - agg: count
301
+ as: requests
302
+ bucket:
303
+ field: total_tokens
304
+ buckets:
305
+ - label: Small
306
+ max: 1000
307
+ - label: Medium
308
+ min: 1000
309
+ max: 10000
310
+ - label: Large
311
+ min: 10000
312
+ ```
313
+
314
+ Example `dashboard_configure_funnel_chart_widget` config:
315
+
316
+ ```yaml
317
+ target: chart
318
+ label: Request funnel
319
+ size: wide
320
+ chart:
321
+ type: funnel
322
+ label:
323
+ field: stage
324
+ label: Stage
325
+ value:
326
+ field: count
327
+ label: Count
328
+ query:
329
+ resource: llm_usage
330
+ select:
331
+ - field: stage
332
+ - agg: count
333
+ as: count
334
+ group_by:
335
+ - stage
336
+ ```
337
+
338
+
45
339
  ## Group creation guard
46
340
 
47
341
  Before creating a group, call dashboard_get_config and check existing groups.
@@ -148,6 +442,7 @@ Use target, not type.
148
442
  For charts, use target: chart and chart.type for the concrete chart kind.
149
443
  Use query, not dataSource.
150
444
  Use resource, not resourceId.
445
+ Never use AdminForth routes such as /resource/llm_usage as resource or target values.
151
446
 
152
447
  ## Query shape rules
153
448
 
@@ -22,26 +22,320 @@ Dashboard root, groups, and widgets are different entities.
22
22
 
23
23
  ## Tool routing
24
24
 
25
+ - Get dashboard slugs: dashboard_get_slugs
25
26
  - Read dashboard: dashboard_get_config
26
27
  - Add group: dashboard_add_dashboard_group
27
28
  - Rename group: dashboard_set_dashboard_group_config
28
29
  - Add widget slot: dashboard_add_dashboard_widget
29
- - Configure table widget: dashboard_configure_table_widget
30
- - Configure KPI card widget: dashboard_configure_kpi_card_widget
31
- - Configure gauge card widget: dashboard_configure_gauge_card_widget
32
- - Configure line chart widget: dashboard_configure_line_chart_widget
33
- - Configure bar chart widget: dashboard_configure_bar_chart_widget
34
- - Configure stacked bar chart widget: dashboard_configure_stacked_bar_chart_widget
35
- - Configure pie chart widget: dashboard_configure_pie_chart_widget
36
- - Configure histogram chart widget: dashboard_configure_histogram_chart_widget
37
- - Configure funnel chart widget: dashboard_configure_funnel_chart_widget
38
- - Configure pivot table widget: dashboard_configure_pivot_table_widget
30
+ - Configure widget:
31
+ - table: dashboard_configure_table_widget
32
+ - kpi_card: dashboard_configure_kpi_card_widget
33
+ - gauge_card: dashboard_configure_gauge_card_widget
34
+ - pivot_table: dashboard_configure_pivot_table_widget
35
+ - line_chart: dashboard_configure_line_chart_widget
36
+ - bar_chart: dashboard_configure_bar_chart_widget
37
+ - stacked_bar_chart: dashboard_configure_stacked_bar_chart_widget
38
+ - pie_chart: dashboard_configure_pie_chart_widget
39
+ - histogram_chart: dashboard_configure_histogram_chart_widget
40
+ - funnel_chart: dashboard_configure_funnel_chart_widget
39
41
  - Move/remove widget/group: matching move/remove tool
40
42
  - Load widget data: dashboard_get_dashboard_widget_data
41
43
 
42
44
  If a known dashboard tool schema is missing, call fetch_tool_schema for that exact tool.
43
45
  If fetch_tool_schema returns but the intended tool is still not callable, stop and report a tool-routing error. Do not substitute another mutation tool.
44
46
 
47
+ ## Configure schema examples
48
+
49
+ These examples show the expected shape only. Do not copy them one-to-one: adapt resource names, fields, aggregations, labels, filters, formats, and calculations to the actual dashboard request and available resource columns.
50
+
51
+ Important:
52
+ - `config.target` is the widget target, never a resource path.
53
+ - Never use values like `/resource/llm_usage` in `config.target`.
54
+ - Put the data resource in `config.query.resource`, for example `query.resource: "llm_usage"`.
55
+ - For chart widgets, `config.target` is always `chart`; the concrete chart kind is `config.chart.type`.
56
+ - `query.calcs[].calc` is an expression over already selected fields/aliases, not raw SQL. Do not use SQL syntax such as `CASE WHEN`.
57
+
58
+ Example `dashboard_configure_table_widget` config:
59
+
60
+ ```yaml
61
+ target: table
62
+ label: Recent usage
63
+ size: wide
64
+ table:
65
+ columns:
66
+ - field: used_at
67
+ label: Date
68
+ - field: model
69
+ label: Model
70
+ - field: total_tokens
71
+ label: Tokens
72
+ format: integer
73
+ pagination: true
74
+ page_size: 20
75
+ query:
76
+ resource: llm_usage
77
+ select:
78
+ - field: used_at
79
+ - field: model
80
+ - field: total_tokens
81
+ order_by:
82
+ - field: used_at
83
+ direction: desc
84
+ ```
85
+
86
+ Example `dashboard_configure_kpi_card_widget` config:
87
+
88
+ ```yaml
89
+ target: kpi_card
90
+ label: Total spend
91
+ size: medium
92
+ card:
93
+ title: Total spend
94
+ value:
95
+ field: spend
96
+ format: currency
97
+ query:
98
+ resource: llm_usage
99
+ select:
100
+ - agg: sum
101
+ field: cost
102
+ as: spend
103
+ ```
104
+
105
+ Example `dashboard_configure_gauge_card_widget` config:
106
+
107
+ ```yaml
108
+ target: gauge_card
109
+ label: Budget usage
110
+ size: medium
111
+ card:
112
+ title: Budget usage
113
+ value:
114
+ field: spend
115
+ format: currency
116
+ progress:
117
+ value_field: spend
118
+ target_value: 1000
119
+ format: percent
120
+ query:
121
+ resource: llm_usage
122
+ select:
123
+ - agg: sum
124
+ field: cost
125
+ as: spend
126
+ ```
127
+
128
+ Example `dashboard_configure_pivot_table_widget` config:
129
+
130
+ ```yaml
131
+ target: pivot_table
132
+ label: Spend by model and purpose
133
+ size: wide
134
+ pivot:
135
+ rows:
136
+ - field: model
137
+ label: Model
138
+ columns:
139
+ - field: purpose
140
+ label: Purpose
141
+ values:
142
+ - field: spend
143
+ label: Spend
144
+ format: currency
145
+ aggregation: sum
146
+ query:
147
+ resource: llm_usage
148
+ select:
149
+ - field: model
150
+ - field: purpose
151
+ - agg: sum
152
+ field: cost
153
+ as: spend
154
+ group_by:
155
+ - model
156
+ - purpose
157
+ ```
158
+
159
+ Example `dashboard_configure_line_chart_widget` config:
160
+
161
+ ```yaml
162
+ target: chart
163
+ label: Daily spend
164
+ size: wide
165
+ chart:
166
+ type: line
167
+ x:
168
+ field: day
169
+ label: Day
170
+ y:
171
+ - field: spend
172
+ label: Spend
173
+ format: currency
174
+ query:
175
+ resource: llm_usage
176
+ select:
177
+ - field: used_at
178
+ grain: day
179
+ as: day
180
+ - agg: sum
181
+ field: cost
182
+ as: spend
183
+ group_by:
184
+ - field: used_at
185
+ grain: day
186
+ as: day
187
+ order_by:
188
+ - field: day
189
+ direction: asc
190
+ ```
191
+
192
+ Example `dashboard_configure_bar_chart_widget` config:
193
+
194
+ ```yaml
195
+ target: chart
196
+ label: Spend by model
197
+ size: wide
198
+ chart:
199
+ type: bar
200
+ x:
201
+ field: model
202
+ label: Model
203
+ y:
204
+ field: spend
205
+ label: Spend
206
+ format: currency
207
+ query:
208
+ resource: llm_usage
209
+ select:
210
+ - field: model
211
+ - agg: sum
212
+ field: cost
213
+ as: spend
214
+ group_by:
215
+ - model
216
+ ```
217
+
218
+ Example `dashboard_configure_stacked_bar_chart_widget` config:
219
+
220
+ ```yaml
221
+ target: chart
222
+ label: Daily spend by purpose
223
+ size: wide
224
+ chart:
225
+ type: stacked_bar
226
+ x:
227
+ field: day
228
+ label: Day
229
+ y:
230
+ field: spend
231
+ label: Spend
232
+ format: currency
233
+ series:
234
+ field: purpose
235
+ label: Purpose
236
+ query:
237
+ resource: llm_usage
238
+ select:
239
+ - field: used_at
240
+ grain: day
241
+ as: day
242
+ - field: purpose
243
+ - agg: sum
244
+ field: cost
245
+ as: spend
246
+ group_by:
247
+ - field: used_at
248
+ grain: day
249
+ as: day
250
+ - purpose
251
+ order_by:
252
+ - field: day
253
+ direction: asc
254
+ ```
255
+
256
+ Example `dashboard_configure_pie_chart_widget` config:
257
+
258
+ ```yaml
259
+ target: chart
260
+ label: Spend share by model
261
+ size: medium
262
+ chart:
263
+ type: pie
264
+ label:
265
+ field: model
266
+ label: Model
267
+ value:
268
+ field: spend
269
+ label: Spend
270
+ format: currency
271
+ query:
272
+ resource: llm_usage
273
+ select:
274
+ - field: model
275
+ - agg: sum
276
+ field: cost
277
+ as: spend
278
+ group_by:
279
+ - model
280
+ ```
281
+
282
+ Example `dashboard_configure_histogram_chart_widget` config:
283
+
284
+ ```yaml
285
+ target: chart
286
+ label: Request size distribution
287
+ size: wide
288
+ chart:
289
+ type: histogram
290
+ x:
291
+ field: total_tokens
292
+ label: Tokens
293
+ y:
294
+ field: requests
295
+ label: Requests
296
+ query:
297
+ resource: llm_usage
298
+ select:
299
+ - field: total_tokens
300
+ - agg: count
301
+ as: requests
302
+ bucket:
303
+ field: total_tokens
304
+ buckets:
305
+ - label: Small
306
+ max: 1000
307
+ - label: Medium
308
+ min: 1000
309
+ max: 10000
310
+ - label: Large
311
+ min: 10000
312
+ ```
313
+
314
+ Example `dashboard_configure_funnel_chart_widget` config:
315
+
316
+ ```yaml
317
+ target: chart
318
+ label: Request funnel
319
+ size: wide
320
+ chart:
321
+ type: funnel
322
+ label:
323
+ field: stage
324
+ label: Stage
325
+ value:
326
+ field: count
327
+ label: Count
328
+ query:
329
+ resource: llm_usage
330
+ select:
331
+ - field: stage
332
+ - agg: count
333
+ as: count
334
+ group_by:
335
+ - stage
336
+ ```
337
+
338
+
45
339
  ## Group creation guard
46
340
 
47
341
  Before creating a group, call dashboard_get_config and check existing groups.
@@ -148,6 +442,7 @@ Use target, not type.
148
442
  For charts, use target: chart and chart.type for the concrete chart kind.
149
443
  Use query, not dataSource.
150
444
  Use resource, not resourceId.
445
+ Never use AdminForth routes such as /resource/llm_usage as resource or target values.
151
446
 
152
447
  ## Query shape rules
153
448
 
@@ -3,6 +3,7 @@ import type { DashboardConfig } from '../custom/model/dashboard.types.js';
3
3
  import type { DashboardRecord } from '../services/dashboardConfigService.js';
4
4
  type DashboardEndpointsContext = {
5
5
  getDashboardRecord: (slug: string) => Promise<DashboardRecord | null>;
6
+ getAllDashboardRecords: () => Promise<DashboardRecord[]>;
6
7
  parseStoredDashboardConfig: (config: unknown) => DashboardConfig;
7
8
  };
8
9
  export declare function registerDashboardEndpoints(server: IHttpServer, ctx: DashboardEndpointsContext): void;
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { DashboardApiResponseSchema, SlugRequestSchema, } from '../schema/api.js';
10
+ import { DashboardApiResponseSchema, GetSlugsResponseSchema, SlugRequestSchema, } from '../schema/api.js';
11
11
  export function registerDashboardEndpoints(server, ctx) {
12
12
  server.endpoint({
13
13
  method: 'POST',
@@ -30,4 +30,18 @@ export function registerDashboardEndpoints(server, ctx) {
30
30
  };
31
31
  }),
32
32
  });
33
+ server.endpoint({
34
+ method: 'GET',
35
+ path: '/dashboard/get-slugs',
36
+ description: 'Returns a list of all dashboard slugs and labels for listing purposes.',
37
+ request_schema: undefined,
38
+ response_schema: GetSlugsResponseSchema,
39
+ handler: () => __awaiter(this, void 0, void 0, function* () {
40
+ const dashboards = yield ctx.getAllDashboardRecords();
41
+ return dashboards.map((dashboard) => ({
42
+ slug: dashboard.slug,
43
+ label: dashboard.label,
44
+ }));
45
+ }),
46
+ });
33
47
  }
@@ -6829,6 +6829,10 @@ export declare const DashboardWidgetDataResponseZodSchema: z.ZodUnion<readonly [
6829
6829
  export declare const SlugRequestZodSchema: z.ZodObject<{
6830
6830
  slug: z.ZodString;
6831
6831
  }, z.core.$strict>;
6832
+ export declare const GetSlugsResponseZodSchema: z.ZodArray<z.ZodObject<{
6833
+ slug: z.ZodString;
6834
+ label: z.ZodString;
6835
+ }, z.core.$strip>>;
6832
6836
  export declare const GroupIdRequestZodSchema: z.ZodObject<{
6833
6837
  slug: z.ZodString;
6834
6838
  groupId: z.ZodString;
@@ -13563,6 +13567,10 @@ export declare const DashboardWidgetDataResponseSchema: z.core.ZodStandardJSONSc
13563
13567
  export declare const SlugRequestSchema: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
13564
13568
  slug: z.ZodString;
13565
13569
  }, z.core.$strict>>;
13570
+ export declare const GetSlugsResponseSchema: z.core.ZodStandardJSONSchemaPayload<z.ZodArray<z.ZodObject<{
13571
+ slug: z.ZodString;
13572
+ label: z.ZodString;
13573
+ }, z.core.$strip>>>;
13566
13574
  export declare const GroupIdRequestSchema: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
13567
13575
  slug: z.ZodString;
13568
13576
  groupId: z.ZodString;
@@ -38,6 +38,10 @@ export const DashboardWidgetDataResponseZodSchema = z.union([
38
38
  export const SlugRequestZodSchema = z.object({
39
39
  slug: z.string(),
40
40
  }).strict();
41
+ export const GetSlugsResponseZodSchema = z.array(z.object({
42
+ slug: z.string(),
43
+ label: z.string(),
44
+ }));
41
45
  export const GroupIdRequestZodSchema = z.object({
42
46
  slug: z.string(),
43
47
  groupId: z.string(),
@@ -168,6 +172,7 @@ export const DashboardMutationResponseZodSchema = z.object({
168
172
  export const DashboardApiResponseSchema = toJSONSchema(z.unknown(), { target: 'draft-07' });
169
173
  export const DashboardWidgetDataResponseSchema = toJSONSchema(DashboardWidgetDataResponseZodSchema, { target: 'draft-07' });
170
174
  export const SlugRequestSchema = toJSONSchema(SlugRequestZodSchema, { target: 'draft-07' });
175
+ export const GetSlugsResponseSchema = toJSONSchema(GetSlugsResponseZodSchema, { target: 'draft-07' });
171
176
  export const GroupIdRequestSchema = toJSONSchema(GroupIdRequestZodSchema, { target: 'draft-07' });
172
177
  export const MoveGroupRequestSchema = toJSONSchema(MoveGroupRequestZodSchema, { target: 'draft-07' });
173
178
  export const SetGroupConfigRequestSchema = toJSONSchema(SetGroupConfigRequestZodSchema, { target: 'draft-07' });
@@ -17,10 +17,12 @@ export type PersistedDashboardResponse = {
17
17
  };
18
18
  type DashboardConfigMutator = (config: DashboardConfig, dashboard: DashboardRecord) => DashboardConfig | null | Promise<DashboardConfig | null>;
19
19
  export declare function getDashboardRecord(adminforth: IAdminForth, dashboardConfigsResourceId: string, slug: string): Promise<DashboardRecord | null>;
20
+ export declare function getAllDashboardRecords(adminforth: IAdminForth, dashboardConfigsResourceId: string): Promise<DashboardRecord[]>;
20
21
  export declare function persistDashboardConfig(adminforth: IAdminForth, dashboardConfigsResourceId: string, dashboard: DashboardRecord, config: DashboardConfig): Promise<PersistedDashboardResponse>;
21
22
  export declare function updateDashboardConfig(adminforth: IAdminForth, dashboardConfigsResourceId: string, slug: string, mutateConfig: DashboardConfigMutator): Promise<PersistedDashboardResponse | null>;
22
23
  export type DashboardConfigService = {
23
24
  getDashboardRecord: (slug: string) => Promise<DashboardRecord | null>;
25
+ getAllDashboardRecords: () => Promise<DashboardRecord[]>;
24
26
  parseStoredDashboardConfig: typeof parseStoredDashboardConfig;
25
27
  persistDashboardConfig: (dashboard: DashboardRecord, config: DashboardConfig) => Promise<PersistedDashboardResponse>;
26
28
  updateDashboardConfig: (slug: string, mutateConfig: DashboardConfigMutator) => Promise<PersistedDashboardResponse | null>;
@@ -57,6 +57,11 @@ export function getDashboardRecord(adminforth, dashboardConfigsResourceId, slug)
57
57
  return dashboard || null;
58
58
  });
59
59
  }
60
+ export function getAllDashboardRecords(adminforth, dashboardConfigsResourceId) {
61
+ return __awaiter(this, void 0, void 0, function* () {
62
+ return yield adminforth.resource(dashboardConfigsResourceId).list([]);
63
+ });
64
+ }
60
65
  export function persistDashboardConfig(adminforth, dashboardConfigsResourceId, dashboard, config) {
61
66
  return __awaiter(this, void 0, void 0, function* () {
62
67
  const normalizedConfig = normalizeDashboardOrder(config);
@@ -103,6 +108,7 @@ export function updateDashboardConfig(adminforth, dashboardConfigsResourceId, sl
103
108
  export function createDashboardConfigService(adminforth, dashboardConfigsResourceId) {
104
109
  return {
105
110
  getDashboardRecord: (slug) => getDashboardRecord(adminforth, dashboardConfigsResourceId, slug),
111
+ getAllDashboardRecords: () => getAllDashboardRecords(adminforth, dashboardConfigsResourceId),
106
112
  parseStoredDashboardConfig,
107
113
  persistDashboardConfig: (dashboard, config) => persistDashboardConfig(adminforth, dashboardConfigsResourceId, dashboard, config),
108
114
  updateDashboardConfig: (slug, mutateConfig) => updateDashboardConfig(adminforth, dashboardConfigsResourceId, slug, mutateConfig),
@@ -2,12 +2,14 @@ import type { IHttpServer } from 'adminforth';
2
2
  import type { DashboardConfig } from '../custom/model/dashboard.types.js';
3
3
  import {
4
4
  DashboardApiResponseSchema,
5
+ GetSlugsResponseSchema,
5
6
  SlugRequestSchema,
6
7
  } from '../schema/api.js';
7
8
  import type { DashboardRecord } from '../services/dashboardConfigService.js';
8
9
 
9
10
  type DashboardEndpointsContext = {
10
11
  getDashboardRecord: (slug: string) => Promise<DashboardRecord | null>;
12
+ getAllDashboardRecords: () => Promise<DashboardRecord[]>;
11
13
  parseStoredDashboardConfig: (config: unknown) => DashboardConfig;
12
14
  };
13
15
 
@@ -38,4 +40,19 @@ export function registerDashboardEndpoints(
38
40
  };
39
41
  },
40
42
  });
43
+
44
+ server.endpoint({
45
+ method: 'GET',
46
+ path: '/dashboard/get-slugs',
47
+ description: 'Returns a list of all dashboard slugs and labels for listing purposes.',
48
+ request_schema: undefined,
49
+ response_schema: GetSlugsResponseSchema,
50
+ handler: async () => {
51
+ const dashboards = await ctx.getAllDashboardRecords();
52
+ return dashboards.map((dashboard) => ({
53
+ slug: dashboard.slug,
54
+ label: dashboard.label,
55
+ }));
56
+ },
57
+ });
41
58
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/dashboard",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
package/schema/api.ts CHANGED
@@ -60,6 +60,11 @@ export const SlugRequestZodSchema = z.object({
60
60
  slug: z.string(),
61
61
  }).strict()
62
62
 
63
+ export const GetSlugsResponseZodSchema = z.array(z.object({
64
+ slug: z.string(),
65
+ label: z.string(),
66
+ }))
67
+
63
68
  export const GroupIdRequestZodSchema = z.object({
64
69
  slug: z.string(),
65
70
  groupId: z.string(),
@@ -213,6 +218,7 @@ export const DashboardMutationResponseZodSchema = z.object({
213
218
  export const DashboardApiResponseSchema = toJSONSchema(z.unknown(), { target: 'draft-07' })
214
219
  export const DashboardWidgetDataResponseSchema = toJSONSchema(DashboardWidgetDataResponseZodSchema, { target: 'draft-07' })
215
220
  export const SlugRequestSchema = toJSONSchema(SlugRequestZodSchema, { target: 'draft-07' })
221
+ export const GetSlugsResponseSchema = toJSONSchema(GetSlugsResponseZodSchema, { target: 'draft-07' })
216
222
  export const GroupIdRequestSchema = toJSONSchema(GroupIdRequestZodSchema, { target: 'draft-07' })
217
223
  export const MoveGroupRequestSchema = toJSONSchema(MoveGroupRequestZodSchema, { target: 'draft-07' })
218
224
  export const SetGroupConfigRequestSchema = toJSONSchema(SetGroupConfigRequestZodSchema, { target: 'draft-07' })
@@ -96,6 +96,13 @@ export async function getDashboardRecord(
96
96
  return dashboard || null;
97
97
  }
98
98
 
99
+ export async function getAllDashboardRecords(
100
+ adminforth: IAdminForth,
101
+ dashboardConfigsResourceId: string,
102
+ ): Promise<DashboardRecord[]> {
103
+ return await adminforth.resource(dashboardConfigsResourceId).list([]);
104
+ }
105
+
99
106
  export async function persistDashboardConfig(
100
107
  adminforth: IAdminForth,
101
108
  dashboardConfigsResourceId: string,
@@ -156,6 +163,7 @@ export async function updateDashboardConfig(
156
163
 
157
164
  export type DashboardConfigService = {
158
165
  getDashboardRecord: (slug: string) => Promise<DashboardRecord | null>;
166
+ getAllDashboardRecords: () => Promise<DashboardRecord[]>;
159
167
  parseStoredDashboardConfig: typeof parseStoredDashboardConfig;
160
168
  persistDashboardConfig: (
161
169
  dashboard: DashboardRecord,
@@ -173,6 +181,7 @@ export function createDashboardConfigService(
173
181
  ): DashboardConfigService {
174
182
  return {
175
183
  getDashboardRecord: (slug) => getDashboardRecord(adminforth, dashboardConfigsResourceId, slug),
184
+ getAllDashboardRecords: () => getAllDashboardRecords(adminforth, dashboardConfigsResourceId),
176
185
  parseStoredDashboardConfig,
177
186
  persistDashboardConfig: (dashboard, config) => persistDashboardConfig(
178
187
  adminforth,