@adminforth/dashboard 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/custom/api/dashboardApi.ts +137 -1
  2. package/custom/model/dashboard.types.ts +32 -22
  3. package/custom/package.json +1 -0
  4. package/custom/pnpm-lock.yaml +31 -0
  5. package/custom/runtime/DashboardRuntime.vue +9 -15
  6. package/custom/runtime/YamlConfigEditor.vue +109 -0
  7. package/custom/skills/adminforth-dashboard/SKILL.md +66 -10
  8. package/custom/widgets/KpiCardWidget.vue +172 -9
  9. package/custom/widgets/chart/ChartWidget.vue +5 -5
  10. package/custom/widgets/registry.ts +4 -4
  11. package/dist/custom/api/dashboardApi.d.ts +46 -1
  12. package/dist/custom/api/dashboardApi.js +90 -0
  13. package/dist/custom/api/dashboardApi.ts +137 -1
  14. package/dist/custom/model/dashboard.types.d.ts +30 -14
  15. package/dist/custom/model/dashboard.types.js +2 -2
  16. package/dist/custom/model/dashboard.types.ts +32 -22
  17. package/dist/custom/package.json +1 -0
  18. package/dist/custom/pnpm-lock.yaml +31 -0
  19. package/dist/custom/queries/useDashboardConfig.d.ts +106 -104
  20. package/dist/custom/queries/useWidgetData.d.ts +106 -104
  21. package/dist/custom/runtime/DashboardRuntime.vue +9 -15
  22. package/dist/custom/runtime/YamlConfigEditor.vue +109 -0
  23. package/dist/custom/skills/adminforth-dashboard/SKILL.md +66 -10
  24. package/dist/custom/widgets/KpiCardWidget.vue +172 -9
  25. package/dist/custom/widgets/chart/ChartWidget.vue +5 -5
  26. package/dist/custom/widgets/registry.js +4 -4
  27. package/dist/custom/widgets/registry.ts +4 -4
  28. package/dist/endpoint/widgets.js +99 -14
  29. package/dist/schema/api.d.ts +11426 -1634
  30. package/dist/schema/api.js +118 -21
  31. package/dist/schema/widget.d.ts +425 -1980
  32. package/dist/schema/widget.js +13 -374
  33. package/dist/schema/widgets/charts.d.ts +1689 -0
  34. package/dist/schema/widgets/charts.js +92 -0
  35. package/dist/schema/widgets/common.d.ts +275 -0
  36. package/dist/schema/widgets/common.js +171 -0
  37. package/dist/schema/widgets/gauge-card.d.ts +172 -0
  38. package/dist/schema/widgets/gauge-card.js +28 -0
  39. package/dist/schema/widgets/kpi-card.d.ts +212 -0
  40. package/dist/schema/widgets/kpi-card.js +43 -0
  41. package/dist/schema/widgets/pivot-table.d.ts +196 -0
  42. package/dist/schema/widgets/pivot-table.js +17 -0
  43. package/dist/schema/widgets/table.d.ts +130 -0
  44. package/dist/schema/widgets/table.js +12 -0
  45. package/dist/services/widgetDataService.js +96 -2
  46. package/endpoint/widgets.ts +173 -26
  47. package/package.json +1 -1
  48. package/schema/api.ts +148 -22
  49. package/schema/widget.ts +43 -425
  50. package/schema/widgets/charts.ts +113 -0
  51. package/schema/widgets/common.ts +194 -0
  52. package/schema/widgets/gauge-card.ts +34 -0
  53. package/schema/widgets/kpi-card.ts +49 -0
  54. package/schema/widgets/pivot-table.ts +24 -0
  55. package/schema/widgets/table.ts +18 -0
  56. package/services/widgetDataService.ts +129 -3
  57. package/shims-vue.d.ts +11 -0
  58. package/tsconfig.json +3 -1
