elearning/Backend/src/controllers/LessonsController.ts

229 lines
7.9 KiB
TypeScript
Raw Normal View History

import { Body, Delete, Path, Post, Put, Request, Response, Route, Security, SuccessResponse, Tags, UploadedFile } from 'tsoa';
import { ValidationError } from '../middleware/errorHandler';
import { ChaptersLessonService } from '../services/ChaptersLesson.service';
import {
UploadedFileInfo,
CreateLessonResponse,
UpdateLessonResponse,
VideoOperationResponse,
AttachmentOperationResponse,
DeleteAttachmentResponse,
YouTubeVideoResponse,
SetYouTubeVideoBody,
} from '../types/ChaptersLesson.typs';
import { SetYouTubeVideoValidator } from '../validators/Lessons.validator';
const chaptersLessonService = new ChaptersLessonService();
@Route('api/instructors/courses/{courseId}/chapters/{chapterId}/lessons')
@Tags('Lessons - File Upload')
export class LessonsController {
/**
* ()
* Upload video to lesson (first time)
*
* @param courseId Course ID
* @param chapterId Chapter ID
* @param lessonId Lesson ID
* @param video (required)
*/
@Post('{lessonId}/video')
@Security('jwt', ['instructor'])
@SuccessResponse('200', 'Video uploaded successfully')
@Response('400', 'Validation error - Video already exists')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden')
@Response('404', 'Lesson not found')
public async uploadVideo(
@Request() request: any,
@Path() courseId: number,
@Path() chapterId: number,
@Path() lessonId: number,
@UploadedFile() video: Express.Multer.File
): Promise<VideoOperationResponse> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) throw new ValidationError('No token provided');
if (!video) {
throw new ValidationError('Video file is required');
}
const videoInfo: UploadedFileInfo = {
originalname: video.originalname,
mimetype: video.mimetype,
size: video.size,
buffer: video.buffer,
};
return await chaptersLessonService.uploadVideo({
token,
course_id: courseId,
lesson_id: lessonId,
video: videoInfo,
});
}
/**
* ()
* Update (replace) video in lesson
*
* @param courseId Course ID
* @param chapterId Chapter ID
* @param lessonId Lesson ID
* @param video (required)
*/
@Put('{lessonId}/video')
@Security('jwt', ['instructor'])
@SuccessResponse('200', 'Video updated successfully')
@Response('400', 'Validation error')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden')
@Response('404', 'Lesson not found')
public async updateVideo(
@Request() request: any,
@Path() courseId: number,
@Path() chapterId: number,
@Path() lessonId: number,
@UploadedFile() video: Express.Multer.File
): Promise<VideoOperationResponse> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) throw new ValidationError('No token provided');
if (!video) {
throw new ValidationError('Video file is required');
}
const videoInfo: UploadedFileInfo = {
originalname: video.originalname,
mimetype: video.mimetype,
size: video.size,
buffer: video.buffer,
};
return await chaptersLessonService.updateVideo({
token,
course_id: courseId,
lesson_id: lessonId,
video: videoInfo,
});
}
/**
*
* Upload a single attachment to lesson
*
* @param courseId Course ID
* @param chapterId Chapter ID
* @param lessonId Lesson ID
* @param attachment (required)
*/
@Post('{lessonId}/attachments')
@Security('jwt', ['instructor'])
@SuccessResponse('200', 'Attachment uploaded successfully')
@Response('400', 'Validation error')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden')
@Response('404', 'Lesson not found')
public async uploadAttachment(
@Request() request: any,
@Path() courseId: number,
@Path() chapterId: number,
@Path() lessonId: number,
@UploadedFile() attachment: Express.Multer.File
): Promise<AttachmentOperationResponse> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) throw new ValidationError('No token provided');
if (!attachment) {
throw new ValidationError('Attachment file is required');
}
const attachmentInfo: UploadedFileInfo = {
originalname: attachment.originalname,
mimetype: attachment.mimetype,
size: attachment.size,
buffer: attachment.buffer,
};
return await chaptersLessonService.uploadAttachment({
token,
course_id: courseId,
lesson_id: lessonId,
attachment: attachmentInfo,
});
}
/**
*
* Delete a single attachment from lesson
*
* @param courseId Course ID
* @param chapterId Chapter ID
* @param lessonId Lesson ID
* @param attachmentId Attachment ID
*/
@Delete('{lessonId}/attachments/{attachmentId}')
@Security('jwt', ['instructor'])
@SuccessResponse('200', 'Attachment deleted successfully')
@Response('400', 'Validation error')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden')
@Response('404', 'Attachment not found')
public async deleteAttachment(
@Request() request: any,
@Path() courseId: number,
@Path() chapterId: number,
@Path() lessonId: number,
@Path() attachmentId: number
): Promise<DeleteAttachmentResponse> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) throw new ValidationError('No token provided');
return await chaptersLessonService.deleteAttachment({
token,
course_id: courseId,
lesson_id: lessonId,
attachment_id: attachmentId,
});
}
/**
* YouTube ()
* Set YouTube video for a lesson (replaces existing video if any)
*
* @param courseId Course ID
* @param chapterId Chapter ID
* @param lessonId Lesson ID
* @param body YouTube video info
*/
@Post('{lessonId}/youtube-video')
@Security('jwt', ['instructor'])
@SuccessResponse('200', 'YouTube video set successfully')
@Response('400', 'Validation error')
@Response('401', 'Unauthorized')
@Response('403', 'Forbidden')
@Response('404', 'Lesson not found')
public async setYouTubeVideo(
@Request() request: any,
@Path() courseId: number,
@Path() chapterId: number,
@Path() lessonId: number,
@Body() body: SetYouTubeVideoBody
): Promise<YouTubeVideoResponse> {
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) throw new ValidationError('No token provided');
const { error } = SetYouTubeVideoValidator.validate(body);
if (error) throw new ValidationError(error.details[0].message);
return await chaptersLessonService.setYouTubeVideo({
token,
course_id: courseId,
lesson_id: lessonId,
youtube_video_id: body.youtube_video_id,
video_title: body.video_title,
});
}
}