@hed-hog/core 0.0.237 → 0.0.238

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/dashboard/dashboard/dashboard.controller.d.ts +102 -0
  2. package/dist/dashboard/dashboard/dashboard.controller.d.ts.map +1 -1
  3. package/dist/dashboard/dashboard/dashboard.service.d.ts +102 -0
  4. package/dist/dashboard/dashboard/dashboard.service.d.ts.map +1 -1
  5. package/dist/dashboard/dashboard/dashboard.service.js +26 -0
  6. package/dist/dashboard/dashboard/dashboard.service.js.map +1 -1
  7. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts.map +1 -1
  8. package/dist/dashboard/dashboard-component/dashboard-component.service.js +39 -0
  9. package/dist/dashboard/dashboard-component/dashboard-component.service.js.map +1 -1
  10. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +7 -1
  11. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts.map +1 -1
  12. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.js +11 -0
  13. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.js.map +1 -1
  14. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +7 -1
  15. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts.map +1 -1
  16. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js +31 -0
  17. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js.map +1 -1
  18. package/dist/dashboard/dashboard-component-role/dto/create-batch.dto.d.ts +5 -0
  19. package/dist/dashboard/dashboard-component-role/dto/create-batch.dto.d.ts.map +1 -0
  20. package/dist/dashboard/dashboard-component-role/dto/create-batch.dto.js +27 -0
  21. package/dist/dashboard/dashboard-component-role/dto/create-batch.dto.js.map +1 -0
  22. package/dist/dashboard/dashboard-component-role/dto/index.d.ts +1 -0
  23. package/dist/dashboard/dashboard-component-role/dto/index.d.ts.map +1 -1
  24. package/dist/dashboard/dashboard-component-role/dto/index.js +1 -0
  25. package/dist/dashboard/dashboard-component-role/dto/index.js.map +1 -1
  26. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +7 -1
  27. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts.map +1 -1
  28. package/dist/dashboard/dashboard-role/dashboard-role.controller.js +11 -0
  29. package/dist/dashboard/dashboard-role/dashboard-role.controller.js.map +1 -1
  30. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +7 -1
  31. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts.map +1 -1
  32. package/dist/dashboard/dashboard-role/dashboard-role.service.js +31 -0
  33. package/dist/dashboard/dashboard-role/dashboard-role.service.js.map +1 -1
  34. package/dist/dashboard/dashboard-role/dto/create-batch.dto.d.ts +5 -0
  35. package/dist/dashboard/dashboard-role/dto/create-batch.dto.d.ts.map +1 -0
  36. package/dist/dashboard/dashboard-role/dto/create-batch.dto.js +27 -0
  37. package/dist/dashboard/dashboard-role/dto/create-batch.dto.js.map +1 -0
  38. package/dist/dashboard/dashboard-role/dto/index.d.ts +1 -0
  39. package/dist/dashboard/dashboard-role/dto/index.d.ts.map +1 -1
  40. package/dist/dashboard/dashboard-role/dto/index.js +1 -0
  41. package/dist/dashboard/dashboard-role/dto/index.js.map +1 -1
  42. package/dist/file/file.controller.d.ts +4 -1
  43. package/dist/file/file.controller.d.ts.map +1 -1
  44. package/dist/file/file.controller.js +47 -8
  45. package/dist/file/file.controller.js.map +1 -1
  46. package/dist/file/file.service.d.ts +1 -0
  47. package/dist/file/file.service.d.ts.map +1 -1
  48. package/dist/file/file.service.js +7 -0
  49. package/dist/file/file.service.js.map +1 -1
  50. package/dist/user/user.controller.d.ts +1 -0
  51. package/dist/user/user.controller.d.ts.map +1 -1
  52. package/dist/user/user.controller.js +13 -0
  53. package/dist/user/user.controller.js.map +1 -1
  54. package/dist/user/user.service.d.ts +1 -0
  55. package/dist/user/user.service.d.ts.map +1 -1
  56. package/dist/user/user.service.js +20 -0
  57. package/dist/user/user.service.js.map +1 -1
  58. package/hedhog/data/route.yaml +24 -0
  59. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +21 -3
  60. package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +344 -5
  61. package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +358 -2
  62. package/hedhog/frontend/messages/en.json +19 -0
  63. package/hedhog/frontend/messages/pt.json +19 -0
  64. package/package.json +4 -4
  65. package/src/dashboard/dashboard/dashboard.service.ts +26 -0
  66. package/src/dashboard/dashboard-component/dashboard-component.service.ts +39 -0
  67. package/src/dashboard/dashboard-component-role/dashboard-component-role.controller.ts +12 -1
  68. package/src/dashboard/dashboard-component-role/dashboard-component-role.service.ts +44 -1
  69. package/src/dashboard/dashboard-component-role/dto/create-batch.dto.ts +11 -0
  70. package/src/dashboard/dashboard-component-role/dto/index.ts +2 -0
  71. package/src/dashboard/dashboard-role/dashboard-role.controller.ts +22 -11
  72. package/src/dashboard/dashboard-role/dashboard-role.service.ts +48 -5
  73. package/src/dashboard/dashboard-role/dto/create-batch.dto.ts +11 -0
  74. package/src/dashboard/dashboard-role/dto/index.ts +2 -0
  75. package/src/file/file.controller.ts +50 -7
  76. package/src/file/file.service.ts +10 -0
  77. package/src/user/user.controller.ts +12 -1
  78. package/src/user/user.service.ts +32 -5
