Compare commits
2 Commits
30bc803dd3
...
9603494c4a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9603494c4a | ||
|
|
e3cec87578 |
@@ -35,7 +35,8 @@ enum UserRole {
|
||||
ADMIN
|
||||
HR
|
||||
|
||||
@@schema("usr")
|
||||
@@schema("usr")
|
||||
|
||||
}
|
||||
|
||||
model Blog {
|
||||
@@ -151,7 +152,6 @@ model KlcArchive {
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
deletedAt DateTime? @map("deleted_at")
|
||||
|
||||
@@map("klc_archive")
|
||||
@@schema("cnt")
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ThrottlerModule } from '@nestjs/throttler';
|
||||
import { PrismaModule } from './common/database/prisma.module';
|
||||
import { AuthModule } from './modules/auth/auth.module';
|
||||
import { BlogsModule } from './modules/blog/blogs.module';
|
||||
import { WebcastsModule } from './modules/webcast/webcasts.module';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
@@ -29,6 +30,7 @@ import { AppService } from './app.service';
|
||||
// Feature modules
|
||||
AuthModule,
|
||||
BlogsModule,
|
||||
WebcastsModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
|
||||
94
src/modules/webcast/controllers/webcasts.controller.ts
Normal file
94
src/modules/webcast/controllers/webcasts.controller.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Body,
|
||||
Patch,
|
||||
Param,
|
||||
Delete,
|
||||
Query,
|
||||
ParseIntPipe,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { WebcastsService } from '../services/webcasts.service';
|
||||
import { CreateWebcastDto } from '../dto/create-webcast.dto';
|
||||
import { UpdateWebcastDto } from '../dto/update-webcast.dto';
|
||||
import { WebcastResponseDto } from '../dto/webcast-response.dto';
|
||||
import { PaginationDto } from '../../../common/dto/pagination.dto';
|
||||
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
|
||||
import { RolesGuard } from '../../../common/guards/roles.guard';
|
||||
import { Roles } from '../../../common/decorators/roles.decorator';
|
||||
|
||||
@ApiTags('webcasts')
|
||||
@Controller('webcasts')
|
||||
export class WebcastsController {
|
||||
constructor(private readonly webcastsService: WebcastsService) {}
|
||||
|
||||
@Post()
|
||||
// @UseGuards(JwtAuthGuard, RolesGuard)
|
||||
// @Roles('ADMIN', 'HR')
|
||||
// @ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Create a new webcast' })
|
||||
@ApiResponse({ status: 201, description: 'Webcast created successfully', type: WebcastResponseDto })
|
||||
@ApiResponse({ status: 401, description: 'Unauthorized' })
|
||||
@ApiResponse({ status: 403, description: 'Forbidden' })
|
||||
async create(@Body() createWebcastDto: CreateWebcastDto): Promise<WebcastResponseDto> {
|
||||
return this.webcastsService.create(createWebcastDto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: 'Get all webcasts with pagination' })
|
||||
@ApiResponse({ status: 200, description: 'Webcasts retrieved successfully' })
|
||||
async findAll(@Query() paginationDto: PaginationDto) {
|
||||
return this.webcastsService.findAll(paginationDto);
|
||||
}
|
||||
|
||||
@Get('tag/:tag')
|
||||
@ApiOperation({ summary: 'Get webcasts by tag' })
|
||||
@ApiResponse({ status: 200, description: 'Webcasts retrieved successfully' })
|
||||
async findByTag(
|
||||
@Param('tag') tag: string,
|
||||
@Query() paginationDto: PaginationDto,
|
||||
) {
|
||||
return this.webcastsService.findByTag(tag, paginationDto);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: 'Get webcast by ID' })
|
||||
@ApiResponse({ status: 200, description: 'Webcast retrieved successfully', type: WebcastResponseDto })
|
||||
@ApiResponse({ status: 404, description: 'Webcast not found' })
|
||||
async findOne(@Param('id', ParseIntPipe) id: number): Promise<WebcastResponseDto> {
|
||||
return this.webcastsService.findOne(id);
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
// @UseGuards(JwtAuthGuard, RolesGuard)
|
||||
// @Roles('ADMIN', 'HR')
|
||||
// @ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Update webcast' })
|
||||
@ApiResponse({ status: 200, description: 'Webcast updated successfully', type: WebcastResponseDto })
|
||||
@ApiResponse({ status: 404, description: 'Webcast not found' })
|
||||
@ApiResponse({ status: 401, description: 'Unauthorized' })
|
||||
@ApiResponse({ status: 403, description: 'Forbidden' })
|
||||
async update(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Body() updateWebcastDto: UpdateWebcastDto,
|
||||
): Promise<WebcastResponseDto> {
|
||||
return this.webcastsService.update(id, updateWebcastDto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
// @UseGuards(JwtAuthGuard, RolesGuard)
|
||||
// @Roles('ADMIN', 'HR')
|
||||
// @ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Delete webcast (soft delete)' })
|
||||
@ApiResponse({ status: 200, description: 'Webcast deleted successfully' })
|
||||
@ApiResponse({ status: 404, description: 'Webcast not found' })
|
||||
@ApiResponse({ status: 401, description: 'Unauthorized' })
|
||||
@ApiResponse({ status: 403, description: 'Forbidden' })
|
||||
async remove(@Param('id', ParseIntPipe) id: number): Promise<{ message: string }> {
|
||||
await this.webcastsService.remove(id);
|
||||
return { message: 'Webcast deleted successfully' };
|
||||
}
|
||||
}
|
||||
22
src/modules/webcast/dto/create-webcast.dto.ts
Normal file
22
src/modules/webcast/dto/create-webcast.dto.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { IsString, IsOptional, IsArray } from 'class-validator';
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
|
||||
export class CreateWebcastDto {
|
||||
@ApiProperty({ description: 'Webcast title' })
|
||||
@IsString()
|
||||
title: string;
|
||||
|
||||
@ApiProperty({ description: 'Webcast description' })
|
||||
@IsString()
|
||||
description: string;
|
||||
|
||||
@ApiProperty({ description: 'Webcast file URL' })
|
||||
@IsString()
|
||||
fileUrl: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Webcast tags', type: [String] })
|
||||
@IsArray()
|
||||
@IsString({ each: true })
|
||||
@IsOptional()
|
||||
tags?: string[];
|
||||
}
|
||||
4
src/modules/webcast/dto/update-webcast.dto.ts
Normal file
4
src/modules/webcast/dto/update-webcast.dto.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { PartialType } from '@nestjs/swagger';
|
||||
import { CreateWebcastDto } from './create-webcast.dto';
|
||||
|
||||
export class UpdateWebcastDto extends PartialType(CreateWebcastDto) {}
|
||||
24
src/modules/webcast/dto/webcast-response.dto.ts
Normal file
24
src/modules/webcast/dto/webcast-response.dto.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
|
||||
export class WebcastResponseDto {
|
||||
@ApiProperty({ description: 'Webcast ID' })
|
||||
id: number;
|
||||
|
||||
@ApiProperty({ description: 'Webcast title' })
|
||||
title: string;
|
||||
|
||||
@ApiProperty({ description: 'Webcast description' })
|
||||
description: string;
|
||||
|
||||
@ApiProperty({ description: 'Webcast file URL' })
|
||||
fileUrl: string;
|
||||
|
||||
@ApiProperty({ description: 'Webcast tags', type: [String] })
|
||||
tags: string[];
|
||||
|
||||
@ApiPropertyOptional({ description: 'Creation date' })
|
||||
createdAt: Date;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Last update date' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
153
src/modules/webcast/services/webcasts.service.ts
Normal file
153
src/modules/webcast/services/webcasts.service.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { PrismaService } from '../../../common/database/prisma.service';
|
||||
import { CreateWebcastDto } from '../dto/create-webcast.dto';
|
||||
import { UpdateWebcastDto } from '../dto/update-webcast.dto';
|
||||
import { WebcastResponseDto } from '../dto/webcast-response.dto';
|
||||
import { PaginationDto } from '../../../common/dto/pagination.dto';
|
||||
import { paginate } from '../../../common/utils/pagination.util';
|
||||
|
||||
@Injectable()
|
||||
export class WebcastsService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async create(createWebcastDto: CreateWebcastDto): Promise<WebcastResponseDto> {
|
||||
const webcast = await this.prisma.webcast.create({
|
||||
data: {
|
||||
...createWebcastDto,
|
||||
tags: createWebcastDto.tags || [],
|
||||
},
|
||||
});
|
||||
|
||||
return this.mapToResponseDto(webcast);
|
||||
}
|
||||
|
||||
async findAll(paginationDto: PaginationDto) {
|
||||
const { page, limit } = paginationDto;
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const [webcasts, total] = await Promise.all([
|
||||
this.prisma.webcast.findMany({
|
||||
where: {
|
||||
deletedAt: null,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
skip,
|
||||
take: limit,
|
||||
}),
|
||||
this.prisma.webcast.count({
|
||||
where: {
|
||||
deletedAt: null,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
const mappedWebcasts = webcasts.map(webcast => this.mapToResponseDto(webcast));
|
||||
|
||||
return paginate(mappedWebcasts, { page, limit }, total);
|
||||
}
|
||||
|
||||
async findOne(id: number): Promise<WebcastResponseDto> {
|
||||
const webcast = await this.prisma.webcast.findFirst({
|
||||
where: {
|
||||
id,
|
||||
deletedAt: null,
|
||||
},
|
||||
});
|
||||
|
||||
if (!webcast) {
|
||||
throw new NotFoundException(`Webcast with ID ${id} not found`);
|
||||
}
|
||||
|
||||
return this.mapToResponseDto(webcast);
|
||||
}
|
||||
|
||||
async update(id: number, updateWebcastDto: UpdateWebcastDto): Promise<WebcastResponseDto> {
|
||||
const existingWebcast = await this.prisma.webcast.findFirst({
|
||||
where: {
|
||||
id,
|
||||
deletedAt: null,
|
||||
},
|
||||
});
|
||||
|
||||
if (!existingWebcast) {
|
||||
throw new NotFoundException(`Webcast with ID ${id} not found`);
|
||||
}
|
||||
|
||||
const webcast = await this.prisma.webcast.update({
|
||||
where: { id },
|
||||
data: {
|
||||
...updateWebcastDto,
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
return this.mapToResponseDto(webcast);
|
||||
}
|
||||
|
||||
async remove(id: number): Promise<void> {
|
||||
const existingWebcast = await this.prisma.webcast.findFirst({
|
||||
where: {
|
||||
id,
|
||||
deletedAt: null,
|
||||
},
|
||||
});
|
||||
|
||||
if (!existingWebcast) {
|
||||
throw new NotFoundException(`Webcast with ID ${id} not found`);
|
||||
}
|
||||
|
||||
await this.prisma.webcast.update({
|
||||
where: { id },
|
||||
data: {
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async findByTag(tag: string, paginationDto: PaginationDto) {
|
||||
const { page, limit } = paginationDto;
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const [webcasts, total] = await Promise.all([
|
||||
this.prisma.webcast.findMany({
|
||||
where: {
|
||||
tags: {
|
||||
has: tag,
|
||||
},
|
||||
deletedAt: null,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
skip,
|
||||
take: limit,
|
||||
}),
|
||||
this.prisma.webcast.count({
|
||||
where: {
|
||||
tags: {
|
||||
has: tag,
|
||||
},
|
||||
deletedAt: null,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
const mappedWebcasts = webcasts.map(webcast => this.mapToResponseDto(webcast));
|
||||
|
||||
return paginate(mappedWebcasts, { page, limit }, total);
|
||||
}
|
||||
|
||||
private mapToResponseDto(webcast: any): WebcastResponseDto {
|
||||
return {
|
||||
id: webcast.id,
|
||||
title: webcast.title,
|
||||
description: webcast.description,
|
||||
fileUrl: webcast.fileUrl,
|
||||
tags: webcast.tags,
|
||||
createdAt: webcast.createdAt,
|
||||
updatedAt: webcast.updatedAt,
|
||||
};
|
||||
}
|
||||
}
|
||||
12
src/modules/webcast/webcasts.module.ts
Normal file
12
src/modules/webcast/webcasts.module.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { WebcastsService } from './services/webcasts.service';
|
||||
import { WebcastsController } from './controllers/webcasts.controller';
|
||||
import { PrismaModule } from '../../common/database/prisma.module';
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
controllers: [WebcastsController],
|
||||
providers: [WebcastsService],
|
||||
exports: [WebcastsService],
|
||||
})
|
||||
export class WebcastsModule {}
|
||||
Reference in New Issue
Block a user