🔧 Fixed table pagination controls and counts

This commit is contained in:
2021-08-16 22:11:44 -07:00
parent d92b2246cb
commit afdff65b6b
5 changed files with 141 additions and 99 deletions

View File

@@ -137,15 +137,18 @@ $border-color: red;
// Library
.library {
table {
td {
border: 0 none;
.card {
margin: 8px 0 7px 0;
.name {
margin: 0 0 4px 0;
tr{
td {
border: 0 none;
.card {
margin: 8px 0 7px 0;
.name {
margin: 0 0 4px 0;
}
}
}
}
}
tbody {
padding: 10px 0 0 0;
}

View File

@@ -65,14 +65,15 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
return { __html: html };
};
const isComicBookMetadataAvailable =
!isNil(comicBookDetailData.sourcedMetadata) &&
comicBookDetailData.sourcedMetadata &&
!isUndefined(comicBookDetailData.sourcedMetadata.comicvine) &&
!isEmpty(comicBookDetailData.sourcedMetadata);
// Tab groups for ComicVine metadata
const tabGroup = [
{
id: 0,
name: "Volume Information",
content: isComicBookMetadataAvailable && (
content: isComicBookMetadataAvailable ? (
<>
<div className="columns">
<div className="column is-narrow">
@@ -126,7 +127,7 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
></div>
</div>
</>
),
) : null,
},
{
id: 1,
@@ -249,7 +250,7 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
</div>
</div>
<MetadataTabGroup />
{isComicBookMetadataAvailable ? <MetadataTabGroup /> : null}
<Drawer
title="ComicVine Search Results"

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect, useMemo, ReactElement } from "react";
import PropTypes from 'prop-types';
import PropTypes from "prop-types";
import { useHistory } from "react-router";
import {
removeLeadingPeriod,
escapePoundSymbol,
@@ -16,27 +17,68 @@ interface IComicBookLibraryProps {
}
export const Library = ({}: IComicBookLibraryProps): ReactElement => {
const [comicPage, setComicPage] = useState(1);
const [isPageSizeDropdownCollapsed, collapsePageSizeDropdown] =
useState(false);
const dispatch = useDispatch();
useEffect(() => {
dispatch(
getComicBooks({
paginationOptions: {
page: comicPage,
limit: 15,
},
}),
);
}, [comicPage, dispatch]);
const data = useSelector(
(state: RootState) => state.fileOps.recentComics.docs,
);
const pageTotal = useSelector(
(state: RootState) => state.fileOps.recentComics.totalDocs,
);
const togglePageSizeDropdown = () =>
collapsePageSizeDropdown(!isPageSizeDropdownCollapsed);
// programatically navigate to comic detail
const history = useHistory();
const navigateToComicDetail = (id) => {
history.push(`/comic/details/${id}`);
};
// raw file details
const RawFileDetails = ({ value }) => {
const encodedFilePath = encodeURI(
"http://localhost:3000" + removeLeadingPeriod(value.path),
);
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>
);
};
const ImportStatus = ({ value }) => {
return `${value.toString()}` ? (
<span className="tag is-info is-light">Imported</span>
) : (
"Not Imported"
);
};
const columns = useMemo(
() => [
{
@@ -45,55 +87,12 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
{
Header: "File Details",
accessor: "rawFileDetails",
// eslint-disable-next-line react/display-name
Cell(props) {
const encodedFilePath = encodeURI(
"http://localhost:3000" +
removeLeadingPeriod(props.cell.value.path),
);
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(props.cell.value.name, 18)}
</li>
<li>
<div className="control">
<div className="tags has-addons">
<span className="tag is-primary is-light">
{props.cell.value.extension}
</span>
<span className="tag is-info is-light">
{prettyBytes(props.cell.value.fileSize)}
</span>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
);
},
Cell: RawFileDetails,
},
{
Header: "Import Status",
accessor: "importStatus.isImported",
Cell(props) {
return `${props.cell.value.toString()}` ? (
<span className="tag is-info is-light">Imported</span>
) : (
"Not Imported"
);
},
Cell: ImportStatus,
},
],
},
@@ -165,29 +164,57 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
[],
);
columns[0].columns[0].Cell.propTypes = {
value: PropTypes.object.isRequired,
RawFileDetails.propTypes = {
name: PropTypes.string,
path: PropTypes.string,
fileSize: PropTypes.number,
extension: PropTypes.string,
};
ImportStatus.propTypes = {
value: PropTypes.bool.isRequired,
};
const {
getTableProps,
getTableBodyProps,
headerGroups,
page,
prepareRow,
pageOptions,
pageCount,
state: { pageIndex, pageSize },
gotoPage,
previousPage,
nextPage,
setPageSize,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = useTable(
{ columns, data, initialState: { pageIndex: 0 } },
{
columns,
data,
manualPagination: true,
initialState: {
pageIndex: 1,
pageSize: 15,
},
pageCount: pageTotal,
},
usePagination,
);
const dispatch = useDispatch();
useEffect(() => {
dispatch(
getComicBooks({
paginationOptions: {
page: pageIndex,
limit: pageSize,
},
}),
);
}, [pageIndex, pageSize]);
const comicBookLibraryItems = React.useMemo(() => {});
return (
@@ -216,7 +243,11 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
{page.map((row, idx) => {
prepareRow(row);
return (
<tr key={idx} {...row.getRowProps()}>
<tr
key={idx}
{...row.getRowProps()}
onClick={() => navigateToComicDetail(row.original._id)}
>
{row.cells.map((cell, idx) => {
return (
<td
@@ -240,7 +271,8 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
aria-label="pagination"
>
<div>
Page {pageIndex + 1} of {pageOptions.length}
Page {pageIndex} of {Math.ceil(pageTotal / pageSize)}
(Total resources: {pageTotal})
</div>
<div className="field has-addons">
<p className="control">
@@ -288,11 +320,9 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
<input
type="number"
className="input"
defaultValue={pageIndex + 1}
defaultValue={pageIndex}
onChange={(e) => {
const page = e.target.value
? Number(e.target.value) - 1
: 0;
const page = e.target.value ? Number(e.target.value) : 0;
gotoPage(page);
}}
style={{ width: "100px" }}

View File

@@ -59,7 +59,7 @@ export const Search = ({}: ISearchProps): ReactElement => {
onSubmit={() =>
getDCPPSearchResults({
query: {
pattern: "secret wars",
pattern: "wolverine",
// file_type: "compressed",
extensions: ["cbz", "cbr"],
},

View File

@@ -2304,15 +2304,15 @@ aggregate-error@^3.0.0:
clean-stack "^2.0.0"
indent-string "^4.0.0"
airdcpp-apisocket@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/airdcpp-apisocket/-/airdcpp-apisocket-2.4.1.tgz#eb2dc28eecd9d6306b25ef8239545d90d6ad005f"
integrity sha512-3mkEvbChG4aRe8F2ZFTi2Z0FG319toex/HquRxWlo6s6Rg69s5bPo0VwGte3NlZ4fnHoBD9vk5KavHgOMkJgZg==
airdcpp-apisocket@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/airdcpp-apisocket/-/airdcpp-apisocket-2.4.2.tgz#884d02ff7768cb452cd92e1083c05f618b892fc0"
integrity sha512-OxrrYe/iNOfle4RhqgaoUNJrgc7LDWCK+WhMQyfprDRxRqkvgPDuWjOavlmf89cAMIgwJ7x5DESpJKWvNGaS/w==
dependencies:
chalk "^4.1.0"
events "^3.2.0"
chalk "^4.1.2"
events "^3.3.0"
invariant "^2.2.4"
is-in-browser "^1.1.3"
is-in-browser "^2.0.0"
promise "^8.1.0"
ajv-errors@^1.0.0:
@@ -3661,6 +3661,14 @@ chalk@^4.0.0, chalk@^4.1.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
char-regex@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
@@ -5450,7 +5458,7 @@ eventemitter3@^4.0.0:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
events@^3.2.0:
events@^3.2.0, events@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
@@ -7281,10 +7289,10 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
is-in-browser@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835"
integrity sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=
is-in-browser@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-2.0.0.tgz#a2343a18d8f8a600e8a20cb3022183a251e30355"
integrity sha512-/NUv5pqj+krUJalhGpj0lyy+x7vrD9jt1PlAfkoIDEXqE+xZgFJ4FU8e9m99WuHbCqsBZVf+nzvAjNso+SO80A==
is-installed-globally@^0.1.0:
version "0.1.0"