🔎 Search page scaffold
This commit is contained in:
@@ -60,13 +60,12 @@ $border-color: red;
|
|||||||
// max-width: 500px;
|
// max-width: 500px;
|
||||||
margin: 0 0 15px 0;
|
margin: 0 0 15px 0;
|
||||||
.card-image {
|
.card-image {
|
||||||
img {
|
img {
|
||||||
border-top-left-radius: 0.3rem;
|
border-top-left-radius: 0.3rem;
|
||||||
border-top-right-radius: 0.3rem;
|
border-top-right-radius: 0.3rem;
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-horizontal {
|
.is-horizontal {
|
||||||
@@ -124,7 +123,17 @@ $border-color: red;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Search
|
||||||
|
.search {
|
||||||
|
.main-search-bar {
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid #999;
|
||||||
|
border-radius: 0;
|
||||||
|
outline: 0;
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Library
|
// Library
|
||||||
.library {
|
.library {
|
||||||
table {
|
table {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Dashboard from "./Dashboard";
|
|||||||
import Import from "./Import";
|
import Import from "./Import";
|
||||||
import { ComicDetail } from "./ComicDetail";
|
import { ComicDetail } from "./ComicDetail";
|
||||||
import Library from "./Library";
|
import Library from "./Library";
|
||||||
|
import Search from "./Search";
|
||||||
|
|
||||||
import { Switch, Route } from "react-router";
|
import { Switch, Route } from "react-router";
|
||||||
import Navbar from "./Navbar";
|
import Navbar from "./Navbar";
|
||||||
@@ -25,6 +26,9 @@ class App extends React.Component {
|
|||||||
<Route path="/library">
|
<Route path="/library">
|
||||||
<Library />
|
<Library />
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route path="/search">
|
||||||
|
<Search />
|
||||||
|
</Route>
|
||||||
<Route
|
<Route
|
||||||
path={"/comic/details/:comicObjectId"}
|
path={"/comic/details/:comicObjectId"}
|
||||||
component={ComicDetail}
|
component={ComicDetail}
|
||||||
|
|||||||
@@ -61,54 +61,68 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const [active, setActive] = useState(0);
|
const [active, setActive] = useState(0);
|
||||||
|
const createDescriptionMarkup = (html) => {
|
||||||
|
return { __html: html };
|
||||||
|
};
|
||||||
|
// Tab groups for ComicVine metadata
|
||||||
const tabGroup = [
|
const tabGroup = [
|
||||||
{
|
{
|
||||||
id: 0,
|
id: 0,
|
||||||
name: "Volume Information",
|
name: "Volume Information",
|
||||||
content: !isNil(comicBookDetailData.sourcedMetadata) && (
|
content: !isNil(comicBookDetailData.sourcedMetadata) && (
|
||||||
<div className="columns">
|
<>
|
||||||
<div className="column is-narrow">
|
<div className="columns">
|
||||||
<figure className="card-image">
|
<div className="column is-narrow">
|
||||||
<img
|
<figure className="card-image">
|
||||||
src={
|
<img
|
||||||
comicBookDetailData.sourcedMetadata.comicvine
|
src={
|
||||||
.volumeInformation.image.thumb_url
|
comicBookDetailData.sourcedMetadata.comicvine
|
||||||
}
|
.volumeInformation.image.thumb_url
|
||||||
/>
|
}
|
||||||
</figure>
|
/>
|
||||||
</div>
|
</figure>
|
||||||
<div className="column is-4">
|
</div>
|
||||||
<dl>
|
<div className="column is-4">
|
||||||
<dt>
|
<dl>
|
||||||
Is a part of{" "}
|
<dt>
|
||||||
<span className="has-text-info">
|
Is a part of{" "}
|
||||||
|
<span className="has-text-info">
|
||||||
|
{
|
||||||
|
comicBookDetailData.sourcedMetadata.comicvine
|
||||||
|
.volumeInformation.name
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Published by
|
||||||
|
<span className="has-text-weight-semibold">
|
||||||
|
{" "}
|
||||||
|
{
|
||||||
|
comicBookDetailData.sourcedMetadata.comicvine
|
||||||
|
.volumeInformation.publisher.name
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</dd>
|
||||||
|
<dd>
|
||||||
|
Total issues in this volume:{" "}
|
||||||
{
|
{
|
||||||
comicBookDetailData.sourcedMetadata.comicvine
|
comicBookDetailData.sourcedMetadata.comicvine
|
||||||
.volumeInformation.name
|
.volumeInformation.count_of_issues
|
||||||
}
|
}
|
||||||
</span>
|
</dd>
|
||||||
</dt>
|
</dl>
|
||||||
<dd>
|
</div>
|
||||||
Published by
|
|
||||||
<span className="has-text-weight-semibold">
|
|
||||||
{" "}
|
|
||||||
{
|
|
||||||
comicBookDetailData.sourcedMetadata.comicvine
|
|
||||||
.volumeInformation.publisher.name
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
</dd>
|
|
||||||
<dd>
|
|
||||||
Total issues in this volume:{" "}
|
|
||||||
{
|
|
||||||
comicBookDetailData.sourcedMetadata.comicvine
|
|
||||||
.volumeInformation.count_of_issues
|
|
||||||
}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="columns">
|
||||||
|
<div
|
||||||
|
className="column is-three-quarters"
|
||||||
|
dangerouslySetInnerHTML={createDescriptionMarkup(
|
||||||
|
comicBookDetailData.sourcedMetadata.comicvine.volumeInformation
|
||||||
|
.description,
|
||||||
|
)}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
import React, {
|
import React, { useState, useEffect, useMemo, ReactElement } from "react";
|
||||||
useState,
|
|
||||||
useEffect,
|
|
||||||
useCallback,
|
|
||||||
useMemo,
|
|
||||||
ReactElement,
|
|
||||||
} from "react";
|
|
||||||
import {
|
import {
|
||||||
removeLeadingPeriod,
|
removeLeadingPeriod,
|
||||||
escapePoundSymbol,
|
escapePoundSymbol,
|
||||||
@@ -12,14 +6,27 @@ import {
|
|||||||
import { useTable } from "react-table";
|
import { useTable } from "react-table";
|
||||||
import prettyBytes from "pretty-bytes";
|
import prettyBytes from "pretty-bytes";
|
||||||
import ellipsize from "ellipsize";
|
import ellipsize from "ellipsize";
|
||||||
|
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { getComicBooks } from "../actions/fileops.actions";
|
||||||
|
|
||||||
interface IComicBookLibraryProps {
|
interface IComicBookLibraryProps {
|
||||||
matches: unknown;
|
matches?: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Library = ({}: IComicBookLibraryProps): ReactElement => {
|
export const Library = ({}: IComicBookLibraryProps): ReactElement => {
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(
|
||||||
|
getComicBooks({
|
||||||
|
paginationOptions: {
|
||||||
|
page: 0,
|
||||||
|
limit: 15,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}, [page, dispatch]);
|
||||||
|
|
||||||
const data = useSelector(
|
const data = useSelector(
|
||||||
(state: RootState) => state.fileOps.recentComics.docs,
|
(state: RootState) => state.fileOps.recentComics.docs,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ const Navbar: React.FunctionComponent = (props) => {
|
|||||||
<Link to="/library" className="navbar-item">
|
<Link to="/library" className="navbar-item">
|
||||||
Library
|
Library
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/library" className="navbar-item">
|
<Link to="/search" className="navbar-item">
|
||||||
Search
|
Search
|
||||||
</Link>
|
</Link>
|
||||||
<div className="navbar-item has-dropdown is-hoverable">
|
<div className="navbar-item has-dropdown is-hoverable">
|
||||||
|
|||||||
47
src/client/components/Search.tsx
Normal file
47
src/client/components/Search.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import React, { useMemo, ReactElement } from "react";
|
||||||
|
import {
|
||||||
|
removeLeadingPeriod,
|
||||||
|
escapePoundSymbol,
|
||||||
|
} from "../shared/utils/formatting.utils";
|
||||||
|
import { useTable } from "react-table";
|
||||||
|
import prettyBytes from "pretty-bytes";
|
||||||
|
import ellipsize from "ellipsize";
|
||||||
|
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
|
interface ISearchProps {}
|
||||||
|
|
||||||
|
export const Search = ({}: ISearchProps): ReactElement => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<section className="container">
|
||||||
|
<div className="section search">
|
||||||
|
<div className="columns">
|
||||||
|
<div className="column is-half">
|
||||||
|
<h1 className="title">Search</h1>
|
||||||
|
<input
|
||||||
|
className="main-search-bar input is-large"
|
||||||
|
type="text"
|
||||||
|
placeholder="Enter a title, ComicVine ID or a series name"
|
||||||
|
></input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<article className="message is-dark is-half">
|
||||||
|
<div className="message-body">
|
||||||
|
<p className="mb-2">
|
||||||
|
<span className="tag is-medium is-info is-light">
|
||||||
|
Search the ComicVine database
|
||||||
|
</span>
|
||||||
|
Search and add issues, series and trade paperbacks to your
|
||||||
|
library. Then, download them using the configured AirDC++ or
|
||||||
|
torrent clients.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Search;
|
||||||
Reference in New Issue
Block a user