casing i fe. detail embryo
This commit is contained in:
@@ -4,6 +4,7 @@ import Home from "./components/Home";
|
|||||||
import BookList from "./components/BookList";
|
import BookList from "./components/BookList";
|
||||||
import AuthorList from "./components/AuthorList";
|
import AuthorList from "./components/AuthorList";
|
||||||
import SeriesList from "./components/SeriesList";
|
import SeriesList from "./components/SeriesList";
|
||||||
|
import BookDetail from "./components/BookDetail";
|
||||||
|
|
||||||
const App: Component = () => {
|
const App: Component = () => {
|
||||||
return (
|
return (
|
||||||
@@ -48,6 +49,7 @@ const App: Component = () => {
|
|||||||
<main class="container">
|
<main class="container">
|
||||||
<Router>
|
<Router>
|
||||||
<Route path="/books/author/:authorid" component={BookList} />
|
<Route path="/books/author/:authorid" component={BookList} />
|
||||||
|
<Route path="/books/:id" component={BookDetail} />
|
||||||
<Route path="/books" component={BookList} />
|
<Route path="/books" component={BookList} />
|
||||||
<Route path="/authors" component={AuthorList} />
|
<Route path="/authors" component={AuthorList} />
|
||||||
<Route path="/series" component={SeriesList} />
|
<Route path="/series" component={SeriesList} />
|
||||||
|
@@ -1,17 +1,22 @@
|
|||||||
import { Show, type Component } from "solid-js";
|
import { Show, type Component } from "solid-js";
|
||||||
import { author } from "../types/types";
|
import { Author } from "../types/types";
|
||||||
import { Card } from "solid-bootstrap";
|
import { Card } from "solid-bootstrap";
|
||||||
|
|
||||||
const AuthorCard: Component<{ author: author }> = (props: {
|
const AuthorCard: Component<{ author: Author }> = (props: {
|
||||||
author: author;
|
author: Author;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<Card class="book-card col-lg-2 col-md-3 col-sm-4">
|
<Card class="book-card col-lg-2 col-md-3 col-sm-4">
|
||||||
<Card.Img
|
<div class="card-img-top missing">?</div>
|
||||||
variant="top"
|
<div
|
||||||
class="padding-1"
|
class="card-img-top author"
|
||||||
src={"/api/bibblan/authorcover/" + encodeURIComponent(props.author.id)}
|
style={{
|
||||||
/>
|
"background-image":
|
||||||
|
'url("/api/bibblan/authorcover/' +
|
||||||
|
encodeURIComponent(props.author.id) +
|
||||||
|
'")',
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
<Card.Body>
|
<Card.Body>
|
||||||
<Card.Title>{props.author.name}</Card.Title>
|
<Card.Title>{props.author.name}</Card.Title>
|
||||||
<Card.Subtitle>
|
<Card.Subtitle>
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import { createSignal, onMount, For, type Component } from "solid-js";
|
import { createSignal, onMount, For, type Component } from "solid-js";
|
||||||
import AuthorCard from "./AuthorCard";
|
import AuthorCard from "./AuthorCard";
|
||||||
import BibblanService from "../services/bibblanservice";
|
import BibblanService from "../services/bibblanservice";
|
||||||
import { author } from "../types/types";
|
import { Author } from "../types/types";
|
||||||
|
|
||||||
const BookList: Component = () => {
|
const BookList: Component = () => {
|
||||||
const [authors, setAuthors] = createSignal<author[]>([]);
|
const [authors, setAuthors] = createSignal<Author[]>([]);
|
||||||
const [query, setQuery] = createSignal("");
|
const [query, setQuery] = createSignal("");
|
||||||
|
|
||||||
const update = (query: string) => {
|
const update = (query: string) => {
|
||||||
|
@@ -1,16 +1,27 @@
|
|||||||
import { Show, type Component } from "solid-js";
|
import { Show, createSignal, type Component } from "solid-js";
|
||||||
import { book } from "../types/types";
|
import { Book } from "../types/types";
|
||||||
import { Card } from "solid-bootstrap";
|
import { Card, Modal } from "solid-bootstrap";
|
||||||
|
|
||||||
|
const BookCard: Component<{ book: Book }> = (props: { book: Book }) => {
|
||||||
|
const [show, setShow] = createSignal(false);
|
||||||
|
|
||||||
|
function handleClick(): void {
|
||||||
|
setShow(true);
|
||||||
|
}
|
||||||
|
|
||||||
const BookCard: Component<{ book: book }> = (props: { book: book }) => {
|
|
||||||
return (
|
return (
|
||||||
<Card class="book-card col-lg-2 col-md-3 col-sm-4">
|
<Card class="book-card col-lg-2 col-md-3 col-sm-4">
|
||||||
|
<div class="card-img-top missing">?</div>
|
||||||
<Show when={true || props.book.hasCover}>
|
<Show when={true || props.book.hasCover}>
|
||||||
<Card.Img
|
<div
|
||||||
variant="top"
|
class="card-img-top"
|
||||||
class="padding-1"
|
style={{
|
||||||
src={"/api/calibre/cover?path=" + encodeURIComponent(props.book.path)}
|
"background-image":
|
||||||
/>
|
'url("/api/calibre/cover?path=' +
|
||||||
|
encodeURIComponent(props.book.path) +
|
||||||
|
'")',
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
</Show>
|
</Show>
|
||||||
<Card.Body>
|
<Card.Body>
|
||||||
<Card.Title>{props.book.title}</Card.Title>
|
<Card.Title>{props.book.title}</Card.Title>
|
||||||
@@ -18,6 +29,7 @@ const BookCard: Component<{ book: book }> = (props: { book: book }) => {
|
|||||||
<Card.Text>
|
<Card.Text>
|
||||||
Series: {props.book.seriesName} {props.book.seriesNumber}
|
Series: {props.book.seriesName} {props.book.seriesNumber}
|
||||||
</Card.Text>
|
</Card.Text>
|
||||||
|
<a href={`/books/${props.book.id}`} class="stretched-link"></a>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
31
Frontend/src/components/BookDetail.tsx
Normal file
31
Frontend/src/components/BookDetail.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { createSignal, onMount, For, Show, type Component } from "solid-js";
|
||||||
|
import { useParams } from "@solidjs/router";
|
||||||
|
import BibblanService from "../services/bibblanservice";
|
||||||
|
import { type BookDetail as BD } from "../types/types";
|
||||||
|
|
||||||
|
const BookDetail: Component = () => {
|
||||||
|
const [detail, setDetail] = createSignal<BD>({} as BD);
|
||||||
|
const params = useParams();
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
BibblanService.getBook(params.id).then((b) => {
|
||||||
|
console.log("detail", b);
|
||||||
|
setDetail(b);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>Book detail - {detail()?.book?.title}</h1>
|
||||||
|
<Show when={detail()?.book?.id !== undefined}>
|
||||||
|
<br />
|
||||||
|
<pre>
|
||||||
|
<code>{JSON.stringify(detail(), null, 2)}</code>
|
||||||
|
</pre>
|
||||||
|
<br />
|
||||||
|
</Show>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BookDetail;
|
@@ -2,10 +2,10 @@ import { createSignal, onMount, For, Show, type Component } from "solid-js";
|
|||||||
import { useParams } from "@solidjs/router";
|
import { useParams } from "@solidjs/router";
|
||||||
import BookCard from "./BookCard";
|
import BookCard from "./BookCard";
|
||||||
import BibblanService from "../services/bibblanservice";
|
import BibblanService from "../services/bibblanservice";
|
||||||
import { book } from "../types/types";
|
import { Book } from "../types/types";
|
||||||
|
|
||||||
const BookList: Component = () => {
|
const BookList: Component = () => {
|
||||||
const [books, setBooks] = createSignal<book[]>([]);
|
const [books, setBooks] = createSignal<Book[]>([]);
|
||||||
const [query, setQuery] = createSignal("");
|
const [query, setQuery] = createSignal("");
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
import { createSignal, onMount, For, type Component, Show } from "solid-js";
|
import { createSignal, onMount, For, type Component, Show } from "solid-js";
|
||||||
import BookCard from "./BookCard";
|
import BookCard from "./BookCard";
|
||||||
import BibblanService from "../services/bibblanservice";
|
import BibblanService from "../services/bibblanservice";
|
||||||
import { series, listBook, book } from "../types/types";
|
import { Series, ListBook, Book } from "../types/types";
|
||||||
import { OverlayTrigger, Popover, Button } from "solid-bootstrap";
|
import { OverlayTrigger, Popover, Button } from "solid-bootstrap";
|
||||||
const SeriesList: Component = () => {
|
const SeriesList: Component = () => {
|
||||||
const [series, setSeries] = createSignal<series[]>([]);
|
const [series, setSeries] = createSignal<Series[]>([]);
|
||||||
const [query, setQuery] = createSignal("");
|
const [query, setQuery] = createSignal("");
|
||||||
const [selected, setSelected] = createSignal<number>(-1);
|
|
||||||
|
|
||||||
const update = (query: string) => {
|
const update = (query: string) => {
|
||||||
setQuery(query);
|
setQuery(query);
|
||||||
@@ -18,7 +17,7 @@ const SeriesList: Component = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const distinctAuthors = (
|
const distinctAuthors = (
|
||||||
books: listBook[]
|
books: ListBook[]
|
||||||
): { id: number; name: string }[] => {
|
): { id: number; name: string }[] => {
|
||||||
return [
|
return [
|
||||||
...new Set(
|
...new Set(
|
||||||
@@ -27,21 +26,21 @@ const SeriesList: Component = () => {
|
|||||||
].map((x) => JSON.parse(x)) as { id: number; name: string }[];
|
].map((x) => JSON.parse(x)) as { id: number; name: string }[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const minDate = (books: listBook[]): string => {
|
const minDate = (books: ListBook[]): string => {
|
||||||
if (books.length === 0) return "";
|
if (books.length === 0) return "";
|
||||||
const darr = books.map((b) => new Date(b.pubDate));
|
const darr = books.map((b) => new Date(b.pubDate));
|
||||||
const d = darr.reduce((min, b) => (b < min ? b : min), darr[0]);
|
const d = darr.reduce((min, b) => (b < min ? b : min), darr[0]);
|
||||||
return d?.toISOString().substr(0, 10) ?? "";
|
return d?.toISOString().substr(0, 10) ?? "";
|
||||||
};
|
};
|
||||||
|
|
||||||
const maxDate = (books: listBook[]): string => {
|
const maxDate = (books: ListBook[]): string => {
|
||||||
if (books.length === 0) return "";
|
if (books.length === 0) return "";
|
||||||
const darr = books.map((b) => new Date(b.pubDate));
|
const darr = books.map((b) => new Date(b.pubDate));
|
||||||
const d = darr.reduce((max, b) => (b > max ? b : max), darr[0]);
|
const d = darr.reduce((max, b) => (b > max ? b : max), darr[0]);
|
||||||
return d?.toISOString().substr(0, 10) ?? "";
|
return d?.toISOString().substr(0, 10) ?? "";
|
||||||
};
|
};
|
||||||
|
|
||||||
function extendBook(item: listBook, seriesName: string): book {
|
function extendBook(item: ListBook, seriesName: string): Book {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
|
|
||||||
@@ -57,7 +56,7 @@ const SeriesList: Component = () => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function orderBySeriesIndex(books: listBook[]): listBook[] {
|
function orderBySeriesIndex(books: ListBook[]): ListBook[] {
|
||||||
return [...books].sort((a, b) => {
|
return [...books].sort((a, b) => {
|
||||||
const indexA = a.seriesIndex ?? 0;
|
const indexA = a.seriesIndex ?? 0;
|
||||||
const indexB = b.seriesIndex ?? 0;
|
const indexB = b.seriesIndex ?? 0;
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import { book, author } from "../types/types";
|
import { Book, Author, Series, BookDetail } from "../types/types";
|
||||||
|
|
||||||
const BibblanService = {
|
const BibblanService = {
|
||||||
getBooks: async (
|
getBooks: async (
|
||||||
authorid: string | undefined = undefined,
|
authorid: string | undefined = undefined,
|
||||||
query: string | undefined = undefined
|
query: string | undefined = undefined
|
||||||
): Promise<book[]> => {
|
): Promise<Book[]> => {
|
||||||
let url = "/api/bibblan/books";
|
let url = "/api/bibblan/books";
|
||||||
if (authorid != undefined) {
|
if (authorid != undefined) {
|
||||||
url += `/author/${authorid}`;
|
url += `/author/${authorid}`;
|
||||||
@@ -15,9 +15,15 @@ const BibblanService = {
|
|||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getBook: async (id: string): Promise<BookDetail> => {
|
||||||
|
let url = "/api/bibblan/books/" + id;
|
||||||
|
const response = await fetch(url);
|
||||||
|
return response.json();
|
||||||
|
},
|
||||||
|
|
||||||
getAuthors: async (
|
getAuthors: async (
|
||||||
query: string | undefined = undefined
|
query: string | undefined = undefined
|
||||||
): Promise<author[]> => {
|
): Promise<Author[]> => {
|
||||||
let url = "/api/bibblan/authors";
|
let url = "/api/bibblan/authors";
|
||||||
if (query != undefined && query.length > 0) {
|
if (query != undefined && query.length > 0) {
|
||||||
url += `?query=${encodeURIComponent(query)}`;
|
url += `?query=${encodeURIComponent(query)}`;
|
||||||
@@ -28,7 +34,7 @@ const BibblanService = {
|
|||||||
|
|
||||||
getSeries: async (
|
getSeries: async (
|
||||||
query: string | undefined = undefined
|
query: string | undefined = undefined
|
||||||
): Promise<author[]> => {
|
): Promise<Series[]> => {
|
||||||
let url = "/api/bibblan/series";
|
let url = "/api/bibblan/series";
|
||||||
if (query != undefined && query.length > 0) {
|
if (query != undefined && query.length > 0) {
|
||||||
url += `?query=${encodeURIComponent(query)}`;
|
url += `?query=${encodeURIComponent(query)}`;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { book } from "../types/types";
|
import { Book } from "../types/types";
|
||||||
|
|
||||||
const CalibreService = {
|
const CalibreService = {
|
||||||
getBooks: async (): Promise<book[]> => {
|
getBooks: async (): Promise<Book[]> => {
|
||||||
const response = await fetch("/api/calibre/books");
|
const response = await fetch("/api/calibre/books");
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
|
@@ -3,7 +3,27 @@
|
|||||||
.book-card {
|
.book-card {
|
||||||
.card-img-top {
|
.card-img-top {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
aspect-ratio: 3 / 4;
|
aspect-ratio: 30 / 47;
|
||||||
|
background-size: contain;
|
||||||
|
width: calc(100% - 1.6rem);
|
||||||
|
margin-left: 0.8rem;
|
||||||
|
margin-top: 0.8rem;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 0 0;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
&.missing {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
font-size: 7rem;
|
||||||
|
font-weight: 900;
|
||||||
|
color: #ccc;
|
||||||
|
text-align: center;
|
||||||
|
opacity: 0.8;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* &.author { } */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
interface book {
|
export interface Book {
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
authorId: number;
|
authorId: number;
|
||||||
@@ -12,13 +12,13 @@ interface book {
|
|||||||
seriesNumber: number;
|
seriesNumber: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface author {
|
export interface Author {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
bookCount: number;
|
bookCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface listBook {
|
export interface ListBook {
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
authorId: number;
|
authorId: number;
|
||||||
@@ -29,10 +29,58 @@ interface listBook {
|
|||||||
seriesIndex: number;
|
seriesIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface series {
|
export interface Series {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
books: Array<listBook>;
|
books: Array<ListBook>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { book, author, series, listBook };
|
export interface Publisher {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
sort: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Tag {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Rating {
|
||||||
|
id: number;
|
||||||
|
book: number;
|
||||||
|
rating: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Language {
|
||||||
|
id: number;
|
||||||
|
book: number;
|
||||||
|
langCode: number;
|
||||||
|
itemOrder: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BookComment {
|
||||||
|
id: number;
|
||||||
|
book: number;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BookData {
|
||||||
|
id: number;
|
||||||
|
book: number;
|
||||||
|
format: string;
|
||||||
|
uncompressedSize: number;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BookDetail {
|
||||||
|
book: Book;
|
||||||
|
authors: Author[];
|
||||||
|
publishers: Publisher[];
|
||||||
|
language: Language[];
|
||||||
|
ratings: any[];
|
||||||
|
series: Author[];
|
||||||
|
tags: Tag[];
|
||||||
|
comments: BookComment[];
|
||||||
|
data: BookData[];
|
||||||
|
}
|
||||||
|
@@ -9,6 +9,7 @@ namespace Bibblan.Business.Services
|
|||||||
|
|
||||||
public class BookFilter
|
public class BookFilter
|
||||||
{
|
{
|
||||||
|
public int? Id;
|
||||||
public int? Author;
|
public int? Author;
|
||||||
public string? Query;
|
public string? Query;
|
||||||
}
|
}
|
||||||
@@ -17,7 +18,7 @@ namespace Bibblan.Business.Services
|
|||||||
{
|
{
|
||||||
readonly BibblanOptions settings = options.Value;
|
readonly BibblanOptions settings = options.Value;
|
||||||
|
|
||||||
public IEnumerable<Books> GetBooks(int count, BookFilter filter = null)
|
public List<Books> GetBooks(int count, BookFilter filter = null)
|
||||||
{
|
{
|
||||||
var conn = new NpgsqlConnection(settings.BibblanConnection);
|
var conn = new NpgsqlConnection(settings.BibblanConnection);
|
||||||
var query = "select * from books";
|
var query = "select * from books";
|
||||||
@@ -28,7 +29,12 @@ namespace Bibblan.Business.Services
|
|||||||
if(filter.Author != null)
|
if(filter.Author != null)
|
||||||
{
|
{
|
||||||
query += $"id in (select book from books_authors_link where author = {filter.Author})";
|
query += $"id in (select book from books_authors_link where author = {filter.Author})";
|
||||||
} else if(!String.IsNullOrWhiteSpace(query))
|
}
|
||||||
|
else if(filter.Id != null)
|
||||||
|
{
|
||||||
|
query += $"id = {filter.Id}";
|
||||||
|
}
|
||||||
|
else if(!String.IsNullOrWhiteSpace(query))
|
||||||
{
|
{
|
||||||
filter.Query = filter.Query.ToLowerInvariant();
|
filter.Query = filter.Query.ToLowerInvariant();
|
||||||
query += $"lower(title) like @query or lower(author_sort) like @query";
|
query += $"lower(title) like @query or lower(author_sort) like @query";
|
||||||
@@ -38,6 +44,47 @@ namespace Bibblan.Business.Services
|
|||||||
return conn.Query<Books>(query, parameters).Take(count).ToList();
|
return conn.Query<Books>(query, parameters).Take(count).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BookDetailVm GetBookDetails(int id)
|
||||||
|
{
|
||||||
|
var query = @"select * from books where id = @book;
|
||||||
|
select * from authors where id in (select author from books_authors_link where book = @book);
|
||||||
|
select * from books_languages_link where book = @book;
|
||||||
|
select * from publishers where id in (select publisher from books_publishers_link where book = @book);
|
||||||
|
select * from books_ratings_link where book = @book;
|
||||||
|
select * from series where id in (select series from books_series_link where book = @book);
|
||||||
|
select * from tags where id in (select tag from books_tags_link where book = @book);
|
||||||
|
select * from comments where book = @book;
|
||||||
|
select * from data where book = @book;";
|
||||||
|
|
||||||
|
using (var conn = new NpgsqlConnection(settings.BibblanConnection))
|
||||||
|
{
|
||||||
|
var results = conn.QueryMultiple(query, new { book = id });
|
||||||
|
var book = results.ReadFirst<Books>();
|
||||||
|
var authors = results.Read<Authors>();
|
||||||
|
var lang = results.Read<BooksLanguagesLink>();
|
||||||
|
var publishers = results.Read<Publishers>();
|
||||||
|
var ratings = results.Read<BooksRatingsLink>();
|
||||||
|
var series = results.Read<Series>();
|
||||||
|
var tags = results.Read<Tags>();
|
||||||
|
var comments = results.Read<Comments>();
|
||||||
|
var data = results.Read<Data>();
|
||||||
|
|
||||||
|
return new BookDetailVm
|
||||||
|
{
|
||||||
|
Book = book,
|
||||||
|
Authors = authors,
|
||||||
|
Language = lang,
|
||||||
|
Publishers = publishers,
|
||||||
|
Ratings = ratings,
|
||||||
|
Series = series,
|
||||||
|
Tags = tags,
|
||||||
|
Comments = comments,
|
||||||
|
Data = data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<AuthorVm> GetAuthors(int count, BookFilter filter = null)
|
public IEnumerable<AuthorVm> GetAuthors(int count, BookFilter filter = null)
|
||||||
{
|
{
|
||||||
var query = "select a.id, a.name, count(bal.*) as bookcount\r\nfrom authors a\r\nleft join books_authors_link bal on a.id = bal.author\r\ngroup by a.id , a.name ";
|
var query = "select a.id, a.name, count(bal.*) as bookcount\r\nfrom authors a\r\nleft join books_authors_link bal on a.id = bal.author\r\ngroup by a.id , a.name ";
|
||||||
|
@@ -30,7 +30,7 @@ namespace Bibblan.Controllers
|
|||||||
[HttpGet("books")]
|
[HttpGet("books")]
|
||||||
public IActionResult GetBooks(string query = null)
|
public IActionResult GetBooks(string query = null)
|
||||||
{
|
{
|
||||||
BookFilter filter = query != null ? new BookFilter
|
BookFilter? filter = query != null ? new BookFilter
|
||||||
{
|
{
|
||||||
Query = query
|
Query = query
|
||||||
} : null;
|
} : null;
|
||||||
@@ -39,10 +39,17 @@ namespace Bibblan.Controllers
|
|||||||
return Ok(books);
|
return Ok(books);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("books/{id}")]
|
||||||
|
public IActionResult GetBook(int id)
|
||||||
|
{
|
||||||
|
var book = _db.GetBookDetails(id);
|
||||||
|
return Ok(book);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("authors")]
|
[HttpGet("authors")]
|
||||||
public IActionResult GetAuthors(string query = null)
|
public IActionResult GetAuthors(string query = null)
|
||||||
{
|
{
|
||||||
BookFilter filter = query != null ? new BookFilter
|
BookFilter? filter = query != null ? new BookFilter
|
||||||
{
|
{
|
||||||
Query = query
|
Query = query
|
||||||
} : null;
|
} : null;
|
||||||
@@ -72,7 +79,7 @@ namespace Bibblan.Controllers
|
|||||||
[HttpGet("series")]
|
[HttpGet("series")]
|
||||||
public IActionResult GetSeries(string query = null)
|
public IActionResult GetSeries(string query = null)
|
||||||
{
|
{
|
||||||
BookFilter filter = query != null ? new BookFilter
|
BookFilter? filter = query != null ? new BookFilter
|
||||||
{
|
{
|
||||||
Query = query
|
Query = query
|
||||||
} : null;
|
} : null;
|
||||||
@@ -84,7 +91,7 @@ namespace Bibblan.Controllers
|
|||||||
[HttpGet("tags")]
|
[HttpGet("tags")]
|
||||||
public IActionResult GetTags(string query = null)
|
public IActionResult GetTags(string query = null)
|
||||||
{
|
{
|
||||||
BookFilter filter = query != null ? new BookFilter
|
BookFilter? filter = query != null ? new BookFilter
|
||||||
{
|
{
|
||||||
Query = query
|
Query = query
|
||||||
} : null;
|
} : null;
|
||||||
|
@@ -2,6 +2,19 @@
|
|||||||
|
|
||||||
namespace Bibblan.ViewModels
|
namespace Bibblan.ViewModels
|
||||||
{
|
{
|
||||||
|
public class BookDetailVm
|
||||||
|
{
|
||||||
|
public Books Book { get; internal set; }
|
||||||
|
public IEnumerable<Authors> Authors { get; internal set; }
|
||||||
|
public IEnumerable<Publishers> Publishers { get; internal set; }
|
||||||
|
public IEnumerable<BooksLanguagesLink> Language { get; internal set; }
|
||||||
|
public IEnumerable<BooksRatingsLink> Ratings { get; internal set; }
|
||||||
|
public IEnumerable<Series> Series { get; internal set; }
|
||||||
|
public IEnumerable<Tags> Tags { get; internal set; }
|
||||||
|
public IEnumerable<Comments> Comments { get; internal set; }
|
||||||
|
public IEnumerable<Data> Data { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class BookVm
|
public class BookVm
|
||||||
{
|
{
|
||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
|
Reference in New Issue
Block a user