@adminforth/dashboard 1.4.2 → 1.6.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.
- package/custom/api/dashboardApi.ts +137 -5
- package/custom/model/dashboard.types.ts +32 -22
- package/custom/runtime/DashboardRuntime.vue +2 -3
- package/custom/skills/adminforth-dashboard/SKILL.md +165 -179
- package/custom/widgets/KpiCardWidget.vue +172 -9
- package/custom/widgets/chart/ChartWidget.vue +5 -5
- package/custom/widgets/registry.ts +4 -4
- package/dist/custom/api/dashboardApi.d.ts +46 -2
- package/dist/custom/api/dashboardApi.js +90 -5
- package/dist/custom/api/dashboardApi.ts +137 -5
- package/dist/custom/model/dashboard.types.d.ts +30 -14
- package/dist/custom/model/dashboard.types.js +2 -2
- package/dist/custom/model/dashboard.types.ts +32 -22
- package/dist/custom/queries/useDashboardConfig.d.ts +106 -104
- package/dist/custom/queries/useWidgetData.d.ts +106 -104
- package/dist/custom/runtime/DashboardRuntime.vue +2 -3
- package/dist/custom/skills/adminforth-dashboard/SKILL.md +165 -179
- package/dist/custom/widgets/KpiCardWidget.vue +172 -9
- package/dist/custom/widgets/chart/ChartWidget.vue +5 -5
- package/dist/custom/widgets/registry.js +4 -4
- package/dist/custom/widgets/registry.ts +4 -4
- package/dist/endpoint/dashboard.d.ts +2 -4
- package/dist/endpoint/dashboard.js +1 -21
- package/dist/endpoint/groups.d.ts +1 -0
- package/dist/endpoint/groups.js +61 -48
- package/dist/endpoint/widgets.d.ts +1 -0
- package/dist/endpoint/widgets.js +167 -64
- package/dist/schema/api.d.ts +11710 -2785
- package/dist/schema/api.js +118 -26
- package/dist/schema/widget.d.ts +425 -1980
- package/dist/schema/widget.js +13 -374
- package/dist/schema/widgets/charts.d.ts +1689 -0
- package/dist/schema/widgets/charts.js +92 -0
- package/dist/schema/widgets/common.d.ts +275 -0
- package/dist/schema/widgets/common.js +171 -0
- package/dist/schema/widgets/gauge-card.d.ts +172 -0
- package/dist/schema/widgets/gauge-card.js +28 -0
- package/dist/schema/widgets/kpi-card.d.ts +212 -0
- package/dist/schema/widgets/kpi-card.js +43 -0
- package/dist/schema/widgets/pivot-table.d.ts +196 -0
- package/dist/schema/widgets/pivot-table.js +17 -0
- package/dist/schema/widgets/table.d.ts +130 -0
- package/dist/schema/widgets/table.js +12 -0
- package/dist/services/dashboardConfigService.d.ts +4 -0
- package/dist/services/dashboardConfigService.js +46 -0
- package/dist/services/widgetDataService.js +96 -2
- package/endpoint/dashboard.ts +2 -33
- package/endpoint/groups.ts +91 -72
- package/endpoint/widgets.ts +260 -87
- package/package.json +1 -1
- package/schema/api.ts +148 -28
- package/schema/widget.ts +43 -425
- package/schema/widgets/charts.ts +113 -0
- package/schema/widgets/common.ts +194 -0
- package/schema/widgets/gauge-card.ts +34 -0
- package/schema/widgets/kpi-card.ts +49 -0
- package/schema/widgets/pivot-table.ts +24 -0
- package/schema/widgets/table.ts +18 -0
- package/services/dashboardConfigService.ts +73 -0
- package/services/widgetDataService.ts +129 -3
|
@@ -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,
|
|
10
|
+
import { DashboardApiResponseSchema, SlugRequestSchema, } from '../schema/api.js';
|
|
11
11
|
export function registerDashboardEndpoints(server, ctx) {
|
|
12
12
|
server.endpoint({
|
|
13
13
|
method: 'POST',
|
|
@@ -30,24 +30,4 @@ export function registerDashboardEndpoints(server, ctx) {
|
|
|
30
30
|
};
|
|
31
31
|
}),
|
|
32
32
|
});
|
|
33
|
-
server.endpoint({
|
|
34
|
-
method: 'POST',
|
|
35
|
-
path: '/dashboard/set_dashboard_config',
|
|
36
|
-
description: 'Replaces one dashboard configuration, including groups and widgets. Superadmin only.',
|
|
37
|
-
request_schema: SetDashboardConfigRequestSchema,
|
|
38
|
-
response_schema: DashboardApiResponseSchema,
|
|
39
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
40
|
-
if (!ctx.canEditDashboard(adminUser)) {
|
|
41
|
-
response.setStatus(403);
|
|
42
|
-
return { error: 'Dashboard edit is not allowed' };
|
|
43
|
-
}
|
|
44
|
-
const dashboard = yield ctx.getDashboardRecord(body.slug);
|
|
45
|
-
if (!dashboard) {
|
|
46
|
-
response.setStatus(404);
|
|
47
|
-
return { error: 'Dashboard not found' };
|
|
48
|
-
}
|
|
49
|
-
const config = body.config;
|
|
50
|
-
return ctx.persistDashboardConfig(dashboard, config);
|
|
51
|
-
}),
|
|
52
|
-
});
|
|
53
33
|
}
|
|
@@ -6,6 +6,7 @@ type GroupEndpointsContext = {
|
|
|
6
6
|
getDashboardRecord: (slug: string) => Promise<DashboardRecord | null>;
|
|
7
7
|
parseStoredDashboardConfig: (config: unknown) => DashboardConfig;
|
|
8
8
|
persistDashboardConfig: (dashboard: DashboardRecord, config: DashboardConfig) => Promise<PersistedDashboardResponse>;
|
|
9
|
+
updateDashboardConfig: (slug: string, mutateConfig: (config: DashboardConfig, dashboard: DashboardRecord) => DashboardConfig | null | Promise<DashboardConfig | null>) => Promise<PersistedDashboardResponse | null>;
|
|
9
10
|
};
|
|
10
11
|
export declare function registerGroupEndpoints(server: IHttpServer, ctx: GroupEndpointsContext): void;
|
|
11
12
|
export {};
|
package/dist/endpoint/groups.js
CHANGED
|
@@ -21,19 +21,20 @@ export function registerGroupEndpoints(server, ctx) {
|
|
|
21
21
|
response.setStatus(403);
|
|
22
22
|
return { error: 'Dashboard edit is not allowed' };
|
|
23
23
|
}
|
|
24
|
-
const
|
|
25
|
-
|
|
24
|
+
const updatedDashboard = yield ctx.updateDashboardConfig(body.slug, (config) => {
|
|
25
|
+
const nextOrder = config.groups.length + 1;
|
|
26
|
+
const group = {
|
|
27
|
+
id: `group_${randomUUID()}`,
|
|
28
|
+
label: 'New group',
|
|
29
|
+
order: nextOrder,
|
|
30
|
+
};
|
|
31
|
+
return Object.assign(Object.assign({}, config), { groups: [...config.groups, group] });
|
|
32
|
+
});
|
|
33
|
+
if (!updatedDashboard) {
|
|
26
34
|
response.setStatus(404);
|
|
27
35
|
return { error: 'Dashboard not found' };
|
|
28
36
|
}
|
|
29
|
-
|
|
30
|
-
const nextOrder = config.groups.length + 1;
|
|
31
|
-
const group = {
|
|
32
|
-
id: `group_${randomUUID()}`,
|
|
33
|
-
label: 'New group',
|
|
34
|
-
order: nextOrder,
|
|
35
|
-
};
|
|
36
|
-
return ctx.persistDashboardConfig(dashboard, Object.assign(Object.assign({}, config), { groups: [...config.groups, group] }));
|
|
37
|
+
return updatedDashboard;
|
|
37
38
|
}),
|
|
38
39
|
});
|
|
39
40
|
server.endpoint({
|
|
@@ -48,21 +49,27 @@ export function registerGroupEndpoints(server, ctx) {
|
|
|
48
49
|
return { error: 'Dashboard edit is not allowed' };
|
|
49
50
|
}
|
|
50
51
|
const groupId = body.groupId;
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
let mutationError = null;
|
|
53
|
+
const updatedDashboard = yield ctx.updateDashboardConfig(body.slug, (config) => {
|
|
54
|
+
const group = config.groups.find((item) => item.id === groupId);
|
|
55
|
+
if (!group) {
|
|
56
|
+
mutationError = 'Dashboard group not found';
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const nextGroup = Object.assign(Object.assign({}, body.config), { id: group.id, order: group.order });
|
|
60
|
+
return Object.assign(Object.assign({}, config), { groups: config.groups.map((item) => item.id === groupId
|
|
61
|
+
? nextGroup
|
|
62
|
+
: item) });
|
|
63
|
+
});
|
|
64
|
+
if (!updatedDashboard) {
|
|
53
65
|
response.setStatus(404);
|
|
54
66
|
return { error: 'Dashboard not found' };
|
|
55
67
|
}
|
|
56
|
-
|
|
57
|
-
const group = config.groups.find((item) => item.id === groupId);
|
|
58
|
-
if (!group) {
|
|
68
|
+
if (mutationError) {
|
|
59
69
|
response.setStatus(404);
|
|
60
|
-
return { error:
|
|
70
|
+
return { error: mutationError };
|
|
61
71
|
}
|
|
62
|
-
|
|
63
|
-
return ctx.persistDashboardConfig(dashboard, Object.assign(Object.assign({}, config), { groups: config.groups.map((item) => item.id === groupId
|
|
64
|
-
? nextGroup
|
|
65
|
-
: item) }));
|
|
72
|
+
return updatedDashboard;
|
|
66
73
|
}),
|
|
67
74
|
});
|
|
68
75
|
server.endpoint({
|
|
@@ -76,32 +83,32 @@ export function registerGroupEndpoints(server, ctx) {
|
|
|
76
83
|
response.setStatus(403);
|
|
77
84
|
return { error: 'Dashboard edit is not allowed' };
|
|
78
85
|
}
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
let mutationError = null;
|
|
87
|
+
const updatedDashboard = yield ctx.updateDashboardConfig(body.slug, (config) => {
|
|
88
|
+
const sortedGroups = [...config.groups].sort((a, b) => a.order - b.order);
|
|
89
|
+
const currentIndex = sortedGroups.findIndex((group) => group.id === body.groupId);
|
|
90
|
+
if (currentIndex === -1) {
|
|
91
|
+
mutationError = 'Dashboard group not found';
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const targetIndex = body.direction === 'up' ? currentIndex - 1 : currentIndex + 1;
|
|
95
|
+
if (targetIndex < 0 || targetIndex >= sortedGroups.length) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const reorderedGroups = [...sortedGroups];
|
|
99
|
+
const [group] = reorderedGroups.splice(currentIndex, 1);
|
|
100
|
+
reorderedGroups.splice(targetIndex, 0, group);
|
|
101
|
+
return Object.assign(Object.assign({}, config), { groups: reorderedGroups });
|
|
102
|
+
});
|
|
103
|
+
if (!updatedDashboard) {
|
|
81
104
|
response.setStatus(404);
|
|
82
105
|
return { error: 'Dashboard not found' };
|
|
83
106
|
}
|
|
84
|
-
|
|
85
|
-
const sortedGroups = [...config.groups].sort((a, b) => a.order - b.order);
|
|
86
|
-
const currentIndex = sortedGroups.findIndex((group) => group.id === body.groupId);
|
|
87
|
-
if (currentIndex === -1) {
|
|
107
|
+
if (mutationError) {
|
|
88
108
|
response.setStatus(404);
|
|
89
|
-
return { error:
|
|
90
|
-
}
|
|
91
|
-
const targetIndex = body.direction === 'up' ? currentIndex - 1 : currentIndex + 1;
|
|
92
|
-
if (targetIndex < 0 || targetIndex >= sortedGroups.length) {
|
|
93
|
-
return {
|
|
94
|
-
id: dashboard.id,
|
|
95
|
-
slug: dashboard.slug,
|
|
96
|
-
label: dashboard.label,
|
|
97
|
-
revision: dashboard.revision,
|
|
98
|
-
config: ctx.parseStoredDashboardConfig(dashboard.config),
|
|
99
|
-
};
|
|
109
|
+
return { error: mutationError };
|
|
100
110
|
}
|
|
101
|
-
|
|
102
|
-
const [group] = reorderedGroups.splice(currentIndex, 1);
|
|
103
|
-
reorderedGroups.splice(targetIndex, 0, group);
|
|
104
|
-
return ctx.persistDashboardConfig(dashboard, Object.assign(Object.assign({}, config), { groups: reorderedGroups }));
|
|
111
|
+
return updatedDashboard;
|
|
105
112
|
}),
|
|
106
113
|
});
|
|
107
114
|
server.endpoint({
|
|
@@ -116,18 +123,24 @@ export function registerGroupEndpoints(server, ctx) {
|
|
|
116
123
|
return { error: 'Dashboard edit is not allowed' };
|
|
117
124
|
}
|
|
118
125
|
const groupId = body.groupId;
|
|
119
|
-
|
|
120
|
-
|
|
126
|
+
let mutationError = null;
|
|
127
|
+
const updatedDashboard = yield ctx.updateDashboardConfig(body.slug, (config) => {
|
|
128
|
+
const nextGroups = config.groups.filter((group) => group.id !== groupId);
|
|
129
|
+
if (nextGroups.length === config.groups.length) {
|
|
130
|
+
mutationError = 'Dashboard group not found';
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
return Object.assign(Object.assign({}, config), { groups: nextGroups, widgets: config.widgets.filter((widget) => widget.group_id !== groupId) });
|
|
134
|
+
});
|
|
135
|
+
if (!updatedDashboard) {
|
|
121
136
|
response.setStatus(404);
|
|
122
137
|
return { error: 'Dashboard not found' };
|
|
123
138
|
}
|
|
124
|
-
|
|
125
|
-
const nextGroups = config.groups.filter((group) => group.id !== groupId);
|
|
126
|
-
if (nextGroups.length === config.groups.length) {
|
|
139
|
+
if (mutationError) {
|
|
127
140
|
response.setStatus(404);
|
|
128
|
-
return { error:
|
|
141
|
+
return { error: mutationError };
|
|
129
142
|
}
|
|
130
|
-
return
|
|
143
|
+
return updatedDashboard;
|
|
131
144
|
}),
|
|
132
145
|
});
|
|
133
146
|
}
|
|
@@ -6,6 +6,7 @@ type WidgetEndpointsContext = {
|
|
|
6
6
|
getDashboardRecord: (slug: string) => Promise<DashboardRecord | null>;
|
|
7
7
|
parseStoredDashboardConfig: (config: unknown) => DashboardConfig;
|
|
8
8
|
persistDashboardConfig: (dashboard: DashboardRecord, config: DashboardConfig) => Promise<PersistedDashboardResponse>;
|
|
9
|
+
updateDashboardConfig: (slug: string, mutateConfig: (config: DashboardConfig, dashboard: DashboardRecord) => DashboardConfig | null | Promise<DashboardConfig | null>) => Promise<PersistedDashboardResponse | null>;
|
|
9
10
|
getWidgetData: (widget: DashboardWidgetConfig, options?: {
|
|
10
11
|
pagination?: {
|
|
11
12
|
page: number;
|
package/dist/endpoint/widgets.js
CHANGED
|
@@ -8,7 +8,53 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { randomUUID } from 'crypto';
|
|
11
|
-
import { DashboardApiResponseSchema, DashboardWidgetDataResponseSchema, GroupIdRequestSchema, MoveWidgetRequestSchema, SetWidgetConfigRequestSchema, WidgetDataRequestSchema, WidgetIdRequestSchema, } from '../schema/api.js';
|
|
11
|
+
import { ConfigureBarChartWidgetRequestSchema, ConfigureFunnelChartWidgetRequestSchema, ConfigureGaugeCardWidgetRequestSchema, ConfigureHistogramChartWidgetRequestSchema, ConfigureKpiCardWidgetRequestSchema, ConfigureLineChartWidgetRequestSchema, ConfigurePieChartWidgetRequestSchema, ConfigurePivotTableWidgetRequestSchema, ConfigureStackedBarChartWidgetRequestSchema, ConfigureTableWidgetRequestSchema, DashboardApiResponseSchema, DashboardWidgetDataResponseSchema, GroupIdRequestSchema, MoveWidgetRequestSchema, SetWidgetConfigRequestSchema, WidgetDataRequestSchema, WidgetIdRequestSchema, } from '../schema/api.js';
|
|
12
|
+
function replaceWidgetConfig(ctx, slug, widgetId, widgetConfig) {
|
|
13
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
14
|
+
let mutationError = null;
|
|
15
|
+
const updatedDashboard = yield ctx.updateDashboardConfig(slug, (config) => {
|
|
16
|
+
const widget = config.widgets.find((item) => item.id === widgetId);
|
|
17
|
+
if (!widget) {
|
|
18
|
+
mutationError = 'Dashboard widget not found';
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const nextWidget = Object.assign(Object.assign({}, widgetConfig), { id: widget.id, group_id: widget.group_id, order: widget.order });
|
|
22
|
+
return Object.assign(Object.assign({}, config), { widgets: config.widgets.map((item) => item.id === widgetId
|
|
23
|
+
? nextWidget
|
|
24
|
+
: item) });
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
updatedDashboard,
|
|
28
|
+
mutationError,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function registerConfigureWidgetEndpoint(server, ctx, options) {
|
|
33
|
+
server.endpoint({
|
|
34
|
+
method: 'POST',
|
|
35
|
+
path: options.path,
|
|
36
|
+
description: options.description,
|
|
37
|
+
request_schema: options.requestSchema,
|
|
38
|
+
response_schema: DashboardApiResponseSchema,
|
|
39
|
+
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
40
|
+
if (!ctx.canEditDashboard(adminUser)) {
|
|
41
|
+
response.setStatus(403);
|
|
42
|
+
return { error: 'Dashboard edit is not allowed' };
|
|
43
|
+
}
|
|
44
|
+
const request = body;
|
|
45
|
+
const { updatedDashboard, mutationError } = yield replaceWidgetConfig(ctx, request.slug, request.widgetId, request.config);
|
|
46
|
+
if (!updatedDashboard) {
|
|
47
|
+
response.setStatus(404);
|
|
48
|
+
return { error: 'Dashboard not found' };
|
|
49
|
+
}
|
|
50
|
+
if (mutationError) {
|
|
51
|
+
response.setStatus(404);
|
|
52
|
+
return { error: mutationError };
|
|
53
|
+
}
|
|
54
|
+
return updatedDashboard;
|
|
55
|
+
}),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
12
58
|
export function registerWidgetEndpoints(server, ctx) {
|
|
13
59
|
server.endpoint({
|
|
14
60
|
method: 'POST',
|
|
@@ -21,27 +67,33 @@ export function registerWidgetEndpoints(server, ctx) {
|
|
|
21
67
|
response.setStatus(403);
|
|
22
68
|
return { error: 'Dashboard edit is not allowed' };
|
|
23
69
|
}
|
|
24
|
-
|
|
25
|
-
|
|
70
|
+
let mutationError = null;
|
|
71
|
+
const updatedDashboard = yield ctx.updateDashboardConfig(body.slug, (config) => {
|
|
72
|
+
const group = config.groups.find((item) => item.id === body.groupId);
|
|
73
|
+
if (!group) {
|
|
74
|
+
mutationError = 'Dashboard group not found';
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const nextOrder = config.widgets.filter((item) => item.group_id === body.groupId).length + 1;
|
|
78
|
+
const widget = {
|
|
79
|
+
id: `widget_${randomUUID()}`,
|
|
80
|
+
group_id: body.groupId,
|
|
81
|
+
label: 'New widget',
|
|
82
|
+
size: 'small',
|
|
83
|
+
order: nextOrder,
|
|
84
|
+
target: 'empty',
|
|
85
|
+
};
|
|
86
|
+
return Object.assign(Object.assign({}, config), { widgets: [...config.widgets, widget] });
|
|
87
|
+
});
|
|
88
|
+
if (!updatedDashboard) {
|
|
26
89
|
response.setStatus(404);
|
|
27
90
|
return { error: 'Dashboard not found' };
|
|
28
91
|
}
|
|
29
|
-
|
|
30
|
-
const group = config.groups.find((item) => item.id === body.groupId);
|
|
31
|
-
if (!group) {
|
|
92
|
+
if (mutationError) {
|
|
32
93
|
response.setStatus(404);
|
|
33
|
-
return { error:
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const widget = {
|
|
37
|
-
id: `widget_${randomUUID()}`,
|
|
38
|
-
group_id: body.groupId,
|
|
39
|
-
label: 'New widget',
|
|
40
|
-
size: 'small',
|
|
41
|
-
order: nextOrder,
|
|
42
|
-
target: 'empty',
|
|
43
|
-
};
|
|
44
|
-
return ctx.persistDashboardConfig(dashboard, Object.assign(Object.assign({}, config), { widgets: [...config.widgets, widget] }));
|
|
94
|
+
return { error: mutationError };
|
|
95
|
+
}
|
|
96
|
+
return updatedDashboard;
|
|
45
97
|
}),
|
|
46
98
|
});
|
|
47
99
|
server.endpoint({
|
|
@@ -55,39 +107,39 @@ export function registerWidgetEndpoints(server, ctx) {
|
|
|
55
107
|
response.setStatus(403);
|
|
56
108
|
return { error: 'Dashboard edit is not allowed' };
|
|
57
109
|
}
|
|
58
|
-
|
|
59
|
-
|
|
110
|
+
let mutationError = null;
|
|
111
|
+
const updatedDashboard = yield ctx.updateDashboardConfig(body.slug, (config) => {
|
|
112
|
+
const widget = config.widgets.find((item) => item.id === body.widgetId);
|
|
113
|
+
if (!widget) {
|
|
114
|
+
mutationError = 'Dashboard widget not found';
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
const sortedWidgets = config.widgets
|
|
118
|
+
.filter((item) => item.group_id === widget.group_id)
|
|
119
|
+
.sort((a, b) => a.order - b.order);
|
|
120
|
+
const currentIndex = sortedWidgets.findIndex((item) => item.id === body.widgetId);
|
|
121
|
+
const targetIndex = body.direction === 'up' ? currentIndex - 1 : currentIndex + 1;
|
|
122
|
+
if (targetIndex < 0 || targetIndex >= sortedWidgets.length) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const reorderedWidgets = [...sortedWidgets];
|
|
126
|
+
const [movedWidget] = reorderedWidgets.splice(currentIndex, 1);
|
|
127
|
+
reorderedWidgets.splice(targetIndex, 0, movedWidget);
|
|
128
|
+
const reorderedWidgetIds = new Map(reorderedWidgets.map((item, index) => [item.id, index + 1]));
|
|
129
|
+
return Object.assign(Object.assign({}, config), { widgets: config.widgets.map((item) => {
|
|
130
|
+
var _a;
|
|
131
|
+
return (Object.assign(Object.assign({}, item), { order: (_a = reorderedWidgetIds.get(item.id)) !== null && _a !== void 0 ? _a : item.order }));
|
|
132
|
+
}) });
|
|
133
|
+
});
|
|
134
|
+
if (!updatedDashboard) {
|
|
60
135
|
response.setStatus(404);
|
|
61
136
|
return { error: 'Dashboard not found' };
|
|
62
137
|
}
|
|
63
|
-
|
|
64
|
-
const widget = config.widgets.find((item) => item.id === body.widgetId);
|
|
65
|
-
if (!widget) {
|
|
138
|
+
if (mutationError) {
|
|
66
139
|
response.setStatus(404);
|
|
67
|
-
return { error:
|
|
68
|
-
}
|
|
69
|
-
const sortedWidgets = config.widgets
|
|
70
|
-
.filter((item) => item.group_id === widget.group_id)
|
|
71
|
-
.sort((a, b) => a.order - b.order);
|
|
72
|
-
const currentIndex = sortedWidgets.findIndex((item) => item.id === body.widgetId);
|
|
73
|
-
const targetIndex = body.direction === 'up' ? currentIndex - 1 : currentIndex + 1;
|
|
74
|
-
if (targetIndex < 0 || targetIndex >= sortedWidgets.length) {
|
|
75
|
-
return {
|
|
76
|
-
id: dashboard.id,
|
|
77
|
-
slug: dashboard.slug,
|
|
78
|
-
label: dashboard.label,
|
|
79
|
-
revision: dashboard.revision,
|
|
80
|
-
config: ctx.parseStoredDashboardConfig(dashboard.config),
|
|
81
|
-
};
|
|
140
|
+
return { error: mutationError };
|
|
82
141
|
}
|
|
83
|
-
|
|
84
|
-
const [movedWidget] = reorderedWidgets.splice(currentIndex, 1);
|
|
85
|
-
reorderedWidgets.splice(targetIndex, 0, movedWidget);
|
|
86
|
-
const reorderedWidgetIds = new Map(reorderedWidgets.map((item, index) => [item.id, index + 1]));
|
|
87
|
-
return ctx.persistDashboardConfig(dashboard, Object.assign(Object.assign({}, config), { widgets: config.widgets.map((item) => {
|
|
88
|
-
var _a;
|
|
89
|
-
return (Object.assign(Object.assign({}, item), { order: (_a = reorderedWidgetIds.get(item.id)) !== null && _a !== void 0 ? _a : item.order }));
|
|
90
|
-
}) }));
|
|
142
|
+
return updatedDashboard;
|
|
91
143
|
}),
|
|
92
144
|
});
|
|
93
145
|
server.endpoint({
|
|
@@ -101,18 +153,24 @@ export function registerWidgetEndpoints(server, ctx) {
|
|
|
101
153
|
response.setStatus(403);
|
|
102
154
|
return { error: 'Dashboard edit is not allowed' };
|
|
103
155
|
}
|
|
104
|
-
|
|
105
|
-
|
|
156
|
+
let mutationError = null;
|
|
157
|
+
const updatedDashboard = yield ctx.updateDashboardConfig(body.slug, (config) => {
|
|
158
|
+
const nextWidgets = config.widgets.filter((item) => item.id !== body.widgetId);
|
|
159
|
+
if (nextWidgets.length === config.widgets.length) {
|
|
160
|
+
mutationError = 'Dashboard widget not found';
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
return Object.assign(Object.assign({}, config), { widgets: nextWidgets });
|
|
164
|
+
});
|
|
165
|
+
if (!updatedDashboard) {
|
|
106
166
|
response.setStatus(404);
|
|
107
167
|
return { error: 'Dashboard not found' };
|
|
108
168
|
}
|
|
109
|
-
|
|
110
|
-
const nextWidgets = config.widgets.filter((item) => item.id !== body.widgetId);
|
|
111
|
-
if (nextWidgets.length === config.widgets.length) {
|
|
169
|
+
if (mutationError) {
|
|
112
170
|
response.setStatus(404);
|
|
113
|
-
return { error:
|
|
171
|
+
return { error: mutationError };
|
|
114
172
|
}
|
|
115
|
-
return
|
|
173
|
+
return updatedDashboard;
|
|
116
174
|
}),
|
|
117
175
|
});
|
|
118
176
|
server.endpoint({
|
|
@@ -126,24 +184,69 @@ export function registerWidgetEndpoints(server, ctx) {
|
|
|
126
184
|
response.setStatus(403);
|
|
127
185
|
return { error: 'Dashboard edit is not allowed' };
|
|
128
186
|
}
|
|
129
|
-
const
|
|
130
|
-
|
|
187
|
+
const request = body;
|
|
188
|
+
const { updatedDashboard, mutationError } = yield replaceWidgetConfig(ctx, request.slug, request.widgetId, request.config);
|
|
189
|
+
if (!updatedDashboard) {
|
|
131
190
|
response.setStatus(404);
|
|
132
191
|
return { error: 'Dashboard not found' };
|
|
133
192
|
}
|
|
134
|
-
|
|
135
|
-
const widget = config.widgets.find((item) => item.id === body.widgetId);
|
|
136
|
-
if (!widget) {
|
|
193
|
+
if (mutationError) {
|
|
137
194
|
response.setStatus(404);
|
|
138
|
-
return { error:
|
|
195
|
+
return { error: mutationError };
|
|
139
196
|
}
|
|
140
|
-
|
|
141
|
-
const nextWidget = Object.assign(Object.assign({}, typedWidgetConfig), { id: widget.id, group_id: widget.group_id, order: widget.order });
|
|
142
|
-
return ctx.persistDashboardConfig(dashboard, Object.assign(Object.assign({}, config), { widgets: config.widgets.map((item) => item.id === body.widgetId
|
|
143
|
-
? nextWidget
|
|
144
|
-
: item) }));
|
|
197
|
+
return updatedDashboard;
|
|
145
198
|
}),
|
|
146
199
|
});
|
|
200
|
+
registerConfigureWidgetEndpoint(server, ctx, {
|
|
201
|
+
path: '/dashboard/configure_table_widget',
|
|
202
|
+
description: 'Configures an existing dashboard widget as a table. Superadmin only.',
|
|
203
|
+
requestSchema: ConfigureTableWidgetRequestSchema,
|
|
204
|
+
});
|
|
205
|
+
registerConfigureWidgetEndpoint(server, ctx, {
|
|
206
|
+
path: '/dashboard/configure_kpi_card_widget',
|
|
207
|
+
description: 'Configures an existing dashboard widget as a KPI card. Superadmin only.',
|
|
208
|
+
requestSchema: ConfigureKpiCardWidgetRequestSchema,
|
|
209
|
+
});
|
|
210
|
+
registerConfigureWidgetEndpoint(server, ctx, {
|
|
211
|
+
path: '/dashboard/configure_gauge_card_widget',
|
|
212
|
+
description: 'Configures an existing dashboard widget as a gauge card. Superadmin only.',
|
|
213
|
+
requestSchema: ConfigureGaugeCardWidgetRequestSchema,
|
|
214
|
+
});
|
|
215
|
+
registerConfigureWidgetEndpoint(server, ctx, {
|
|
216
|
+
path: '/dashboard/configure_pivot_table_widget',
|
|
217
|
+
description: 'Configures an existing dashboard widget as a pivot table. Superadmin only.',
|
|
218
|
+
requestSchema: ConfigurePivotTableWidgetRequestSchema,
|
|
219
|
+
});
|
|
220
|
+
registerConfigureWidgetEndpoint(server, ctx, {
|
|
221
|
+
path: '/dashboard/configure_line_chart_widget',
|
|
222
|
+
description: 'Configures an existing dashboard widget as a line chart. Superadmin only.',
|
|
223
|
+
requestSchema: ConfigureLineChartWidgetRequestSchema,
|
|
224
|
+
});
|
|
225
|
+
registerConfigureWidgetEndpoint(server, ctx, {
|
|
226
|
+
path: '/dashboard/configure_bar_chart_widget',
|
|
227
|
+
description: 'Configures an existing dashboard widget as a bar chart. Superadmin only.',
|
|
228
|
+
requestSchema: ConfigureBarChartWidgetRequestSchema,
|
|
229
|
+
});
|
|
230
|
+
registerConfigureWidgetEndpoint(server, ctx, {
|
|
231
|
+
path: '/dashboard/configure_stacked_bar_chart_widget',
|
|
232
|
+
description: 'Configures an existing dashboard widget as a stacked bar chart. Superadmin only.',
|
|
233
|
+
requestSchema: ConfigureStackedBarChartWidgetRequestSchema,
|
|
234
|
+
});
|
|
235
|
+
registerConfigureWidgetEndpoint(server, ctx, {
|
|
236
|
+
path: '/dashboard/configure_pie_chart_widget',
|
|
237
|
+
description: 'Configures an existing dashboard widget as a pie chart. Superadmin only.',
|
|
238
|
+
requestSchema: ConfigurePieChartWidgetRequestSchema,
|
|
239
|
+
});
|
|
240
|
+
registerConfigureWidgetEndpoint(server, ctx, {
|
|
241
|
+
path: '/dashboard/configure_histogram_chart_widget',
|
|
242
|
+
description: 'Configures an existing dashboard widget as a histogram chart. Superadmin only.',
|
|
243
|
+
requestSchema: ConfigureHistogramChartWidgetRequestSchema,
|
|
244
|
+
});
|
|
245
|
+
registerConfigureWidgetEndpoint(server, ctx, {
|
|
246
|
+
path: '/dashboard/configure_funnel_chart_widget',
|
|
247
|
+
description: 'Configures an existing dashboard widget as a funnel chart. Superadmin only.',
|
|
248
|
+
requestSchema: ConfigureFunnelChartWidgetRequestSchema,
|
|
249
|
+
});
|
|
147
250
|
server.endpoint({
|
|
148
251
|
method: 'POST',
|
|
149
252
|
path: '/dashboard/get_dashboard_widget_data',
|