diff --git a/app/Controllers/Http/ExperiencesController.ts b/app/Controllers/Http/ExperiencesController.ts new file mode 100644 index 0000000..d27ffb0 --- /dev/null +++ b/app/Controllers/Http/ExperiencesController.ts @@ -0,0 +1,60 @@ +import {HttpContextContract} from "@ioc:Adonis/Core/HttpContext"; +import Experience from "App/Models/Experience"; +import ExperienceStoreValidator from "App/Validators/experience/ExperienceStoreValidator"; +import getTranslation from "App/Tasks/getTranslation"; +import ExperienceUpdateValidator from "App/Validators/experience/ExperienceUpdateValidator"; + +export default class ExperiencesController { + + public async index ({ response }: HttpContextContract) { + const experiences = await Experience + .query() + .orderBy('begin_date', 'desc') + .preload('title') + return response.status(200).send({ + experiences: experiences + }) + } + + public async store ({ request, response }: HttpContextContract) { + const data = await request.validate(ExperienceStoreValidator) + const experience = await Experience.create(data) + await experience.related('title').associate(await getTranslation(data.title)) + + return response.status(200).send({ + experience: experience + }) + } + + public async show ({ params, response }: HttpContextContract) { + const experience = await Experience.findOrFail(params.id) + experience.load('title') + return response.status(200).send({ + experience + }) + } + + public async update ({ request, params, response }: HttpContextContract) { + const data = await request.validate(ExperienceUpdateValidator) + const experience = await Experience.findOrFail(params.id) + + if (data.title) { + await experience.related('title').associate(await getTranslation(data.title)) + } + + await experience.merge(data).save() + + return response.status(200).send({ + experience + }) + } + + public async destroy ({ response, params }: HttpContextContract) { + const experience = await Experience.findOrFail(params.id) + await experience.delete() + return response.status(200).send({ + message: 'Experience successfully deleted!' + }) + } + +} diff --git a/app/Controllers/Http/FormationsController.ts b/app/Controllers/Http/FormationsController.ts new file mode 100644 index 0000000..e392e2b --- /dev/null +++ b/app/Controllers/Http/FormationsController.ts @@ -0,0 +1,68 @@ +import {HttpContextContract} from "@ioc:Adonis/Core/HttpContext"; +import getTranslation from "App/Tasks/getTranslation"; +import FormationStoreValidator from "App/Validators/formation/FormationStoreValidator"; +import FormationUpdateValidator from "App/Validators/formation/FormationUpdateValidator"; +import Formation from "App/Models/Formation"; + +export default class FormationsController { + + public async index ({ response }: HttpContextContract) { + const formations = await Formation + .query() + .orderBy('begin_date', 'desc') + .preload('title') + .preload('description') + return response.status(200).send({ + formations: formations + }) + } + + public async store ({ request, response }: HttpContextContract) { + const data = await request.validate(FormationStoreValidator) + const formation = await Formation.create(data) + + await formation.related('title').associate(await getTranslation(data.title)) + await formation.related('description').associate(await getTranslation(data.description)) + + return response.status(200).send({ + formation: formation + }) + } + + public async show ({ params, response }: HttpContextContract) { + const formation = await Formation.findOrFail(params.id) + formation.load('title') + formation.load('description') + return response.status(200).send({ + formation + }) + } + + public async update ({ request, params, response }: HttpContextContract) { + const data = await request.validate(FormationUpdateValidator) + const formation = await Formation.findOrFail(params.id) + + if (data.title) { + await formation.related('title').associate(await getTranslation(data.title)) + } + + if (data.description) { + await formation.related('description').associate(await getTranslation(data.description)) + } + + await formation.merge(data).save() + + return response.status(200).send({ + formation + }) + } + + public async destroy ({ response, params }: HttpContextContract) { + const formation = await Formation.findOrFail(params.id) + await formation.delete() + return response.status(200).send({ + message: 'Formation successfully deleted!' + }) + } + +} diff --git a/app/Models/Experience.ts b/app/Models/Experience.ts new file mode 100644 index 0000000..c11cd71 --- /dev/null +++ b/app/Models/Experience.ts @@ -0,0 +1,34 @@ +import { DateTime } from 'luxon' +import {BaseModel, BelongsTo, belongsTo, column} from '@ioc:Adonis/Lucid/Orm' +import Translation from "App/Models/Translation"; + +export default class Experience extends BaseModel { + @column({ isPrimary: true }) + public id: number + + @belongsTo(() => Translation, { + foreignKey: 'titleId' + }) + public title: BelongsTo + + @column() + public titleId: number + + @column() + public company: string + + @column() + public location: string + + @column() + public beginDate: string + + @column() + public endDate: string + + @column.dateTime({ autoCreate: true }) + public createdAt: DateTime + + @column.dateTime({ autoCreate: true, autoUpdate: true }) + public updatedAt: DateTime +} diff --git a/app/Models/Formation.ts b/app/Models/Formation.ts new file mode 100644 index 0000000..eab04c5 --- /dev/null +++ b/app/Models/Formation.ts @@ -0,0 +1,39 @@ +import { DateTime } from 'luxon' +import {BaseModel, BelongsTo, belongsTo, column} from '@ioc:Adonis/Lucid/Orm' +import Translation from "App/Models/Translation"; + +export default class Formation extends BaseModel { + @column({ isPrimary: true }) + public id: number + + @belongsTo(() => Translation, { + foreignKey: 'titleId' + }) + public title: BelongsTo + + @column() + public titleId: number + + @belongsTo(() => Translation, { + foreignKey: 'descriptionId' + }) + public description: BelongsTo + + @column() + public descriptionId: number + + @column() + public location: string + + @column() + public beginDate: string + + @column() + public endDate: string + + @column.dateTime({ autoCreate: true }) + public createdAt: DateTime + + @column.dateTime({ autoCreate: true, autoUpdate: true }) + public updatedAt: DateTime +} diff --git a/app/Validators/experience/ExperienceStoreValidator.ts b/app/Validators/experience/ExperienceStoreValidator.ts new file mode 100644 index 0000000..1bd3e2e --- /dev/null +++ b/app/Validators/experience/ExperienceStoreValidator.ts @@ -0,0 +1,19 @@ +import { schema } from '@ioc:Adonis/Core/Validator' +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' + +export default class ExperienceStoreValidator { + constructor (protected ctx: HttpContextContract) { + } + + public schema = schema.create({ + title: schema.string(), + company: schema.string(), + location: schema.string(), + beginDate: schema.string(), + endDate: schema.string() + }) + + public messages = { + required: 'The field {{field}} is required' + } +} diff --git a/app/Validators/experience/ExperienceUpdateValidator.ts b/app/Validators/experience/ExperienceUpdateValidator.ts index 3c6af58..03bec85 100644 --- a/app/Validators/experience/ExperienceUpdateValidator.ts +++ b/app/Validators/experience/ExperienceUpdateValidator.ts @@ -5,38 +5,15 @@ export default class ExperienceUpdateValidator { constructor (protected ctx: HttpContextContract) { } - /* - * Define schema to validate the "shape", "type", "formatting" and "integrity" of data. - * - * For example: - * 1. The username must be of data type string. But then also, it should - * not contain special characters or numbers. - * ``` - * schema.string({}, [ rules.alpha() ]) - * ``` - * - * 2. The email must be of data type string, formatted as a valid - * email. But also, not used by any other user. - * ``` - * schema.string({}, [ - * rules.email(), - * rules.unique({ table: 'users', column: 'email' }), - * ]) - * ``` - */ public schema = schema.create({ + title: schema.string.optional(), + company: schema.string.optional(), + location: schema.string.optional(), + beginDate: schema.string.optional(), + endDate: schema.string.optional() }) - /** - * Custom messages for validation failures. You can make use of dot notation `(.)` - * for targeting nested fields and array expressions `(*)` for targeting all - * children of an array. For example: - * - * { - * 'profile.username.required': 'Username is required', - * 'scores.*.number': 'Define scores as valid numbers' - * } - * - */ - public messages = {} + public messages = { + required: 'The field {{field}} is required' + } } diff --git a/app/Validators/formation/FormationStoreValidator.ts b/app/Validators/formation/FormationStoreValidator.ts new file mode 100644 index 0000000..613af84 --- /dev/null +++ b/app/Validators/formation/FormationStoreValidator.ts @@ -0,0 +1,19 @@ +import { schema } from '@ioc:Adonis/Core/Validator' +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' + +export default class FormationStoreValidator { + constructor (protected ctx: HttpContextContract) { + } + + public schema = schema.create({ + title: schema.string(), + description: schema.string(), + location: schema.string(), + beginDate: schema.string(), + endDate: schema.string() + }) + + public messages = { + required: 'The field {{field}} is required' + } +} diff --git a/app/Validators/formation/FormationUpdateValidator.ts b/app/Validators/formation/FormationUpdateValidator.ts new file mode 100644 index 0000000..f331d41 --- /dev/null +++ b/app/Validators/formation/FormationUpdateValidator.ts @@ -0,0 +1,19 @@ +import { schema } from '@ioc:Adonis/Core/Validator' +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' + +export default class FormationUpdateValidator { + constructor (protected ctx: HttpContextContract) { + } + + public schema = schema.create({ + title: schema.string.optional(), + description: schema.string.optional(), + location: schema.string.optional(), + beginDate: schema.string.optional(), + endDate: schema.string.optional() + }) + + public messages = { + required: 'The field {{field}} is required' + } +} diff --git a/database/migrations/1629143076777_experiences.ts b/database/migrations/1629143076777_experiences.ts new file mode 100644 index 0000000..18a90dc --- /dev/null +++ b/database/migrations/1629143076777_experiences.ts @@ -0,0 +1,25 @@ +import BaseSchema from '@ioc:Adonis/Lucid/Schema' + +export default class Experiences extends BaseSchema { + protected tableName = 'experiences' + + public async up () { + this.schema.createTable(this.tableName, (table) => { + table.increments('id').primary() + table + .increments('title_id') + .unsigned() + .references('translations.id') + .onDelete('CASCADE') + table.string('company').notNullable() + table.string('location').notNullable() + table.string('begin_date').notNullable() + table.string('end_date').defaultTo('Today').notNullable() + table.timestamps(true, true) + }) + } + + public async down () { + this.schema.dropTable(this.tableName) + } +} diff --git a/database/migrations/1629145139594_formations.ts b/database/migrations/1629145139594_formations.ts new file mode 100644 index 0000000..2360fd9 --- /dev/null +++ b/database/migrations/1629145139594_formations.ts @@ -0,0 +1,29 @@ +import BaseSchema from '@ioc:Adonis/Lucid/Schema' + +export default class Formations extends BaseSchema { + protected tableName = 'formations' + + public async up () { + this.schema.createTable(this.tableName, (table) => { + table.increments('id').primary() + table + .integer('title_id') + .unsigned() + .references('translations.id') + .onDelete('CASCADE') + table + .integer('description_id') + .unsigned() + .references('translations.id') + .onDelete('CASCADE') + table.string('location').notNullable() + table.string('begin_date').notNullable() + table.string('end_date').defaultTo('Today').notNullable() + table.timestamps(true, true) + }) + } + + public async down () { + this.schema.dropTable(this.tableName) + } +} diff --git a/start/routes/artsite.ts b/start/routes/artsite.ts index 3bf6630..56fd905 100644 --- a/start/routes/artsite.ts +++ b/start/routes/artsite.ts @@ -5,6 +5,10 @@ Route.group(() => { Route.resource('/announces', 'AnnouncesController').except(['edit', 'create']) + Route.resource('/experiences', 'ExperiencesController').except(['edit', 'create']) + + Route.resource('/formations', 'FormationsController').except(['edit', 'create']) + Route.resource('/skills', 'SkillsController').except(['edit', 'create']) Route.resource('/projects', 'ProjectsController').except(['edit', 'create'])