@adminforth/dashboard 1.0.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 (107) hide show
  1. package/.woodpecker/buildRelease.sh +13 -0
  2. package/.woodpecker/buildSlackNotify.sh +46 -0
  3. package/.woodpecker/release.yml +57 -0
  4. package/README.md +59 -0
  5. package/custom/api/dashboardApi.ts +213 -0
  6. package/custom/composables/useElementSize.ts +41 -0
  7. package/custom/model/dashboard.types.ts +73 -0
  8. package/custom/package.json +9 -0
  9. package/custom/pnpm-lock.yaml +24 -0
  10. package/custom/queries/useDashboardConfig.ts +51 -0
  11. package/custom/queries/useWidgetData.ts +51 -0
  12. package/custom/runtime/DashboardGroup.vue +185 -0
  13. package/custom/runtime/DashboardPage.vue +122 -0
  14. package/custom/runtime/DashboardRuntime.vue +435 -0
  15. package/custom/runtime/WidgetRenderer.vue +60 -0
  16. package/custom/runtime/WidgetShell.vue +152 -0
  17. package/custom/skills/adminforth-dashboard/SKILL.md +125 -0
  18. package/custom/widgets/chart/ChartWidget.vue +188 -0
  19. package/custom/widgets/chart/bar/BarChart.vue +167 -0
  20. package/custom/widgets/chart/chart.types.ts +34 -0
  21. package/custom/widgets/chart/chart.utils.ts +54 -0
  22. package/custom/widgets/chart/funnel/FunnelChart.vue +197 -0
  23. package/custom/widgets/chart/histogram/HistogramChart.vue +21 -0
  24. package/custom/widgets/chart/line/LineChart.vue +175 -0
  25. package/custom/widgets/chart/pie/PieChart.vue +161 -0
  26. package/custom/widgets/chart/stacked-bar/StackedBarChart.vue +256 -0
  27. package/custom/widgets/gauge-card/GaugeCardWidget.vue +107 -0
  28. package/custom/widgets/kpi-card/KpiCardWidget.vue +73 -0
  29. package/custom/widgets/pivot-table/PivotTableWidget.vue +122 -0
  30. package/custom/widgets/registry.ts +51 -0
  31. package/custom/widgets/table/TableWidget.vue +110 -0
  32. package/dist/custom/api/dashboardApi.d.ts +32 -0
  33. package/dist/custom/api/dashboardApi.js +179 -0
  34. package/dist/custom/api/dashboardApi.ts +213 -0
  35. package/dist/custom/composables/useElementSize.d.ts +8 -0
  36. package/dist/custom/composables/useElementSize.js +30 -0
  37. package/dist/custom/composables/useElementSize.ts +41 -0
  38. package/dist/custom/model/dashboard.types.d.ts +45 -0
  39. package/dist/custom/model/dashboard.types.js +14 -0
  40. package/dist/custom/model/dashboard.types.ts +73 -0
  41. package/dist/custom/package.json +9 -0
  42. package/dist/custom/pnpm-lock.yaml +24 -0
  43. package/dist/custom/queries/useDashboardConfig.d.ts +112 -0
  44. package/dist/custom/queries/useDashboardConfig.js +57 -0
  45. package/dist/custom/queries/useDashboardConfig.ts +51 -0
  46. package/dist/custom/queries/useWidgetData.d.ts +90 -0
  47. package/dist/custom/queries/useWidgetData.js +57 -0
  48. package/dist/custom/queries/useWidgetData.ts +51 -0
  49. package/dist/custom/runtime/DashboardGroup.vue +185 -0
  50. package/dist/custom/runtime/DashboardPage.vue +122 -0
  51. package/dist/custom/runtime/DashboardRuntime.vue +435 -0
  52. package/dist/custom/runtime/WidgetRenderer.vue +60 -0
  53. package/dist/custom/runtime/WidgetShell.vue +152 -0
  54. package/dist/custom/skills/adminforth-dashboard/SKILL.md +125 -0
  55. package/dist/custom/widgets/chart/ChartWidget.vue +188 -0
  56. package/dist/custom/widgets/chart/bar/BarChart.vue +167 -0
  57. package/dist/custom/widgets/chart/chart.types.d.ts +25 -0
  58. package/dist/custom/widgets/chart/chart.types.js +2 -0
  59. package/dist/custom/widgets/chart/chart.types.ts +34 -0
  60. package/dist/custom/widgets/chart/chart.utils.d.ts +5 -0
  61. package/dist/custom/widgets/chart/chart.utils.js +52 -0
  62. package/dist/custom/widgets/chart/chart.utils.ts +54 -0
  63. package/dist/custom/widgets/chart/funnel/FunnelChart.vue +197 -0
  64. package/dist/custom/widgets/chart/histogram/HistogramChart.vue +21 -0
  65. package/dist/custom/widgets/chart/line/LineChart.vue +175 -0
  66. package/dist/custom/widgets/chart/pie/PieChart.vue +161 -0
  67. package/dist/custom/widgets/chart/stacked-bar/StackedBarChart.vue +256 -0
  68. package/dist/custom/widgets/gauge-card/GaugeCardWidget.vue +107 -0
  69. package/dist/custom/widgets/kpi-card/KpiCardWidget.vue +73 -0
  70. package/dist/custom/widgets/pivot-table/PivotTableWidget.vue +122 -0
  71. package/dist/custom/widgets/registry.d.ts +11 -0
  72. package/dist/custom/widgets/registry.js +47 -0
  73. package/dist/custom/widgets/registry.ts +51 -0
  74. package/dist/custom/widgets/table/TableWidget.vue +110 -0
  75. package/dist/endpoint/dashboard.d.ts +7 -0
  76. package/dist/endpoint/dashboard.js +29 -0
  77. package/dist/endpoint/groups.d.ts +30 -0
  78. package/dist/endpoint/groups.js +131 -0
  79. package/dist/endpoint/widgets.d.ts +15 -0
  80. package/dist/endpoint/widgets.js +182 -0
  81. package/dist/index.d.ts +13 -0
  82. package/dist/index.js +124 -0
  83. package/dist/schema/api.d.ts +1205 -0
  84. package/dist/schema/api.js +84 -0
  85. package/dist/schema/widget.d.ts +514 -0
  86. package/dist/schema/widget.js +133 -0
  87. package/dist/services/dashboardConfigService.d.ts +35 -0
  88. package/dist/services/dashboardConfigService.js +79 -0
  89. package/dist/services/widgetConfigValidator.d.ts +8 -0
  90. package/dist/services/widgetConfigValidator.js +65 -0
  91. package/dist/services/widgetDataService.d.ts +20 -0
  92. package/dist/services/widgetDataService.js +32 -0
  93. package/dist/types.d.ts +8 -0
  94. package/dist/types.js +1 -0
  95. package/endpoint/dashboard.ts +32 -0
  96. package/endpoint/groups.ts +213 -0
  97. package/endpoint/widgets.ts +255 -0
  98. package/index.ts +141 -0
  99. package/package.json +64 -0
  100. package/schema/api.ts +99 -0
  101. package/schema/widget.ts +159 -0
  102. package/services/dashboardConfigService.ts +136 -0
  103. package/services/widgetConfigValidator.ts +93 -0
  104. package/services/widgetDataService.ts +57 -0
  105. package/shims-vue.d.ts +5 -0
  106. package/tsconfig.json +18 -0
  107. package/types.ts +8 -0
