@adminforth/dashboard 1.6.0 → 1.8.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 (36) hide show
  1. package/custom/model/dashboard.types.ts +25 -10
  2. package/custom/package.json +1 -0
  3. package/custom/pnpm-lock.yaml +31 -0
  4. package/custom/runtime/DashboardRuntime.vue +7 -12
  5. package/custom/runtime/YamlConfigEditor.vue +109 -0
  6. package/custom/skills/adminforth-dashboard/SKILL.md +26 -3
  7. package/dist/custom/model/dashboard.types.d.ts +19 -7
  8. package/dist/custom/model/dashboard.types.ts +25 -10
  9. package/dist/custom/package.json +1 -0
  10. package/dist/custom/pnpm-lock.yaml +31 -0
  11. package/dist/custom/queries/useDashboardConfig.d.ts +322 -4
  12. package/dist/custom/queries/useWidgetData.d.ts +322 -4
  13. package/dist/custom/runtime/DashboardRuntime.vue +7 -12
  14. package/dist/custom/runtime/YamlConfigEditor.vue +109 -0
  15. package/dist/custom/skills/adminforth-dashboard/SKILL.md +26 -3
  16. package/dist/schema/api.d.ts +8099 -1620
  17. package/dist/schema/api.js +2 -2
  18. package/dist/schema/widget.d.ts +622 -33
  19. package/dist/schema/widget.js +1 -1
  20. package/dist/schema/widgets/charts.d.ts +785 -39
  21. package/dist/schema/widgets/charts.js +2 -2
  22. package/dist/schema/widgets/common.d.ts +35 -6
  23. package/dist/schema/widgets/common.js +23 -5
  24. package/dist/schema/widgets/gauge-card.d.ts +56 -2
  25. package/dist/schema/widgets/kpi-card.d.ts +56 -2
  26. package/dist/schema/widgets/pivot-table.d.ts +56 -2
  27. package/dist/schema/widgets/table.d.ts +56 -2
  28. package/dist/services/widgetDataService.js +37 -32
  29. package/package.json +1 -1
  30. package/schema/api.ts +1 -2
  31. package/schema/widget.ts +0 -1
  32. package/schema/widgets/charts.ts +1 -2
  33. package/schema/widgets/common.ts +24 -5
  34. package/services/widgetDataService.ts +62 -50
  35. package/shims-vue.d.ts +11 -0
  36. package/tsconfig.json +3 -1
