Collection: new widget to add book to collection
This commit is contained in:
95
front/src/AddBookToCollection.vue
Normal file
95
front/src/AddBookToCollection.vue
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { getSearchBooks, postCollectionAddBook, extractFormErrorFromField } from './api.js'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
collectionId: Number,
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['created'])
|
||||||
|
|
||||||
|
const book = ref({
|
||||||
|
id: 0,
|
||||||
|
title: '',
|
||||||
|
})
|
||||||
|
const addingBook = ref(false)
|
||||||
|
const data = ref(null)
|
||||||
|
const error = ref(null)
|
||||||
|
const titleError = computed(() => {
|
||||||
|
return extractFormErrorFromField('Title', error.value)
|
||||||
|
})
|
||||||
|
const vFocus = {
|
||||||
|
mounted: (el) => el.focus(),
|
||||||
|
}
|
||||||
|
|
||||||
|
const limit = 5
|
||||||
|
|
||||||
|
function fetchBooks() {
|
||||||
|
if (!book || book.value.title.length < 3) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const lang = navigator.language.substring(0, 2)
|
||||||
|
getSearchBooks(data, error, book.value.title, lang, 0, limit, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
function addBook(bookId) {
|
||||||
|
postCollectionAddBook(props.collectionId, bookId).then((res) => {
|
||||||
|
if (res.ok) {
|
||||||
|
addingBook.value = false
|
||||||
|
book.value.id = 0
|
||||||
|
book.value.title = ''
|
||||||
|
data.value = null
|
||||||
|
error.value = null
|
||||||
|
emit('created')
|
||||||
|
} else {
|
||||||
|
res.json().then((json) => {
|
||||||
|
console.log(json)
|
||||||
|
error.value = json
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="field has-addons">
|
||||||
|
<div v-if="addingBook" class="control">
|
||||||
|
<input
|
||||||
|
:class="'input is-large ' + (titleError ? 'is-danger' : '')"
|
||||||
|
v-focus
|
||||||
|
@keyup="fetchBooks()"
|
||||||
|
type="text"
|
||||||
|
maxlength="300"
|
||||||
|
v-model="book.title"
|
||||||
|
:placeholder="$t('addbook.title')"
|
||||||
|
/>
|
||||||
|
<p v-if="titleError" class="help is-danger">{{ titleError }}</p>
|
||||||
|
<ul v-if="data" class="popupresults has-background-dark">
|
||||||
|
<li v-for="book in data.books" @click="addBook(book.id)" class="bookresult p-2">
|
||||||
|
{{ book.title }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div v-if="!addingBook" class="control">
|
||||||
|
<button @click="addingBook = true" class="button is-large mb-2">
|
||||||
|
<span class="icon" :title="$t('collections.add')">
|
||||||
|
<b-icon-plus />
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.popupresults {
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookresult {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookresult:hover {
|
||||||
|
background-color: var(--bulma-text-40);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { getCollection } from './api.js'
|
import { getCollection } from './api.js'
|
||||||
import CollectionFormBookItem from './CollectionFormBookItem.vue'
|
import CollectionFormBookItem from './CollectionFormBookItem.vue'
|
||||||
|
import AddBookToCollection from './AddBookToCollection.vue'
|
||||||
import Pagination from './Pagination.vue'
|
import Pagination from './Pagination.vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -27,14 +28,20 @@ getCollection(data, error, props.id, limit, offset.value)
|
|||||||
function pageChange(newPageNumber) {
|
function pageChange(newPageNumber) {
|
||||||
pageNumber.value = newPageNumber
|
pageNumber.value = newPageNumber
|
||||||
data.value = null
|
data.value = null
|
||||||
|
error.value = null
|
||||||
getCollection(data, error, props.id, limit, offset.value)
|
getCollection(data, error, props.id, limit, offset.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fetchCollection() {
|
||||||
|
pageChange(1)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="error">{{ $t('bookform.error', { error: error.message }) }}</div>
|
<div v-if="error">{{ $t('bookform.error', { error: error.message }) }}</div>
|
||||||
<div v-if="data">
|
<div v-if="data">
|
||||||
<h2 class="title">{{ data.name }}</h2>
|
<h2 class="title">{{ data.name }}</h2>
|
||||||
|
<AddBookToCollection :collection-id="props.id" @created="fetchCollection" />
|
||||||
<div>
|
<div>
|
||||||
<CollectionFormBookItem v-for="book in data.books" :key="book.id" v-bind="book" />
|
<CollectionFormBookItem v-for="book in data.books" :key="book.id" v-bind="book" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -36,7 +36,15 @@ function fetchData(searchTerm, authorId) {
|
|||||||
error.value = null
|
error.value = null
|
||||||
if (searchTerm != null) {
|
if (searchTerm != null) {
|
||||||
const lang = navigator.language.substring(0, 2)
|
const lang = navigator.language.substring(0, 2)
|
||||||
getSearchBooks(data, error, searchTerm, lang, forceSearchInventaire.value, limit, offset.value)
|
getSearchBooks(
|
||||||
|
data,
|
||||||
|
error,
|
||||||
|
searchTerm,
|
||||||
|
lang,
|
||||||
|
forceSearchInventaire.value ? 2 : 1,
|
||||||
|
limit,
|
||||||
|
offset.value,
|
||||||
|
)
|
||||||
} else if (authorId != null) {
|
} else if (authorId != null) {
|
||||||
getAuthorBooks(data, error, authorId, limit, offset.value)
|
getAuthorBooks(data, error, authorId, limit, offset.value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,14 @@ export function postCollection(collection) {
|
|||||||
return genericPayloadCall('/ws/collection', collection, 'POST')
|
return genericPayloadCall('/ws/collection', collection, 'POST')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function postCollectionAddBook(collectionId, bookId) {
|
||||||
|
return genericPayloadCall(
|
||||||
|
'/ws/collection/' + collectionId + '/addbook',
|
||||||
|
{ bookId: bookId },
|
||||||
|
'POST',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function putBook(id, book) {
|
export function putBook(id, book) {
|
||||||
return genericPayloadCall('/ws/book/edit/' + id, book.value, 'PUT')
|
return genericPayloadCall('/ws/book/edit/' + id, book.value, 'PUT')
|
||||||
}
|
}
|
||||||
@@ -219,10 +227,9 @@ export function genericPayloadCall(apiRoute, object, method) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function extractFormErrorFromField(fieldName, errors) {
|
export function extractFormErrorFromField(fieldName, errors) {
|
||||||
if (errors == null) {
|
if (errors == null || typeof errors == 'undefined' || !Array.isArray(errors)) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
console.log(errors.value)
|
|
||||||
const titleErr = errors.find((e) => e['field'] === fieldName)
|
const titleErr = errors.find((e) => e['field'] === fieldName)
|
||||||
if (typeof titleErr !== 'undefined') {
|
if (typeof titleErr !== 'undefined') {
|
||||||
return titleErr.error
|
return titleErr.error
|
||||||
|
|||||||
64
internal/apitest/post_collection_addbook_test.go
Normal file
64
internal/apitest/post_collection_addbook_test.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package apitest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.artlef.fr/bibliomane/internal/testutils"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPostCollectionBookHandler_Ok(t *testing.T) {
|
||||||
|
payload :=
|
||||||
|
`{
|
||||||
|
"bookId": 9
|
||||||
|
}`
|
||||||
|
collectionId := "1"
|
||||||
|
status := testPostCollectionBookHandler(t, collectionId, payload)
|
||||||
|
assert.Equal(t, http.StatusOK, status)
|
||||||
|
_, collection := testGetCollection(t, collectionId, "10", "0")
|
||||||
|
assert.Equal(t, int64(7), collection.Count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostCollectionBookHandler_CollectionNotFound(t *testing.T) {
|
||||||
|
payload :=
|
||||||
|
`{
|
||||||
|
"bookId": 9
|
||||||
|
}`
|
||||||
|
status := testPostCollectionBookHandler(t, "12", payload)
|
||||||
|
assert.Equal(t, http.StatusNotFound, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostCollectionBookHandler_BookNotFound(t *testing.T) {
|
||||||
|
payload :=
|
||||||
|
`{
|
||||||
|
"bookId": 14654
|
||||||
|
}`
|
||||||
|
status := testPostCollectionBookHandler(t, "1", payload)
|
||||||
|
assert.Equal(t, http.StatusNotFound, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostCollectionBookHandler_Unauthorized(t *testing.T) {
|
||||||
|
payload :=
|
||||||
|
`{
|
||||||
|
"bookId": 9
|
||||||
|
}`
|
||||||
|
status := testPostCollectionBookHandler(t, "3", payload)
|
||||||
|
assert.Equal(t, http.StatusUnauthorized, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPostCollectionBookHandler(t *testing.T, collectionId string, payload string) int {
|
||||||
|
router := testutils.TestSetup()
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
token := testutils.ConnectDemoUser(router)
|
||||||
|
req, _ := http.NewRequest("POST", "/ws/collection/"+collectionId+"/addbook",
|
||||||
|
strings.NewReader(payload))
|
||||||
|
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||||
|
router.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
return w.Code
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package apitest
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@@ -15,14 +16,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestSearchBook_MultipleBooks(t *testing.T) {
|
func TestSearchBook_MultipleBooks(t *testing.T) {
|
||||||
result := testSearchBook(t, "san", "", "")
|
result := testSearchBook(t, "san", "", "", dto.NoInventaireSearch)
|
||||||
|
|
||||||
assert.Equal(t, int64(2), result.Count)
|
assert.Equal(t, int64(2), result.Count)
|
||||||
assert.Equal(t, 2, len(result.Books))
|
assert.Equal(t, 2, len(result.Books))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchBook_OneBookNotUserBook(t *testing.T) {
|
func TestSearchBook_OneBookNotUserBook(t *testing.T) {
|
||||||
result := testSearchBook(t, "iliade", "", "")
|
result := testSearchBook(t, "iliade", "", "", dto.NoInventaireSearch)
|
||||||
assert.Equal(t, int64(1), result.Count)
|
assert.Equal(t, int64(1), result.Count)
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
[]dto.BookItemGet{{
|
[]dto.BookItemGet{{
|
||||||
@@ -38,7 +39,7 @@ func TestSearchBook_OneBookNotUserBook(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchBook_OneBookRead(t *testing.T) {
|
func TestSearchBook_OneBookRead(t *testing.T) {
|
||||||
result := testSearchBook(t, "dieux", "", "")
|
result := testSearchBook(t, "dieux", "", "", dto.NoInventaireSearch)
|
||||||
assert.Equal(t, int64(1), result.Count)
|
assert.Equal(t, int64(1), result.Count)
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
[]dto.BookItemGet{{
|
[]dto.BookItemGet{{
|
||||||
@@ -55,7 +56,7 @@ func TestSearchBook_OneBookRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchBook_OneBookStartRead(t *testing.T) {
|
func TestSearchBook_OneBookStartRead(t *testing.T) {
|
||||||
result := testSearchBook(t, "Recherches", "", "")
|
result := testSearchBook(t, "Recherches", "", "", dto.NoInventaireSearch)
|
||||||
assert.Equal(t, int64(1), result.Count)
|
assert.Equal(t, int64(1), result.Count)
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
[]dto.BookItemGet{{
|
[]dto.BookItemGet{{
|
||||||
@@ -72,7 +73,7 @@ func TestSearchBook_OneBookStartRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchBook_ISBN(t *testing.T) {
|
func TestSearchBook_ISBN(t *testing.T) {
|
||||||
result := testSearchBook(t, "9782070337903", "", "")
|
result := testSearchBook(t, "9782070337903", "", "", dto.NoInventaireSearch)
|
||||||
assert.Equal(t, int64(1), result.Count)
|
assert.Equal(t, int64(1), result.Count)
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
[]dto.BookItemGet{{
|
[]dto.BookItemGet{{
|
||||||
@@ -88,7 +89,7 @@ func TestSearchBook_ISBN(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchBook_ISBNInventaire(t *testing.T) {
|
func TestSearchBook_ISBNInventaire(t *testing.T) {
|
||||||
result := testSearchBook(t, "9782253158400", "", "")
|
result := testSearchBook(t, "9782253158400", "", "", dto.InventaireIfNothingFound)
|
||||||
assert.Equal(t, int64(1), result.Count)
|
assert.Equal(t, int64(1), result.Count)
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
[]dto.BookItemGet{{
|
[]dto.BookItemGet{{
|
||||||
@@ -107,17 +108,17 @@ func TestSearchBook_ISBNInventaire(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchBook_Limit(t *testing.T) {
|
func TestSearchBook_Limit(t *testing.T) {
|
||||||
result := testSearchBook(t, "a", "10", "")
|
result := testSearchBook(t, "a", "10", "", dto.NoInventaireSearch)
|
||||||
assert.Equal(t, 10, len(result.Books))
|
assert.Equal(t, 10, len(result.Books))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchBook_Offset(t *testing.T) {
|
func TestSearchBook_Offset(t *testing.T) {
|
||||||
result := testSearchBook(t, "sa", "", "2")
|
result := testSearchBook(t, "sa", "", "2", dto.NoInventaireSearch)
|
||||||
assert.Equal(t, int64(5), result.Count)
|
assert.Equal(t, int64(5), result.Count)
|
||||||
assert.Equal(t, 3, len(result.Books))
|
assert.Equal(t, 3, len(result.Books))
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSearchBook(t *testing.T, searchterm string, limit string, offset string) dto.BookItemsGet {
|
func testSearchBook(t *testing.T, searchterm string, limit string, offset string, inventaireSearchType dto.InventaireSearchType) dto.BookItemsGet {
|
||||||
router := testutils.TestSetup()
|
router := testutils.TestSetup()
|
||||||
|
|
||||||
u, err := url.Parse("/ws/search/" + searchterm)
|
u, err := url.Parse("/ws/search/" + searchterm)
|
||||||
@@ -137,6 +138,7 @@ func testSearchBook(t *testing.T, searchterm string, limit string, offset string
|
|||||||
|
|
||||||
q := u.Query()
|
q := u.Query()
|
||||||
q.Set("lang", "fr")
|
q.Set("lang", "fr")
|
||||||
|
q.Set("inventaire", strconv.Itoa(int(inventaireSearchType)))
|
||||||
u.RawQuery = q.Encode()
|
u.RawQuery = q.Encode()
|
||||||
|
|
||||||
token := testutils.ConnectDemoUser(router)
|
token := testutils.ConnectDemoUser(router)
|
||||||
|
|||||||
@@ -5,9 +5,17 @@ type AuthorGet struct {
|
|||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InventaireSearchType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
NoInventaireSearch InventaireSearchType = iota
|
||||||
|
InventaireIfNothingFound
|
||||||
|
ForceInventaireSearch
|
||||||
|
)
|
||||||
|
|
||||||
type BookSearchGetParam struct {
|
type BookSearchGetParam struct {
|
||||||
Lang string `form:"lang" binding:"max=5"`
|
Lang string `form:"lang" binding:"max=5"`
|
||||||
Inventaire bool `form:"inventaire"`
|
Inventaire InventaireSearchType `form:"inventaire"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BookFields struct {
|
type BookFields struct {
|
||||||
@@ -39,6 +47,10 @@ type CollectionFields struct {
|
|||||||
Name string `json:"name" binding:"required,max=300"`
|
Name string `json:"name" binding:"required,max=300"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CollectionBook struct {
|
||||||
|
BookID uint `json:"bookId" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
type FileInfoPost struct {
|
type FileInfoPost struct {
|
||||||
FileID uint `json:"fileId"`
|
FileID uint `json:"fileId"`
|
||||||
FilePath string `json:"filepath"`
|
FilePath string `json:"filepath"`
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ func ReturnErrorsAsJsonResponse(ac *appcontext.AppContext, err error) {
|
|||||||
ac.C.JSON(httpError.StatusCode, gin.H{"error": httpError.Err.Error()})
|
ac.C.JSON(httpError.StatusCode, gin.H{"error": httpError.Err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
ac.C.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||||
|
}
|
||||||
ac.C.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
ac.C.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func GetSearchBooksHandler(ac appcontext.AppContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var returnedBooks dto.BookItemsGet
|
var returnedBooks dto.BookItemsGet
|
||||||
if !params.Inventaire {
|
if params.Inventaire != dto.ForceInventaireSearch {
|
||||||
books, err := query.FetchBookSearchGet(ac.Db, user.ID, searchterm, limit, offset)
|
books, err := query.FetchBookSearchGet(ac.Db, user.ID, searchterm, limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||||
@@ -51,7 +51,7 @@ func GetSearchBooksHandler(ac appcontext.AppContext) {
|
|||||||
}
|
}
|
||||||
returnedBooks = dto.BookItemsGet{Count: count, Inventaire: false, Books: books}
|
returnedBooks = dto.BookItemsGet{Count: count, Inventaire: false, Books: books}
|
||||||
}
|
}
|
||||||
if params.Inventaire || len(returnedBooks.Books) == 0 {
|
if (params.Inventaire == dto.InventaireIfNothingFound && len(returnedBooks.Books) == 0) || (params.Inventaire == dto.ForceInventaireSearch) {
|
||||||
returnedBooksPtr, err := searchInInventaireAPI(ac.Config.InventaireUrl, searchterm, limit, offset, params)
|
returnedBooksPtr, err := searchInInventaireAPI(ac.Config.InventaireUrl, searchterm, limit, offset, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||||
|
|||||||
62
internal/routes/collectionaddbookpost.go
Normal file
62
internal/routes/collectionaddbookpost.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"git.artlef.fr/bibliomane/internal/appcontext"
|
||||||
|
"git.artlef.fr/bibliomane/internal/dto"
|
||||||
|
"git.artlef.fr/bibliomane/internal/i18nresource"
|
||||||
|
"git.artlef.fr/bibliomane/internal/model"
|
||||||
|
"git.artlef.fr/bibliomane/internal/myvalidator"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PostCollectionBookHandler(ac appcontext.AppContext) {
|
||||||
|
collectionId, err := strconv.ParseUint(ac.C.Param("id"), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
ac.C.JSON(http.StatusBadRequest, gin.H{"error": err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := ac.GetAuthenticatedUser()
|
||||||
|
if err != nil {
|
||||||
|
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var collection model.Collection
|
||||||
|
err = ac.Db.First(&collection, collectionId).Error
|
||||||
|
if err != nil {
|
||||||
|
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if collection.UserID != user.ID {
|
||||||
|
err := myvalidator.HttpError{
|
||||||
|
StatusCode: http.StatusUnauthorized,
|
||||||
|
Err: errors.New(i18nresource.GetTranslatedMessage(&ac, "Unauthorized")),
|
||||||
|
}
|
||||||
|
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var collectionBook dto.CollectionBook
|
||||||
|
err = ac.C.ShouldBindJSON(&collectionBook)
|
||||||
|
if err != nil {
|
||||||
|
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var book model.Book
|
||||||
|
err = ac.Db.First(&book, collectionBook.BookID).Error
|
||||||
|
if err != nil {
|
||||||
|
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
collection.Books = append(collection.Books, book)
|
||||||
|
ac.Db.Save(&collection)
|
||||||
|
ac.C.String(http.StatusOK, "Success")
|
||||||
|
}
|
||||||
@@ -84,6 +84,9 @@ func Setup(config *config.Config) *gin.Engine {
|
|||||||
ws.GET("/collection/:id", func(c *gin.Context) {
|
ws.GET("/collection/:id", func(c *gin.Context) {
|
||||||
routes.GetCollectionHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
|
routes.GetCollectionHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
|
||||||
})
|
})
|
||||||
|
ws.POST("/collection/:id/addbook", func(c *gin.Context) {
|
||||||
|
routes.PostCollectionBookHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
|
||||||
|
})
|
||||||
ws.POST("/collection", func(c *gin.Context) {
|
ws.POST("/collection", func(c *gin.Context) {
|
||||||
routes.PostCollectionHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
|
routes.PostCollectionHandler(appcontext.AppContext{C: c, Db: db, I18n: bundle, Config: config})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user