mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-09 15:05:35 +00:00
feat: create edit collection page
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
import PATHS from '#constants/paths';
|
||||
import Collection from '#models/collection';
|
||||
import User from '#models/user';
|
||||
import { collectionValidator } from '#validators/collection';
|
||||
import {
|
||||
createCollectionValidator,
|
||||
updateCollectionValidator,
|
||||
} from '#validators/collection';
|
||||
import type { HttpContext } from '@adonisjs/core/http';
|
||||
|
||||
export default class CollectionsController {
|
||||
// Dashboard
|
||||
async index({ auth, inertia, request, response }: HttpContext) {
|
||||
const collections = await this.getCollectionByAuthorId(auth.user!.id);
|
||||
const collections = await this.getCollectionsByAuthorId(auth.user!.id);
|
||||
if (collections.length === 0) {
|
||||
return response.redirect('/collections/create');
|
||||
}
|
||||
@@ -29,7 +32,7 @@ export default class CollectionsController {
|
||||
|
||||
// Create collection form
|
||||
async showCreatePage({ inertia, auth }: HttpContext) {
|
||||
const collections = await this.getCollectionByAuthorId(auth.user!.id);
|
||||
const collections = await this.getCollectionsByAuthorId(auth.user!.id);
|
||||
return inertia.render('collections/create', {
|
||||
disableHomeLink: collections.length === 0,
|
||||
});
|
||||
@@ -37,7 +40,7 @@ export default class CollectionsController {
|
||||
|
||||
// Method called when creating a collection
|
||||
async store({ request, response, auth }: HttpContext) {
|
||||
const payload = await request.validateUsing(collectionValidator);
|
||||
const payload = await request.validateUsing(createCollectionValidator);
|
||||
const collection = await Collection.create({
|
||||
...payload,
|
||||
authorId: auth.user?.id!,
|
||||
@@ -45,11 +48,54 @@ export default class CollectionsController {
|
||||
return this.redirectToCollectionId(response, collection.id);
|
||||
}
|
||||
|
||||
async getCollectionById(id: Collection['id']) {
|
||||
return await Collection.find(id);
|
||||
async showEditPage({ auth, request, inertia, response }: HttpContext) {
|
||||
const collectionId = request.qs()?.collectionId;
|
||||
if (!collectionId) {
|
||||
return response.redirect('/dashboard');
|
||||
}
|
||||
|
||||
const collection = await this.getCollectionById(
|
||||
collectionId,
|
||||
auth.user!.id
|
||||
);
|
||||
return inertia.render('collections/edit', {
|
||||
collection,
|
||||
});
|
||||
}
|
||||
|
||||
async getCollectionByAuthorId(authorId: User['id']) {
|
||||
/**
|
||||
* Get collection by id.
|
||||
*
|
||||
* /!\ Only return private collection (create by the current user)
|
||||
*/
|
||||
async getCollectionById(id: Collection['id'], userId: User['id']) {
|
||||
return await Collection.query()
|
||||
.where('id', id)
|
||||
.andWhere('author_id', userId)
|
||||
.firstOrFail();
|
||||
}
|
||||
|
||||
async update({ request, auth, response }: HttpContext) {
|
||||
const { params, ...payload } = await request.validateUsing(
|
||||
updateCollectionValidator
|
||||
);
|
||||
|
||||
// Cant use validator (vinejs) custom rule 'cause its too generic,
|
||||
// because we have to find a collection by identifier and
|
||||
// check whether the current user is the author.
|
||||
// https://vinejs.dev/docs/extend/custom_rules
|
||||
await this.getCollectionById(params.id, auth.user!.id);
|
||||
|
||||
await Collection.updateOrCreate(
|
||||
{
|
||||
id: params.id,
|
||||
},
|
||||
payload
|
||||
);
|
||||
return this.redirectToCollectionId(response, params.id);
|
||||
}
|
||||
|
||||
async getCollectionsByAuthorId(authorId: User['id']) {
|
||||
return await Collection.query()
|
||||
.where('author_id', authorId)
|
||||
.preload('links');
|
||||
|
||||
@@ -10,7 +10,7 @@ export default class LinksController {
|
||||
|
||||
async showCreatePage({ auth, inertia }: HttpContext) {
|
||||
const collections =
|
||||
await this.collectionsController.getCollectionByAuthorId(auth.user!.id);
|
||||
await this.collectionsController.getCollectionsByAuthorId(auth.user!.id);
|
||||
return inertia.render('links/create', { collections });
|
||||
}
|
||||
|
||||
@@ -18,7 +18,10 @@ export default class LinksController {
|
||||
const { collectionId, ...payload } =
|
||||
await request.validateUsing(linkValidator);
|
||||
|
||||
await this.collectionsController.getCollectionById(collectionId);
|
||||
await this.collectionsController.getCollectionById(
|
||||
collectionId,
|
||||
auth.user!.id
|
||||
);
|
||||
await Link.create({
|
||||
...payload,
|
||||
collectionId,
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import PATHS from '#constants/paths';
|
||||
import { ExceptionHandler, HttpContext } from '@adonisjs/core/http';
|
||||
import app from '@adonisjs/core/services/app';
|
||||
import { HttpContext, ExceptionHandler } from '@adonisjs/core/http';
|
||||
import type { StatusPageRange, StatusPageRenderer } from '@adonisjs/core/types/http';
|
||||
import type {
|
||||
StatusPageRange,
|
||||
StatusPageRenderer,
|
||||
} from '@adonisjs/core/types/http';
|
||||
import { errors } from '@adonisjs/lucid';
|
||||
|
||||
export default class HttpExceptionHandler extends ExceptionHandler {
|
||||
/**
|
||||
@@ -21,8 +26,10 @@ export default class HttpExceptionHandler extends ExceptionHandler {
|
||||
* to return the HTML contents to send as a response.
|
||||
*/
|
||||
protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
|
||||
'404': (error, { inertia }) => inertia.render('errors/not_found', { error }),
|
||||
'500..599': (error, { inertia }) => inertia.render('errors/server_error', { error }),
|
||||
'404': (error, { inertia }) =>
|
||||
inertia.render('errors/not_found', { error }),
|
||||
'500..599': (error, { inertia }) =>
|
||||
inertia.render('errors/server_error', { error }),
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -30,6 +37,9 @@ export default class HttpExceptionHandler extends ExceptionHandler {
|
||||
* response to the client
|
||||
*/
|
||||
async handle(error: unknown, ctx: HttpContext) {
|
||||
if (error instanceof errors.E_ROW_NOT_FOUND) {
|
||||
return ctx.response.redirect(PATHS.DASHBOARD);
|
||||
}
|
||||
return super.handle(error, ctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,29 @@
|
||||
import vine, { SimpleMessagesProvider } from '@vinejs/vine';
|
||||
import { Visibility } from '../enums/visibility.js';
|
||||
|
||||
export const collectionValidator = vine.compile(
|
||||
export const createCollectionValidator = vine.compile(
|
||||
vine.object({
|
||||
name: vine.string().trim().minLength(1).maxLength(254),
|
||||
description: vine.string().trim().maxLength(300).optional(),
|
||||
description: vine.string().trim().maxLength(254).nullable(),
|
||||
visibility: vine.enum(Visibility),
|
||||
nextId: vine.string().optional(),
|
||||
})
|
||||
);
|
||||
|
||||
collectionValidator.messagesProvider = new SimpleMessagesProvider({
|
||||
export const updateCollectionValidator = vine.compile(
|
||||
vine.object({
|
||||
name: vine.string().trim().minLength(1).maxLength(254),
|
||||
description: vine.string().trim().maxLength(254).nullable(),
|
||||
visibility: vine.enum(Visibility),
|
||||
nextId: vine.string().optional(),
|
||||
|
||||
params: vine.object({
|
||||
id: vine.string().trim(),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
createCollectionValidator.messagesProvider = new SimpleMessagesProvider({
|
||||
name: 'Collection name is required',
|
||||
'visibility.required': 'Collection visibiliy is required',
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user