Add basic author form
This commit is contained in:
@@ -36,7 +36,9 @@ INSERT INTO static_files(name, path) VALUES ('Recherches-philosophiques.jpg', 'R
|
||||
INSERT INTO static_files(name, path) VALUES ('le_chateau.jpg', 'le_chateau.jpg');
|
||||
|
||||
-- authors
|
||||
INSERT INTO authors(created_at, name) VALUES ('NOW', 'Jean-Patrick Manchette');
|
||||
INSERT INTO authors(created_at, name, description) VALUES ('NOW', 'Jean-Patrick Manchette', 'Jean-Patrick Manchette, né le 19 décembre 1942 à Marseille et mort le 3 juin 1995 à Paris 12e, est un écrivain français, auteur de romans policiers, critique littéraire et de cinéma, scénariste et dialoguiste de cinéma, et traducteur.
|
||||
|
||||
Considéré comme l''un des auteurs les plus marquants du polar français des années 1970-1980, il est également connu pour ses opinions libertaires d''extrême gauche, proches de l''Internationale situationniste. Sur la couverture de la plupart de ses ouvrages, il est crédité en tant que J.P. Manchette, ou J-P Manchette.');
|
||||
INSERT INTO authors(created_at, name) VALUES ('NOW', 'Louis-Ferdinand Céline');
|
||||
INSERT INTO authors(created_at, name) VALUES ('NOW', 'Anatole France');
|
||||
INSERT INTO authors(created_at, name) VALUES ('NOW', 'Marguerite Duras');
|
||||
|
||||
30
front/src/AuthorForm.vue
Normal file
30
front/src/AuthorForm.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { getAuthor } from './api.js'
|
||||
import { onBeforeRouteUpdate } from 'vue-router'
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
id: String
|
||||
});
|
||||
|
||||
let data = ref(null);
|
||||
let error = ref(null);
|
||||
|
||||
getAuthor(data, error, props.id);
|
||||
|
||||
onBeforeRouteUpdate(async (to, from) => {
|
||||
getAuthor(data, error, to.params.id);
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="error">{{$t('authorform.error', {err: error.message})}}</div>
|
||||
<div v-if="data">
|
||||
<h3 class="title">{{data.name}}</h3>
|
||||
<p v-if="data.description">{{data.description}}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
@@ -41,6 +41,10 @@ export function getSearchBooks(data, error, searchterm, limit, offset) {
|
||||
return useFetch(data, error, baseUrl + '/search/' + encodeURIComponent(searchterm) + "?" + queryParams.toString());
|
||||
}
|
||||
|
||||
export function getAuthor(data, error, id) {
|
||||
return useFetch(data, error, baseUrl + '/author/' + id);
|
||||
}
|
||||
|
||||
export function getBook(data, error, id) {
|
||||
return useFetch(data, error, baseUrl + '/book/' + id);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@
|
||||
"startread": "Start reading",
|
||||
"wantread": "I want to read it"
|
||||
},
|
||||
"authorform": {
|
||||
"error": "Erreur when loading author: {error}"
|
||||
},
|
||||
"bookform": {
|
||||
"error": "Error when loading book: {error}",
|
||||
"read": "Read",
|
||||
|
||||
@@ -43,6 +43,9 @@
|
||||
"startread": "Commencer la lecture",
|
||||
"wantread": "Je veux le lire"
|
||||
},
|
||||
"authorform": {
|
||||
"error": "Erreur pendant le chargement de l'auteur: {error}"
|
||||
},
|
||||
"bookform": {
|
||||
"error": "Erreur pendant le chargement du livre: {error}",
|
||||
"read": "Lu",
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
import BooksBrowser from './BooksBrowser.vue'
|
||||
import AddBook from './AddBook.vue'
|
||||
import AuthorForm from './AuthorForm.vue'
|
||||
import BookForm from './BookForm.vue'
|
||||
import SignUp from './SignUp.vue'
|
||||
import LogIn from './LogIn.vue'
|
||||
@@ -13,11 +14,11 @@ const routes = [
|
||||
{ path: '/', component: Home },
|
||||
{ path: '/books', component: BooksBrowser },
|
||||
{ path: '/book/:id', component: BookForm, props: true },
|
||||
{ path: '/author/:id', component: AuthorForm, props: true },
|
||||
{ path: '/search/:searchterm', component: SearchBook, props: true },
|
||||
{ path: '/add', component: AddBook },
|
||||
{ path: '/signup', component: SignUp },
|
||||
{ path: '/login', component: LogIn },
|
||||
{ path: '/book', component: LogIn },
|
||||
]
|
||||
|
||||
export const router = createRouter({
|
||||
|
||||
51
internal/apitest/get_author_test.go
Normal file
51
internal/apitest/get_author_test.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package apitest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/testutils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type fetchedAuthor struct {
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
func TestGetAuthor_Ok(t *testing.T) {
|
||||
author := testGetAuthor(t, "1", http.StatusOK)
|
||||
expectedDescription := `Jean-Patrick Manchette, né le 19 décembre 1942 à Marseille et mort le 3 juin 1995 à Paris 12e, est un écrivain français, auteur de romans policiers, critique littéraire et de cinéma, scénariste et dialoguiste de cinéma, et traducteur.
|
||||
|
||||
Considéré comme l'un des auteurs les plus marquants du polar français des années 1970-1980, il est également connu pour ses opinions libertaires d'extrême gauche, proches de l'Internationale situationniste. Sur la couverture de la plupart de ses ouvrages, il est crédité en tant que J.P. Manchette, ou J-P Manchette.`
|
||||
assert.Equal(t, fetchedAuthor{Name: "Jean-Patrick Manchette", Description: expectedDescription}, author)
|
||||
}
|
||||
|
||||
func TestGetAuthor_IdNotFound(t *testing.T) {
|
||||
testGetAuthor(t, "46544", http.StatusNotFound)
|
||||
}
|
||||
|
||||
func TestGetAuthor_IdNotInt(t *testing.T) {
|
||||
testGetAuthor(t, "wrong", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
func testGetAuthor(t *testing.T, authorId string, status int) fetchedAuthor {
|
||||
router := testutils.TestSetup()
|
||||
|
||||
token := testutils.ConnectDemoUser(router)
|
||||
req, _ := http.NewRequest("GET", "/author/"+authorId, nil)
|
||||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
var author fetchedAuthor
|
||||
err := json.Unmarshal(w.Body.Bytes(), &author)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, status, w.Code)
|
||||
return author
|
||||
}
|
||||
38
internal/routes/authorget.go
Normal file
38
internal/routes/authorget.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/appcontext"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/model"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/myvalidator"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type AuthorGet struct {
|
||||
Name string `json:"name" binding:"required,max=100"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
func GetAuthorHandler(ac appcontext.AppContext) {
|
||||
authorId, err := strconv.ParseUint(ac.C.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
ac.C.JSON(http.StatusBadRequest, gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
err = myvalidator.ValidateId(ac.Db, uint(authorId), &model.Author{})
|
||||
if err != nil {
|
||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||
return
|
||||
}
|
||||
var author model.Author
|
||||
res := ac.Db.First(&author, authorId)
|
||||
if res.Error != nil {
|
||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, res.Error)
|
||||
return
|
||||
}
|
||||
ac.C.JSON(http.StatusOK, AuthorGet{
|
||||
Name: author.Name,
|
||||
Description: author.Description})
|
||||
}
|
||||
@@ -29,7 +29,7 @@ func GetBookHandler(ac appcontext.AppContext) {
|
||||
}
|
||||
book, queryErr := query.FetchBookGet(ac.Db, user.ID, bookId)
|
||||
if queryErr != nil {
|
||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, queryErr)
|
||||
return
|
||||
}
|
||||
ac.C.JSON(http.StatusOK, book)
|
||||
|
||||
@@ -66,6 +66,9 @@ func Setup(config *config.Config) *gin.Engine {
|
||||
r.POST("/book", func(c *gin.Context) {
|
||||
routes.PostBookHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
|
||||
})
|
||||
r.GET("/author/:id", func(c *gin.Context) {
|
||||
routes.GetAuthorHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
|
||||
})
|
||||
r.POST("/auth/signup", func(c *gin.Context) {
|
||||
routes.PostSignupHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user