@hed-hog/core 0.0.298 → 0.0.300
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/dist/dashboard/dashboard/dashboard.controller.d.ts +9 -0
- package/dist/dashboard/dashboard/dashboard.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard/dashboard.service.d.ts +9 -0
- package/dist/dashboard/dashboard/dashboard.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +14 -1
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component/dashboard-component.controller.js +28 -3
- package/dist/dashboard/dashboard-component/dashboard-component.controller.js.map +1 -1
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +22 -1
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component/dashboard-component.service.js +185 -35
- package/dist/dashboard/dashboard-component/dashboard-component.service.js.map +1 -1
- package/dist/dashboard/dashboard-component/dto/create.dto.d.ts +1 -0
- package/dist/dashboard/dashboard-component/dto/create.dto.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component/dto/create.dto.js +5 -0
- package/dist/dashboard/dashboard-component/dto/create.dto.js.map +1 -1
- package/dist/dashboard/dashboard-component/dto/update.dto.d.ts +1 -0
- package/dist/dashboard/dashboard-component/dto/update.dto.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component/dto/update.dto.js +5 -0
- package/dist/dashboard/dashboard-component/dto/update.dto.js.map +1 -1
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +1 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +1 -0
- package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +72 -1
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.controller.js +111 -0
- package/dist/dashboard/dashboard-core/dashboard-core.controller.js.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +76 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.js +614 -23
- package/dist/dashboard/dashboard-core/dashboard-core.service.js.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts +3 -0
- package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts +3 -0
- package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +2 -0
- package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +2 -0
- package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts.map +1 -1
- package/hedhog/data/dashboard.yaml +12 -6
- package/hedhog/data/dashboard_component_role.yaml +66 -0
- package/hedhog/data/dashboard_item.yaml +1 -1
- package/hedhog/data/dashboard_role.yaml +2 -8
- package/hedhog/data/route.yaml +84 -0
- package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +457 -135
- package/hedhog/frontend/app/dashboard/[slug]/types.ts.ejs +3 -0
- package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +365 -28
- package/hedhog/frontend/app/dashboard/components/add-widget-selector-dialog.tsx.ejs +376 -247
- package/hedhog/frontend/app/dashboard/components/draggable-grid.tsx.ejs +64 -18
- package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +1389 -0
- package/hedhog/frontend/app/dashboard/dashboard.css.ejs +37 -0
- package/hedhog/frontend/app/dashboard/management/page.tsx.ejs +1 -1
- package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +6 -6
- package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +8 -8
- package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +3 -3
- package/hedhog/frontend/app/dashboard/page.tsx.ejs +3 -25
- package/hedhog/frontend/messages/en.json +115 -2
- package/hedhog/frontend/messages/pt.json +114 -1
- package/hedhog/frontend/public/dashboard-previews/.gitkeep +12 -0
- package/hedhog/frontend/public/dashboard-previews/account-security.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/active-users-card.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/activity-timeline.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/cash-balance-kpi.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/cash-flow-chart.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/default-kpi.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/email-notifications.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/financial-alerts.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/login-history-chart.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/mail-sent-card.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/mail-sent-chart.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/menus-card.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/payable-30d-kpi.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/permissions-card.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/permissions-chart.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/profile-card.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/receivable-30d-kpi.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/routes-card.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/session-activity-chart.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/sessions-today-card.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/stat-access-level.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/stat-actions-today.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/stat-consecutive-days.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/stat-online-time.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/upcoming-payable.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/upcoming-receivable.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/user-growth-chart.png +0 -0
- package/hedhog/frontend/public/dashboard-previews/user-roles.png +0 -0
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/account-security.tsx.ejs +34 -30
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/active-users-card.tsx.ejs +2 -2
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/activity-timeline.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/email-notifications.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/locale-config.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/login-history-chart.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/mail-config.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/mail-sent-card.tsx.ejs +2 -2
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/mail-sent-chart.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/menus-card.tsx.ejs +2 -2
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/oauth-config.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/permissions-card.tsx.ejs +2 -2
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/permissions-chart.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/profile-card.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/routes-card.tsx.ejs +2 -2
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/session-activity-chart.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/sessions-today-card.tsx.ejs +2 -2
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/stat-access-level.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/stat-actions-today.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/stat-consecutive-days.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/stat-online-time.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/storage-config.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/theme-config.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/user-growth-chart.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/user-roles.tsx.ejs +1 -1
- package/hedhog/frontend/{app/dashboard/components/widgets → widgets}/user-sessions.tsx.ejs +2 -2
- package/hedhog/table/dashboard.yaml +6 -0
- package/hedhog/table/dashboard_component.yaml +7 -0
- package/package.json +5 -5
- package/src/dashboard/dashboard-component/dashboard-component.controller.ts +51 -14
- package/src/dashboard/dashboard-component/dashboard-component.service.ts +254 -43
- package/src/dashboard/dashboard-component/dto/create.dto.ts +4 -0
- package/src/dashboard/dashboard-component/dto/update.dto.ts +4 -0
- package/src/dashboard/dashboard-core/dashboard-core.controller.ts +112 -1
- package/src/dashboard/dashboard-core/dashboard-core.service.ts +782 -24
|
@@ -430,6 +430,115 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
430
430
|
}
|
|
431
431
|
return value.map((provider) => String(provider).toLowerCase());
|
|
432
432
|
}
|
|
433
|
+
slugifyDashboardName(value) {
|
|
434
|
+
const normalized = value
|
|
435
|
+
.normalize('NFD')
|
|
436
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
437
|
+
.toLowerCase()
|
|
438
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
439
|
+
.replace(/^-+|-+$/g, '');
|
|
440
|
+
return normalized || `dashboard-${Date.now()}`;
|
|
441
|
+
}
|
|
442
|
+
getDashboardDisplayName(dashboard) {
|
|
443
|
+
var _a, _b;
|
|
444
|
+
return ((_b = (_a = dashboard.dashboard_locale) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.name) || dashboard.slug;
|
|
445
|
+
}
|
|
446
|
+
async buildUniqueDashboardSlug(baseSlug) {
|
|
447
|
+
let slug = baseSlug;
|
|
448
|
+
let suffix = 2;
|
|
449
|
+
while (await this.prismaService.dashboard.findFirst({
|
|
450
|
+
where: { slug },
|
|
451
|
+
select: { id: true },
|
|
452
|
+
})) {
|
|
453
|
+
slug = `${baseSlug}-${suffix}`;
|
|
454
|
+
suffix += 1;
|
|
455
|
+
}
|
|
456
|
+
return slug;
|
|
457
|
+
}
|
|
458
|
+
async getDashboardUserOrThrow(userId, slug, locale) {
|
|
459
|
+
const dashboardUser = await this.prismaService.dashboard_user.findFirst({
|
|
460
|
+
where: {
|
|
461
|
+
user_id: userId,
|
|
462
|
+
dashboard: { slug },
|
|
463
|
+
},
|
|
464
|
+
include: {
|
|
465
|
+
dashboard: {
|
|
466
|
+
include: {
|
|
467
|
+
dashboard_locale: {
|
|
468
|
+
where: {
|
|
469
|
+
locale: {
|
|
470
|
+
code: locale,
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
});
|
|
478
|
+
if (!dashboardUser) {
|
|
479
|
+
throw new common_1.ForbiddenException((0, api_locale_1.getLocaleText)('dashboardNotFound', locale, 'Dashboard not found.'));
|
|
480
|
+
}
|
|
481
|
+
return dashboardUser;
|
|
482
|
+
}
|
|
483
|
+
async getUserRoleIds(userId) {
|
|
484
|
+
const roleUsers = await this.prismaService.role_user.findMany({
|
|
485
|
+
where: { user_id: userId },
|
|
486
|
+
select: { role_id: true },
|
|
487
|
+
});
|
|
488
|
+
return roleUsers.map((roleUser) => roleUser.role_id);
|
|
489
|
+
}
|
|
490
|
+
async getAccessibleTemplateOrThrow(userId, templateSlug, locale) {
|
|
491
|
+
const userRoleIds = await this.getUserRoleIds(userId);
|
|
492
|
+
const templateAccessFilter = userRoleIds.length > 0
|
|
493
|
+
? {
|
|
494
|
+
OR: [
|
|
495
|
+
{
|
|
496
|
+
dashboard_role: {
|
|
497
|
+
some: {
|
|
498
|
+
role_id: {
|
|
499
|
+
in: userRoleIds,
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
dashboard_role: {
|
|
506
|
+
none: {},
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
],
|
|
510
|
+
}
|
|
511
|
+
: {
|
|
512
|
+
dashboard_role: {
|
|
513
|
+
none: {},
|
|
514
|
+
},
|
|
515
|
+
};
|
|
516
|
+
const template = await this.prismaService.dashboard.findFirst({
|
|
517
|
+
where: Object.assign({ slug: templateSlug, is_template: true }, templateAccessFilter),
|
|
518
|
+
include: {
|
|
519
|
+
dashboard_locale: {
|
|
520
|
+
where: {
|
|
521
|
+
locale: {
|
|
522
|
+
code: locale,
|
|
523
|
+
},
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
dashboard_item: {
|
|
527
|
+
select: {
|
|
528
|
+
component_id: true,
|
|
529
|
+
width: true,
|
|
530
|
+
height: true,
|
|
531
|
+
x_axis: true,
|
|
532
|
+
y_axis: true,
|
|
533
|
+
},
|
|
534
|
+
},
|
|
535
|
+
},
|
|
536
|
+
});
|
|
537
|
+
if (!template) {
|
|
538
|
+
throw new common_1.ForbiddenException((0, api_locale_1.getLocaleText)('dashboardNotFound', locale, 'Dashboard template not found.'));
|
|
539
|
+
}
|
|
540
|
+
return template;
|
|
541
|
+
}
|
|
433
542
|
async getHome(userId, locale) {
|
|
434
543
|
const user = await this.prismaService.user.findUnique({
|
|
435
544
|
where: { id: userId },
|
|
@@ -739,6 +848,7 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
739
848
|
i: `widget-${item.id}`,
|
|
740
849
|
component_id: item.component_id,
|
|
741
850
|
slug: component.slug,
|
|
851
|
+
library_slug: component.library_slug,
|
|
742
852
|
name: (locale === null || locale === void 0 ? void 0 : locale.name) || component.slug,
|
|
743
853
|
description: (locale === null || locale === void 0 ? void 0 : locale.description) || '',
|
|
744
854
|
x: item.x_axis,
|
|
@@ -770,26 +880,29 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
770
880
|
if (!canAccess) {
|
|
771
881
|
throw new common_1.ForbiddenException('Access denied to this dashboard');
|
|
772
882
|
}
|
|
773
|
-
|
|
774
|
-
const itemId = parseInt(item.i.replace('widget-', ''));
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
dashboard_id: dashboard.id,
|
|
779
|
-
},
|
|
780
|
-
});
|
|
781
|
-
if (!dashboardItem) {
|
|
782
|
-
continue;
|
|
883
|
+
const layoutUpdates = layout.flatMap((item) => {
|
|
884
|
+
const itemId = Number.parseInt(item.i.replace('widget-', ''), 10);
|
|
885
|
+
if (Number.isNaN(itemId)) {
|
|
886
|
+
this.logger.warn(`Skipping dashboard layout item with invalid id: ${item.i}`);
|
|
887
|
+
return [];
|
|
783
888
|
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
889
|
+
return [
|
|
890
|
+
this.prismaService.dashboard_item.updateMany({
|
|
891
|
+
where: {
|
|
892
|
+
id: itemId,
|
|
893
|
+
dashboard_id: dashboard.id,
|
|
894
|
+
},
|
|
895
|
+
data: {
|
|
896
|
+
x_axis: item.x,
|
|
897
|
+
y_axis: item.y,
|
|
898
|
+
width: item.w,
|
|
899
|
+
height: item.h,
|
|
900
|
+
},
|
|
901
|
+
}),
|
|
902
|
+
];
|
|
903
|
+
});
|
|
904
|
+
if (layoutUpdates.length > 0) {
|
|
905
|
+
await this.prismaService.$transaction(layoutUpdates);
|
|
793
906
|
}
|
|
794
907
|
return { success: true };
|
|
795
908
|
}
|
|
@@ -811,8 +924,44 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
811
924
|
if (!canAccess) {
|
|
812
925
|
throw new common_1.ForbiddenException('Access denied to this dashboard');
|
|
813
926
|
}
|
|
927
|
+
const userRoles = await this.prismaService.role_user.findMany({
|
|
928
|
+
where: { user_id: userId },
|
|
929
|
+
select: { role_id: true },
|
|
930
|
+
});
|
|
931
|
+
const userRoleIds = userRoles.map((item) => item.role_id);
|
|
932
|
+
if (userRoleIds.length === 0) {
|
|
933
|
+
throw new common_1.ForbiddenException('Access denied to this component');
|
|
934
|
+
}
|
|
935
|
+
const slugParts = componentSlug.split('.').filter(Boolean);
|
|
936
|
+
const requestedSlug = slugParts.length > 0 ? slugParts[slugParts.length - 1] : componentSlug;
|
|
937
|
+
const requestedLibrarySlug = slugParts.length > 1 ? slugParts[0] : undefined;
|
|
814
938
|
const component = await this.prismaService.dashboard_component.findFirst({
|
|
815
|
-
where: {
|
|
939
|
+
where: {
|
|
940
|
+
AND: [
|
|
941
|
+
requestedLibrarySlug
|
|
942
|
+
? {
|
|
943
|
+
OR: [
|
|
944
|
+
{ slug: componentSlug },
|
|
945
|
+
{
|
|
946
|
+
slug: requestedSlug,
|
|
947
|
+
library_slug: requestedLibrarySlug,
|
|
948
|
+
},
|
|
949
|
+
],
|
|
950
|
+
}
|
|
951
|
+
: {
|
|
952
|
+
OR: [{ slug: componentSlug }, { slug: requestedSlug }],
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
dashboard_component_role: {
|
|
956
|
+
some: {
|
|
957
|
+
role_id: {
|
|
958
|
+
in: userRoleIds,
|
|
959
|
+
},
|
|
960
|
+
},
|
|
961
|
+
},
|
|
962
|
+
},
|
|
963
|
+
],
|
|
964
|
+
},
|
|
816
965
|
include: {
|
|
817
966
|
dashboard_component_locale: {
|
|
818
967
|
where: {
|
|
@@ -824,7 +973,7 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
824
973
|
},
|
|
825
974
|
});
|
|
826
975
|
if (!component) {
|
|
827
|
-
throw new
|
|
976
|
+
throw new common_1.ForbiddenException('Access denied to this component');
|
|
828
977
|
}
|
|
829
978
|
let dashboardItem = await this.prismaService.dashboard_item.findFirst({
|
|
830
979
|
where: {
|
|
@@ -833,6 +982,16 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
833
982
|
},
|
|
834
983
|
});
|
|
835
984
|
if (!dashboardItem) {
|
|
985
|
+
const dashboardItems = await this.prismaService.dashboard_item.findMany({
|
|
986
|
+
where: {
|
|
987
|
+
dashboard_id: dashboard.id,
|
|
988
|
+
},
|
|
989
|
+
select: {
|
|
990
|
+
y_axis: true,
|
|
991
|
+
height: true,
|
|
992
|
+
},
|
|
993
|
+
});
|
|
994
|
+
const nextAvailableY = dashboardItems.reduce((maxY, item) => Math.max(maxY, item.y_axis + item.height), 0);
|
|
836
995
|
dashboardItem = await this.prismaService.dashboard_item.create({
|
|
837
996
|
data: {
|
|
838
997
|
dashboard_id: dashboard.id,
|
|
@@ -840,7 +999,7 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
840
999
|
width: component.width,
|
|
841
1000
|
height: component.height,
|
|
842
1001
|
x_axis: 0,
|
|
843
|
-
y_axis:
|
|
1002
|
+
y_axis: nextAvailableY,
|
|
844
1003
|
},
|
|
845
1004
|
});
|
|
846
1005
|
}
|
|
@@ -849,6 +1008,7 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
849
1008
|
i: `widget-${dashboardItem.id}`,
|
|
850
1009
|
component_id: component.id,
|
|
851
1010
|
slug: component.slug,
|
|
1011
|
+
library_slug: component.library_slug,
|
|
852
1012
|
name: (locale === null || locale === void 0 ? void 0 : locale.name) || component.slug,
|
|
853
1013
|
description: (locale === null || locale === void 0 ? void 0 : locale.description) || '',
|
|
854
1014
|
x: dashboardItem.x_axis,
|
|
@@ -863,7 +1023,43 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
863
1023
|
};
|
|
864
1024
|
}
|
|
865
1025
|
async removeWidgetFromUserDashboard(userId, slug, widgetId) {
|
|
866
|
-
|
|
1026
|
+
const dashboard = await this.prismaService.dashboard.findFirst({
|
|
1027
|
+
where: { slug },
|
|
1028
|
+
});
|
|
1029
|
+
if (!dashboard) {
|
|
1030
|
+
throw new Error(`Dashboard with slug '${slug}' not found`);
|
|
1031
|
+
}
|
|
1032
|
+
const canAccess = await this.prismaService.dashboard_user.findFirst({
|
|
1033
|
+
where: {
|
|
1034
|
+
dashboard_id: dashboard.id,
|
|
1035
|
+
user_id: userId,
|
|
1036
|
+
},
|
|
1037
|
+
select: { id: true },
|
|
1038
|
+
});
|
|
1039
|
+
if (!canAccess) {
|
|
1040
|
+
throw new common_1.ForbiddenException('Access denied to this dashboard');
|
|
1041
|
+
}
|
|
1042
|
+
const parsedWidgetId = Number(widgetId.replace(/^widget-/, ''));
|
|
1043
|
+
if (!Number.isInteger(parsedWidgetId) || parsedWidgetId <= 0) {
|
|
1044
|
+
throw new common_1.BadRequestException('Invalid widget id');
|
|
1045
|
+
}
|
|
1046
|
+
const dashboardItem = await this.prismaService.dashboard_item.findFirst({
|
|
1047
|
+
where: {
|
|
1048
|
+
id: parsedWidgetId,
|
|
1049
|
+
dashboard_id: dashboard.id,
|
|
1050
|
+
},
|
|
1051
|
+
select: { id: true },
|
|
1052
|
+
});
|
|
1053
|
+
if (!dashboardItem) {
|
|
1054
|
+
throw new common_1.BadRequestException('Widget not found in this dashboard');
|
|
1055
|
+
}
|
|
1056
|
+
await this.prismaService.dashboard_item.delete({
|
|
1057
|
+
where: { id: dashboardItem.id },
|
|
1058
|
+
});
|
|
1059
|
+
return {
|
|
1060
|
+
success: true,
|
|
1061
|
+
removedWidgetId: `widget-${dashboardItem.id}`,
|
|
1062
|
+
};
|
|
867
1063
|
}
|
|
868
1064
|
async checkDashboardAccess(userId, slug, locale) {
|
|
869
1065
|
var _a;
|
|
@@ -904,6 +1100,7 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
904
1100
|
};
|
|
905
1101
|
}
|
|
906
1102
|
async getUserDashboards(userId, locale) {
|
|
1103
|
+
await this.getHome(userId, locale);
|
|
907
1104
|
const dashboardUsers = await this.prismaService.dashboard_user.findMany({
|
|
908
1105
|
where: { user_id: userId },
|
|
909
1106
|
include: {
|
|
@@ -919,6 +1116,7 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
919
1116
|
},
|
|
920
1117
|
},
|
|
921
1118
|
},
|
|
1119
|
+
orderBy: [{ is_home: 'desc' }, { id: 'asc' }],
|
|
922
1120
|
});
|
|
923
1121
|
const uniqueByDashboardId = new Map();
|
|
924
1122
|
for (const dashboardUser of dashboardUsers) {
|
|
@@ -929,9 +1127,402 @@ let DashboardCoreService = DashboardCoreService_1 = class DashboardCoreService {
|
|
|
929
1127
|
return Array.from(uniqueByDashboardId.values()).map((dashboardUser) => ({
|
|
930
1128
|
id: dashboardUser.dashboard.id,
|
|
931
1129
|
slug: dashboardUser.dashboard.slug,
|
|
1130
|
+
name: this.getDashboardDisplayName(dashboardUser.dashboard),
|
|
1131
|
+
icon: dashboardUser.dashboard.icon,
|
|
1132
|
+
is_home: dashboardUser.is_home,
|
|
932
1133
|
dashboard_locale: dashboardUser.dashboard.dashboard_locale,
|
|
933
1134
|
}));
|
|
934
1135
|
}
|
|
1136
|
+
async getAvailableTemplates(userId, locale) {
|
|
1137
|
+
const userRoleIds = await this.getUserRoleIds(userId);
|
|
1138
|
+
const templateAccessFilter = userRoleIds.length > 0
|
|
1139
|
+
? {
|
|
1140
|
+
OR: [
|
|
1141
|
+
{
|
|
1142
|
+
dashboard_role: {
|
|
1143
|
+
some: {
|
|
1144
|
+
role_id: {
|
|
1145
|
+
in: userRoleIds,
|
|
1146
|
+
},
|
|
1147
|
+
},
|
|
1148
|
+
},
|
|
1149
|
+
},
|
|
1150
|
+
{
|
|
1151
|
+
dashboard_role: {
|
|
1152
|
+
none: {},
|
|
1153
|
+
},
|
|
1154
|
+
},
|
|
1155
|
+
],
|
|
1156
|
+
}
|
|
1157
|
+
: {
|
|
1158
|
+
dashboard_role: {
|
|
1159
|
+
none: {},
|
|
1160
|
+
},
|
|
1161
|
+
};
|
|
1162
|
+
const templates = await this.prismaService.dashboard.findMany({
|
|
1163
|
+
where: Object.assign({ is_template: true }, templateAccessFilter),
|
|
1164
|
+
include: {
|
|
1165
|
+
dashboard_locale: {
|
|
1166
|
+
where: {
|
|
1167
|
+
locale: {
|
|
1168
|
+
code: locale,
|
|
1169
|
+
},
|
|
1170
|
+
},
|
|
1171
|
+
},
|
|
1172
|
+
dashboard_item: {
|
|
1173
|
+
select: { id: true },
|
|
1174
|
+
},
|
|
1175
|
+
},
|
|
1176
|
+
orderBy: [{ id: 'asc' }],
|
|
1177
|
+
});
|
|
1178
|
+
return templates.map((template) => ({
|
|
1179
|
+
id: template.id,
|
|
1180
|
+
slug: template.slug,
|
|
1181
|
+
name: this.getDashboardDisplayName(template),
|
|
1182
|
+
icon: template.icon,
|
|
1183
|
+
itemCount: template.dashboard_item.length,
|
|
1184
|
+
}));
|
|
1185
|
+
}
|
|
1186
|
+
async createUserDashboard(userId, data, locale) {
|
|
1187
|
+
var _a, _b, _c, _d;
|
|
1188
|
+
const templateSlug = this.toNullableString(data === null || data === void 0 ? void 0 : data.templateSlug);
|
|
1189
|
+
const template = templateSlug
|
|
1190
|
+
? await this.getAccessibleTemplateOrThrow(userId, templateSlug, locale)
|
|
1191
|
+
: null;
|
|
1192
|
+
const templateName = template ? this.getDashboardDisplayName(template) : null;
|
|
1193
|
+
const name = this.toNullableString(data === null || data === void 0 ? void 0 : data.name) || templateName;
|
|
1194
|
+
if (!name) {
|
|
1195
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('validation.fieldRequired', locale, 'Dashboard name is required.'));
|
|
1196
|
+
}
|
|
1197
|
+
const requestedSlug = this.toNullableString(data === null || data === void 0 ? void 0 : data.slug);
|
|
1198
|
+
const baseSlug = this.slugifyDashboardName(requestedSlug || name);
|
|
1199
|
+
const slug = await this.buildUniqueDashboardSlug(baseSlug);
|
|
1200
|
+
const icon = (data === null || data === void 0 ? void 0 : data.icon) === undefined
|
|
1201
|
+
? (_a = template === null || template === void 0 ? void 0 : template.icon) !== null && _a !== void 0 ? _a : null
|
|
1202
|
+
: (_c = (_b = this.toNullableString(data === null || data === void 0 ? void 0 : data.icon)) !== null && _b !== void 0 ? _b : template === null || template === void 0 ? void 0 : template.icon) !== null && _c !== void 0 ? _c : null;
|
|
1203
|
+
const [localeRecord, existingCount] = await Promise.all([
|
|
1204
|
+
this.prismaService.locale.findFirst({
|
|
1205
|
+
where: { code: locale },
|
|
1206
|
+
select: { id: true },
|
|
1207
|
+
}),
|
|
1208
|
+
this.prismaService.dashboard_user.count({
|
|
1209
|
+
where: { user_id: userId },
|
|
1210
|
+
}),
|
|
1211
|
+
]);
|
|
1212
|
+
const dashboard = await this.prismaService.dashboard.create({
|
|
1213
|
+
data: {
|
|
1214
|
+
slug,
|
|
1215
|
+
icon,
|
|
1216
|
+
},
|
|
1217
|
+
});
|
|
1218
|
+
if (localeRecord) {
|
|
1219
|
+
await this.prismaService.dashboard_locale.create({
|
|
1220
|
+
data: {
|
|
1221
|
+
dashboard_id: dashboard.id,
|
|
1222
|
+
locale_id: localeRecord.id,
|
|
1223
|
+
name,
|
|
1224
|
+
},
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
await this.prismaService.dashboard_user.create({
|
|
1228
|
+
data: {
|
|
1229
|
+
dashboard_id: dashboard.id,
|
|
1230
|
+
user_id: userId,
|
|
1231
|
+
is_home: existingCount === 0,
|
|
1232
|
+
},
|
|
1233
|
+
});
|
|
1234
|
+
if ((_d = template === null || template === void 0 ? void 0 : template.dashboard_item) === null || _d === void 0 ? void 0 : _d.length) {
|
|
1235
|
+
await this.prismaService.dashboard_item.createMany({
|
|
1236
|
+
data: template.dashboard_item.map((item) => ({
|
|
1237
|
+
dashboard_id: dashboard.id,
|
|
1238
|
+
component_id: item.component_id,
|
|
1239
|
+
width: item.width,
|
|
1240
|
+
height: item.height,
|
|
1241
|
+
x_axis: item.x_axis,
|
|
1242
|
+
y_axis: item.y_axis,
|
|
1243
|
+
})),
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
return {
|
|
1247
|
+
id: dashboard.id,
|
|
1248
|
+
slug,
|
|
1249
|
+
name,
|
|
1250
|
+
icon,
|
|
1251
|
+
is_home: existingCount === 0,
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
async renameUserDashboard(userId, slug, data, locale) {
|
|
1255
|
+
var _a, _b;
|
|
1256
|
+
const dashboardUser = await this.getDashboardUserOrThrow(userId, slug, locale);
|
|
1257
|
+
const name = this.toNullableString(data === null || data === void 0 ? void 0 : data.name);
|
|
1258
|
+
const normalizedIcon = (data === null || data === void 0 ? void 0 : data.icon) === undefined ? undefined : this.toNullableString(data === null || data === void 0 ? void 0 : data.icon);
|
|
1259
|
+
if (!name && (data === null || data === void 0 ? void 0 : data.icon) === undefined) {
|
|
1260
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('validation.fieldRequired', locale, 'Dashboard name or icon is required.'));
|
|
1261
|
+
}
|
|
1262
|
+
if ((data === null || data === void 0 ? void 0 : data.icon) !== undefined) {
|
|
1263
|
+
await this.prismaService.dashboard.update({
|
|
1264
|
+
where: { id: dashboardUser.dashboard_id },
|
|
1265
|
+
data: {
|
|
1266
|
+
icon: normalizedIcon !== null && normalizedIcon !== void 0 ? normalizedIcon : null,
|
|
1267
|
+
},
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
if (name) {
|
|
1271
|
+
const localeRecord = await this.prismaService.locale.findFirst({
|
|
1272
|
+
where: { code: locale },
|
|
1273
|
+
select: { id: true },
|
|
1274
|
+
});
|
|
1275
|
+
if (!localeRecord) {
|
|
1276
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('localeNotFound', locale, 'Locale not found.'));
|
|
1277
|
+
}
|
|
1278
|
+
const existingLocale = await this.prismaService.dashboard_locale.findFirst({
|
|
1279
|
+
where: {
|
|
1280
|
+
dashboard_id: dashboardUser.dashboard_id,
|
|
1281
|
+
locale_id: localeRecord.id,
|
|
1282
|
+
},
|
|
1283
|
+
select: { id: true },
|
|
1284
|
+
});
|
|
1285
|
+
if (existingLocale) {
|
|
1286
|
+
await this.prismaService.dashboard_locale.update({
|
|
1287
|
+
where: { id: existingLocale.id },
|
|
1288
|
+
data: { name },
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
else {
|
|
1292
|
+
await this.prismaService.dashboard_locale.create({
|
|
1293
|
+
data: {
|
|
1294
|
+
dashboard_id: dashboardUser.dashboard_id,
|
|
1295
|
+
locale_id: localeRecord.id,
|
|
1296
|
+
name,
|
|
1297
|
+
},
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
const updatedDashboard = await this.prismaService.dashboard.findUnique({
|
|
1302
|
+
where: { id: dashboardUser.dashboard_id },
|
|
1303
|
+
include: {
|
|
1304
|
+
dashboard_locale: {
|
|
1305
|
+
where: {
|
|
1306
|
+
locale: {
|
|
1307
|
+
code: locale,
|
|
1308
|
+
},
|
|
1309
|
+
},
|
|
1310
|
+
},
|
|
1311
|
+
},
|
|
1312
|
+
});
|
|
1313
|
+
return {
|
|
1314
|
+
success: true,
|
|
1315
|
+
slug,
|
|
1316
|
+
name: name ||
|
|
1317
|
+
(updatedDashboard
|
|
1318
|
+
? this.getDashboardDisplayName(updatedDashboard)
|
|
1319
|
+
: slug),
|
|
1320
|
+
icon: (_b = (_a = updatedDashboard === null || updatedDashboard === void 0 ? void 0 : updatedDashboard.icon) !== null && _a !== void 0 ? _a : normalizedIcon) !== null && _b !== void 0 ? _b : null,
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
async setHomeDashboard(userId, slug, locale) {
|
|
1324
|
+
const dashboardUser = await this.getDashboardUserOrThrow(userId, slug, locale);
|
|
1325
|
+
await this.prismaService.dashboard_user.updateMany({
|
|
1326
|
+
where: { user_id: userId },
|
|
1327
|
+
data: { is_home: false },
|
|
1328
|
+
});
|
|
1329
|
+
await this.prismaService.dashboard_user.update({
|
|
1330
|
+
where: { id: dashboardUser.id },
|
|
1331
|
+
data: { is_home: true },
|
|
1332
|
+
});
|
|
1333
|
+
return {
|
|
1334
|
+
success: true,
|
|
1335
|
+
slug,
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1338
|
+
async getDashboardShares(userId, slug, locale) {
|
|
1339
|
+
const dashboardUser = await this.getDashboardUserOrThrow(userId, slug, locale);
|
|
1340
|
+
const sharedUsers = await this.prismaService.dashboard_user.findMany({
|
|
1341
|
+
where: {
|
|
1342
|
+
dashboard_id: dashboardUser.dashboard_id,
|
|
1343
|
+
},
|
|
1344
|
+
include: {
|
|
1345
|
+
user: {
|
|
1346
|
+
select: {
|
|
1347
|
+
id: true,
|
|
1348
|
+
name: true,
|
|
1349
|
+
user_identifier: {
|
|
1350
|
+
where: {
|
|
1351
|
+
type: 'email',
|
|
1352
|
+
},
|
|
1353
|
+
select: {
|
|
1354
|
+
value: true,
|
|
1355
|
+
},
|
|
1356
|
+
take: 1,
|
|
1357
|
+
},
|
|
1358
|
+
},
|
|
1359
|
+
},
|
|
1360
|
+
},
|
|
1361
|
+
orderBy: {
|
|
1362
|
+
id: 'asc',
|
|
1363
|
+
},
|
|
1364
|
+
});
|
|
1365
|
+
return sharedUsers.map((sharedDashboardUser) => {
|
|
1366
|
+
var _a, _b;
|
|
1367
|
+
return ({
|
|
1368
|
+
id: sharedDashboardUser.user.id,
|
|
1369
|
+
name: sharedDashboardUser.user.name,
|
|
1370
|
+
email: (_b = (_a = sharedDashboardUser.user.user_identifier[0]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : null,
|
|
1371
|
+
isCurrentUser: sharedDashboardUser.user.id === userId,
|
|
1372
|
+
isHome: sharedDashboardUser.is_home,
|
|
1373
|
+
});
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
async getShareableUsers(userId, slug, search, locale) {
|
|
1377
|
+
const dashboardUser = await this.getDashboardUserOrThrow(userId, slug, locale);
|
|
1378
|
+
const normalizedSearch = this.toNullableString(search);
|
|
1379
|
+
const existingUsers = await this.prismaService.dashboard_user.findMany({
|
|
1380
|
+
where: {
|
|
1381
|
+
dashboard_id: dashboardUser.dashboard_id,
|
|
1382
|
+
},
|
|
1383
|
+
select: {
|
|
1384
|
+
user_id: true,
|
|
1385
|
+
},
|
|
1386
|
+
});
|
|
1387
|
+
const users = await this.prismaService.user.findMany({
|
|
1388
|
+
where: Object.assign({ id: {
|
|
1389
|
+
notIn: existingUsers.map((item) => item.user_id),
|
|
1390
|
+
} }, (normalizedSearch
|
|
1391
|
+
? {
|
|
1392
|
+
OR: [
|
|
1393
|
+
{
|
|
1394
|
+
name: {
|
|
1395
|
+
contains: normalizedSearch,
|
|
1396
|
+
mode: 'insensitive',
|
|
1397
|
+
},
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
user_identifier: {
|
|
1401
|
+
some: {
|
|
1402
|
+
type: 'email',
|
|
1403
|
+
value: {
|
|
1404
|
+
contains: normalizedSearch,
|
|
1405
|
+
mode: 'insensitive',
|
|
1406
|
+
},
|
|
1407
|
+
},
|
|
1408
|
+
},
|
|
1409
|
+
},
|
|
1410
|
+
],
|
|
1411
|
+
}
|
|
1412
|
+
: {})),
|
|
1413
|
+
select: {
|
|
1414
|
+
id: true,
|
|
1415
|
+
name: true,
|
|
1416
|
+
user_identifier: {
|
|
1417
|
+
where: {
|
|
1418
|
+
type: 'email',
|
|
1419
|
+
},
|
|
1420
|
+
select: {
|
|
1421
|
+
value: true,
|
|
1422
|
+
},
|
|
1423
|
+
take: 1,
|
|
1424
|
+
},
|
|
1425
|
+
},
|
|
1426
|
+
take: 20,
|
|
1427
|
+
orderBy: {
|
|
1428
|
+
id: 'desc',
|
|
1429
|
+
},
|
|
1430
|
+
});
|
|
1431
|
+
return users.map((candidateUser) => {
|
|
1432
|
+
var _a, _b;
|
|
1433
|
+
return ({
|
|
1434
|
+
id: candidateUser.id,
|
|
1435
|
+
name: candidateUser.name,
|
|
1436
|
+
email: (_b = (_a = candidateUser.user_identifier[0]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : null,
|
|
1437
|
+
});
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1440
|
+
async shareDashboard(userId, slug, sharedUserId, locale) {
|
|
1441
|
+
if (!sharedUserId || Number.isNaN(Number(sharedUserId))) {
|
|
1442
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('validation.fieldRequired', locale, 'User is required.'));
|
|
1443
|
+
}
|
|
1444
|
+
const dashboardUser = await this.getDashboardUserOrThrow(userId, slug, locale);
|
|
1445
|
+
if (sharedUserId === userId) {
|
|
1446
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('validation.invalidValue', locale, 'You already have access to this dashboard.'));
|
|
1447
|
+
}
|
|
1448
|
+
const targetUser = await this.prismaService.user.findUnique({
|
|
1449
|
+
where: { id: sharedUserId },
|
|
1450
|
+
select: { id: true },
|
|
1451
|
+
});
|
|
1452
|
+
if (!targetUser) {
|
|
1453
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('userNotFound', locale, 'User not found.'));
|
|
1454
|
+
}
|
|
1455
|
+
const existingShare = await this.prismaService.dashboard_user.findFirst({
|
|
1456
|
+
where: {
|
|
1457
|
+
dashboard_id: dashboardUser.dashboard_id,
|
|
1458
|
+
user_id: sharedUserId,
|
|
1459
|
+
},
|
|
1460
|
+
select: { id: true },
|
|
1461
|
+
});
|
|
1462
|
+
if (existingShare) {
|
|
1463
|
+
return {
|
|
1464
|
+
success: true,
|
|
1465
|
+
alreadyShared: true,
|
|
1466
|
+
};
|
|
1467
|
+
}
|
|
1468
|
+
await this.prismaService.dashboard_user.create({
|
|
1469
|
+
data: {
|
|
1470
|
+
dashboard_id: dashboardUser.dashboard_id,
|
|
1471
|
+
user_id: sharedUserId,
|
|
1472
|
+
is_home: false,
|
|
1473
|
+
},
|
|
1474
|
+
});
|
|
1475
|
+
return {
|
|
1476
|
+
success: true,
|
|
1477
|
+
};
|
|
1478
|
+
}
|
|
1479
|
+
async revokeDashboardShare(userId, slug, sharedUserId, locale) {
|
|
1480
|
+
const dashboardUser = await this.getDashboardUserOrThrow(userId, slug, locale);
|
|
1481
|
+
if (sharedUserId === userId) {
|
|
1482
|
+
throw new common_1.BadRequestException((0, api_locale_1.getLocaleText)('validation.invalidValue', locale, 'Use the remove dashboard action to leave this tab.'));
|
|
1483
|
+
}
|
|
1484
|
+
await this.prismaService.dashboard_user.deleteMany({
|
|
1485
|
+
where: {
|
|
1486
|
+
dashboard_id: dashboardUser.dashboard_id,
|
|
1487
|
+
user_id: sharedUserId,
|
|
1488
|
+
},
|
|
1489
|
+
});
|
|
1490
|
+
return {
|
|
1491
|
+
success: true,
|
|
1492
|
+
};
|
|
1493
|
+
}
|
|
1494
|
+
async removeUserDashboard(userId, slug, locale) {
|
|
1495
|
+
const dashboardUser = await this.getDashboardUserOrThrow(userId, slug, locale);
|
|
1496
|
+
await this.prismaService.dashboard_user.delete({
|
|
1497
|
+
where: { id: dashboardUser.id },
|
|
1498
|
+
});
|
|
1499
|
+
if (dashboardUser.is_home) {
|
|
1500
|
+
const nextDashboard = await this.prismaService.dashboard_user.findFirst({
|
|
1501
|
+
where: { user_id: userId },
|
|
1502
|
+
orderBy: { id: 'asc' },
|
|
1503
|
+
});
|
|
1504
|
+
if (nextDashboard) {
|
|
1505
|
+
await this.prismaService.dashboard_user.update({
|
|
1506
|
+
where: { id: nextDashboard.id },
|
|
1507
|
+
data: { is_home: true },
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
const remainingShares = await this.prismaService.dashboard_user.count({
|
|
1512
|
+
where: {
|
|
1513
|
+
dashboard_id: dashboardUser.dashboard_id,
|
|
1514
|
+
},
|
|
1515
|
+
});
|
|
1516
|
+
if (remainingShares === 0) {
|
|
1517
|
+
await this.prismaService.dashboard.delete({
|
|
1518
|
+
where: { id: dashboardUser.dashboard_id },
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1521
|
+
return {
|
|
1522
|
+
success: true,
|
|
1523
|
+
removedSlug: slug,
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
935
1526
|
async getAccountSecurity(userId) {
|
|
936
1527
|
const now = new Date();
|
|
937
1528
|
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|