diff --git a/app/Controllers/Http/Api/v1/CoursesController.ts b/app/Controllers/Http/Api/v1/CoursesController.ts index c11b878..206f817 100644 --- a/app/Controllers/Http/Api/v1/CoursesController.ts +++ b/app/Controllers/Http/Api/v1/CoursesController.ts @@ -12,6 +12,7 @@ import CourseService from 'App/Services/CourseService'; import AddCourseToUserValidator from 'App/Validators/Course/AddCourseToUserValidator'; import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator'; import DelCourseFromUserValidator from 'App/Validators/Course/DelCourseFromUserValidator'; +import SetCourseStatusValidator from 'App/Validators/Course/SetCourseStatusValidator'; import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator'; import BaseController from '../../BaseController'; @@ -224,6 +225,21 @@ export default class CoursesController extends BaseController { return this.sendResponse(ctx, result.data, result.message, result.status); } + + /** + * Set course status + * POST /courses/:id/set-status + */ + public async setStatus(ctx: HttpContextContract) { + const payload = await ctx.request.validate(SetCourseStatusValidator); + const result = await this.courseService.setCourseStatus(ctx.params.id, payload.status); + + if (!result.success && result.error) { + throw new Exception(result.message, result.status, result.error.code); + } + + return this.sendResponse(ctx, result.data, result.message, result.status); + } } new Ioc().make(CoursesController); diff --git a/app/Models/Course.ts b/app/Models/Course.ts index caccd12..9563947 100644 --- a/app/Models/Course.ts +++ b/app/Models/Course.ts @@ -34,7 +34,7 @@ export default class Course extends BaseModel { @column() public category_id: string; - @column() + @column({ serializeAs: null }) public status: CourseStatusEnum; @belongsTo(() => Category, { diff --git a/app/Repositories/CourseRepository.ts b/app/Repositories/CourseRepository.ts index 3ad6d7c..c64f6ef 100644 --- a/app/Repositories/CourseRepository.ts +++ b/app/Repositories/CourseRepository.ts @@ -1,3 +1,8 @@ +/** + * Datatypes + */ +import CourseStatusEnum from 'App/Datatypes/Enums/CourseStatusEnum'; + /** * Models */ @@ -19,13 +24,28 @@ export default class CourseRepository { this.Course = Course; } + /** + * Set status on course + * + * @param id Course id + * @returns Data result + */ + public async setStatus(id: string | number, status: CourseStatusEnum): Promise { + const data = await this.Course.query().where('id', id).update({ status }).first(); + return data; + } + /** * Get all courses * * @returns List of courses */ public async getAll(): Promise { - const courses = await this.Course.query().preload('teacher').preload('category').preload('lessons'); + const courses = await this.Course.query() + .preload('teacher') + .preload('category') + .preload('lessons') + .where('status', CourseStatusEnum.PUBLISHED); return courses; } @@ -42,6 +62,7 @@ export default class CourseRepository { .preload('lessons') .preload('students') .where('id', id) + .where('status', CourseStatusEnum.PUBLISHED) .first(); return course; @@ -115,7 +136,13 @@ export default class CourseRepository { * @returns Created course */ public async create(data: CreateCourseValidator['schema']['props']): Promise { - const createdCourse = await this.Course.create(data); + const createdCourse = await this.Course.create({ + title: data.title, + description: data.description, + status: CourseStatusEnum.DRAFT, // make course DRAFT before adding lessons + teacher_id: data.teacher_id, + category_id: data.category_id, + }); return createdCourse; } diff --git a/app/Services/CourseService.ts b/app/Services/CourseService.ts index e617157..3928647 100644 --- a/app/Services/CourseService.ts +++ b/app/Services/CourseService.ts @@ -1,10 +1,11 @@ import { inject, Ioc } from '@adonisjs/core/build/standalone'; import { AuthContract } from '@ioc:Adonis/Addons/Auth'; -import RoleEnum from 'App/Datatypes/Enums/RoleEnum'; /** * Datatypes */ +import RoleEnum from 'App/Datatypes/Enums/RoleEnum'; +import CourseStatusEnum from 'App/Datatypes/Enums/CourseStatusEnum'; import StatusCodeEnum from 'App/Datatypes/Enums/StatusCodeEnum'; import IResponse from 'App/Datatypes/Interfaces/IResponse'; import RoleHelper from 'App/Helpers/RoleHelper'; @@ -555,6 +556,30 @@ export default class CourseService { data: {}, }; } + + public async setCourseStatus(id: string | number, status: CourseStatusEnum): Promise { + const data = await this.courseRepository.setStatus(id, status); + console.log(data); + + if (!data) { + return { + success: false, + status: StatusCodeEnum.BAD_REQUEST, + message: `Cannot set status for course with id "${id}"`, + data: {}, + error: { + code: 'E_BAD_REQUEST', + }, + }; + } + + return { + success: true, + status: StatusCodeEnum.OK, + message: 'Status changed.', + data: {}, + }; + } } new Ioc().make(CourseService); diff --git a/app/Validators/Course/SetCourseStatusValidator.ts b/app/Validators/Course/SetCourseStatusValidator.ts new file mode 100644 index 0000000..001c473 --- /dev/null +++ b/app/Validators/Course/SetCourseStatusValidator.ts @@ -0,0 +1,17 @@ +import { schema } from '@ioc:Adonis/Core/Validator'; +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; + +/** + * Datatypes + */ +import CourseStatusEnum from 'App/Datatypes/Enums/CourseStatusEnum'; + +export default class SetCourseStatusValidator { + constructor(protected ctx: HttpContextContract) {} + + public schema = schema.create({ + status: schema.enum(Object.values(CourseStatusEnum)), + }); + + public messages = {}; +} diff --git a/database/migrations/1627300211260_courses.ts b/database/migrations/1627300211260_courses.ts index 58046ea..f1891b4 100644 --- a/database/migrations/1627300211260_courses.ts +++ b/database/migrations/1627300211260_courses.ts @@ -1,5 +1,10 @@ import BaseSchema from '@ioc:Adonis/Lucid/Schema'; +/** + * Datatypes + */ +import CourseStatusEnum from 'App/Datatypes/Enums/CourseStatusEnum'; + export default class Courses extends BaseSchema { protected tableName = 'courses'; @@ -11,7 +16,7 @@ export default class Courses extends BaseSchema { table.string('teacher_id', 21).unsigned().references('users.id').onDelete('CASCADE'); table.string('category_id', 21).unsigned().references('categories.id').onDelete('CASCADE'); table - .enu('status', ['DRAFT', 'PUBLISHED'], { + .enu('status', Object.values(CourseStatusEnum), { useNative: true, enumName: 'course_status', existingType: false, diff --git a/routes/apis/v1/courses.ts b/routes/apis/v1/courses.ts index 43caaee..e85e6d6 100644 --- a/routes/apis/v1/courses.ts +++ b/routes/apis/v1/courses.ts @@ -41,4 +41,8 @@ Route.group(() => { Route.delete('/:id/likes', 'Api/v1/CoursesController.unsetLike') .middleware('role:admin,teacher,student') .as('courses.unset-like'); + + Route.post('/:id/set-status', 'Api/v1/CoursesController.setStatus') + .middleware('role:admin,teacher') + .as('courses.set-status'); }).prefix('courses');