@@ -0,0 +1,130 @@
1
+ import { z } from 'zod';
2
+ export declare const TableViewConfigSchema: z.ZodObject<{
3
+ columns: z.ZodOptional<z.ZodArray<z.ZodObject<{
4
+ field: z.ZodString;
5
+ label: z.ZodOptional<z.ZodString>;
6
+ format: z.ZodOptional<z.ZodEnum<{
7
+ number: "number";
8
+ integer: "integer";
9
+ compact_number: "compact_number";
10
+ currency: "currency";
11
+ percent: "percent";
12
+ percent_delta: "percent_delta";
13
+ number_delta: "number_delta";
14
+ currency_delta: "currency_delta";
15
+ }>>;
16
+ }, z.core.$strict>>>;
17
+ pagination: z.ZodOptional<z.ZodBoolean>;
18
+ page_size: z.ZodOptional<z.ZodNumber>;
19
+ }, z.core.$strict>;
20
+ export declare const TableWidgetConfigSchema: z.ZodObject<{
21
+ id: z.ZodString;
22
+ group_id: z.ZodString;
23
+ order: z.ZodNumber;
24
+ label: z.ZodOptional<z.ZodString>;
25
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
26
+ size: z.ZodOptional<z.ZodEnum<{
27
+ small: "small";
28
+ medium: "medium";
29
+ large: "large";
30
+ wide: "wide";
31
+ full: "full";
32
+ }>>;
33
+ width: z.ZodOptional<z.ZodNumber>;
34
+ height: z.ZodOptional<z.ZodNumber>;
35
+ min_width: z.ZodOptional<z.ZodNumber>;
36
+ max_width: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
37
+ target: z.ZodLiteral<"table">;
38
+ table: z.ZodOptional<z.ZodObject<{
39
+ columns: z.ZodOptional<z.ZodArray<z.ZodObject<{
40
+ field: z.ZodString;
41
+ label: z.ZodOptional<z.ZodString>;
42
+ format: z.ZodOptional<z.ZodEnum<{
43
+ number: "number";
44
+ integer: "integer";
45
+ compact_number: "compact_number";
46
+ currency: "currency";
47
+ percent: "percent";
48
+ percent_delta: "percent_delta";
49
+ number_delta: "number_delta";
50
+ currency_delta: "currency_delta";
51
+ }>>;
52
+ }, z.core.$strict>>>;
53
+ pagination: z.ZodOptional<z.ZodBoolean>;
54
+ page_size: z.ZodOptional<z.ZodNumber>;
55
+ }, z.core.$strict>>;
56
+ query: z.ZodObject<{
57
+ resource: z.ZodString;
58
+ select: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
59
+ field: z.ZodString;
60
+ as: z.ZodOptional<z.ZodString>;
61
+ grain: z.ZodOptional<z.ZodEnum<{
62
+ day: "day";
63
+ week: "week";
64
+ month: "month";
65
+ year: "year";
66
+ }>>;
67
+ }, z.core.$strict>, z.ZodObject<{
68
+ agg: z.ZodEnum<{
69
+ sum: "sum";
70
+ count: "count";
71
+ count_distinct: "count_distinct";
72
+ avg: "avg";
73
+ min: "min";
74
+ max: "max";
75
+ median: "median";
76
+ }>;
77
+ field: z.ZodOptional<z.ZodString>;
78
+ as: z.ZodString;
79
+ filters: z.ZodOptional<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
80
+ }, z.core.$strict>, z.ZodObject<{
81
+ calc: z.ZodString;
82
+ as: z.ZodString;
83
+ }, z.core.$strict>]>>>;
84
+ sparkline: z.ZodOptional<z.ZodObject<{
85
+ field: z.ZodString;
86
+ grain: z.ZodEnum<{
87
+ day: "day";
88
+ week: "week";
89
+ month: "month";
90
+ year: "year";
91
+ }>;
92
+ as: z.ZodString;
93
+ fill_missing: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
94
+ }, z.core.$strict>>;
95
+ filters: z.ZodOptional<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
96
+ group_by: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
97
+ field: z.ZodString;
98
+ as: z.ZodOptional<z.ZodString>;
99
+ grain: z.ZodOptional<z.ZodEnum<{
100
+ day: "day";
101
+ week: "week";
102
+ month: "month";
103
+ year: "year";
104
+ }>>;
105
+ timezone: z.ZodOptional<z.ZodString>;
106
+ }, z.core.$strict>]>>>;
107
+ order_by: z.ZodOptional<z.ZodArray<z.ZodObject<{
108
+ field: z.ZodString;
109
+ direction: z.ZodOptional<z.ZodEnum<{
110
+ asc: "asc";
111
+ desc: "desc";
112
+ }>>;
113
+ }, z.core.$strict>>>;
114
+ limit: z.ZodOptional<z.ZodNumber>;
115
+ offset: z.ZodOptional<z.ZodNumber>;
116
+ bucket: z.ZodOptional<z.ZodObject<{
117
+ field: z.ZodString;
118
+ buckets: z.ZodArray<z.ZodObject<{
119
+ label: z.ZodString;
120
+ min: z.ZodOptional<z.ZodNumber>;
121
+ max: z.ZodOptional<z.ZodNumber>;
122
+ }, z.core.$strict>>;
123
+ }, z.core.$strict>>;
124
+ calcs: z.ZodOptional<z.ZodArray<z.ZodObject<{
125
+ calc: z.ZodString;
126
+ as: z.ZodString;
127
+ }, z.core.$strict>>>;
128
+ formatting: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
129
+ }, z.core.$strict>;
130
+ }, z.core.$strict>;
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+ import { ChartFieldRefSchema, QueryConfigSchema, WidgetBaseSchema, } from './common.js';
3
+ export const TableViewConfigSchema = z.object({
4
+ columns: z.array(ChartFieldRefSchema).optional(),
5
+ pagination: z.boolean().optional(),
6
+ page_size: z.number().int().positive().optional(),
7
+ }).strict();
8
+ export const TableWidgetConfigSchema = WidgetBaseSchema.extend({
9
+ target: z.literal('table'),
10
+ table: TableViewConfigSchema.optional(),
11
+ query: QueryConfigSchema,
12
+ });
@@ -11,7 +11,8 @@ import { Filters, Sorts } from 'adminforth';
11
11
  const CALC_IDENTIFIER_RE = /\b[a-zA-Z_][a-zA-Z0-9_]*\b/g;
