mirror of
https://github.com/sergeyyarkov/educt-server.git
synced 2026-10-11 18:29:15 +03:00
refactor: aseets route & database seeders
This commit is contained in:
parent
ee25d495e1
commit
98a67f1744
@ -19,7 +19,7 @@ export default class AssetsController extends BaseController {
|
||||
|
||||
/**
|
||||
* Send background image of course
|
||||
* GET /media/images/courses/:fileName
|
||||
* GET /assets/images/courses/:fileName
|
||||
*/
|
||||
public async serveCourseImage(ctx: HttpContextContract) {
|
||||
const result = await this.assetsService.getCourseImagePath(ctx.params.fileName);
|
||||
|
||||
@ -17,14 +17,14 @@ import Category from 'App/Models/Category';
|
||||
import Lesson from 'App/Models/Lesson';
|
||||
import User from 'App/Models/User';
|
||||
import CourseStatusEnum from 'App/Datatypes/Enums/CourseStatusEnum';
|
||||
import Image from './Image';
|
||||
// import Image from './Image';
|
||||
|
||||
export default class Course extends BaseModel {
|
||||
@column({ isPrimary: true })
|
||||
public id: string;
|
||||
|
||||
@column({ serializeAs: null })
|
||||
public bg_image_id: number;
|
||||
@column()
|
||||
public bg_image_path: string;
|
||||
|
||||
@column()
|
||||
public title: string;
|
||||
@ -46,10 +46,10 @@ export default class Course extends BaseModel {
|
||||
})
|
||||
public category: BelongsTo<typeof Category>;
|
||||
|
||||
@belongsTo(() => Image, {
|
||||
foreignKey: 'bg_image_id',
|
||||
})
|
||||
public image: BelongsTo<typeof Image>;
|
||||
// @belongsTo(() => Image, {
|
||||
// foreignKey: 'bg_image_id',
|
||||
// })
|
||||
// public image: BelongsTo<typeof Image>;
|
||||
|
||||
@belongsTo(() => User, {
|
||||
foreignKey: 'teacher_id',
|
||||
|
||||
@ -5,7 +5,7 @@ export default class Image extends BaseModel {
|
||||
@column({ isPrimary: true })
|
||||
public id: number;
|
||||
|
||||
@column({ serializeAs: null })
|
||||
@column()
|
||||
public path: string;
|
||||
|
||||
@column()
|
||||
|
||||
@ -59,12 +59,7 @@ export default class CourseRepository {
|
||||
query.andWhere('status', status);
|
||||
}
|
||||
|
||||
const courses = await query
|
||||
.preload('category')
|
||||
.preload('image')
|
||||
.withCount('students')
|
||||
.withCount('likes')
|
||||
.withCount('lessons');
|
||||
const courses = await query.preload('category').withCount('students').withCount('likes').withCount('lessons');
|
||||
|
||||
return courses;
|
||||
}
|
||||
@ -81,7 +76,6 @@ export default class CourseRepository {
|
||||
.preload('category')
|
||||
.preload('lessons')
|
||||
.preload('students')
|
||||
.preload('image')
|
||||
.where('id', id)
|
||||
.where('status', CourseStatusEnum.PUBLISHED)
|
||||
.first();
|
||||
@ -190,7 +184,7 @@ export default class CourseRepository {
|
||||
* Create new course
|
||||
*/
|
||||
const course = await this.Course.create({
|
||||
bg_image_id: data.bg_image_id,
|
||||
bg_image_path: data.image?.filePath,
|
||||
title: data.title,
|
||||
description: data.description,
|
||||
status: data.status,
|
||||
@ -210,7 +204,6 @@ export default class CourseRepository {
|
||||
public async delete(id: string | number): Promise<Course | null> {
|
||||
const course = await this.Course.query()
|
||||
.preload('category')
|
||||
.preload('image')
|
||||
.withCount('students')
|
||||
.withCount('likes')
|
||||
.withCount('lessons')
|
||||
|
||||
@ -25,11 +25,11 @@ export default class ImageRepository {
|
||||
return images;
|
||||
}
|
||||
|
||||
public async create(file: MultipartFileContract): Promise<Image> {
|
||||
public async create({ file, location }: { file: MultipartFileContract; location: string }): Promise<Image> {
|
||||
/**
|
||||
* Save image to disk
|
||||
*/
|
||||
await file.moveToDisk('images/courses');
|
||||
await file.moveToDisk(location);
|
||||
|
||||
/**
|
||||
* Save image to database
|
||||
|
||||
@ -312,11 +312,6 @@ export default class CourseService {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete background image from course
|
||||
*/
|
||||
await this.imageRepository.delete(course.bg_image_id);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
status: HttpStatusEnum.OK,
|
||||
|
||||
@ -47,7 +47,7 @@ export default class ImageService {
|
||||
}
|
||||
|
||||
public async createImage(data: CreateImageValidator['schema']['props']): Promise<IResponse> {
|
||||
const image = await this.imageRepository.create(data.image);
|
||||
const image = await this.imageRepository.create({ file: data.image, location: 'images' });
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
||||
@ -10,11 +10,14 @@ export default class UpdateContactsValidator {
|
||||
locales: ['ru-RU', 'en-US'],
|
||||
strict: true,
|
||||
}),
|
||||
rules.unique({ table: 'contacts', column: 'phone_number' }),
|
||||
]),
|
||||
vk_id: schema.string.optional({}, [rules.regex(/^([a-zA-Z0-9_]){1,64}$/)]),
|
||||
twitter_id: schema.string.optional({}, [rules.regex(/(^|[^@\w])@(\w{1,15})\b/)]),
|
||||
telegram_id: schema.string.optional({}, [rules.regex(/(^|[^@\w])@(\w{1,64})\b/)]),
|
||||
});
|
||||
|
||||
public messages = {};
|
||||
public messages = {
|
||||
'phone_number.unique': 'This phone number is not available',
|
||||
};
|
||||
}
|
||||
|
||||
@ -8,7 +8,10 @@ export default class CreateCourseValidator {
|
||||
public schema = schema.create({
|
||||
title: schema.string(),
|
||||
description: schema.string(),
|
||||
bg_image_id: schema.number.optional([rules.exists({ table: 'images', column: 'id' })]),
|
||||
image: schema.file.optional({
|
||||
size: '10mb',
|
||||
extnames: ['jpg', 'jpeg', 'png'],
|
||||
}),
|
||||
teacher_id: schema.string({}, [rules.exists({ table: 'users', column: 'id' })]),
|
||||
category_id: schema.string({}, [rules.exists({ table: 'categories', column: 'id' })]),
|
||||
status: schema.enum(Object.values(CourseStatusEnum)),
|
||||
|
||||
@ -13,6 +13,7 @@ import Contact from 'App/Models/Contact';
|
||||
import Course from 'App/Models/Course';
|
||||
import Lesson from 'App/Models/Lesson';
|
||||
import LessonContent from 'App/Models/LessonContent';
|
||||
import Role from 'App/Models/Role';
|
||||
import User from 'App/Models/User';
|
||||
|
||||
export const ContactFactory = Factory.define(Contact, ({ faker }) => {
|
||||
@ -25,7 +26,7 @@ export const UserFactory = Factory.define(User, ({ faker }) => {
|
||||
return {
|
||||
first_name: faker.name.firstName(),
|
||||
last_name: faker.name.lastName(),
|
||||
login: `${faker.lorem.word(6)}${faker.datatype.number(10)}`,
|
||||
login: `${faker.lorem.word(12)}${faker.datatype.number(100)}`,
|
||||
email: faker.internet.exampleEmail(),
|
||||
password: '123456',
|
||||
};
|
||||
@ -33,6 +34,25 @@ export const UserFactory = Factory.define(User, ({ faker }) => {
|
||||
.relation('contacts', () => ContactFactory)
|
||||
.build();
|
||||
|
||||
export const TeacherFactory = Factory.define(User, ({ faker }) => {
|
||||
return {
|
||||
first_name: faker.name.firstName(),
|
||||
last_name: faker.name.lastName(),
|
||||
login: `${faker.lorem.word(12)}${faker.datatype.number(100)}`,
|
||||
email: faker.internet.exampleEmail(),
|
||||
password: '123456',
|
||||
};
|
||||
})
|
||||
.relation('contacts', () => ContactFactory)
|
||||
.after('create', async (_, user: User) => {
|
||||
/**
|
||||
* Get teacher role to attach after create new user
|
||||
*/
|
||||
const role = await Role.findByOrFail('slug', 'teacher');
|
||||
user.related('roles').attach([role.id]);
|
||||
})
|
||||
.build();
|
||||
|
||||
export const LessonContentFactory = Factory.define(LessonContent, ({ faker }) => {
|
||||
return {
|
||||
video_url: `https://www.youtube.com/embed/${faker.datatype.string(10)}`,
|
||||
@ -64,5 +84,5 @@ export const CourseFactory = Factory.define(Course, ({ faker }) => {
|
||||
})
|
||||
.relation('category', () => CategoryFactory)
|
||||
.relation('lessons', () => LessonFactory)
|
||||
// .relation('teacher', () => UserFactory)
|
||||
.relation('teacher', () => TeacherFactory)
|
||||
.build();
|
||||
|
||||
@ -11,7 +11,7 @@ export default class Courses extends BaseSchema {
|
||||
public async up() {
|
||||
this.schema.createTable(this.tableName, table => {
|
||||
table.string('id', 21).primary();
|
||||
table.integer('bg_image_id').unsigned().references('images.id').onDelete('SET NULL');
|
||||
table.string('bg_image_path');
|
||||
table.string('title').notNullable();
|
||||
table.string('description').notNullable();
|
||||
table.string('teacher_id', 21).unsigned().references('users.id').onDelete('CASCADE');
|
||||
|
||||
@ -1,21 +1,15 @@
|
||||
import BaseSeeder from '@ioc:Adonis/Lucid/Seeder';
|
||||
import Course from 'App/Models/Course';
|
||||
import User from 'App/Models/User';
|
||||
import { CourseFactory } from 'Database/factories';
|
||||
|
||||
export default class CourseSeeder extends BaseSeeder {
|
||||
private User: typeof User;
|
||||
private CourseFactory: typeof CourseFactory;
|
||||
|
||||
public async run() {
|
||||
this.User = User;
|
||||
this.CourseFactory = CourseFactory;
|
||||
|
||||
const teacher = await this.User.query()
|
||||
.preload('roles')
|
||||
.whereHas('roles', q => q.where('slug', 'teacher'))
|
||||
.firstOrFail();
|
||||
|
||||
await CourseFactory.with('category')
|
||||
.with('lessons', 2, lessonFactory => lessonFactory.with('content'))
|
||||
.createMany(3, (course: Course) => course.related('teacher').associate(teacher));
|
||||
await this.CourseFactory.with('lessons', 2, lessonFactory => lessonFactory.with('content'))
|
||||
.with('category')
|
||||
.with('teacher')
|
||||
.createMany(3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,6 @@ export default class UserSeeder extends BaseSeeder {
|
||||
*/
|
||||
const roles = {
|
||||
admin: await Role.findByOrFail('slug', 'admin'),
|
||||
teacher: await Role.findByOrFail('slug', 'teacher'),
|
||||
student: await Role.findByOrFail('slug', 'student'),
|
||||
};
|
||||
|
||||
@ -27,12 +26,6 @@ export default class UserSeeder extends BaseSeeder {
|
||||
});
|
||||
await userAdmin.related('roles').attach([roles.admin.id]);
|
||||
|
||||
/**
|
||||
* Teacher
|
||||
*/
|
||||
const userTeacher = await UserFactory.with('contacts').create();
|
||||
await userTeacher.related('roles').attach([roles.teacher.id]);
|
||||
|
||||
/**
|
||||
* Student
|
||||
*/
|
||||
|
||||
@ -6,11 +6,6 @@ Route.group(() => {
|
||||
* v1
|
||||
*/
|
||||
require('./apis/v1/index');
|
||||
|
||||
/**
|
||||
* Assets routes
|
||||
*/
|
||||
require('./apis/assets/index');
|
||||
})
|
||||
.prefix('api')
|
||||
.as('api');
|
||||
|
||||
@ -26,4 +26,9 @@ Route.group(() => {
|
||||
* Api routes
|
||||
*/
|
||||
require('./api');
|
||||
|
||||
/**
|
||||
* Serve assets
|
||||
*/
|
||||
require('./assets');
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user