Added inventaire import from ISBN
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { putReadBook, getImagePathOrDefault } from './api.js'
|
||||
import { putReadBook, getImagePathOrDefault, postImportBook } from './api.js'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter();
|
||||
@@ -8,6 +8,7 @@
|
||||
const props = defineProps({
|
||||
id: Number,
|
||||
inventaireid: String,
|
||||
isinventaireedition: Boolean,
|
||||
title: String,
|
||||
author: String,
|
||||
description: String,
|
||||
@@ -19,20 +20,32 @@
|
||||
const imagePathOrDefault = computed(() => getImagePathOrDefault(props.coverPath));
|
||||
const error = ref(null)
|
||||
|
||||
async function onUserBookRead() {
|
||||
const res = await putReadBook(props.id);
|
||||
if (res.ok) {
|
||||
router.push('/books')
|
||||
} else {
|
||||
res.json().then((json) => (error.value = json));
|
||||
async function onUserBookRead() {
|
||||
const res = await putReadBook(props.id);
|
||||
if (res.ok) {
|
||||
router.push('/books')
|
||||
} else {
|
||||
res.json().then((json) => (error.value = json));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openBook() {
|
||||
if (props.id != 0) {
|
||||
router.push(`/book/${props.id}`);
|
||||
async function openBook() {
|
||||
if (props.id != 0) {
|
||||
router.push(`/book/${props.id}`);
|
||||
} else if (props.isinventaireedition) {
|
||||
importInventaireEdition()
|
||||
} else if (props.inventaireid != "") {
|
||||
router.push(`/import/inventaire/${props.inventaireid}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function importInventaireEdition(inventaireid) {
|
||||
const res = await postImportBook(props.inventaireid, navigator.language.substring(0,2));
|
||||
const json = await res.json();
|
||||
if (res.ok) {
|
||||
router.push(`/book/${json.id}`);
|
||||
} else {
|
||||
router.push(`/import/inventaire/${props.inventaireid}`)
|
||||
error.value = json;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,25 +9,11 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/dto"
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/testutils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type bookSearchGet struct {
|
||||
Count int64 `json:"count"`
|
||||
Books []bookSearchGetBook `json:"books"`
|
||||
}
|
||||
|
||||
type bookSearchGetBook struct {
|
||||
Id uint `json:"id"`
|
||||
Title string `json:"title" binding:"required,max=300"`
|
||||
Author string `json:"author" binding:"max=100"`
|
||||
Rating int `json:"rating"`
|
||||
Read bool `json:"read"`
|
||||
WantRead bool `json:"wantread"`
|
||||
CoverPath string `json:"coverPath"`
|
||||
}
|
||||
|
||||
func TestSearchBook_MultipleBooks(t *testing.T) {
|
||||
result := testSearchBook(t, "san", "", "")
|
||||
|
||||
@@ -39,10 +25,10 @@ func TestSearchBook_OneBookNotUserBook(t *testing.T) {
|
||||
result := testSearchBook(t, "iliade", "", "")
|
||||
assert.Equal(t, int64(1), result.Count)
|
||||
assert.Equal(t,
|
||||
[]bookSearchGetBook{{
|
||||
[]dto.BookSearchGetBook{{
|
||||
Title: "Iliade",
|
||||
Author: "Homère",
|
||||
Id: 29,
|
||||
ID: 29,
|
||||
Rating: 0,
|
||||
Read: false,
|
||||
WantRead: false,
|
||||
@@ -55,10 +41,10 @@ func TestSearchBook_OneBookRead(t *testing.T) {
|
||||
result := testSearchBook(t, "dieux", "", "")
|
||||
assert.Equal(t, int64(1), result.Count)
|
||||
assert.Equal(t,
|
||||
[]bookSearchGetBook{{
|
||||
[]dto.BookSearchGetBook{{
|
||||
Title: "Les dieux ont soif",
|
||||
Author: "Anatole France",
|
||||
Id: 4,
|
||||
ID: 4,
|
||||
Rating: 7,
|
||||
Read: true,
|
||||
WantRead: false,
|
||||
@@ -71,10 +57,10 @@ func TestSearchBook_ISBN(t *testing.T) {
|
||||
result := testSearchBook(t, "9782070337903", "", "")
|
||||
assert.Equal(t, int64(1), result.Count)
|
||||
assert.Equal(t,
|
||||
[]bookSearchGetBook{{
|
||||
[]dto.BookSearchGetBook{{
|
||||
Title: "Le complot contre l'Amérique",
|
||||
Author: "Philip Roth",
|
||||
Id: 22,
|
||||
ID: 22,
|
||||
Rating: 6,
|
||||
Read: true,
|
||||
WantRead: false,
|
||||
@@ -83,6 +69,25 @@ func TestSearchBook_ISBN(t *testing.T) {
|
||||
result.Books)
|
||||
}
|
||||
|
||||
func TestSearchBook_ISBNInventaire(t *testing.T) {
|
||||
result := testSearchBook(t, "9782253158400", "", "")
|
||||
assert.Equal(t, int64(1), result.Count)
|
||||
assert.Equal(t,
|
||||
[]dto.BookSearchGetBook{{
|
||||
ID: 0,
|
||||
Title: "Les premières enquêtes de Maigret",
|
||||
Author: "Georges Simenon",
|
||||
Description: "roman de Georges Simenon",
|
||||
InventaireID: "isbn:9782253158400",
|
||||
IsInventaireEdition: true,
|
||||
Rating: 0,
|
||||
Read: false,
|
||||
WantRead: false,
|
||||
CoverPath: "https://inventaire.io/img/entities/17663a503d984204078c910d5bae68d52942b47d",
|
||||
}},
|
||||
result.Books)
|
||||
}
|
||||
|
||||
func TestSearchBook_Limit(t *testing.T) {
|
||||
result := testSearchBook(t, "a", "10", "")
|
||||
assert.Equal(t, 10, len(result.Books))
|
||||
@@ -94,7 +99,7 @@ func TestSearchBook_Offset(t *testing.T) {
|
||||
assert.Equal(t, 3, len(result.Books))
|
||||
}
|
||||
|
||||
func testSearchBook(t *testing.T, searchterm string, limit string, offset string) bookSearchGet {
|
||||
func testSearchBook(t *testing.T, searchterm string, limit string, offset string) dto.BookSearchGet {
|
||||
router := testutils.TestSetup()
|
||||
|
||||
u, err := url.Parse("/search/" + searchterm)
|
||||
@@ -112,13 +117,17 @@ func testSearchBook(t *testing.T, searchterm string, limit string, offset string
|
||||
u.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
q := u.Query()
|
||||
q.Set("lang", "fr")
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
token := testutils.ConnectDemoUser(router)
|
||||
req, _ := http.NewRequest("GET", u.String(), nil)
|
||||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
var result bookSearchGet
|
||||
var result dto.BookSearchGet
|
||||
s := w.Body.String()
|
||||
err = json.Unmarshal([]byte(s), &result)
|
||||
if err != nil {
|
||||
|
||||
@@ -37,13 +37,14 @@ type BookSearchGet struct {
|
||||
}
|
||||
|
||||
type BookSearchGetBook struct {
|
||||
ID uint `json:"id"`
|
||||
Title string `json:"title" binding:"required,max=300"`
|
||||
Author string `json:"author" binding:"max=100"`
|
||||
Description string `json:"description"`
|
||||
InventaireID string `json:"inventaireid"`
|
||||
Rating int `json:"rating"`
|
||||
Read bool `json:"read"`
|
||||
WantRead bool `json:"wantread"`
|
||||
CoverPath string `json:"coverPath"`
|
||||
ID uint `json:"id"`
|
||||
Title string `json:"title" binding:"required,max=300"`
|
||||
Author string `json:"author" binding:"max=100"`
|
||||
Description string `json:"description"`
|
||||
InventaireID string `json:"inventaireid"`
|
||||
IsInventaireEdition bool `json:"isinventaireedition"`
|
||||
Rating int `json:"rating"`
|
||||
Read bool `json:"read"`
|
||||
WantRead bool `json:"wantread"`
|
||||
CoverPath string `json:"coverPath"`
|
||||
}
|
||||
|
||||
@@ -125,3 +125,27 @@ func TestCallInventaireEdition(t *testing.T) {
|
||||
},
|
||||
result)
|
||||
}
|
||||
|
||||
func TestCallInventaireEditionFromISBN(t *testing.T) {
|
||||
result, err := CallInventaireFromISBN("9782070379248", "fr")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t,
|
||||
&InventaireEditionDetailedSingleResult{
|
||||
Id: "isbn:9782070379248",
|
||||
Title: "Du côté de chez swann",
|
||||
Author: &InventaireAuthorResult{
|
||||
ID: "Q7199",
|
||||
Name: "Marcel Proust",
|
||||
Description: "écrivain, critique et essayiste français",
|
||||
},
|
||||
Description: "roman de Marcel Proust",
|
||||
ISBN: "978-2-07-037924-8",
|
||||
Publisher: "Éditions Gallimard",
|
||||
ReleaseDate: "1988",
|
||||
Image: "https://inventaire.io/img/entities/646a3ef031d6a1adc27cb5f556d2a403a2f525a7",
|
||||
Lang: "fr",
|
||||
},
|
||||
result)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,14 @@ type InventaireEditionDetailedSingleResult struct {
|
||||
Lang string
|
||||
}
|
||||
|
||||
type ErrorEditionNotFound struct {
|
||||
InventaireId string
|
||||
}
|
||||
|
||||
func (e *ErrorEditionNotFound) Error() string {
|
||||
return fmt.Sprintf("No edition found on inventaire for id %s\n", e.InventaireId)
|
||||
}
|
||||
|
||||
func CallInventaireEdition(inventaireId string, lang string) (InventaireEditionDetailedSingleResult, error) {
|
||||
var result InventaireEditionDetailedSingleResult
|
||||
editionQueryResults, err := callInventaireEditionEntities([]string{inventaireId})
|
||||
@@ -24,7 +32,7 @@ func CallInventaireEdition(inventaireId string, lang string) (InventaireEditionD
|
||||
}
|
||||
var editionQueryResult inventaireEditionQueryEntity
|
||||
if len(editionQueryResults.Entities) < 1 {
|
||||
return result, fmt.Errorf("No edition found on inventaire for id %s", inventaireId)
|
||||
return result, &ErrorEditionNotFound{InventaireId: inventaireId}
|
||||
}
|
||||
|
||||
editionQueryResult = editionQueryResults.Entities[0]
|
||||
|
||||
16
internal/inventaire/inventaireeditionfromisbn.go
Normal file
16
internal/inventaire/inventaireeditionfromisbn.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package inventaire
|
||||
|
||||
import "errors"
|
||||
|
||||
func CallInventaireFromISBN(isbn string, lang string) (*InventaireEditionDetailedSingleResult, error) {
|
||||
inventaireInfo, err := CallInventaireEdition("isbn:"+isbn, lang)
|
||||
if err != nil {
|
||||
if errors.Is(err, &ErrorEditionNotFound{}) {
|
||||
//suppress the not found error, returns nil instead
|
||||
return nil, nil
|
||||
} else {
|
||||
return &inventaireInfo, err
|
||||
}
|
||||
}
|
||||
return &inventaireInfo, err
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.artlef.fr/PersonalLibraryManager/internal/appcontext"
|
||||
@@ -51,17 +52,64 @@ func GetSearchBooksHandler(ac appcontext.AppContext) {
|
||||
returnedBooks = dto.BookSearchGet{Count: count, Inventaire: false, Books: books}
|
||||
}
|
||||
if params.Inventaire || len(returnedBooks.Books) == 0 {
|
||||
queryResult, err := inventaire.CallInventaireSearch(searchterm, params.Lang, limit, offset)
|
||||
returnedBooksPtr, err := searchInInventaireAPI(searchterm, limit, offset, params)
|
||||
if err != nil {
|
||||
myvalidator.ReturnErrorsAsJsonResponse(&ac, err)
|
||||
return
|
||||
}
|
||||
returnedBooks = InventaireBooksToBookSearchGet(queryResult)
|
||||
returnedBooks = *returnedBooksPtr
|
||||
}
|
||||
ac.C.JSON(http.StatusOK, returnedBooks)
|
||||
}
|
||||
|
||||
func InventaireBooksToBookSearchGet(results inventaire.InventaireSearchResult) dto.BookSearchGet {
|
||||
func searchInInventaireAPI(searchterm string, limit int, offset int, params dto.BookSearchGetParam) (*dto.BookSearchGet, error) {
|
||||
|
||||
isIsbn, err := regexp.Match(`\d{10,13}`, []byte(searchterm))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isIsbn {
|
||||
queryResult, err := inventaire.CallInventaireFromISBN(searchterm, params.Lang)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var bookSearchGet dto.BookSearchGet
|
||||
if queryResult != nil {
|
||||
bookSearchGet = inventaireEditionToBookSearchGet(*queryResult)
|
||||
} else {
|
||||
bookSearchGet = dto.BookSearchGet{Count: 0, Inventaire: true}
|
||||
}
|
||||
return &bookSearchGet, err
|
||||
} else {
|
||||
queryResult, err := inventaire.CallInventaireSearch(searchterm, params.Lang, limit, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bookSearchGet := inventaireBooksToBookSearchGet(queryResult)
|
||||
return &bookSearchGet, err
|
||||
}
|
||||
}
|
||||
|
||||
func inventaireEditionToBookSearchGet(result inventaire.InventaireEditionDetailedSingleResult) dto.BookSearchGet {
|
||||
var books []dto.BookSearchGetBook
|
||||
bookSearchGetBook := dto.BookSearchGetBook{
|
||||
ID: 0,
|
||||
Title: result.Title,
|
||||
Author: result.Author.Name,
|
||||
Description: result.Description,
|
||||
InventaireID: result.Id,
|
||||
IsInventaireEdition: true,
|
||||
Rating: 0,
|
||||
Read: false,
|
||||
WantRead: false,
|
||||
CoverPath: result.Image,
|
||||
}
|
||||
books = append(books, bookSearchGetBook)
|
||||
return dto.BookSearchGet{Count: 1, Inventaire: true, Books: books}
|
||||
}
|
||||
|
||||
func inventaireBooksToBookSearchGet(results inventaire.InventaireSearchResult) dto.BookSearchGet {
|
||||
var books []dto.BookSearchGetBook
|
||||
for _, b := range results.Results {
|
||||
coverPath := ""
|
||||
|
||||
Reference in New Issue
Block a user