refactor: aseets route & database seeders

This commit is contained in:
Sergey Yarkov 2021-10-23 21:08:08 +03:00
parent ee25d495e1
commit 98a67f1744
16 changed files with 56 additions and 55 deletions

View File

@ -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);

View File

@ -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',

View File

@ -5,7 +5,7 @@ export default class Image extends BaseModel {
@column({ isPrimary: true })
public id: number;
@column({ serializeAs: null })
@column()
public path: string;
@column()

View File

@ -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')

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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',
};
}

View File

@ -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)),

View File

@ -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();

View File

@ -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');

View File

@ -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);
}
}

View File

@ -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
*/

View File

@ -6,11 +6,6 @@ Route.group(() => {
* v1
*/
require('./apis/v1/index');
/**
* Assets routes
*/
require('./apis/assets/index');
})
.prefix('api')
.as('api');

View File

@ -26,4 +26,9 @@ Route.group(() => {
* Api routes
*/
require('./api');
/**
* Serve assets
*/
require('./assets');
});