diff --git a/src/config/swagger.config.ts b/src/config/swagger.config.ts index fe3b7a8..3bbcc25 100644 --- a/src/config/swagger.config.ts +++ b/src/config/swagger.config.ts @@ -3,8 +3,8 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; export function getSwaggerConfig(app: INestApplication) { const config = new DocumentBuilder() - .setTitle('D-menu API') - .setDescription('API documentation for D-menu backend') + .setTitle('D-kala API') + .setDescription('API documentation for D-kala backend') .setVersion('1.0') .addBearerAuth() // optional: for JWT endpoints .build(); diff --git a/src/modules/icons/controllers/icons.controller.ts b/src/modules/icons/controllers/icons.controller.ts index bdc0c7c..92168a8 100644 --- a/src/modules/icons/controllers/icons.controller.ts +++ b/src/modules/icons/controllers/icons.controller.ts @@ -1,14 +1,17 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { Controller, Get, Post, Body, Patch, Param, Delete, UseInterceptors, UploadedFiles } from '@nestjs/common'; import { IconService } from '../providers/icon.service'; import { GroupService } from '../providers/group.service'; import { CreateIconDto } from '../dto/create-icon.dto'; import { UpdateIconDto } from '../dto/update-icon.dto'; import { CreateGroupDto } from '../dto/create-group.dto'; import { UpdateGroupDto } from '../dto/update-group.dto'; -import { ApiTags, ApiOperation, ApiParam, ApiBody, ApiBearerAuth } from '@nestjs/swagger'; +import { ApiTags, ApiOperation, ApiParam, ApiBody, ApiBearerAuth, ApiConsumes } from '@nestjs/swagger'; import { SuperAdminAuthGuard } from 'src/modules/auth/guards/superAdminAuth.guard'; import { UseGuards } from '@nestjs/common'; import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard'; +import { FilesInterceptor } from '@nest-lab/fastify-multer'; +import { File } from '@nest-lab/fastify-multer'; +import { CreateBatchIconsDto } from '../dto/create-batch-icons.dto'; @ApiTags('icons') @Controller() @@ -16,7 +19,7 @@ export class IconsController { constructor( private readonly iconService: IconService, private readonly groupService: GroupService, - ) {} + ) { } @Get('admin/groups/icons') @UseGuards(AdminAuthGuard) @@ -111,4 +114,16 @@ export class IconsController { removeGroup(@Param('id') id: string) { return this.groupService.remove(id); } + + @Post('super-admin/icons/batch') + @UseGuards(SuperAdminAuthGuard) + @ApiOperation({ summary: 'Upload batch icons' }) + @ApiConsumes('multipart/form-data') + @ApiBody({ + type: CreateBatchIconsDto + }) + @UseInterceptors(FilesInterceptor('files', 50)) + uploadBatchIcons(@UploadedFiles() files: File[], @Body('groupId') groupId: string,) { + return this.iconService.uploadBatchIcons(groupId,files); + } } diff --git a/src/modules/icons/dto/create-batch-icons.dto.ts b/src/modules/icons/dto/create-batch-icons.dto.ts new file mode 100644 index 0000000..dd19fb4 --- /dev/null +++ b/src/modules/icons/dto/create-batch-icons.dto.ts @@ -0,0 +1,17 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsString } from 'class-validator'; + +export class CreateBatchIconsDto { + @IsString() + @ApiProperty({ example: 'group-id-here' }) + groupId!: string; + + @ApiProperty({ + type: 'array', + items: { + type: 'string', + format: 'binary', + }, + }) + files!: any[]; +} diff --git a/src/modules/icons/icons.module.ts b/src/modules/icons/icons.module.ts index 2e8931a..4cb0536 100644 --- a/src/modules/icons/icons.module.ts +++ b/src/modules/icons/icons.module.ts @@ -8,9 +8,10 @@ import { IconRepository } from './repositories/icon.repository'; import { GroupRepository } from './repositories/group.repository'; import { IconsController } from './controllers/icons.controller'; import { JwtModule } from '@nestjs/jwt'; +import { UploaderModule } from '../uploader/uploader.module'; @Module({ - imports: [MikroOrmModule.forFeature([Icon, Group]), JwtModule], + imports: [MikroOrmModule.forFeature([Icon, Group]), JwtModule, UploaderModule], controllers: [IconsController], providers: [IconService, GroupService, IconRepository, GroupRepository], exports: [IconRepository, GroupRepository, IconService, GroupService], diff --git a/src/modules/icons/providers/icon.service.ts b/src/modules/icons/providers/icon.service.ts index 66ccfda..2948b03 100644 --- a/src/modules/icons/providers/icon.service.ts +++ b/src/modules/icons/providers/icon.service.ts @@ -7,13 +7,47 @@ import { RequiredEntityData } from '@mikro-orm/core'; import { Icon } from '../entities/icon.entity'; import { IconMessage, GroupMessage } from 'src/common/enums/message.enum'; import { Group } from '../entities/group.entity'; +import { UploaderService } from 'src/modules/uploader/providers/uploader.service'; +import { File } from '@nest-lab/fastify-multer'; +import { Logger } from '@nestjs/common'; +import { GroupService } from './group.service'; @Injectable() export class IconService { + private readonly logger = new Logger(IconService.name); + constructor( private readonly iconRepository: IconRepository, private readonly em: EntityManager, - ) {} + private readonly uploaderService: UploaderService, + private readonly groupService: GroupService, + ) { } + + /** + * Upload batch icons using multiple file uploader + */ + async uploadBatchIcons(groupId: string, files: File[]) { + this.logger.log(`Uploading batch of ${files.length} icon files`); + const group = await this.groupService.findOne(groupId); + try { + const uploadResults = await this.uploaderService.uploadMultiple(files); + + const icons = uploadResults.map(({ url }) => + this.iconRepository.create({ + url, + group, + }), + ); + + await this.em.persistAndFlush(icons); + this.logger.log(`Successfully uploaded ${uploadResults.length} icons`); + return icons; + + } catch (error) { + this.logger.error('Failed to upload batch icons', error); + throw error; + } + } async create(dto: CreateIconDto): Promise { const group = await this.em.findOne(Group, { id: dto.groupId }); @@ -73,4 +107,3 @@ export class IconService { await this.em.removeAndFlush(icon); } } -