12
12
  const LOOKUP_CALL_RE = /lookup\(\s*(\$variables(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)\s*,\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)/g;
13
13
  const VARIABLE_PATH_PREFIX_RE = /^\$variables\.?/;
14
- const SAFE_CALC_EXPRESSION_RE = /^[\d+\-*/().\s]+$/;
14
+ const SAFE_CALC_EXPRESSION_RE = /^[\d+\-*/().\s?:<>=!]+$/;
15
+ const RELATIVE_DURATION_RE = /^(\d+)(h|d|w|mo|y)$/;
15
16
  const FILTER_OPERATORS = {
16
17
  eq: Filters.EQ,
17
18
  neq: Filters.NEQ,
@@ -78,6 +79,10 @@ function getFunnelWidgetData(adminforth, query, variables) {
78
79
  function getQueryWidgetData(adminforth, query, variables) {
79
80
  return __awaiter(this, void 0, void 0, function* () {
80
81
  var _a, _b, _c;
82
+ const metricSelect = getSingleAggregateMetricSelect(query);
83
+ if (metricSelect) {
84
+ return getMetricWidgetData(adminforth, query, metricSelect);
85
+ }
81
86
  const selectedRows = isAggregateQuery(query)
82
87
  ? yield buildAggregateQueryRows(adminforth, query, variables)
83
88
  : buildPlainQueryRows(yield getResourceRows(adminforth, query.resource, query.filters, getBackendSort(query.order_by)), query, variables);
@@ -97,6 +102,43 @@ function getQueryWidgetData(adminforth, query, variables) {
97
102
  };
98
103
  });
99
104
  }
105
+ function getMetricWidgetData(adminforth, query, metric) {
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ var _a;
108
+ const [currentValues = {}] = yield getAggregateRows(adminforth, query.resource, query.filters, [metric], []);
109
+ const values = {
110
+ [metric.as]: (_a = currentValues[metric.as]) !== null && _a !== void 0 ? _a : 0,
111
+ };
112
+ const rows = query.sparkline
113
+ ? yield getMetricSparklineRows(adminforth, query, metric, getAdminForthFilters(query.filters))
114
+ : [values];
115
+ const columns = Array.from(new Set([
116
+ metric.as,
117
+ ...(query.sparkline ? [query.sparkline.as] : []),
118
+ ]));
119
+ return {
120
+ kind: 'aggregate',
121
+ columns,
122
+ rows,
123
+ values,
124
+ };
125
+ });
126
+ }
127
+ function getMetricSparklineRows(adminforth, query, metric, filters) {
128
+ return __awaiter(this, void 0, void 0, function* () {
129
+ const sparkline = query.sparkline;
130
+ const groupBy = [{
131
+ field: sparkline.field,
132
+ as: sparkline.as,
133
+ grain: sparkline.grain,
134
+ }];
135
+ const rows = yield getAggregateRows(adminforth, query.resource, filters, [metric], groupBy);
136
+ return rows.map((row) => {
137
+ var _a;
138
+ return (Object.assign(Object.assign({}, (_a = query.sparkline) === null || _a === void 0 ? void 0 : _a.fill_missing), row));
139
+ });
140
+ });
141
+ }
100
142
  function getResourceRows(adminforth, resourceId, filters, sort) {
101
143
  return __awaiter(this, void 0, void 0, function* () {
102
144
  return adminforth.resource(resourceId).list(getAdminForthFilters(filters), undefined, 0, sort);
@@ -238,6 +280,18 @@ function isAggregateQuery(query) {
238
280
  return Boolean(((_a = query.group_by) === null || _a === void 0 ? void 0 : _a.length)
239
281
  || ((_b = query.select) === null || _b === void 0 ? void 0 : _b.some((item) => isAggregateSelectItem(item))));
240
282
  }
283
+ function getSingleAggregateMetricSelect(query) {
284
+ var _a, _b;
285
+ if ((_a = query.group_by) === null || _a === void 0 ? void 0 : _a.length) {
286
+ return undefined;
287
+ }
288
+ const select = (_b = query.select) !== null && _b !== void 0 ? _b : [];
289
+ const aggregateItems = select.filter(isAggregateSelectItem);
290
+ if (aggregateItems.length !== 1 || aggregateItems.length !== select.length) {
291
+ return undefined;
292
+ }
293
+ return aggregateItems[0];
294
+ }
241
295
  function isFieldSelectItem(item) {
242
296
  return 'field' in item && !('agg' in item);
243
297
  }
@@ -454,11 +508,51 @@ function toAdminForthFilter(filter) {
454
508
  }
455
509
  for (const [operator, createFilter] of Object.entries(FILTER_OPERATORS)) {
456
510
  if (Object.prototype.hasOwnProperty.call(filter, operator)) {
457
- return createFilter(filter.field, filter[operator]);
511
+ return createFilter(filter.field, resolveFilterValue(filter[operator]));
458
512
  }
459
513
  }
460
514
  return Filters.AND([]);
461
515
  }
516
+ function resolveFilterValue(value) {
517
+ if (Array.isArray(value)) {
518
+ return value.map((item) => resolveFilterValue(item));
519
+ }
520
+ if (!isRecord(value)) {
521
+ return value;
522
+ }
523
+ if (value.now === true) {
524
+ return new Date().toISOString();
525
+ }
526
+ if (typeof value.now_minus === 'string') {
527
+ return subtractDuration(new Date(), value.now_minus).toISOString();
528
+ }
529
+ return value;
530
+ }
531
+ function subtractDuration(now, duration) {
532
+ const match = duration.match(RELATIVE_DURATION_RE);
533
+ if (!match) {
534
+ throw new Error(`Unsupported relative date duration: ${duration}`);
535
+ }
536
+ const amount = Number(match[1]);
537
+ const unit = match[2];
538
+ const date = new Date(now);
539
+ if (unit === 'h') {
540
+ date.setUTCHours(date.getUTCHours() - amount);
541
+ }
542
+ else if (unit === 'd') {
543
+ date.setUTCDate(date.getUTCDate() - amount);
544
+ }
545
+ else if (unit === 'w') {
546
+ date.setUTCDate(date.getUTCDate() - amount * 7);
547
+ }
548
+ else if (unit === 'mo') {
549
+ date.setUTCMonth(date.getUTCMonth() - amount);
550
+ }
551
+ else if (unit === 'y') {
552
+ date.setUTCFullYear(date.getUTCFullYear() - amount);
553
+ }
554
+ return date;
555
+ }
462
556
  function toFiniteNumber(value) {
463
557
  const numberValue = typeof value === 'number' ? value : Number(value);
464
558
  return Number.isFinite(numberValue) ? numberValue : 0;
@@ -1,12 +1,26 @@
1
1
  import type { AdminUser, IHttpServer } from 'adminforth';
2
2
  import { randomUUID } from 'crypto';
3
3
  import type {
4
+ ChartDashboardWidgetConfig,
4
5
  DashboardConfig,
5
6
  DashboardVariables,
6
7
  DashboardWidgetConfig,
7
- EditableDashboardWidgetConfig,
8
+ GaugeCardWidgetConfig,
9
+ KpiCardWidgetConfig,
10
+ PivotTableWidgetConfig,
11
+ TableWidgetConfig,
8
12
  } from '../custom/model/dashboard.types.js';
9
13
  import {
14
+ ConfigureBarChartWidgetRequestSchema,
15
+ ConfigureFunnelChartWidgetRequestSchema,
16
+ ConfigureGaugeCardWidgetRequestSchema,
17
+ ConfigureHistogramChartWidgetRequestSchema,
18
+ ConfigureKpiCardWidgetRequestSchema,
19
+ ConfigureLineChartWidgetRequestSchema,
20
+ ConfigurePieChartWidgetRequestSchema,
21
+ ConfigurePivotTableWidgetRequestSchema,
22
+ ConfigureStackedBarChartWidgetRequestSchema,
23
+ ConfigureTableWidgetRequestSchema,
10
24
  DashboardApiResponseSchema,
11
25
  DashboardWidgetDataResponseSchema,
12
26
  GroupIdRequestSchema,
@@ -17,6 +31,21 @@ import {
17
31
  } from '../schema/api.js';
18
32
  import type { DashboardRecord, PersistedDashboardResponse } from '../services/dashboardConfigService.js';
19
33
 
34
+ type ConfigurableWidgetConfig =
35
+ | Omit<TableWidgetConfig, 'id' | 'group_id' | 'order'>
36
+ | Omit<KpiCardWidgetConfig, 'id' | 'group_id' | 'order'>
37
+ | Omit<GaugeCardWidgetConfig, 'id' | 'group_id' | 'order'>
38
+ | Omit<ChartDashboardWidgetConfig, 'id' | 'group_id' | 'order'>
39
+ | Omit<PivotTableWidgetConfig, 'id' | 'group_id' | 'order'>;
40
+
41
+ type ConfigureWidgetRequest = {
42
+ slug: string;
43
+ widgetId: string;
44
+ config: ConfigurableWidgetConfig;
45
+ };
46
+
47
+ type EndpointRequestSchema = Parameters<IHttpServer['endpoint']>[0]['request_schema'];
48
+
20
49
  type WidgetEndpointsContext = {
21
50
  canEditDashboard: (adminUser: AdminUser) => boolean;
22
51
  getDashboardRecord: (slug: string) => Promise<DashboardRecord | null>;
@@ -38,6 +67,86 @@ type WidgetEndpointsContext = {
38
67
  ) => Promise<unknown>;
39
68
  };
40
69
 
70
+ async function replaceWidgetConfig(
71
+ ctx: WidgetEndpointsContext,
72
+ slug: string,
73
+ widgetId: string,
74
+ widgetConfig: ConfigurableWidgetConfig,
75
+ ) {
76
+ let mutationError: string | null = null;
77
+ const updatedDashboard = await ctx.updateDashboardConfig(slug, (config) => {
78
+ const widget = config.widgets.find((item) => item.id === widgetId);
79
+
80
+ if (!widget) {
81
+ mutationError = 'Dashboard widget not found';
82
+ return null;
83
+ }
84
+
85
+ const nextWidget: DashboardWidgetConfig = {
86
+ ...widgetConfig,
87
+ id: widget.id,
88
+ group_id: widget.group_id,
89
+ order: widget.order,
90
+ } as DashboardWidgetConfig;
91
+
92
+ return {
93
+ ...config,
94
+ widgets: config.widgets.map((item) => item.id === widgetId
95
+ ? nextWidget
96
+ : item),
97
+ };
98
+ });
99
+
100
+ return {
101
+ updatedDashboard,
102
+ mutationError,
103
+ };
104
+ }
105
+
106
+ function registerConfigureWidgetEndpoint(
107
+ server: IHttpServer,
108
+ ctx: WidgetEndpointsContext,
109
+ options: {
110
+ path: string;
111
+ description: string;
112
+ requestSchema: EndpointRequestSchema;
113
+ },
114
+ ) {
115
+ server.endpoint({
116
+ method: 'POST',
117
+ path: options.path,
118
+ description: options.description,
119
+ request_schema: options.requestSchema,
120
+ response_schema: DashboardApiResponseSchema,
121
+ handler: async ({ body, adminUser, response }) => {
122
+ if (!ctx.canEditDashboard(adminUser)) {
123
+ response.setStatus(403);
124
+ return { error: 'Dashboard edit is not allowed' };
125
+ }
126
+
127
+ const request = body as ConfigureWidgetRequest;
128
+ const { updatedDashboard, mutationError } = await replaceWidgetConfig(
129
+ ctx,
130
+ request.slug,
131
+ request.widgetId,
132
+ request.config,
133
+ );
134
+
135
+ if (!updatedDashboard) {
136
+ response.setStatus(404);
137
+ return { error: 'Dashboard not found' };
138
+ }
139
+
140
+ if (mutationError) {
141
+ response.setStatus(404);
142
+ return { error: mutationError };
143
+ }
144
+
145
+ return updatedDashboard;
146
+ },
147
+ });
148
+ }
149
+
41
150
  export function registerWidgetEndpoints(
42
151
  server: IHttpServer,
43
152
  ctx: WidgetEndpointsContext,
@@ -193,6 +302,7 @@ export function registerWidgetEndpoints(
193
302
  },
194
303
  });
195
304
 
305
+
196
306
  server.endpoint({
197
307
  method: 'POST',
198
308
  path: '/dashboard/set_widget_config',
@@ -205,31 +315,8 @@ export function registerWidgetEndpoints(
205
315
  return { error: 'Dashboard edit is not allowed' };
206
316
  }
207
317
 
208
- let mutationError: string | null = null;
209
- const updatedDashboard = await ctx.updateDashboardConfig(body.slug, (config) => {
210
- const widget = config.widgets.find((item) => item.id === body.widgetId);
211
-
212
- if (!widget) {
213
- mutationError = 'Dashboard widget not found';
214
- return null;
215
- }
216
-
217
- const typedWidgetConfig = body.config as EditableDashboardWidgetConfig;
218
-
219
- const nextWidget: DashboardWidgetConfig = {
220
- ...typedWidgetConfig,
221
- id: widget.id,
222
- group_id: widget.group_id,
223
- order: widget.order,
224
- };
225
-
226
- return {
227
- ...config,
228
- widgets: config.widgets.map((item) => item.id === body.widgetId
229
- ? nextWidget
230
- : item),
231
- };
232
- });
318
+ const request = body as ConfigureWidgetRequest;
319
+ const { updatedDashboard, mutationError } = await replaceWidgetConfig(ctx, request.slug, request.widgetId, request.config);
233
320
 
234
321
  if (!updatedDashboard) {
235
322
  response.setStatus(404);
@@ -245,6 +332,66 @@ export function registerWidgetEndpoints(
245
332
  },
246
333
  });
247
334
 
335
+ registerConfigureWidgetEndpoint(server, ctx, {
336
+ path: '/dashboard/configure_table_widget',
337
+ description: 'Configures an existing dashboard widget as a table. Superadmin only.',
338
+ requestSchema: ConfigureTableWidgetRequestSchema,
339
+ });
340
+
341
+ registerConfigureWidgetEndpoint(server, ctx, {
342
+ path: '/dashboard/configure_kpi_card_widget',
343
+ description: 'Configures an existing dashboard widget as a KPI card. Superadmin only.',
344
+ requestSchema: ConfigureKpiCardWidgetRequestSchema,
345
+ });
346
+
347
+ registerConfigureWidgetEndpoint(server, ctx, {
348
+ path: '/dashboard/configure_gauge_card_widget',
349
+ description: 'Configures an existing dashboard widget as a gauge card. Superadmin only.',
350
+ requestSchema: ConfigureGaugeCardWidgetRequestSchema,
351
+ });
352
+
353
+ registerConfigureWidgetEndpoint(server, ctx, {
354
+ path: '/dashboard/configure_pivot_table_widget',
355
+ description: 'Configures an existing dashboard widget as a pivot table. Superadmin only.',
356
+ requestSchema: ConfigurePivotTableWidgetRequestSchema,
357
+ });
358
+
359
+ registerConfigureWidgetEndpoint(server, ctx, {
360
+ path: '/dashboard/configure_line_chart_widget',
361
+ description: 'Configures an existing dashboard widget as a line chart. Superadmin only.',
362
+ requestSchema: ConfigureLineChartWidgetRequestSchema,
363
+ });
364
+
365
+ registerConfigureWidgetEndpoint(server, ctx, {
366
+ path: '/dashboard/configure_bar_chart_widget',
367
+ description: 'Configures an existing dashboard widget as a bar chart. Superadmin only.',
368
+ requestSchema: ConfigureBarChartWidgetRequestSchema,
369
+ });
370
+
371
+ registerConfigureWidgetEndpoint(server, ctx, {
372
+ path: '/dashboard/configure_stacked_bar_chart_widget',
373
+ description: 'Configures an existing dashboard widget as a stacked bar chart. Superadmin only.',
374
+ requestSchema: ConfigureStackedBarChartWidgetRequestSchema,
375
+ });
376
+
377
+ registerConfigureWidgetEndpoint(server, ctx, {
378
+ path: '/dashboard/configure_pie_chart_widget',
379
+ description: 'Configures an existing dashboard widget as a pie chart. Superadmin only.',
380
+ requestSchema: ConfigurePieChartWidgetRequestSchema,
381
+ });
382
+
383
+ registerConfigureWidgetEndpoint(server, ctx, {
384
+ path: '/dashboard/configure_histogram_chart_widget',
385
+ description: 'Configures an existing dashboard widget as a histogram chart. Superadmin only.',
386
+ requestSchema: ConfigureHistogramChartWidgetRequestSchema,
387
+ });
388
+
389
+ registerConfigureWidgetEndpoint(server, ctx, {
390
+ path: '/dashboard/configure_funnel_chart_widget',
391
+ description: 'Configures an existing dashboard widget as a funnel chart. Superadmin only.',
392
+ requestSchema: ConfigureFunnelChartWidgetRequestSchema,
393
+ });
394
+
248
395
  server.endpoint({
249
396
  method: 'POST',
250
397
  path: '/dashboard/get_dashboard_widget_data',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/dashboard",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",