🧱 Broke Library into components
This commit is contained in:
@@ -1,20 +1,13 @@
|
||||
import React, { useState, useEffect, useMemo, ReactElement } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { useHistory } from "react-router";
|
||||
import {
|
||||
removeLeadingPeriod,
|
||||
escapePoundSymbol,
|
||||
} from "../shared/utils/formatting.utils";
|
||||
import { useTable, usePagination } from "react-table";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import styled from "styled-components";
|
||||
import ellipsize from "ellipsize";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Form, Field } from "react-final-form";
|
||||
import { getComicBooks } from "../actions/fileops.actions";
|
||||
import { isNil } from "lodash";
|
||||
import { IMPORT_SERVICE_HOST } from "../constants/endpoints";
|
||||
import { Link } from "react-router-dom";
|
||||
import { isEmpty, isNil } from "lodash";
|
||||
import { RawFileDetails } from "./Library/RawFileDetails";
|
||||
import { ComicVineDetails } from "./Library/ComicVineDetails";
|
||||
import { SearchBar } from "./Library/SearchBar";
|
||||
|
||||
interface IComicBookLibraryProps {
|
||||
matches?: unknown;
|
||||
@@ -38,79 +31,7 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
|
||||
const navigateToComicDetail = (id) => {
|
||||
history.push(`/comic/details/${id}`);
|
||||
};
|
||||
// raw file details
|
||||
const RawFileDetails = ({ value }) => {
|
||||
if (!isNil(value.path)) {
|
||||
const encodedFilePath = encodeURI(
|
||||
`${IMPORT_SERVICE_HOST}/${value.cover.filePath}`,
|
||||
);
|
||||
const filePath = escapePoundSymbol(encodedFilePath);
|
||||
return (
|
||||
<div className="card-container">
|
||||
<div className="card">
|
||||
<div className="is-horizontal">
|
||||
<div className="card-image">
|
||||
<figure>
|
||||
<img className="image" src={filePath} />
|
||||
</figure>
|
||||
</div>
|
||||
<ul className="card-content">
|
||||
<li className="name has-text-weight-medium">
|
||||
{ellipsize(value.name, 18)}
|
||||
</li>
|
||||
<li>
|
||||
<div className="control">
|
||||
<div className="tags has-addons">
|
||||
<span className="tag is-primary is-light">
|
||||
{value.extension}
|
||||
</span>
|
||||
<span className="tag is-info is-light">
|
||||
{prettyBytes(value.fileSize)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else if (!isNil(value.comicvine)) {
|
||||
return (
|
||||
<div className="card-container">
|
||||
<div className="card">
|
||||
<div className="is-horizontal">
|
||||
<div className="card-image">
|
||||
<figure>
|
||||
<img
|
||||
className="image"
|
||||
src={value.comicvine.image.thumb_url}
|
||||
/>
|
||||
</figure>
|
||||
</div>
|
||||
<ul className="card-content">
|
||||
<li className="name has-text-weight-medium">
|
||||
{ellipsize(value.name, 18)}
|
||||
</li>
|
||||
<li>
|
||||
<div className="control">
|
||||
<div className="tags has-addons">
|
||||
<span className="tag is-primary is-light">
|
||||
ComicVine ID
|
||||
</span>
|
||||
<span className="tag is-info is-light">
|
||||
{value.comicvine.id}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const ImportStatus = ({ value }) => {
|
||||
return value ? (
|
||||
<span className="tag is-info is-light">Imported</span>
|
||||
@@ -119,53 +40,6 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
|
||||
);
|
||||
};
|
||||
|
||||
const foo = () => {};
|
||||
const SearchBar = () => {
|
||||
return (
|
||||
<div className="box columns sticky">
|
||||
<Form
|
||||
onSubmit={foo}
|
||||
initialValues={{}}
|
||||
render={({ handleSubmit, form, submitting, pristine, values }) => (
|
||||
<div className="column is-three-quarters search">
|
||||
<label>Search</label>
|
||||
<Field name="search">
|
||||
{({ input, meta }) => {
|
||||
return (
|
||||
<input
|
||||
{...input}
|
||||
className="input main-search-bar is-medium"
|
||||
placeholder="Type an issue/volume name"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Field>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<div className="column one-fifth">
|
||||
<div className="field has-addons">
|
||||
<p className="control">
|
||||
<button className="button">
|
||||
<span className="icon is-small">
|
||||
<i className="fa-solid fa-list"></i>
|
||||
</span>
|
||||
</button>
|
||||
</p>
|
||||
<p className="control">
|
||||
<button className="button">
|
||||
<Link to="/library-grid">
|
||||
<span className="icon is-small">
|
||||
<i className="fa-solid fa-image"></i>
|
||||
</span>
|
||||
</Link>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
{
|
||||
@@ -178,7 +52,16 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
|
||||
!isNil(row.rawFileDetails)
|
||||
? row.rawFileDetails
|
||||
: row.sourcedMetadata,
|
||||
Cell: RawFileDetails,
|
||||
Cell: ({ value }) => {
|
||||
// If no CV info available, use raw file metadata
|
||||
if (!isNil(value.cover)) {
|
||||
return <RawFileDetails data={value} />;
|
||||
}
|
||||
// If CV metadata available, show it
|
||||
if (!isNil(value.comicvine)) {
|
||||
return <ComicVineDetails data={value} />;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: "Import Status",
|
||||
@@ -255,18 +138,6 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
|
||||
[],
|
||||
);
|
||||
|
||||
RawFileDetails.propTypes = {
|
||||
value: PropTypes.shape({
|
||||
cover: PropTypes.shape({
|
||||
filePath: PropTypes.string,
|
||||
}),
|
||||
name: PropTypes.string,
|
||||
path: PropTypes.string,
|
||||
fileSize: PropTypes.number,
|
||||
extension: PropTypes.string,
|
||||
}),
|
||||
};
|
||||
|
||||
ImportStatus.propTypes = {
|
||||
value: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
37
src/client/components/Library/ComicVineDetails.tsx
Normal file
37
src/client/components/Library/ComicVineDetails.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React, { ReactElement } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import ellipsize from "ellipsize";
|
||||
|
||||
export const ComicVineDetails = (comicVineData): ReactElement => {
|
||||
const { data } = comicVineData;
|
||||
return (
|
||||
<div className="card-container">
|
||||
<div className="card">
|
||||
<div className="is-horizontal">
|
||||
<div className="card-image">
|
||||
<figure>
|
||||
<img className="image" src={data.comicvine.image.thumb_url} />
|
||||
</figure>
|
||||
</div>
|
||||
<ul className="card-content">
|
||||
<li className="name has-text-weight-medium">
|
||||
{ellipsize(data.name, 18)}
|
||||
</li>
|
||||
<li>
|
||||
<div className="control">
|
||||
<div className="tags has-addons">
|
||||
<span className="tag is-primary is-light">ComicVine ID</span>
|
||||
<span className="tag is-info is-light">
|
||||
{data.comicvine.id}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ComicVineDetails;
|
||||
59
src/client/components/Library/RawFileDetails.tsx
Normal file
59
src/client/components/Library/RawFileDetails.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import React, { ReactElement } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { escapePoundSymbol } from "../../shared/utils/formatting.utils";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import ellipsize from "ellipsize";
|
||||
import { IMPORT_SERVICE_HOST } from "../../constants/endpoints";
|
||||
|
||||
// raw file details
|
||||
export const RawFileDetails = (rawFileData): ReactElement => {
|
||||
const { data } = rawFileData;
|
||||
const encodedFilePath = encodeURI(
|
||||
`${IMPORT_SERVICE_HOST}/${data.cover.filePath}`,
|
||||
);
|
||||
const filePath = escapePoundSymbol(encodedFilePath);
|
||||
return (
|
||||
<div className="card-container">
|
||||
<div className="card">
|
||||
<div className="is-horizontal">
|
||||
<div className="card-image">
|
||||
<figure>
|
||||
<img className="image" src={filePath} />
|
||||
</figure>
|
||||
</div>
|
||||
<ul className="card-content">
|
||||
<li className="name has-text-weight-medium">
|
||||
{ellipsize(data.name, 18)}
|
||||
</li>
|
||||
<li>
|
||||
<div className="control">
|
||||
<div className="tags has-addons">
|
||||
<span className="tag is-primary is-light">
|
||||
{data.extension}
|
||||
</span>
|
||||
<span className="tag is-info is-light">
|
||||
{prettyBytes(data.fileSize)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RawFileDetails;
|
||||
|
||||
RawFileDetails.propTypes = {
|
||||
data: PropTypes.shape({
|
||||
cover: PropTypes.shape({
|
||||
filePath: PropTypes.string,
|
||||
}),
|
||||
name: PropTypes.string,
|
||||
path: PropTypes.string,
|
||||
fileSize: PropTypes.number,
|
||||
extension: PropTypes.string,
|
||||
}),
|
||||
};
|
||||
54
src/client/components/Library/SearchBar.tsx
Normal file
54
src/client/components/Library/SearchBar.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import React, { ReactElement } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { Form, Field } from "react-final-form";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export const SearchBar = (): ReactElement => {
|
||||
const foo = () => {};
|
||||
return (
|
||||
<div className="box columns sticky">
|
||||
<Form
|
||||
onSubmit={foo}
|
||||
initialValues={{}}
|
||||
render={({ handleSubmit, form, submitting, pristine, values }) => (
|
||||
<div className="column is-three-quarters search">
|
||||
<label>Search</label>
|
||||
<Field name="search">
|
||||
{({ input, meta }) => {
|
||||
return (
|
||||
<input
|
||||
{...input}
|
||||
className="input main-search-bar is-medium"
|
||||
placeholder="Type an issue/volume name"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Field>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<div className="column one-fifth">
|
||||
<div className="field has-addons">
|
||||
<p className="control">
|
||||
<button className="button">
|
||||
<span className="icon is-small">
|
||||
<i className="fa-solid fa-list"></i>
|
||||
</span>
|
||||
</button>
|
||||
</p>
|
||||
<p className="control">
|
||||
<button className="button">
|
||||
<Link to="/library-grid">
|
||||
<span className="icon is-small">
|
||||
<i className="fa-solid fa-image"></i>
|
||||
</span>
|
||||
</Link>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchBar;
|
||||
@@ -45,7 +45,7 @@ export const RecentlyImported = ({
|
||||
);
|
||||
imagePath = escapePoundSymbol(encodedFilePath);
|
||||
comicName = rawFileDetails.name;
|
||||
} else if (!isNil(sourcedMetadata)) {
|
||||
} else if (!isNil(sourcedMetadata.comicvine)) {
|
||||
imagePath = sourcedMetadata.comicvine.image.small_url;
|
||||
comicName = sourcedMetadata.comicvine.name;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user