@hed-hog/core 0.0.151 → 0.0.153
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 +214 -9
- package/dist/dashboard/dashboard/dashboard.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard/dashboard.controller.js +35 -35
- package/dist/dashboard/dashboard/dashboard.controller.js.map +1 -1
- package/dist/dashboard/dashboard/dashboard.module.d.ts +1 -1
- package/dist/dashboard/dashboard/dashboard.module.d.ts.map +1 -1
- package/dist/dashboard/dashboard/dashboard.module.js +11 -6
- package/dist/dashboard/dashboard/dashboard.module.js.map +1 -1
- package/dist/dashboard/dashboard/dashboard.service.d.ts +217 -16
- package/dist/dashboard/dashboard/dashboard.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard/dashboard.service.js +115 -28
- package/dist/dashboard/dashboard/dashboard.service.js.map +1 -1
- package/dist/dashboard/dashboard/dto/create.dto.d.ts +4 -2
- package/dist/dashboard/dashboard/dto/create.dto.d.ts.map +1 -1
- package/dist/dashboard/dashboard/dto/create.dto.js +10 -1
- package/dist/dashboard/dashboard/dto/create.dto.js.map +1 -1
- package/dist/dashboard/dashboard/dto/index.d.ts +5 -0
- package/dist/dashboard/dashboard/dto/index.d.ts.map +1 -0
- package/dist/dashboard/dashboard/dto/index.js +25 -0
- package/dist/dashboard/dashboard/dto/index.js.map +1 -0
- package/dist/dashboard/dashboard/dto/update.dto.d.ts +5 -4
- package/dist/dashboard/dashboard/dto/update.dto.d.ts.map +1 -1
- package/dist/dashboard/dashboard/dto/update.dto.js +27 -3
- package/dist/dashboard/dashboard/dto/update.dto.js.map +1 -1
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +114 -9
- package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component/dashboard-component.controller.js +35 -36
- package/dist/dashboard/dashboard-component/dashboard-component.controller.js.map +1 -1
- package/dist/dashboard/dashboard-component/dashboard-component.module.js +4 -3
- package/dist/dashboard/dashboard-component/dashboard-component.module.js.map +1 -1
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +116 -15
- package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component/dashboard-component.service.js +109 -22
- package/dist/dashboard/dashboard-component/dashboard-component.service.js.map +1 -1
- package/dist/dashboard/dashboard-component/dto/create.dto.d.ts +4 -2
- package/dist/dashboard/dashboard-component/dto/create.dto.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component/dto/create.dto.js +10 -1
- package/dist/dashboard/dashboard-component/dto/create.dto.js.map +1 -1
- package/dist/dashboard/dashboard-component/dto/index.d.ts +5 -0
- package/dist/dashboard/dashboard-component/dto/index.d.ts.map +1 -0
- package/dist/dashboard/dashboard-component/dto/index.js +25 -0
- package/dist/dashboard/dashboard-component/dto/index.js.map +1 -0
- package/dist/dashboard/dashboard-component/dto/update.dto.d.ts +13 -4
- package/dist/dashboard/dashboard-component/dto/update.dto.d.ts.map +1 -1
- package/dist/dashboard/dashboard-component/dto/update.dto.js +67 -3
- package/dist/dashboard/dashboard-component/dto/update.dto.js.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +56 -0
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.controller.js +65 -0
- package/dist/dashboard/dashboard-core/dashboard-core.controller.js.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +52 -0
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.js +221 -0
- package/dist/dashboard/dashboard-core/dashboard-core.service.js.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts +26 -29
- package/dist/dashboard/dashboard-item/dashboard-item.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.controller.js +24 -43
- package/dist/dashboard/dashboard-item/dashboard-item.controller.js.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts +30 -34
- package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-item/dashboard-item.service.js +51 -35
- package/dist/dashboard/dashboard-item/dashboard-item.service.js.map +1 -1
- package/dist/dashboard/dashboard-item/dto/index.d.ts +5 -0
- package/dist/dashboard/dashboard-item/dto/index.d.ts.map +1 -0
- package/dist/dashboard/dashboard-item/dto/index.js +25 -0
- package/dist/dashboard/dashboard-item/dto/index.js.map +1 -0
- package/dist/dashboard/dashboard-item/dto/update.dto.d.ts +7 -4
- package/dist/dashboard/dashboard-item/dto/update.dto.d.ts.map +1 -1
- package/dist/dashboard/dashboard-item/dto/update.dto.js +42 -3
- package/dist/dashboard/dashboard-item/dto/update.dto.js.map +1 -1
- package/dist/dashboard/dashboard.module.js +1 -1
- package/dist/dashboard/dashboard.module.js.map +1 -1
- package/dist/oauth/oauth.controller.d.ts.map +1 -1
- package/dist/oauth/oauth.controller.js.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
- package/dist/oauth/providers/microsoft-entra-id.provider.js +7 -4
- package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +1 -0
- package/dist/setting/setting.service.js.map +1 -1
- package/hedhog/data/route.yaml +44 -14
- package/hedhog/data/setting_group.yaml +10 -0
- package/hedhog/query/dashboard-seed.sql +131 -0
- package/package.json +1 -1
- package/src/dashboard/dashboard/dashboard.controller.ts +26 -23
- package/src/dashboard/dashboard/dashboard.module.ts +7 -2
- package/src/dashboard/dashboard/dashboard.service.ts +125 -44
- package/src/dashboard/dashboard/dto/create.dto.ts +12 -3
- package/src/dashboard/dashboard/dto/index.ts +7 -0
- package/src/dashboard/dashboard/dto/update.dto.ts +17 -3
- package/src/dashboard/dashboard-component/dashboard-component.controller.ts +22 -19
- package/src/dashboard/dashboard-component/dashboard-component.module.ts +3 -3
- package/src/dashboard/dashboard-component/dashboard-component.service.ts +128 -39
- package/src/dashboard/dashboard-component/dto/create.dto.ts +12 -3
- package/src/dashboard/dashboard-component/dto/index.ts +7 -0
- package/src/dashboard/dashboard-component/dto/update.dto.ts +49 -3
- package/src/dashboard/dashboard-core/dashboard-core.controller.ts +53 -2
- package/src/dashboard/dashboard-core/dashboard-core.service.ts +271 -0
- package/src/dashboard/dashboard-item/dashboard-item.controller.ts +17 -26
- package/src/dashboard/dashboard-item/dashboard-item.service.ts +55 -47
- package/src/dashboard/dashboard-item/dto/index.ts +7 -0
- package/src/dashboard/dashboard-item/dto/update.dto.ts +27 -3
- package/src/dashboard/dashboard.module.ts +2 -2
- package/src/language/en.json +4 -1
- package/src/language/pt.json +4 -1
- package/src/oauth/oauth.controller.ts +1 -2
- package/src/oauth/providers/microsoft-entra-id.provider.ts +9 -4
- package/src/setting/setting.service.ts +1 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import { LocaleModule } from '@hed-hog/api-locale';
|
|
1
2
|
import { PaginationModule } from '@hed-hog/api-pagination';
|
|
2
3
|
import { PrismaModule } from '@hed-hog/api-prisma';
|
|
3
|
-
import { LocaleModule } from '@hed-hog/api-locale';
|
|
4
4
|
import { forwardRef, Module } from '@nestjs/common';
|
|
5
|
-
import { DashboardComponentService } from './dashboard-component.service';
|
|
6
5
|
import { DashboardComponentController } from './dashboard-component.controller';
|
|
6
|
+
import { DashboardComponentService } from './dashboard-component.service';
|
|
7
7
|
|
|
8
8
|
@Module({
|
|
9
|
-
imports: [forwardRef(() => LocaleModule), forwardRef(() => PrismaModule)],
|
|
9
|
+
imports: [forwardRef(() => LocaleModule), forwardRef(() => PaginationModule), forwardRef(() => PrismaModule)],
|
|
10
10
|
controllers: [DashboardComponentController],
|
|
11
11
|
providers: [DashboardComponentService],
|
|
12
12
|
exports: [DashboardComponentService],
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getLocaleText } from '@hed-hog/api-locale';
|
|
2
|
+
import { PaginationService } from '@hed-hog/api-pagination';
|
|
2
3
|
import { PrismaService } from '@hed-hog/api-prisma';
|
|
3
4
|
import {
|
|
4
|
-
|
|
5
|
+
forwardRef,
|
|
5
6
|
Inject,
|
|
6
7
|
Injectable,
|
|
7
|
-
|
|
8
|
+
NotFoundException
|
|
8
9
|
} from '@nestjs/common';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import {
|
|
11
|
+
CreateDashboardComponentDTO,
|
|
12
|
+
UpdateDashboardComponentDTO,
|
|
13
|
+
} from './dto';
|
|
14
14
|
@Injectable()
|
|
15
15
|
export class DashboardComponentService {
|
|
16
16
|
private readonly modelName = 'dashboard_component';
|
|
@@ -19,52 +19,141 @@ export class DashboardComponentService {
|
|
|
19
19
|
constructor(
|
|
20
20
|
@Inject(forwardRef(() => PrismaService))
|
|
21
21
|
private readonly prismaService: PrismaService,
|
|
22
|
-
@Inject(forwardRef(() =>
|
|
23
|
-
private readonly
|
|
22
|
+
@Inject(forwardRef(() => PaginationService))
|
|
23
|
+
private readonly paginationService: PaginationService,
|
|
24
24
|
) {}
|
|
25
25
|
|
|
26
|
-
async
|
|
27
|
-
return this.
|
|
28
|
-
|
|
29
|
-
this.modelName,
|
|
26
|
+
async getAllComponents(paginationParams) {
|
|
27
|
+
return this.paginationService.paginate(
|
|
28
|
+
this.prismaService.dashboard_component,
|
|
30
29
|
paginationParams,
|
|
30
|
+
{
|
|
31
|
+
include: {
|
|
32
|
+
dashboard_component_locale: {
|
|
33
|
+
include: {
|
|
34
|
+
locale: true,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
orderBy: {
|
|
39
|
+
created_at: 'desc',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
'dashboardComponent',
|
|
31
43
|
);
|
|
32
44
|
}
|
|
33
45
|
|
|
34
|
-
async
|
|
35
|
-
|
|
46
|
+
async getComponent(id: number, locale: string) {
|
|
47
|
+
const component = await this.prismaService.dashboard_component.findUnique({
|
|
48
|
+
where: { id },
|
|
49
|
+
include: {
|
|
50
|
+
dashboard_component_locale: {
|
|
51
|
+
include: {
|
|
52
|
+
locale: true,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (!component) {
|
|
59
|
+
throw new NotFoundException(
|
|
60
|
+
getLocaleText('dashboardComponentNotFound', locale, 'Dashboard component not found'),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return component;
|
|
36
65
|
}
|
|
37
66
|
|
|
38
|
-
async
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
67
|
+
async createComponent(data: CreateDashboardComponentDTO, locale: string) {
|
|
68
|
+
const component = await this.prismaService.dashboard_component.create({
|
|
69
|
+
data: {
|
|
70
|
+
slug: data.slug,
|
|
71
|
+
path: data.path,
|
|
72
|
+
min_width: data.min_width,
|
|
73
|
+
max_width: data.max_width,
|
|
74
|
+
min_height: data.min_height,
|
|
75
|
+
max_height: data.max_height,
|
|
76
|
+
width: data.width,
|
|
77
|
+
height: data.height,
|
|
78
|
+
is_resizable: data.is_resizable ?? true,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (data.locale) {
|
|
83
|
+
for (const [localeCode, localeData] of Object.entries(data.locale)) {
|
|
84
|
+
const localeRecord = await this.prismaService.locale.findFirst({
|
|
85
|
+
where: { code: localeCode },
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (localeRecord) {
|
|
89
|
+
await this.prismaService.dashboard_component_locale.create({
|
|
90
|
+
data: {
|
|
91
|
+
dashboard_component_id: component.id,
|
|
92
|
+
locale_id: localeRecord.id,
|
|
93
|
+
name: localeData.name,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return this.getComponent(component.id, locale);
|
|
44
101
|
}
|
|
45
102
|
|
|
46
|
-
async
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
103
|
+
async updateComponent(id: number, data: UpdateDashboardComponentDTO, locale: string) {
|
|
104
|
+
await this.prismaService.dashboard_component.update({
|
|
105
|
+
where: { id },
|
|
106
|
+
data: {
|
|
107
|
+
slug: data.slug,
|
|
108
|
+
path: data.path,
|
|
109
|
+
min_width: data.min_width,
|
|
110
|
+
max_width: data.max_width,
|
|
111
|
+
min_height: data.min_height,
|
|
112
|
+
max_height: data.max_height,
|
|
113
|
+
width: data.width,
|
|
114
|
+
height: data.height,
|
|
115
|
+
is_resizable: data.is_resizable,
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
if (data.locale) {
|
|
120
|
+
await this.prismaService.dashboard_component_locale.deleteMany({
|
|
121
|
+
where: { dashboard_component_id: id },
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
for (const [localeCode, localeData] of Object.entries(data.locale)) {
|
|
125
|
+
const localeRecord = await this.prismaService.locale.findFirst({
|
|
126
|
+
where: { code: localeCode },
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
if (localeRecord) {
|
|
130
|
+
await this.prismaService.dashboard_component_locale.create({
|
|
131
|
+
data: {
|
|
132
|
+
dashboard_component_id: id,
|
|
133
|
+
locale_id: localeRecord.id,
|
|
134
|
+
name: localeData.name,
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return this.getComponent(id, locale);
|
|
53
142
|
}
|
|
54
143
|
|
|
55
|
-
async
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
144
|
+
async deleteComponent(id: number, locale: string) {
|
|
145
|
+
const component = await this.prismaService.dashboard_component.findUnique({
|
|
146
|
+
where: { id },
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (!component) {
|
|
150
|
+
throw new NotFoundException(
|
|
151
|
+
getLocaleText('dashboardComponentNotFound', locale, 'Dashboard component not found'),
|
|
59
152
|
);
|
|
60
153
|
}
|
|
61
154
|
|
|
62
|
-
return this.prismaService.dashboard_component.
|
|
63
|
-
where: {
|
|
64
|
-
id: {
|
|
65
|
-
in: ids,
|
|
66
|
-
},
|
|
67
|
-
},
|
|
155
|
+
return this.prismaService.dashboard_component.delete({
|
|
156
|
+
where: { id },
|
|
68
157
|
});
|
|
69
158
|
}
|
|
70
159
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { getLocaleText
|
|
2
|
-
import { IsBoolean, IsNumber, IsOptional, IsString } from 'class-validator';
|
|
1
|
+
import { getLocaleText } from '@hed-hog/api-locale';
|
|
2
|
+
import { IsBoolean, IsNotEmpty, IsNumber, IsObject, IsOptional, IsString } from 'class-validator';
|
|
3
3
|
|
|
4
|
-
export class CreateDTO
|
|
4
|
+
export class CreateDTO {
|
|
5
5
|
@IsString({ message: (args) => getLocaleText('validation.stringRequired', args.value) })
|
|
6
6
|
slug: string;
|
|
7
7
|
|
|
@@ -33,4 +33,13 @@ export class CreateDTO extends WithLocaleDTO {
|
|
|
33
33
|
@IsOptional()
|
|
34
34
|
@IsBoolean({ message: (args) => getLocaleText('validation.booleanRequired', args.value) })
|
|
35
35
|
is_resizable?: boolean;
|
|
36
|
+
|
|
37
|
+
@IsObject({
|
|
38
|
+
message: (args) =>
|
|
39
|
+
getLocaleText('validation.localeMustBeObject', args.value),
|
|
40
|
+
})
|
|
41
|
+
@IsNotEmpty({
|
|
42
|
+
message: (args) => getLocaleText('validation.localeRequired', args.value),
|
|
43
|
+
})
|
|
44
|
+
locale: Record<string, { name: string }>;
|
|
36
45
|
}
|
|
@@ -1,4 +1,50 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { getLocaleText } from '@hed-hog/api-locale';
|
|
2
|
+
import { IsBoolean, IsNotEmpty, IsNumber, IsObject, IsOptional, IsString } from 'class-validator';
|
|
3
3
|
|
|
4
|
-
export class UpdateDTO
|
|
4
|
+
export class UpdateDTO {
|
|
5
|
+
@IsOptional()
|
|
6
|
+
@IsString({ message: (args) => getLocaleText('validation.stringRequired', args.value) })
|
|
7
|
+
slug?: string;
|
|
8
|
+
|
|
9
|
+
@IsOptional()
|
|
10
|
+
@IsString({ message: (args) => getLocaleText('validation.stringRequired', args.value) })
|
|
11
|
+
path?: string;
|
|
12
|
+
|
|
13
|
+
@IsOptional()
|
|
14
|
+
@IsNumber({}, { message: (args) => getLocaleText('validation.numberRequired', args.value) })
|
|
15
|
+
min_width?: number;
|
|
16
|
+
|
|
17
|
+
@IsOptional()
|
|
18
|
+
@IsNumber({}, { message: (args) => getLocaleText('validation.numberRequired', args.value) })
|
|
19
|
+
max_width?: number;
|
|
20
|
+
|
|
21
|
+
@IsOptional()
|
|
22
|
+
@IsNumber({}, { message: (args) => getLocaleText('validation.numberRequired', args.value) })
|
|
23
|
+
min_height?: number;
|
|
24
|
+
|
|
25
|
+
@IsOptional()
|
|
26
|
+
@IsNumber({}, { message: (args) => getLocaleText('validation.numberRequired', args.value) })
|
|
27
|
+
max_height?: number;
|
|
28
|
+
|
|
29
|
+
@IsOptional()
|
|
30
|
+
@IsNumber({}, { message: (args) => getLocaleText('validation.numberRequired', args.value) })
|
|
31
|
+
width?: number;
|
|
32
|
+
|
|
33
|
+
@IsOptional()
|
|
34
|
+
@IsNumber({}, { message: (args) => getLocaleText('validation.numberRequired', args.value) })
|
|
35
|
+
height?: number;
|
|
36
|
+
|
|
37
|
+
@IsOptional()
|
|
38
|
+
@IsBoolean({ message: (args) => getLocaleText('validation.booleanRequired', args.value) })
|
|
39
|
+
is_resizable?: boolean;
|
|
40
|
+
|
|
41
|
+
@IsOptional()
|
|
42
|
+
@IsObject({
|
|
43
|
+
message: (args) =>
|
|
44
|
+
getLocaleText('validation.localeMustBeObject', args.value),
|
|
45
|
+
})
|
|
46
|
+
@IsNotEmpty({
|
|
47
|
+
message: (args) => getLocaleText('validation.localeRequired', args.value),
|
|
48
|
+
})
|
|
49
|
+
locale?: Record<string, { name: string }>;
|
|
50
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Role } from '@hed-hog/api';
|
|
1
|
+
import { Role, User } from '@hed-hog/api';
|
|
2
2
|
import { Locale } from '@hed-hog/api-locale';
|
|
3
|
-
import { Controller, Get, Param } from '@nestjs/common';
|
|
3
|
+
import { Body, Controller, Delete, Get, Param, Post } from '@nestjs/common';
|
|
4
4
|
import { DashboardCoreService } from './dashboard-core.service';
|
|
5
|
+
|
|
5
6
|
@Role()
|
|
6
7
|
@Controller('dashboard-core')
|
|
7
8
|
export class DashboardCoreController {
|
|
@@ -11,4 +12,54 @@ export class DashboardCoreController {
|
|
|
11
12
|
fromSlug(@Param('slug') slug: string, @Locale() locale) {
|
|
12
13
|
return this.dashboardCoreService.fromSlug(slug, locale);
|
|
13
14
|
}
|
|
15
|
+
|
|
16
|
+
@Get('stats/overview')
|
|
17
|
+
getStatistics() {
|
|
18
|
+
return this.dashboardCoreService.getStatistics();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@Get('stats/user-growth')
|
|
22
|
+
getUserGrowth() {
|
|
23
|
+
return this.dashboardCoreService.getUserGrowth();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Get('layout/:slug')
|
|
27
|
+
getUserLayout(@User() user, @Param('slug') slug: string) {
|
|
28
|
+
return this.dashboardCoreService.getUserLayout(user.id, slug);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Post('layout/:slug')
|
|
32
|
+
saveUserLayout(
|
|
33
|
+
@User() user,
|
|
34
|
+
@Param('slug') slug: string,
|
|
35
|
+
@Body() body: { layout: Array<{ i: string; x: number; y: number; w: number; h: number }> },
|
|
36
|
+
) {
|
|
37
|
+
return this.dashboardCoreService.saveUserLayout(user.id, slug, body.layout);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Post('widget/:slug')
|
|
41
|
+
addWidget(
|
|
42
|
+
@User() user,
|
|
43
|
+
@Param('slug') slug: string,
|
|
44
|
+
@Body() body: { componentSlug: string },
|
|
45
|
+
) {
|
|
46
|
+
return this.dashboardCoreService.addWidgetToUserDashboard(
|
|
47
|
+
user.id,
|
|
48
|
+
slug,
|
|
49
|
+
body.componentSlug,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Delete('widget/:slug/:widgetId')
|
|
54
|
+
removeWidget(
|
|
55
|
+
@User() user,
|
|
56
|
+
@Param('slug') slug: string,
|
|
57
|
+
@Param('widgetId') widgetId: string,
|
|
58
|
+
) {
|
|
59
|
+
return this.dashboardCoreService.removeWidgetFromUserDashboard(
|
|
60
|
+
user.id,
|
|
61
|
+
slug,
|
|
62
|
+
widgetId,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
14
65
|
}
|
|
@@ -24,4 +24,275 @@ export class DashboardCoreService {
|
|
|
24
24
|
},
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
async getStatistics() {
|
|
29
|
+
const now = new Date();
|
|
30
|
+
const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
31
|
+
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
32
|
+
|
|
33
|
+
// Total de usuários
|
|
34
|
+
const totalUsers = await this.prismaService.user.count();
|
|
35
|
+
|
|
36
|
+
// Usuários criados nos últimos 7 dias
|
|
37
|
+
const recentUsers = await this.prismaService.user.count({
|
|
38
|
+
where: {
|
|
39
|
+
created_at: {
|
|
40
|
+
gte: sevenDaysAgo,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Usuários ativos (criados nos últimos 30 dias como aproximação)
|
|
46
|
+
const activeUsers = await this.prismaService.user.count({
|
|
47
|
+
where: {
|
|
48
|
+
created_at: {
|
|
49
|
+
gte: thirtyDaysAgo,
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Total de roles
|
|
55
|
+
const totalRoles = await this.prismaService.role.count();
|
|
56
|
+
|
|
57
|
+
// Total de menus
|
|
58
|
+
const totalMenus = await this.prismaService.menu.count();
|
|
59
|
+
|
|
60
|
+
// Total de rotas
|
|
61
|
+
const totalRoutes = await this.prismaService.route.count();
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
totalUsers,
|
|
65
|
+
recentUsers,
|
|
66
|
+
activeUsers,
|
|
67
|
+
totalRoles,
|
|
68
|
+
totalMenus,
|
|
69
|
+
totalRoutes,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async getUserGrowth() {
|
|
74
|
+
const now = new Date();
|
|
75
|
+
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
76
|
+
|
|
77
|
+
// Contagem de usuários criados por dia nos últimos 30 dias
|
|
78
|
+
const usersByDay = await this.prismaService.$queryRaw<
|
|
79
|
+
Array<{ date: Date; count: bigint }>
|
|
80
|
+
>`
|
|
81
|
+
SELECT DATE("created_at") as date, COUNT(*) as count
|
|
82
|
+
FROM "user"
|
|
83
|
+
WHERE "created_at" >= ${thirtyDaysAgo}
|
|
84
|
+
GROUP BY DATE("created_at")
|
|
85
|
+
ORDER BY date ASC
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
return usersByDay.map((item) => ({
|
|
89
|
+
date: item.date,
|
|
90
|
+
count: Number(item.count),
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async getUserLayout(userId: number, slug: string) {
|
|
95
|
+
// Busca os itens do dashboard para este slug
|
|
96
|
+
const dashboardItems = await this.prismaService.dashboard_item.findMany({
|
|
97
|
+
where: {
|
|
98
|
+
dashboard: {
|
|
99
|
+
slug,
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
include: {
|
|
103
|
+
dashboard_user: {
|
|
104
|
+
where: {
|
|
105
|
+
user_id: userId,
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
dashboard_component: true,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return dashboardItems.map((item) => {
|
|
113
|
+
const userLayout = item.dashboard_user[0];
|
|
114
|
+
return {
|
|
115
|
+
i: `widget-${item.id}`,
|
|
116
|
+
component_id: item.component_id,
|
|
117
|
+
slug: item.dashboard_component.slug,
|
|
118
|
+
x: userLayout?.x_axis ?? item.x_axis ?? 0,
|
|
119
|
+
y: userLayout?.y_axis ?? item.y_axis ?? 0,
|
|
120
|
+
w: userLayout?.width ?? item.width ?? 2,
|
|
121
|
+
h: userLayout?.height ?? item.height ?? 2,
|
|
122
|
+
minW: item.dashboard_component.min_width,
|
|
123
|
+
maxW: item.dashboard_component.max_width,
|
|
124
|
+
minH: item.dashboard_component.min_height,
|
|
125
|
+
maxH: item.dashboard_component.max_height,
|
|
126
|
+
isResizable: item.dashboard_component.is_resizable ?? true,
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async saveUserLayout(
|
|
132
|
+
userId: number,
|
|
133
|
+
slug: string,
|
|
134
|
+
layout: Array<{
|
|
135
|
+
i: string;
|
|
136
|
+
x: number;
|
|
137
|
+
y: number;
|
|
138
|
+
w: number;
|
|
139
|
+
h: number;
|
|
140
|
+
}>,
|
|
141
|
+
) {
|
|
142
|
+
// Busca o dashboard
|
|
143
|
+
const dashboard = await this.prismaService.dashboard.findFirst({
|
|
144
|
+
where: { slug },
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (!dashboard) {
|
|
148
|
+
throw new Error(`Dashboard with slug '${slug}' not found`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Para cada item do layout, salva ou atualiza o dashboard_user
|
|
152
|
+
for (const item of layout) {
|
|
153
|
+
// Extrai o ID do item do identificador
|
|
154
|
+
const itemId = parseInt(item.i.replace('widget-', ''));
|
|
155
|
+
|
|
156
|
+
// Verifica se o item existe
|
|
157
|
+
const dashboardItem = await this.prismaService.dashboard_item.findFirst({
|
|
158
|
+
where: {
|
|
159
|
+
id: itemId,
|
|
160
|
+
dashboard_id: dashboard.id,
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
if (!dashboardItem) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Busca se já existe um dashboard_user para este item e usuário
|
|
169
|
+
const existingUserLayout =
|
|
170
|
+
await this.prismaService.dashboard_user.findFirst({
|
|
171
|
+
where: {
|
|
172
|
+
item_id: itemId,
|
|
173
|
+
user_id: userId,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (existingUserLayout) {
|
|
178
|
+
// Atualiza o layout existente
|
|
179
|
+
await this.prismaService.dashboard_user.update({
|
|
180
|
+
where: {
|
|
181
|
+
id: existingUserLayout.id,
|
|
182
|
+
},
|
|
183
|
+
data: {
|
|
184
|
+
x_axis: item.x,
|
|
185
|
+
y_axis: item.y,
|
|
186
|
+
width: item.w,
|
|
187
|
+
height: item.h,
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
} else {
|
|
191
|
+
// Cria um novo layout de usuário
|
|
192
|
+
await this.prismaService.dashboard_user.create({
|
|
193
|
+
data: {
|
|
194
|
+
item_id: itemId,
|
|
195
|
+
user_id: userId,
|
|
196
|
+
x_axis: item.x,
|
|
197
|
+
y_axis: item.y,
|
|
198
|
+
width: item.w,
|
|
199
|
+
height: item.h,
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return { success: true };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async addWidgetToUserDashboard(
|
|
209
|
+
userId: number,
|
|
210
|
+
slug: string,
|
|
211
|
+
componentSlug: string,
|
|
212
|
+
) {
|
|
213
|
+
// Busca o dashboard
|
|
214
|
+
const dashboard = await this.prismaService.dashboard.findFirst({
|
|
215
|
+
where: { slug },
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
if (!dashboard) {
|
|
219
|
+
throw new Error(`Dashboard with slug '${slug}' not found`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Busca o componente
|
|
223
|
+
const component = await this.prismaService.dashboard_component.findFirst({
|
|
224
|
+
where: { slug: componentSlug },
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
if (!component) {
|
|
228
|
+
throw new Error(`Component with slug '${componentSlug}' not found`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Verifica se já existe um item para este componente no dashboard
|
|
232
|
+
let dashboardItem = await this.prismaService.dashboard_item.findFirst({
|
|
233
|
+
where: {
|
|
234
|
+
dashboard_id: dashboard.id,
|
|
235
|
+
component_id: component.id,
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Se não existe, cria um novo item
|
|
240
|
+
if (!dashboardItem) {
|
|
241
|
+
dashboardItem = await this.prismaService.dashboard_item.create({
|
|
242
|
+
data: {
|
|
243
|
+
dashboard_id: dashboard.id,
|
|
244
|
+
component_id: component.id,
|
|
245
|
+
width: component.width,
|
|
246
|
+
height: component.height,
|
|
247
|
+
x_axis: 0,
|
|
248
|
+
y_axis: 0,
|
|
249
|
+
},
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Cria um registro de dashboard_user para este usuário
|
|
254
|
+
const userLayout = await this.prismaService.dashboard_user.create({
|
|
255
|
+
data: {
|
|
256
|
+
item_id: dashboardItem.id,
|
|
257
|
+
user_id: userId,
|
|
258
|
+
width: component.width,
|
|
259
|
+
height: component.height,
|
|
260
|
+
x_axis: 0,
|
|
261
|
+
y_axis: 999, // Coloca no final
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
i: `widget-${dashboardItem.id}`,
|
|
267
|
+
component_id: component.id,
|
|
268
|
+
slug: component.slug,
|
|
269
|
+
x: userLayout.x_axis,
|
|
270
|
+
y: userLayout.y_axis,
|
|
271
|
+
w: userLayout.width,
|
|
272
|
+
h: userLayout.height,
|
|
273
|
+
minW: component.min_width,
|
|
274
|
+
maxW: component.max_width,
|
|
275
|
+
minH: component.min_height,
|
|
276
|
+
maxH: component.max_height,
|
|
277
|
+
isResizable: component.is_resizable ?? true,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
async removeWidgetFromUserDashboard(
|
|
282
|
+
userId: number,
|
|
283
|
+
slug: string,
|
|
284
|
+
widgetId: string,
|
|
285
|
+
) {
|
|
286
|
+
const itemId = parseInt(widgetId.replace('widget-', ''));
|
|
287
|
+
|
|
288
|
+
// Remove o dashboard_user
|
|
289
|
+
await this.prismaService.dashboard_user.deleteMany({
|
|
290
|
+
where: {
|
|
291
|
+
item_id: itemId,
|
|
292
|
+
user_id: userId,
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
return { success: true };
|
|
297
|
+
}
|
|
27
298
|
}
|