@@ -9,7 +9,6 @@ import type {
9
9
  DashboardWidgetConfig,
10
10
  DashboardWidgetData,
11
11
  DashboardVariables,
12
- FunnelQueryConfig,
13
12
  FilterExpression,
14
13
  QueryAggregateSelectItem,
15
14
  QueryCalcSelectItem,
@@ -17,6 +16,8 @@ import type {
17
16
  QueryFieldSelectItem,
18
17
  QueryGroupByItem,
19
18
  QueryOrderByItem,
19
+ ResourceQueryConfig,
20
+ StepsQueryStepConfig,
20
21
  QuerySelectItem,
21
22
  TimeGrain,
22
23
  } from '../custom/model/dashboard.types.js';
@@ -98,9 +99,7 @@ export async function getWidgetData(
98
99
  return null;
99
100
  }
100
101
 
101
- const data = 'steps' in widget.query
102
- ? await getFunnelWidgetData(adminforth, widget.query, options.variables ?? {})
103
- : await getQueryWidgetData(adminforth, widget.query, options.variables ?? {});
102
+ const data = await getQueryWidgetData(adminforth, widget.query, options.variables ?? {});
104
103
 
105
104
  if (widget.target !== 'table' || !options.pagination) {
106
105
  return data;
@@ -122,50 +121,15 @@ export async function getWidgetData(
122
121
  };
123
122
  }
124
123
 
125
- async function getFunnelWidgetData(
126
- adminforth: IAdminForth,
127
- query: FunnelQueryConfig,
128
- variables: DashboardVariables,
129
- ): Promise<DashboardWidgetData> {
130
- const rows = await Promise.all(query.steps.map(async (step) => {
131
- const valueField = step.metric.as;
132
- const [values = {}] = await getAggregateRows(
133
- adminforth,
134
- step.resource,
135
- step.filters,
136
- [step.metric],
137
- [],
138
- );
139
-
140
- const row: Record<string, unknown> = {
141
- name: step.name,
142
- resource: step.resource,
143
- [valueField]: values[valueField] ?? 0,
144
- };
145
-
146
- for (const calc of query.calcs ?? []) {
147
- row[calc.as] = evaluateCalc(calc.calc, row, variables);
148
- }
149
-
150
- return row;
151
- }));
152
-
153
- return {
154
- kind: 'aggregate',
155
- columns: [
156
- 'name',
157
- ...Array.from(new Set(query.steps.map((step) => step.metric.as))),
158
- ...Array.from(new Set((query.calcs ?? []).map((calc) => calc.as))),
159
- ],
160
- rows,
161
- };
162
- }
163
-
164
124
  async function getQueryWidgetData(
165
125
  adminforth: IAdminForth,
166
126
  query: QueryConfig,
167
127
  variables: DashboardVariables,
168
128
  ): Promise<DashboardWidgetData> {
129
+ if (isStepsQuery(query)) {
130
+ return getStepsQueryData(adminforth, query, variables);
131
+ }
132
+
169
133
  const metricSelect = getSingleAggregateMetricSelect(query);
170
134
 
171
135
  if (metricSelect) {
@@ -203,9 +167,49 @@ async function getQueryWidgetData(
203
167
  };
204
168
  }
205
169
 
170
+ async function getStepsQueryData(
171
+ adminforth: IAdminForth,
172
+ query: Extract<QueryConfig, { source: 'steps' }>,
173
+ variables: DashboardVariables,
174
+ ): Promise<DashboardWidgetData> {
175
+ const rows = await Promise.all(query.steps.map(async (step) => {
176
+ const select = getStepSelect(step);
177
+ const [values = {}] = await getAggregateRows(
178
+ adminforth,
179
+ step.resource,
180
+ step.filters,
181
+ select,
182
+ [],
183
+ );
184
+ const row = buildCalculatedRow({
185
+ name: step.name,
186
+ resource: step.resource,
187
+ ...values,
188
+ }, select, query.calcs, variables);
189
+
190
+ return row;
191
+ }));
192
+ const orderedRows = sortRows(rows, query.order_by);
193
+ const slicedRows = typeof query.limit === 'number'
194
+ ? orderedRows.slice(query.offset ?? 0, (query.offset ?? 0) + query.limit)
195
+ : orderedRows.slice(query.offset ?? 0);
196
+ const columns = Array.from(new Set([
197
+ 'name',
198
+ 'resource',
199
+ ...query.steps.flatMap((step) => getStepSelect(step).map((item) => item.as)),
200
+ ...(query.calcs ?? []).map((item) => item.as),
201
+ ]));
202
+
203
+ return {
204
+ kind: 'aggregate',
205
+ columns,
206
+ rows: slicedRows,
207
+ };
208
+ }
209
+
206
210
  async function getMetricWidgetData(
207
211
  adminforth: IAdminForth,
208
- query: QueryConfig,
212
+ query: ResourceQueryConfig,
209
213
  metric: QueryAggregateSelectItem,
210
214
  ): Promise<DashboardWidgetData> {
211
215
  const [currentValues = {}] = await getAggregateRows(
@@ -237,7 +241,7 @@ async function getMetricWidgetData(
237
241
 
238
242
  async function getMetricSparklineRows(
239
243
  adminforth: IAdminForth,
240
- query: QueryConfig,
244
+ query: ResourceQueryConfig,
241
245
  metric: QueryAggregateSelectItem,
242
246
  filters: DashboardWidgetFilters,
243
247
  ) {
@@ -275,14 +279,14 @@ async function getResourceRows(
275
279
  );
276
280
  }
277
281
 
278
- function buildPlainQueryRows(rows: Record<string, unknown>[], query: QueryConfig, variables: DashboardVariables) {
282
+ function buildPlainQueryRows(rows: Record<string, unknown>[], query: ResourceQueryConfig, variables: DashboardVariables) {
279
283
  const select = query.select ?? getDefaultSelect(rows);
280
284
  return rows.map((row) => buildPlainRow(row, select, query.calcs, variables));
281
285
  }
282
286
 
283
287
  async function buildAggregateQueryRows(
284
288
  adminforth: IAdminForth,
285
- query: QueryConfig,
289
+ query: ResourceQueryConfig,
286
290
  variables: DashboardVariables,
287
291
  ) {
288
292
  const select = query.select ?? [];
@@ -449,7 +453,7 @@ function getBackendSort(orderBy: QueryOrderByItem[] | undefined) {
449
453
  : Sorts.DESC(order.field));
450
454
  }
451
455
 
452
- function getColumns(rows: Record<string, unknown>[], query: QueryConfig) {
456
+ function getColumns(rows: Record<string, unknown>[], query: ResourceQueryConfig) {
453
457
  const selectColumns = [
454
458
  ...(query.group_by ?? []).map(getGroupByAlias),
455
459
  ...(query.select ?? []).map(getSelectAlias),
@@ -463,14 +467,14 @@ function getDefaultSelect(rows: Record<string, unknown>[]): QuerySelectItem[] {
463
467
  return Object.keys(rows[0] ?? {}).map((field) => ({ field }));
464
468
  }
465
469
 
466
- function isAggregateQuery(query: QueryConfig) {
470
+ function isAggregateQuery(query: ResourceQueryConfig) {
467
471
  return Boolean(
468
472
  query.group_by?.length
469
473
  || query.select?.some((item) => isAggregateSelectItem(item)),
470
474
  );
471
475
  }
472
476
 
473
- function getSingleAggregateMetricSelect(query: QueryConfig) {
477
+ function getSingleAggregateMetricSelect(query: ResourceQueryConfig) {
474
478
  if (query.group_by?.length) {
475
479
  return undefined;
476
480
  }
@@ -485,6 +489,14 @@ function getSingleAggregateMetricSelect(query: QueryConfig) {
485
489
  return aggregateItems[0];
486
490
  }
487
491
 
492
+ function isStepsQuery(query: QueryConfig): query is Extract<QueryConfig, { source: 'steps' }> {
493
+ return query.source === 'steps';
494
+ }
495
+
496
+ function getStepSelect(step: StepsQueryStepConfig): QueryAggregateSelectItem[] {
497
+ return 'select' in step ? step.select : [step.metric];
498
+ }
499
+
488
500
  function isFieldSelectItem(item: QuerySelectItem): item is QueryFieldSelectItem {
489
501
  return 'field' in item && !('agg' in item);
490
502
  }
package/shims-vue.d.ts CHANGED
@@ -3,3 +3,14 @@ declare module '*.vue' {
3
3
  const component: DefineComponent<{}, {}, any>;
4
4
  export default component;
5
5
  }
6
+
7
+ declare module '*.css';
8
+
9
+ declare module '*?worker' {
10
+ const WorkerFactory: {
11
+ new (): Worker;
12
+ };
13
+ export default WorkerFactory;
14
+ }
15
+
16
+ declare module 'monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution';
package/tsconfig.json CHANGED
@@ -11,7 +11,9 @@
11
11
  "skipLibCheck": true,
12
12
  "paths": {
13
13
  "@/afcl": ["./node_modules/adminforth/dist/spa/src/afcl/index.ts"],
14
- "@/*": ["./node_modules/adminforth/dist/spa/src/*"]
14
+ "@/*": ["./node_modules/adminforth/dist/spa/src/*"],
15
+ "monaco-editor": ["./custom/node_modules/monaco-editor/esm/vs/editor/editor.api.d.ts"],
16
+ "monaco-editor/*": ["./custom/node_modules/monaco-editor/*"]
15
17
  }
16
18
  },
17
19
  "exclude": ["node_modules", "dist"]