From 4c0377d234527edf45c08e09c35c8131e0ff4e12 Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Sun, 12 Jun 2022 19:55:13 +0300 Subject: [PATCH] feat: upload video lesson via src link --- app/Models/Lesson.ts | 3 ++ app/Repositories/LessonRepository.ts | 27 ++++++++++++------ app/Services/CourseService.ts | 28 ++++--------------- .../Lesson/CreateLessonValidator.ts | 3 +- .../Lesson/UpdateLessonValidator.ts | 1 + database/migrations/1628016919501_lessons.ts | 1 + 6 files changed, 31 insertions(+), 32 deletions(-) diff --git a/app/Models/Lesson.ts b/app/Models/Lesson.ts index 973d17a..94ff146 100644 --- a/app/Models/Lesson.ts +++ b/app/Models/Lesson.ts @@ -37,6 +37,9 @@ export default class Lesson extends BaseModel { @column() public description: string; + @column() + public linked_video_url: string | null; + @column() public duration: string; diff --git a/app/Repositories/LessonRepository.ts b/app/Repositories/LessonRepository.ts index 4875996..275b2b6 100644 --- a/app/Repositories/LessonRepository.ts +++ b/app/Repositories/LessonRepository.ts @@ -106,6 +106,7 @@ export default class LessonRepository { duration: data.duration.toFormat('HH:mm:ss'), display_order: Number.parseInt(course.$extras.lessons_count, 10) + 1, course_id: course.id, + linked_video_url: !data.video ? data.linked_video_url : null, }); /** @@ -116,7 +117,9 @@ export default class LessonRepository { /** * Move video file to disk and save to database */ - await this.createVideo(lesson, data.video); + if (data.video) { + await this.createVideo(lesson, data.video); + } /** * Create materials @@ -154,22 +157,28 @@ export default class LessonRepository { }); /** - * Update video + * Update linked video url */ - if (data.video) { - /** - * Delete video from drive and database - */ + if (data.linked_video_url && !data.video) { if (lesson.video) { await this.Drive.delete(`videos/${lesson.video.name}`); } await lesson.related('video').query().delete(); + lesson.merge({ linked_video_url: data.linked_video_url }); + } - /** - * Upload new video to drive and save to database - */ + /** + * Update file video + */ + if (data.video) { + if (lesson.video) { + await this.Drive.delete(`videos/${lesson.video.name}`); + } + + await lesson.related('video').query().delete(); await this.createVideo(lesson, data.video); + lesson.merge({ linked_video_url: null }); } /** diff --git a/app/Services/CourseService.ts b/app/Services/CourseService.ts index 8a569b4..66b1f86 100644 --- a/app/Services/CourseService.ts +++ b/app/Services/CourseService.ts @@ -312,23 +312,7 @@ export default class CourseService { }; } - /** - * Collect all file names from lessons in course and delete files - */ - const videos: string[] = course.lessons.map(lesson => lesson.video.name); - const materials: string[] = course.lessons.map(lesson => lesson.materials.map(m => m.name)).flat(); - - await Promise.all( - videos.map(async name => { - await Drive.delete(`videos/${name}`); - }) - ); - - await Promise.all( - materials.map(async name => { - await Drive.delete(`materials/${name}`); - }) - ); + await this.deleteAllFiles([course]); return { success: true, @@ -377,13 +361,13 @@ export default class CourseService { await teacher.load('roles'); - const isTeacher = RoleHelper.userContainRoles(teacher.roles, [RoleEnum.TEACHER]); + const isTeacherOrAdmin = RoleHelper.userContainRoles(teacher.roles, [RoleEnum.ADMIN, RoleEnum.TEACHER]); - if (!isTeacher) { + if (!isTeacherOrAdmin) { return { success: false, status: HttpStatusEnum.BAD_REQUEST, - message: 'Author is not a teacher.', + message: 'Author is not a teacher or admin.', data: {}, error: { code: 'E_BAD_REQUEST', @@ -392,13 +376,13 @@ export default class CourseService { } } - await this.courseRepository.update(id, data); + const updated = await this.courseRepository.update(id, data); return { success: true, status: HttpStatusEnum.OK, message: 'Course updated.', - data: course, + data: updated || {}, }; } diff --git a/app/Validators/Lesson/CreateLessonValidator.ts b/app/Validators/Lesson/CreateLessonValidator.ts index 976de89..ca92e7d 100644 --- a/app/Validators/Lesson/CreateLessonValidator.ts +++ b/app/Validators/Lesson/CreateLessonValidator.ts @@ -9,10 +9,11 @@ export default class CreateLessonValidator { title: schema.string({}, [rules.maxLength(255)]), description: schema.string(), duration: schema.date({ format: 'HH:mm:ss' }), - video: schema.file({ + video: schema.file.optional({ size: '5000mb', extnames: ['mp4', 'mov', 'avi', 'wmv', 'webm', 'flv'], }), + linked_video_url: schema.string.optional([rules.regex(new RegExp('^(http|https|ftp)://'))]), materials: schema.array.optional().members( schema.file({ size: '100mb', diff --git a/app/Validators/Lesson/UpdateLessonValidator.ts b/app/Validators/Lesson/UpdateLessonValidator.ts index 909fc7d..4f5b03d 100644 --- a/app/Validators/Lesson/UpdateLessonValidator.ts +++ b/app/Validators/Lesson/UpdateLessonValidator.ts @@ -13,6 +13,7 @@ export default class UpdateLessonValidator { size: '5000mb', extnames: ['mp4', 'mov', 'avi', 'wmv', 'webm', 'flv'], }), + linked_video_url: schema.string.optional([rules.regex(new RegExp('^(http|https|ftp)://'))]), materials: schema.array.nullableAndOptional().members( schema.file({ size: '100mb', diff --git a/database/migrations/1628016919501_lessons.ts b/database/migrations/1628016919501_lessons.ts index 6c65853..e3fb51f 100644 --- a/database/migrations/1628016919501_lessons.ts +++ b/database/migrations/1628016919501_lessons.ts @@ -11,6 +11,7 @@ export default class Lessons extends BaseSchema { table.integer('display_order').notNullable(); table.integer('color_id').unsigned().references('colors.id'); table.string('description'); + table.text('linked_video_url').nullable(); table.time('duration').notNullable(); table.timestamp('created_at', { useTz: true }); table.timestamp('updated_at', { useTz: true });