@@ -7,7 +7,10 @@ import {
7
7
  Injectable,
8
8
  NotFoundException,
9
9
  } from '@nestjs/common';
10
- import { CreateDashboardComponentRoleDTO } from './dto';
10
+ import {
11
+ CreateDashboardComponentRoleBatchDTO,
12
+ CreateDashboardComponentRoleDTO,
13
+ } from './dto';
11
14
 
12
15
  @Injectable()
13
16
  export class DashboardComponentRoleService {
@@ -117,6 +120,46 @@ export class DashboardComponentRoleService {
117
120
  });
118
121
  }
119
122
 
123
+ async createBatch(data: CreateDashboardComponentRoleBatchDTO, locale: string) {
124
+ const uniqueRoleIds = [...new Set(data.role_ids)];
125
+
126
+ const existingRelations = await this.prismaService.dashboard_component_role.findMany({
127
+ where: {
128
+ component_id: data.component_id,
129
+ role_id: {
130
+ in: uniqueRoleIds,
131
+ },
132
+ },
133
+ select: {
134
+ role_id: true,
135
+ },
136
+ });
137
+
138
+ const existingRoleIds = new Set(existingRelations.map((item) => item.role_id));
139
+ const roleIdsToCreate = uniqueRoleIds.filter((roleId) => !existingRoleIds.has(roleId));
140
+
141
+ if (roleIdsToCreate.length > 0) {
142
+ await this.prismaService.dashboard_component_role.createMany({
143
+ data: roleIdsToCreate.map((roleId) => ({
144
+ component_id: data.component_id,
145
+ role_id: roleId,
146
+ })),
147
+ skipDuplicates: true,
148
+ });
149
+ }
150
+
151
+ return {
152
+ success: true,
153
+ created: roleIdsToCreate.length,
154
+ skipped: uniqueRoleIds.length - roleIdsToCreate.length,
155
+ message: getLocaleText(
156
+ 'dashboardComponentRoleBatchCreated',
157
+ locale,
158
+ 'Dashboard component roles processed successfully',
159
+ ),
160
+ };
161
+ }
162
+
120
163
  async delete(id: number, locale: string) {
121
164
  const relation = await this.prismaService.dashboard_component_role.findUnique({
122
165
  where: { id },
@@ -0,0 +1,11 @@
1
+ import { ArrayNotEmpty, IsArray, IsInt } from 'class-validator';
2
+
3
+ export class CreateDashboardComponentRoleBatchDTO {
4
+ @IsInt()
5
+ component_id: number;
6
+
7
+ @IsArray()
8
+ @ArrayNotEmpty()
9
+ @IsInt({ each: true })
10
+ role_ids: number[];
11
+ }
@@ -1 +1,3 @@
1
+ export * from './create-batch.dto';
1
2
  export * from './create.dto';
3
+
@@ -2,19 +2,22 @@ import { Role } from '@hed-hog/api';
2
2
  import { Locale } from '@hed-hog/api-locale';
3
3
  import { Pagination } from '@hed-hog/api-pagination';
4
4
  import {
5
- Body,
6
- Controller,
7
- Delete,
8
- Get,
9
- Inject,
10
- Param,
11
- ParseIntPipe,
12
- Post,
13
- Query,
14
- forwardRef,
5
+ Body,
6
+ Controller,
7
+ Delete,
8
+ Get,
9
+ Inject,
10
+ Param,
11
+ ParseIntPipe,
12
+ Post,
13
+ Query,
14
+ forwardRef,
15
15
  } from '@nestjs/common';
16
16
  import { DashboardRoleService } from './dashboard-role.service';
17
- import { CreateDashboardRoleDTO } from './dto';
17
+ import {
18
+ CreateDashboardRoleBatchDTO,
19
+ CreateDashboardRoleDTO,
20
+ } from './dto';
18
21
 
19
22
  @Role()
20
23
  @Controller('dashboard-role')
@@ -38,6 +41,14 @@ export class DashboardRoleController {
38
41
  return this.service.create(data, locale);
39
42
  }
40
43
 
44
+ @Post('batch')
45
+ createBatch(
46
+ @Body() data: CreateDashboardRoleBatchDTO,
47
+ @Locale() locale: string,
48
+ ) {
49
+ return this.service.createBatch(data, locale);
50
+ }
51
+
41
52
  @Delete(':id')
42
53
  delete(@Param('id', ParseIntPipe) id: number, @Locale() locale: string) {
43
54
  return this.service.delete(id, locale);
@@ -2,12 +2,15 @@ import { getLocaleText } from '@hed-hog/api-locale';
2
2
  import { PaginationService } from '@hed-hog/api-pagination';
3
3
  import { PrismaService } from '@hed-hog/api-prisma';
4
4
  import {
5
- forwardRef,
6
- Inject,
7
- Injectable,
8
- NotFoundException,
5
+ forwardRef,
6
+ Inject,
7
+ Injectable,
8
+ NotFoundException,
9
9
  } from '@nestjs/common';
10
- import { CreateDashboardRoleDTO } from './dto';
10
+ import {
11
+ CreateDashboardRoleBatchDTO,
12
+ CreateDashboardRoleDTO,
13
+ } from './dto';
11
14
 
12
15
  @Injectable()
13
16
  export class DashboardRoleService {
@@ -116,6 +119,46 @@ export class DashboardRoleService {
116
119
  });
117
120
  }
118
121
 
122
+ async createBatch(data: CreateDashboardRoleBatchDTO, locale: string) {
123
+ const uniqueRoleIds = [...new Set(data.role_ids)];
124
+
125
+ const existingRelations = await this.prismaService.dashboard_role.findMany({
126
+ where: {
127
+ dashboard_id: data.dashboard_id,
128
+ role_id: {
129
+ in: uniqueRoleIds,
130
+ },
131
+ },
132
+ select: {
133
+ role_id: true,
134
+ },
135
+ });
136
+
137
+ const existingRoleIds = new Set(existingRelations.map((item) => item.role_id));
138
+ const roleIdsToCreate = uniqueRoleIds.filter((roleId) => !existingRoleIds.has(roleId));
139
+
140
+ if (roleIdsToCreate.length > 0) {
141
+ await this.prismaService.dashboard_role.createMany({
142
+ data: roleIdsToCreate.map((roleId) => ({
143
+ dashboard_id: data.dashboard_id,
144
+ role_id: roleId,
145
+ })),
146
+ skipDuplicates: true,
147
+ });
148
+ }
149
+
150
+ return {
151
+ success: true,
152
+ created: roleIdsToCreate.length,
153
+ skipped: uniqueRoleIds.length - roleIdsToCreate.length,
154
+ message: getLocaleText(
155
+ 'dashboardRoleBatchCreated',
156
+ locale,
157
+ 'Dashboard roles processed successfully',
158
+ ),
159
+ };
160
+ }
161
+
119
162
  async delete(id: number, locale: string) {
120
163
  const relation = await this.prismaService.dashboard_role.findUnique({ where: { id } });
121
164
 
@@ -0,0 +1,11 @@
1
+ import { ArrayNotEmpty, IsArray, IsInt } from 'class-validator';
2
+
3
+ export class CreateDashboardRoleBatchDTO {
4
+ @IsInt()
5
+ dashboard_id: number;
6
+
7
+ @IsArray()
8
+ @ArrayNotEmpty()
9
+ @IsInt({ each: true })
10
+ role_ids: number[];
11
+ }
@@ -1 +1,3 @@
1
+ export * from './create-batch.dto';
1
2
  export * from './create.dto';
3
+
@@ -44,13 +44,13 @@ export class FileController {
44
44
  return this.fileService.get(id);
45
45
  }
46
46
 
47
- @Public()
48
- @Get('open/:fileId')
49
- async getLocalFile(
50
- @Param('fileId', ParseIntPipe) fileId: number,
51
- @Res() res,
52
- ) {
53
- return this.fileService.getLocalFile(fileId, res)
47
+ @Put('open/:id')
48
+ async getTempOpenURL(@Param('id', ParseIntPipe) id: number) {
49
+ return {
50
+ url: await this.fileService.tempOpenURL(
51
+ (await this.fileService.get(id)).path,
52
+ ),
53
+ };
54
54
  }
55
55
 
56
56
  @Put('download/:id')
@@ -109,6 +109,49 @@ export class FileController {
109
109
  }
110
110
  }
111
111
 
112
+ @Public()
113
+ @Get('open/:token')
114
+ async open(
115
+ @Param('token') token: string,
116
+ @Res({ passthrough: true }) res: Response,
117
+ @Locale() locale: string,
118
+ ) {
119
+
120
+ try {
121
+
122
+ const { stream, filename, mimetype } = await this.fileService.download(locale, token);
123
+
124
+ res.set({
125
+ 'Content-Type': mimetype || 'application/octet-stream',
126
+ 'Content-Disposition': `inline; filename="${filename}"`,
127
+ });
128
+
129
+ return new StreamableFile(stream);
130
+
131
+ } catch (error:any) {
132
+ const errorTitle = getLocaleText('file.download.error_title', locale);
133
+ const errorMessage = getLocaleText('file.download.error_message', locale);
134
+ const errorDetailsLabel = getLocaleText('file.download.error_details', locale);
135
+ const goBackText = getLocaleText('file.download.go_back', locale);
136
+
137
+ const templatePath = join(__dirname, 'templates', 'download-error.html');
138
+ const templateSource = readFileSync(templatePath, 'utf-8');
139
+ const template = Handlebars.compile(templateSource);
140
+
141
+ const html = template({
142
+ locale: locale || 'en',
143
+ errorTitle,
144
+ errorMessage,
145
+ errorDetailsLabel,
146
+ errorDetails: error?.message || 'Unknown error occurred',
147
+ goBackText,
148
+ });
149
+
150
+ res.set('Content-Type', 'text/html');
151
+ return html;
152
+ }
153
+ }
154
+
112
155
  @Post()
113
156
  @UseInterceptors(FileInterceptor('file'))
114
157
  async upload(
@@ -423,4 +423,14 @@ export class FileService implements OnModuleInit {
423
423
  async tempURL(filepath: string, expires = 3600) {
424
424
  return (await this.getProvider()).tempURL(filepath, expires);
425
425
  }
426
+
427
+ async tempOpenURL(filepath: string, expires = 3600) {
428
+ const url = await this.tempURL(filepath, expires);
429
+
430
+ if (typeof url === 'string') {
431
+ return url.replace('/file/download/', '/file/open/');
432
+ }
433
+
434
+ return url;
435
+ }
426
436
  }
@@ -1,4 +1,4 @@
1
- import { Role } from '@hed-hog/api';
1
+ import { Public, Role } from '@hed-hog/api';
2
2
  import { Locale } from '@hed-hog/api-locale';
3
3
  import { Pagination } from '@hed-hog/api-pagination';
4
4
  import {
@@ -12,6 +12,7 @@ import {
12
12
  ParseIntPipe,
13
13
  Patch,
14
14
  Post,
15
+ Res,
15
16
  UploadedFile,
16
17
  UseInterceptors,
17
18
  forwardRef,
@@ -40,6 +41,16 @@ export class UserController {
40
41
  return this.userService.get(locale, userId);
41
42
  }
42
43
 
44
+ @Public()
45
+ @Get('avatar/:fileId')
46
+ async openPublicAvatar(
47
+ @Param('fileId', ParseIntPipe) fileId: number,
48
+ @Locale() locale: string,
49
+ @Res() res,
50
+ ) {
51
+ return this.userService.openPublicAvatar(locale, fileId, res);
52
+ }
53
+
43
54
  @Post()
44
55
  async create(@Body() data: CreateWithEmailAndPasswordDTO, @Locale() locale: string) {
45
56
  return this.userService.createWithEmailAndPassword(locale, data);
@@ -2,11 +2,11 @@ import { getLocaleText } from '@hed-hog/api-locale';
2
2
  import { PaginationService } from '@hed-hog/api-pagination';
3
3
  import { PrismaService } from '@hed-hog/api-prisma';
4
4
  import {
5
- BadRequestException,
6
- Inject,
7
- Injectable,
8
- NotFoundException,
9
- forwardRef,
5
+ BadRequestException,
6
+ Inject,
7
+ Injectable,
8
+ NotFoundException,
9
+ forwardRef,
10
10
  } from '@nestjs/common';
11
11
  import { ChallengeService } from '../challenge/challenge.service';
12
12
  import { DeleteDTO } from '../dto/delete.dto';
@@ -238,6 +238,33 @@ export class UserService {
238
238
  };
239
239
  }
240
240
 
241
+ async openPublicAvatar(locale: string, fileId: number, res: any) {
242
+ const userWithAvatar = await this.prismaService.user.findFirst({
243
+ where: {
244
+ photo_id: fileId,
245
+ },
246
+ select: {
247
+ id: true,
248
+ },
249
+ });
250
+
251
+ if (!userWithAvatar) {
252
+ throw new NotFoundException(
253
+ getLocaleText('userNotFound', locale, 'User not found')
254
+ );
255
+ }
256
+
257
+ const { file, buffer } = await this.file.getBuffer(fileId);
258
+
259
+ res.set({
260
+ 'Content-Type': file.file_mimetype.name,
261
+ 'Content-Length': buffer.length,
262
+ 'Cache-Control': 'public, max-age=3600',
263
+ });
264
+
265
+ res.send(buffer);
266
+ }
267
+
241
268
  // ==========================================
242
269
  // User Lookup Methods
243
270
  // ==========================================