v0.09
This commit is contained in:
1
backend/Cargo.lock
generated
1
backend/Cargo.lock
generated
@@ -423,6 +423,7 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"entity",
|
"entity",
|
||||||
"error-chain",
|
"error-chain",
|
||||||
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ tower = "^0.4"
|
|||||||
tower-http = { version = "^0.3", features = ["full"] }
|
tower-http = { version = "^0.3", features = ["full"] }
|
||||||
tracing = "^0.1"
|
tracing = "^0.1"
|
||||||
tracing-subscriber = "^0.3"
|
tracing-subscriber = "^0.3"
|
||||||
|
itertools = "0.10"
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
version = "^0.9.2" # sea-orm version
|
version = "^0.9.2" # sea-orm version
|
||||||
|
|||||||
@@ -15,19 +15,47 @@ use tower::ServiceBuilder;
|
|||||||
use tower_http::cors::CorsLayer;
|
use tower_http::cors::CorsLayer;
|
||||||
use tower_http::trace::TraceLayer;
|
use tower_http::trace::TraceLayer;
|
||||||
use booksman_orm::{
|
use booksman_orm::{
|
||||||
sea_orm::{Database, DatabaseConnection},
|
sea_orm::{Database, DatabaseConnection, ActiveValue},
|
||||||
Mutation as MutationCore, Query as QueryCore,
|
Mutation as MutationCore, Query as QueryCore,
|
||||||
};
|
};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::iter::Peekable;
|
||||||
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn};
|
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
|
struct BookUI {
|
||||||
|
id: i32,
|
||||||
|
open_library_key: Option<String>,
|
||||||
|
title: String,
|
||||||
|
edition_count: Option<i32>,
|
||||||
|
first_publish_year: Option<i32>,
|
||||||
|
median_page_count: Option<i32>,
|
||||||
|
goodread_id: Option<String>,
|
||||||
|
description: Option<String>,
|
||||||
|
cover: Option<String>,
|
||||||
|
location: Option<String>,
|
||||||
|
time_added: Option<String>,
|
||||||
|
rating: Option<i32>,
|
||||||
|
comments: Option<String>,
|
||||||
|
author_name: Option<Vec<String>>,
|
||||||
|
person: Option<Vec<String>>,
|
||||||
|
place: Option<Vec<String>>,
|
||||||
|
subject: Option<Vec<String>>,
|
||||||
|
time: Option<Vec<String>>,
|
||||||
|
isbn: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
struct Docs {
|
struct Docs {
|
||||||
key: String,
|
key: String,
|
||||||
title: String,
|
title: String,
|
||||||
first_publish_year: Option<u32>,
|
edition_count: Option<i32>,
|
||||||
number_of_pages_median: Option<u32>,
|
first_publish_year: Option<i32>,
|
||||||
|
number_of_pages_median: Option<i32>,
|
||||||
|
goodread_id: Option<String>,
|
||||||
|
description: Option<String>,
|
||||||
isbn: Option<Vec<String>>,
|
isbn: Option<Vec<String>>,
|
||||||
cover_i: Option<u32>,
|
cover_i: Option<i32>,
|
||||||
cover_url: Option<String>,
|
cover_url: Option<String>,
|
||||||
author_name: Option<Vec<String>>,
|
author_name: Option<Vec<String>>,
|
||||||
person: Option<Vec<String>>,
|
person: Option<Vec<String>>,
|
||||||
@@ -133,9 +161,35 @@ async fn search_openlibrary(
|
|||||||
resjson.docs.truncate(10);
|
resjson.docs.truncate(10);
|
||||||
resjson.set_all_cover_urls();
|
resjson.set_all_cover_urls();
|
||||||
print!("Search token {:?}\n", search);
|
print!("Search token {:?}\n", search);
|
||||||
return Json(resjson);
|
let mut vec = Vec::with_capacity(10);
|
||||||
|
for i in 0..10 as usize {
|
||||||
|
let doc = resjson.docs[i].clone();
|
||||||
|
vec.push(
|
||||||
|
BookUI{
|
||||||
|
id: (i+1) as i32,
|
||||||
|
open_library_key: Some(doc.key),
|
||||||
|
title: doc.title,
|
||||||
|
edition_count: doc.edition_count,
|
||||||
|
first_publish_year: doc.first_publish_year,
|
||||||
|
median_page_count: doc.number_of_pages_median,
|
||||||
|
goodread_id: doc.goodread_id,
|
||||||
|
description: doc.description,
|
||||||
|
cover: doc.cover_url,
|
||||||
|
location: None,
|
||||||
|
time_added: None,
|
||||||
|
rating: None,
|
||||||
|
comments: None,
|
||||||
|
author_name: doc.author_name,
|
||||||
|
person: doc.person,
|
||||||
|
place: doc.place,
|
||||||
|
subject: doc.subject,
|
||||||
|
time: doc.time,
|
||||||
|
isbn: doc.isbn
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Json(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn delete_book(
|
async fn delete_book(
|
||||||
Extension(ref conn): Extension<DatabaseConnection>,
|
Extension(ref conn): Extension<DatabaseConnection>,
|
||||||
@@ -150,34 +204,126 @@ async fn delete_book(
|
|||||||
async fn list_book(
|
async fn list_book(
|
||||||
Extension(ref conn): Extension<DatabaseConnection>,
|
Extension(ref conn): Extension<DatabaseConnection>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let books = QueryCore::find_books_in_page(conn,1,5)
|
let books = QueryCore::find_books_plus_meta_in_page(conn,1,5)
|
||||||
.await
|
.await
|
||||||
.expect("could not list books");
|
.expect("could not list books");
|
||||||
"success"
|
let res: Vec<BookUI> = (books.0).iter()
|
||||||
|
.group_by(|x| (x.id, x.title.clone()) ).into_iter().peekable()
|
||||||
|
.map(|((id,title), group )| BookUI{
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
open_library_key: group.map( |u| u.open_library_key).peek(),
|
||||||
|
edition_count: group.clone().map(|u| u.edition_count).next(),
|
||||||
|
first_publish_year: group.clone().map(|u| u.first_publish_year).next(),
|
||||||
|
median_page_count: group.clone().map(|u| u.median_page_count).next(),
|
||||||
|
goodread_id: group.clone().map(|u| u.goodread_id).next(),
|
||||||
|
description: group.clone().map(|u| u.description).next(),
|
||||||
|
cover: group.clone().map(|u| u.cover).next(),
|
||||||
|
location: group.clone().map(|u| u.location).next(),
|
||||||
|
time_added: group.clone().map(|u| u.time_added).next(),
|
||||||
|
rating: group.clone().map(|u| u.rating).next(),
|
||||||
|
comments: group.clone().map(|u| u.comments).next(),
|
||||||
|
author_name: Some(group.map(|u| u.author_name).collect()),
|
||||||
|
person: Some(group.map(|u| u.person).collect()),
|
||||||
|
place: Some(group.map(|u| u.place).collect()),
|
||||||
|
subject: Some(group.map(|u| u.subject).collect()),
|
||||||
|
time: Some(group.map(|u| u.time).collect()),
|
||||||
|
isbn: Some(group.map(|u| u.isbn).collect()),
|
||||||
|
}).collect();
|
||||||
|
return Json(res);
|
||||||
|
// "success"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn create_book(
|
async fn create_book(
|
||||||
Extension(ref conn): Extension<DatabaseConnection>,
|
Extension(ref conn): Extension<DatabaseConnection>,
|
||||||
doc_sent : Form<Docs>,
|
doc_sent : Form<BookUI>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let book: book::Model = book::Model{
|
let book: book::Model = book::Model{
|
||||||
open_library_key: "NONE".to_string(),
|
open_library_key: doc_sent.open_library_key.to_owned(),
|
||||||
title: (doc_sent.title.to_owned()),
|
title: (doc_sent.title.to_owned()),
|
||||||
edition_count: 1,
|
edition_count: doc_sent.edition_count.to_owned(),
|
||||||
first_publish_year: 1,//(doc_sent.first_publish_year.unwrap().to_owned()),
|
first_publish_year: (doc_sent.first_publish_year.to_owned()),
|
||||||
median_page_count: 1, //(doc_sent.number_of_pages_median.unwrap().to_owned()),
|
median_page_count: (doc_sent.median_page_count.to_owned()),
|
||||||
goodread_id: "NONE".to_string(),
|
goodread_id: doc_sent.goodread_id.to_owned(),
|
||||||
description: "NONE".to_string(),
|
description: doc_sent.description.to_owned(),
|
||||||
comments: "NONE".to_string(),
|
comments: doc_sent.comments.to_owned(),
|
||||||
cover: "NONE".to_string(),
|
cover: doc_sent.cover.to_owned(),
|
||||||
rating: 1,
|
rating: doc_sent.rating.to_owned(),
|
||||||
time_added: "NONE".to_string(),
|
time_added: doc_sent.time_added.to_owned(),
|
||||||
id: 1,
|
id: 1,
|
||||||
location: "NONE".to_string(),
|
location: doc_sent.location.to_owned(),
|
||||||
};
|
};
|
||||||
let created_book = MutationCore::create_book(conn, book)
|
let created_book = MutationCore::create_book(conn, book)
|
||||||
.await
|
.await
|
||||||
.expect("could not create book");
|
.expect("could not create book");
|
||||||
|
|
||||||
|
for author_name in doc_sent.author_name.as_ref().unwrap().iter() {
|
||||||
|
let record : book_author::Model = book_author::Model{
|
||||||
|
id: 1,
|
||||||
|
book_id: (created_book.last_insert_id),
|
||||||
|
author_name: author_name.to_owned(),
|
||||||
|
};
|
||||||
|
MutationCore::create_book_author(conn, record)
|
||||||
|
.await
|
||||||
|
.expect("could not create book");
|
||||||
|
}
|
||||||
|
for person in doc_sent.person.as_ref().unwrap().iter() {
|
||||||
|
let record : book_person::Model = book_person::Model{
|
||||||
|
id: 1,
|
||||||
|
book_id: (created_book.last_insert_id),
|
||||||
|
person: person.to_owned(),
|
||||||
|
};
|
||||||
|
MutationCore::create_book_person(conn, record)
|
||||||
|
.await
|
||||||
|
.expect("could not create book");
|
||||||
|
|
||||||
|
}
|
||||||
|
for place in doc_sent.place.as_ref().unwrap().iter() {
|
||||||
|
let record : book_place::Model = book_place::Model{
|
||||||
|
id: 1,
|
||||||
|
book_id: (created_book.last_insert_id),
|
||||||
|
place: place.to_owned(),
|
||||||
|
};
|
||||||
|
MutationCore::create_book_place(conn, record)
|
||||||
|
.await
|
||||||
|
.expect("could not create book");
|
||||||
|
|
||||||
|
}
|
||||||
|
for subject in doc_sent.subject.as_ref().unwrap().iter() {
|
||||||
|
let record : book_subject::Model = book_subject::Model{
|
||||||
|
id: 1,
|
||||||
|
book_id: (created_book.last_insert_id),
|
||||||
|
subject: subject.to_owned(),
|
||||||
|
};
|
||||||
|
MutationCore::create_book_subject(conn, record)
|
||||||
|
.await
|
||||||
|
.expect("could not create book");
|
||||||
|
|
||||||
|
}
|
||||||
|
for time in doc_sent.time.as_ref().unwrap().iter() {
|
||||||
|
let record : book_time::Model = book_time::Model{
|
||||||
|
id: 1,
|
||||||
|
book_id: (created_book.last_insert_id),
|
||||||
|
time: time.to_owned(),
|
||||||
|
};
|
||||||
|
MutationCore::create_book_time(conn, record)
|
||||||
|
.await
|
||||||
|
.expect("could not create book");
|
||||||
|
|
||||||
|
}
|
||||||
|
for isbn in doc_sent.isbn.as_ref().unwrap().iter() {
|
||||||
|
let record : book_isbn::Model = book_isbn::Model{
|
||||||
|
id: 1,
|
||||||
|
book_id: (created_book.last_insert_id),
|
||||||
|
isbn: isbn.to_owned(),
|
||||||
|
};
|
||||||
|
MutationCore::create_book_isbn(conn, record)
|
||||||
|
.await
|
||||||
|
.expect("could not create book");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
"success"
|
"success"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,18 +7,18 @@ use sea_orm::entity::prelude::*;
|
|||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub open_library_key: String,
|
pub open_library_key: Option<String>,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub edition_count: i32,
|
pub edition_count: Option<i32>,
|
||||||
pub first_publish_year: i32,
|
pub first_publish_year: Option<i32>,
|
||||||
pub median_page_count: i32,
|
pub median_page_count: Option<i32>,
|
||||||
pub goodread_id: String,
|
pub goodread_id: Option<String>,
|
||||||
pub description: String,
|
pub description: Option<String>,
|
||||||
pub cover: String,
|
pub cover: Option<String>,
|
||||||
pub location: String,
|
pub location: Option<String>,
|
||||||
pub time_added: String,
|
pub time_added: Option<String>,
|
||||||
pub rating: i32,
|
pub rating: Option<i32>,
|
||||||
pub comments: String,
|
pub comments: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
|||||||
@@ -22,18 +22,18 @@ impl MigrationTrait for Migration {
|
|||||||
.auto_increment()
|
.auto_increment()
|
||||||
.primary_key(),
|
.primary_key(),
|
||||||
)
|
)
|
||||||
.col(ColumnDef::new(Book::OpenLibraryKey).string().not_null())
|
.col(ColumnDef::new(Book::OpenLibraryKey).string())
|
||||||
.col(ColumnDef::new(Book::Title).string().not_null())
|
.col(ColumnDef::new(Book::Title).string().not_null())
|
||||||
.col(ColumnDef::new(Book::EditionCount).integer().not_null())
|
.col(ColumnDef::new(Book::EditionCount).integer())
|
||||||
.col(ColumnDef::new(Book::FirstPublishYear).integer().not_null())
|
.col(ColumnDef::new(Book::FirstPublishYear).integer())
|
||||||
.col(ColumnDef::new(Book::MedianPageCount).integer().not_null())
|
.col(ColumnDef::new(Book::MedianPageCount).integer())
|
||||||
.col(ColumnDef::new(Book::GoodreadId).string().not_null())
|
.col(ColumnDef::new(Book::GoodreadId).string())
|
||||||
.col(ColumnDef::new(Book::Description).string().not_null())
|
.col(ColumnDef::new(Book::Description).string())
|
||||||
.col(ColumnDef::new(Book::Cover).string().not_null())
|
.col(ColumnDef::new(Book::Cover).string())
|
||||||
.col(ColumnDef::new(Book::Location).string().not_null())
|
.col(ColumnDef::new(Book::Location).string())
|
||||||
.col(ColumnDef::new(Book::TimeAdded).time().not_null())
|
.col(ColumnDef::new(Book::TimeAdded).time())
|
||||||
.col(ColumnDef::new(Book::Rating).integer().not_null())
|
.col(ColumnDef::new(Book::Rating).integer())
|
||||||
.col(ColumnDef::new(Book::Comments).string().not_null())
|
.col(ColumnDef::new(Book::Comments).string())
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ impl Mutation {
|
|||||||
pub async fn create_book(
|
pub async fn create_book(
|
||||||
db: &DbConn,
|
db: &DbConn,
|
||||||
form_data: book::Model,
|
form_data: book::Model,
|
||||||
) -> Result<book::ActiveModel, DbErr> {
|
) -> Result<InsertResult<book::ActiveModel>, DbErr> {
|
||||||
book::ActiveModel {
|
let record = book::ActiveModel {
|
||||||
open_library_key: Set(form_data.open_library_key.to_owned()),
|
open_library_key: Set(form_data.open_library_key.to_owned()),
|
||||||
title: Set(form_data.title.to_owned()),
|
title: Set(form_data.title.to_owned()),
|
||||||
edition_count: Set(form_data.edition_count.to_owned()),
|
edition_count: Set(form_data.edition_count.to_owned()),
|
||||||
@@ -27,9 +27,8 @@ impl Mutation {
|
|||||||
rating: Set(form_data.rating.to_owned()),
|
rating: Set(form_data.rating.to_owned()),
|
||||||
comments: Set(form_data.comments.to_owned()),
|
comments: Set(form_data.comments.to_owned()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
};
|
||||||
.save(db)
|
Book::insert(record).exec(db).await
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_book_author(
|
pub async fn create_book_author(
|
||||||
|
|||||||
Reference in New Issue
Block a user