@@ -0,0 +1,73 @@
1
+ import type { ChartWidgetConfig } from '../widgets/chart/chart.types.js'
2
+
3
+ export type DashboardConfig = {
4
+ version: number
5
+ groups: DashboardGroupConfig[]
6
+ widgets: DashboardWidgetConfig[]
7
+ }
8
+
9
+ export type DashboardGroupConfig = {
10
+ id: string
11
+ label: string
12
+ order: number
13
+ }
14
+
15
+ export type DashboardGroupMoveDirection = 'up' | 'down'
16
+
17
+ export type DashboardWidgetMoveDirection = 'up' | 'down'
18
+
19
+ export type DashboardWidgetTarget =
20
+ | 'empty'
21
+ | 'table'
22
+ | 'chart'
23
+ | 'kpi_card'
24
+ | 'pivot_table'
25
+ | 'gauge_card'
26
+
27
+ export type DashboardWidgetSize = 'small' | 'medium' | 'large' | 'wide' | 'full'
28
+
29
+ export type WidgetLayout = {
30
+ size?: DashboardWidgetSize
31
+ width?: number
32
+ minWidth?: number
33
+ maxWidth?: number | null
34
+ height?: number
35
+ }
36
+
37
+ export type DashboardWidgetConfig = {
38
+ id: string
39
+ group_id: string
40
+ label?: string
41
+ size?: DashboardWidgetSize
42
+ width?: number
43
+ height?: number
44
+ minWidth?: number
45
+ maxWidth?: number | null
46
+ order: number
47
+ target: DashboardWidgetTarget
48
+ chart?: ChartWidgetConfig
49
+ table?: unknown
50
+ kpi_card?: unknown
51
+ pivot_table?: unknown
52
+ gauge_card?: unknown
53
+ query?: unknown
54
+ }
55
+
56
+ export type DashboardWidgetTableData = {
57
+ columns: string[]
58
+ rows: Record<string, unknown>[]
59
+ }
60
+
61
+ export function normalizeDashboardConfig(config: unknown): DashboardConfig {
62
+ const value = isRecord(config) ? config : {}
63
+
64
+ return {
65
+ version: typeof value.version === 'number' ? value.version : 1,
66
+ groups: Array.isArray(value.groups) ? (value.groups as DashboardGroupConfig[]) : [],
67
+ widgets: Array.isArray(value.widgets) ? (value.widgets as DashboardWidgetConfig[]) : [],
68
+ }
69
+ }
70
+
71
+ function isRecord(value: unknown): value is Record<string, unknown> {
72
+ return typeof value === 'object' && value !== null
73
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "custom",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "license": "MIT",
6
+ "dependencies": {
7
+ "yaml": "^2.9.0"
8
+ }
9
+ }
@@ -0,0 +1,24 @@
1
+ lockfileVersion: '9.0'
2
+
3
+ settings:
4
+ autoInstallPeers: true
5
+ excludeLinksFromLockfile: false
6
+
7
+ importers:
8
+
9
+ .:
10
+ dependencies:
11
+ yaml:
12
+ specifier: ^2.9.0
13
+ version: 2.9.0
14
+
15
+ packages:
16
+
17
+ yaml@2.9.0:
18
+ resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==}
19
+ engines: {node: '>= 14.6'}
20
+ hasBin: true
21
+
22
+ snapshots:
23
+
24
+ yaml@2.9.0: {}
@@ -0,0 +1,112 @@
1
+ import { type Ref } from 'vue';
2
+ export declare function useDashboardConfig(slug: Ref<string>): {
3
+ data: Ref<{
4
+ id: string;
5
+ slug: string;
6
+ label: string;
7
+ revision: number;
8
+ config: {
9
+ version: number;
10
+ groups: {
11
+ id: string;
12
+ label: string;
13
+ order: number;
14
+ }[];
15
+ widgets: {
16
+ id: string;
17
+ group_id: string;
18
+ label?: string | undefined;
19
+ size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
20
+ width?: number | undefined;
21
+ height?: number | undefined;
22
+ minWidth?: number | undefined;
23
+ maxWidth?: number | null | undefined;
24
+ order: number;
25
+ target: import("../model/dashboard.types.js").DashboardWidgetTarget;
26
+ chart?: {
27
+ type: import("../widgets/chart/chart.types.js").ChartWidgetType;
28
+ title?: string | undefined;
29
+ x_field?: string | undefined;
30
+ y_field?: string | undefined;
31
+ label_field?: string | undefined;
32
+ value_field?: string | undefined;
33
+ bucket_field?: string | undefined;
34
+ buckets?: {
35
+ label: string;
36
+ min?: number | undefined;
37
+ max?: number | undefined;
38
+ }[] | undefined;
39
+ series?: {
40
+ name: string;
41
+ field: string;
42
+ color?: string | undefined;
43
+ }[] | undefined;
44
+ series_name?: string | undefined;
45
+ color?: string | undefined;
46
+ colors?: string[] | undefined;
47
+ } | undefined;
48
+ table?: unknown;
49
+ kpi_card?: unknown;
50
+ pivot_table?: unknown;
51
+ gauge_card?: unknown;
52
+ query?: unknown;
53
+ }[];
54
+ };
55
+ } | null, import("../api/dashboardApi.js").DashboardResponse | {
56
+ id: string;
57
+ slug: string;
58
+ label: string;
59
+ revision: number;
60
+ config: {
61
+ version: number;
62
+ groups: {
63
+ id: string;
64
+ label: string;
65
+ order: number;
66
+ }[];
67
+ widgets: {
68
+ id: string;
69
+ group_id: string;
70
+ label?: string | undefined;
71
+ size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
72
+ width?: number | undefined;
73
+ height?: number | undefined;
74
+ minWidth?: number | undefined;
75
+ maxWidth?: number | null | undefined;
76
+ order: number;
77
+ target: import("../model/dashboard.types.js").DashboardWidgetTarget;
78
+ chart?: {
79
+ type: import("../widgets/chart/chart.types.js").ChartWidgetType;
80
+ title?: string | undefined;
81
+ x_field?: string | undefined;
82
+ y_field?: string | undefined;
83
+ label_field?: string | undefined;
84
+ value_field?: string | undefined;
85
+ bucket_field?: string | undefined;
86
+ buckets?: {
87
+ label: string;
88
+ min?: number | undefined;
89
+ max?: number | undefined;
90
+ }[] | undefined;
91
+ series?: {
92
+ name: string;
93
+ field: string;
94
+ color?: string | undefined;
95
+ }[] | undefined;
96
+ series_name?: string | undefined;
97
+ color?: string | undefined;
98
+ colors?: string[] | undefined;
99
+ } | undefined;
100
+ table?: unknown;
101
+ kpi_card?: unknown;
102
+ pivot_table?: unknown;
103
+ gauge_card?: unknown;
104
+ query?: unknown;
105
+ }[];
106
+ };
107
+ } | null>;
108
+ isLoading: Ref<boolean, boolean>;
109
+ isFetching: Ref<boolean, boolean>;
110
+ error: Ref<unknown, unknown>;
111
+ refetch: () => Promise<import("../api/dashboardApi.js").DashboardResponse | null>;
112
+ };
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.useDashboardConfig = useDashboardConfig;
13
+ const vue_1 = require("vue");
14
+ const dashboardApi_js_1 = require("../api/dashboardApi.js");
15
+ function useDashboardConfig(slug) {
16
+ const data = (0, vue_1.ref)(null);
17
+ const isLoading = (0, vue_1.ref)(false);
18
+ const isFetching = (0, vue_1.ref)(false);
19
+ const error = (0, vue_1.ref)(null);
20
+ function refetch() {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ if (!slug.value) {
23
+ data.value = null;
24
+ error.value = null;
25
+ return null;
26
+ }
27
+ isFetching.value = true;
28
+ if (data.value === null) {
29
+ isLoading.value = true;
30
+ }
31
+ try {
32
+ const response = yield dashboardApi_js_1.dashboardApi.getDashboardConfig(slug.value);
33
+ data.value = response;
34
+ error.value = null;
35
+ return response;
36
+ }
37
+ catch (e) {
38
+ error.value = e;
39
+ throw e;
40
+ }
41
+ finally {
42
+ isFetching.value = false;
43
+ isLoading.value = false;
44
+ }
45
+ });
46
+ }
47
+ (0, vue_1.watch)(slug, () => {
48
+ void refetch();
49
+ }, { immediate: true });
50
+ return {
51
+ data,
52
+ isLoading,
53
+ isFetching,
54
+ error,
55
+ refetch,
56
+ };
57
+ }
@@ -0,0 +1,51 @@
1
+ import { ref, watch, type Ref } from 'vue'
2
+ import { dashboardApi } from '../api/dashboardApi.js'
3
+
4
+ export function useDashboardConfig(slug: Ref<string>) {
5
+ const data = ref<Awaited<ReturnType<typeof dashboardApi.getDashboardConfig>> | null>(null)
6
+ const isLoading = ref(false)
7
+ const isFetching = ref(false)
8
+ const error = ref<unknown>(null)
9
+
10
+ async function refetch() {
11
+ if (!slug.value) {
12
+ data.value = null
13
+ error.value = null
14
+ return null
15
+ }
16
+
17
+ isFetching.value = true
18
+ if (data.value === null) {
19
+ isLoading.value = true
20
+ }
21
+
22
+ try {
23
+ const response = await dashboardApi.getDashboardConfig(slug.value)
24
+ data.value = response
25
+ error.value = null
26
+ return response
27
+ } catch (e) {
28
+ error.value = e
29
+ throw e
30
+ } finally {
31
+ isFetching.value = false
32
+ isLoading.value = false
33
+ }
34
+ }
35
+
36
+ watch(
37
+ slug,
38
+ () => {
39
+ void refetch()
40
+ },
41
+ { immediate: true },
42
+ )
43
+
44
+ return {
45
+ data,
46
+ isLoading,
47
+ isFetching,
48
+ error,
49
+ refetch,
50
+ }
51
+ }
@@ -0,0 +1,90 @@
1
+ import { type Ref } from 'vue';
2
+ export declare function useWidgetData(slug: Ref<string>, widgetId: Ref<string>): {
3
+ data: Ref<{
4
+ widget: {
5
+ id: string;
6
+ group_id: string;
7
+ label?: string | undefined;
8
+ size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
9
+ width?: number | undefined;
10
+ height?: number | undefined;
11
+ minWidth?: number | undefined;
12
+ maxWidth?: number | null | undefined;
13
+ order: number;
14
+ target: import("../model/dashboard.types.js").DashboardWidgetTarget;
15
+ chart?: {
16
+ type: import("../widgets/chart/chart.types.js").ChartWidgetType;
17
+ title?: string | undefined;
18
+ x_field?: string | undefined;
19
+ y_field?: string | undefined;
20
+ label_field?: string | undefined;
21
+ value_field?: string | undefined;
22
+ bucket_field?: string | undefined;
23
+ buckets?: {
24
+ label: string;
25
+ min?: number | undefined;
26
+ max?: number | undefined;
27
+ }[] | undefined;
28
+ series?: {
29
+ name: string;
30
+ field: string;
31
+ color?: string | undefined;
32
+ }[] | undefined;
33
+ series_name?: string | undefined;
34
+ color?: string | undefined;
35
+ colors?: string[] | undefined;
36
+ } | undefined;
37
+ table?: unknown;
38
+ kpi_card?: unknown;
39
+ pivot_table?: unknown;
40
+ gauge_card?: unknown;
41
+ query?: unknown;
42
+ };
43
+ data: unknown;
44
+ } | null, import("../api/dashboardApi.js").DashboardWidgetDataResponse | {
45
+ widget: {
46
+ id: string;
47
+ group_id: string;
48
+ label?: string | undefined;
49
+ size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
50
+ width?: number | undefined;
51
+ height?: number | undefined;
52
+ minWidth?: number | undefined;
53
+ maxWidth?: number | null | undefined;
54
+ order: number;
55
+ target: import("../model/dashboard.types.js").DashboardWidgetTarget;
56
+ chart?: {
57
+ type: import("../widgets/chart/chart.types.js").ChartWidgetType;
58
+ title?: string | undefined;
59
+ x_field?: string | undefined;
60
+ y_field?: string | undefined;
61
+ label_field?: string | undefined;
62
+ value_field?: string | undefined;
63
+ bucket_field?: string | undefined;
64
+ buckets?: {
65
+ label: string;
66
+ min?: number | undefined;
67
+ max?: number | undefined;
68
+ }[] | undefined;
69
+ series?: {
70
+ name: string;
71
+ field: string;
72
+ color?: string | undefined;
73
+ }[] | undefined;
74
+ series_name?: string | undefined;
75
+ color?: string | undefined;
76
+ colors?: string[] | undefined;
77
+ } | undefined;
78
+ table?: unknown;
79
+ kpi_card?: unknown;
80
+ pivot_table?: unknown;
81
+ gauge_card?: unknown;
82
+ query?: unknown;
83
+ };
84
+ data: unknown;
85
+ } | null>;
86
+ isLoading: Ref<boolean, boolean>;
87
+ isFetching: Ref<boolean, boolean>;
88
+ error: Ref<unknown, unknown>;
89
+ refetch: () => Promise<import("../api/dashboardApi.js").DashboardWidgetDataResponse | null>;
90
+ };
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.useWidgetData = useWidgetData;
13
+ const vue_1 = require("vue");
14
+ const dashboardApi_js_1 = require("../api/dashboardApi.js");
15
+ function useWidgetData(slug, widgetId) {
16
+ const data = (0, vue_1.ref)(null);
17
+ const isLoading = (0, vue_1.ref)(false);
18
+ const isFetching = (0, vue_1.ref)(false);
19
+ const error = (0, vue_1.ref)(null);
20
+ function refetch() {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ if (!slug.value || !widgetId.value) {
23
+ data.value = null;
24
+ error.value = null;
25
+ return null;
26
+ }
27
+ isFetching.value = true;
28
+ if (data.value === null) {
29
+ isLoading.value = true;
30
+ }
31
+ try {
32
+ const response = yield dashboardApi_js_1.dashboardApi.getDashboardWidgetData(slug.value, widgetId.value);
33
+ data.value = response;
34
+ error.value = null;
35
+ return response;
36
+ }
37
+ catch (e) {
38
+ error.value = e;
39
+ throw e;
40
+ }
41
+ finally {
42
+ isFetching.value = false;
43
+ isLoading.value = false;
44
+ }
45
+ });
46
+ }
47
+ (0, vue_1.watch)([slug, widgetId], () => {
48
+ void refetch();
49
+ }, { immediate: true });
50
+ return {
51
+ data,
52
+ isLoading,
53
+ isFetching,
54
+ error,
55
+ refetch,
56
+ };
57
+ }
@@ -0,0 +1,51 @@
1
+ import { ref, watch, type Ref } from 'vue'
2
+ import { dashboardApi } from '../api/dashboardApi.js'
3
+
4
+ export function useWidgetData(slug: Ref<string>, widgetId: Ref<string>) {
5
+ const data = ref<Awaited<ReturnType<typeof dashboardApi.getDashboardWidgetData>> | null>(null)
6
+ const isLoading = ref(false)
7
+ const isFetching = ref(false)
8
+ const error = ref<unknown>(null)
9
+
10
+ async function refetch() {
11
+ if (!slug.value || !widgetId.value) {
12
+ data.value = null
13
+ error.value = null
14
+ return null
15
+ }
16
+
17
+ isFetching.value = true
18
+ if (data.value === null) {
19
+ isLoading.value = true
20
+ }
21
+
22
+ try {
23
+ const response = await dashboardApi.getDashboardWidgetData(slug.value, widgetId.value)
24
+ data.value = response
25
+ error.value = null
26
+ return response
27
+ } catch (e) {
28
+ error.value = e
29
+ throw e
30
+ } finally {
31
+ isFetching.value = false
32
+ isLoading.value = false
33
+ }
34
+ }
35
+
36
+ watch(
37
+ [slug, widgetId],
38
+ () => {
39
+ void refetch()
40
+ },
41
+ { immediate: true },
42
+ )
43
+
44
+ return {
45
+ data,
46
+ isLoading,
47
+ isFetching,
48
+ error,
49
+ refetch,
50
+ }
51
+ }