🏗️ Refactoring the Library page
This commit is contained in:
@@ -4,9 +4,10 @@ import { useNavigate } from "react-router-dom";
|
||||
import { isEmpty, isNil, isUndefined } from "lodash";
|
||||
import MetadataPanel from "../shared/MetadataPanel";
|
||||
import T2Table from "../shared/T2Table";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { searchIssue } from "../../actions/fileops.actions";
|
||||
import ellipsize from "ellipsize";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
/**
|
||||
* Component that tabulates the contents of the user's ThreeTwo Library.
|
||||
@@ -16,29 +17,31 @@ import ellipsize from "ellipsize";
|
||||
* <Library />
|
||||
*/
|
||||
export const Library = (): ReactElement => {
|
||||
const searchResults = useSelector(
|
||||
(state: RootState) => state.fileOps.libraryComics,
|
||||
);
|
||||
const searchError = useSelector((state: RootState) => state.fileOps.librarySearchError);
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
searchIssue(
|
||||
{
|
||||
// const searchResults = useSelector(
|
||||
// (state: RootState) => state.fileOps.libraryComics,
|
||||
// );
|
||||
// const searchError = useSelector(
|
||||
// (state: RootState) => state.fileOps.librarySearchError,
|
||||
// );
|
||||
// const dispatch = useDispatch();
|
||||
const { data, isLoading, isError } = useQuery({
|
||||
queryKey: ["comics"],
|
||||
queryFn: async () =>
|
||||
axios({
|
||||
method: "POST",
|
||||
url: "http://localhost:3000/api/search/searchIssue",
|
||||
data: {
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
pagination: {
|
||||
size: 15,
|
||||
from: 0,
|
||||
},
|
||||
type: "all",
|
||||
trigger: "libraryPage",
|
||||
},
|
||||
),
|
||||
);
|
||||
}, []);
|
||||
|
||||
}),
|
||||
});
|
||||
const searchResults = data?.data;
|
||||
console.log(searchResults);
|
||||
// programatically navigate to comic detail
|
||||
const navigate = useNavigate();
|
||||
const navigateToComicDetail = (row) => {
|
||||
@@ -157,21 +160,21 @@ export const Library = (): ReactElement => {
|
||||
*
|
||||
**/
|
||||
const nextPage = useCallback((pageIndex: number, pageSize: number) => {
|
||||
dispatch(
|
||||
searchIssue(
|
||||
{
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
pagination: {
|
||||
size: pageSize,
|
||||
from: pageSize * pageIndex + 1,
|
||||
},
|
||||
type: "all",
|
||||
trigger: "libraryPage",
|
||||
},
|
||||
),
|
||||
);
|
||||
// dispatch(
|
||||
// searchIssue(
|
||||
// {
|
||||
// query: {},
|
||||
// },
|
||||
// {
|
||||
// pagination: {
|
||||
// size: pageSize,
|
||||
// from: pageSize * pageIndex + 1,
|
||||
// },
|
||||
// type: "all",
|
||||
// trigger: "libraryPage",
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
}, []);
|
||||
|
||||
/**
|
||||
@@ -188,21 +191,21 @@ export const Library = (): ReactElement => {
|
||||
} else {
|
||||
from = (pageIndex - 1) * pageSize + 2 - 16;
|
||||
}
|
||||
dispatch(
|
||||
searchIssue(
|
||||
{
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
pagination: {
|
||||
size: pageSize,
|
||||
from,
|
||||
},
|
||||
type: "all",
|
||||
trigger: "libraryPage",
|
||||
},
|
||||
),
|
||||
);
|
||||
// dispatch(
|
||||
// searchIssue(
|
||||
// {
|
||||
// query: {},
|
||||
// },
|
||||
// {
|
||||
// pagination: {
|
||||
// size: pageSize,
|
||||
// from,
|
||||
// },
|
||||
// type: "all",
|
||||
// trigger: "libraryPage",
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
}, []);
|
||||
|
||||
// ImportStatus.propTypes = {
|
||||
@@ -214,7 +217,7 @@ export const Library = (): ReactElement => {
|
||||
<div className="header-area">
|
||||
<h1 className="title">Library</h1>
|
||||
</div>
|
||||
{!isEmpty(searchResults) ? (
|
||||
{!isUndefined(searchResults?.data?.data) ? (
|
||||
<div>
|
||||
<div className="library">
|
||||
<T2Table
|
||||
@@ -240,9 +243,9 @@ export const Library = (): ReactElement => {
|
||||
</div>
|
||||
</article>
|
||||
<pre>
|
||||
{!isUndefined(searchError.data) &&
|
||||
{!isUndefined(searchResults?.code === 404 && !isLoading) &&
|
||||
JSON.stringify(
|
||||
searchError.data.meta.body.error.root_cause,
|
||||
searchResults.data.meta.body.error.root_cause,
|
||||
null,
|
||||
4,
|
||||
)}
|
||||
|
||||
@@ -2,29 +2,27 @@ import React, { ReactElement, useCallback } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { Form, Field } from "react-final-form";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { searchIssue } from "../../actions/fileops.actions";
|
||||
|
||||
export const SearchBar = (): ReactElement => {
|
||||
const dispatch = useDispatch();
|
||||
const handleSubmit = useCallback((e) => {
|
||||
dispatch(
|
||||
searchIssue(
|
||||
{
|
||||
query: {
|
||||
volumeName: e.search,
|
||||
},
|
||||
},
|
||||
{
|
||||
pagination: {
|
||||
size: 25,
|
||||
from: 0,
|
||||
},
|
||||
type: "volumeName",
|
||||
trigger: "libraryPage",
|
||||
},
|
||||
),
|
||||
);
|
||||
// dispatch(
|
||||
// searchIssue(
|
||||
// {
|
||||
// query: {
|
||||
// volumeName: e.search,
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// pagination: {
|
||||
// size: 25,
|
||||
// from: 0,
|
||||
// },
|
||||
// type: "volumeName",
|
||||
// trigger: "libraryPage",
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
}, []);
|
||||
return (
|
||||
<div className="box">
|
||||
@@ -56,7 +54,6 @@ export const SearchBar = (): ReactElement => {
|
||||
</form>
|
||||
)}
|
||||
/>
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
import React, { ReactElement, useEffect, useMemo } from "react";
|
||||
import T2Table from "../shared/T2Table";
|
||||
import { getWeeklyPullList } from "../../actions/comicinfo.actions";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import Card from "../shared/Carda";
|
||||
import ellipsize from "ellipsize";
|
||||
import { isNil } from "lodash";
|
||||
|
||||
export const PullList = (): ReactElement => {
|
||||
const pullListComics = useSelector(
|
||||
(state: RootState) => state.comicInfo.pullList,
|
||||
);
|
||||
// const pullListComics = useSelector(
|
||||
// (state: RootState) => state.comicInfo.pullList,
|
||||
// );
|
||||
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
getWeeklyPullList({
|
||||
startDate: "2023-7-28",
|
||||
pageSize: "15",
|
||||
currentPage: "1",
|
||||
}),
|
||||
);
|
||||
// dispatch(
|
||||
// getWeeklyPullList({
|
||||
// startDate: "2023-7-28",
|
||||
// pageSize: "15",
|
||||
// currentPage: "1",
|
||||
// }),
|
||||
// );
|
||||
}, []);
|
||||
const nextPageHandler = () => {};
|
||||
const previousPageHandler = () => {};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { ReactElement, useEffect, useMemo } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { searchIssue } from "../../actions/fileops.actions";
|
||||
import Card from "../shared/Carda";
|
||||
import T2Table from "../shared/T2Table";
|
||||
@@ -8,24 +7,23 @@ import { convert } from "html-to-text";
|
||||
import { isUndefined } from "lodash";
|
||||
|
||||
export const Volumes = (props): ReactElement => {
|
||||
const volumes = useSelector((state: RootState) => state.fileOps.volumes);
|
||||
const dispatch = useDispatch();
|
||||
// const volumes = useSelector((state: RootState) => state.fileOps.volumes);
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
searchIssue(
|
||||
{
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
pagination: {
|
||||
size: 25,
|
||||
from: 0,
|
||||
},
|
||||
type: "volumes",
|
||||
trigger: "volumesPage",
|
||||
},
|
||||
),
|
||||
);
|
||||
// dispatch(
|
||||
// searchIssue(
|
||||
// {
|
||||
// query: {},
|
||||
// },
|
||||
// {
|
||||
// pagination: {
|
||||
// size: 25,
|
||||
// from: 0,
|
||||
// },
|
||||
// type: "volumes",
|
||||
// trigger: "volumesPage",
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
}, []);
|
||||
const columnData = useMemo(
|
||||
() => [
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React, { ReactElement, useCallback, useEffect, useMemo } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { searchIssue } from "../../actions/fileops.actions";
|
||||
import SearchBar from "../Library/SearchBar";
|
||||
import T2Table from "../shared/T2Table";
|
||||
@@ -7,26 +6,25 @@ import { isEmpty, isUndefined } from "lodash";
|
||||
import MetadataPanel from "../shared/MetadataPanel";
|
||||
|
||||
export const WantedComics = (props): ReactElement => {
|
||||
const wantedComics = useSelector(
|
||||
(state: RootState) => state.fileOps.wantedComics,
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
// const wantedComics = useSelector(
|
||||
// (state: RootState) => state.fileOps.wantedComics,
|
||||
// );
|
||||
useEffect(() => {
|
||||
dispatch(
|
||||
searchIssue(
|
||||
{
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
pagination: {
|
||||
size: 25,
|
||||
from: 0,
|
||||
},
|
||||
type: "wanted",
|
||||
trigger: "wantedComicsPage"
|
||||
},
|
||||
),
|
||||
);
|
||||
// dispatch(
|
||||
// searchIssue(
|
||||
// {
|
||||
// query: {},
|
||||
// },
|
||||
// {
|
||||
// pagination: {
|
||||
// size: 25,
|
||||
// from: 0,
|
||||
// },
|
||||
// type: "wanted",
|
||||
// trigger: "wantedComicsPage"
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
}, []);
|
||||
|
||||
const columnData = [
|
||||
@@ -37,7 +35,7 @@ export const WantedComics = (props): ReactElement => {
|
||||
header: "Details",
|
||||
id: "comicDetails",
|
||||
minWidth: 350,
|
||||
accessorFn: data => data,
|
||||
accessorFn: (data) => data,
|
||||
cell: (value) => <MetadataPanel data={value.getValue()} />,
|
||||
},
|
||||
],
|
||||
@@ -49,8 +47,10 @@ export const WantedComics = (props): ReactElement => {
|
||||
header: "Files",
|
||||
accessorKey: "acquisition",
|
||||
align: "right",
|
||||
cell: props => {
|
||||
const { directconnect: { downloads } } = props.getValue();
|
||||
cell: (props) => {
|
||||
const {
|
||||
directconnect: { downloads },
|
||||
} = props.getValue();
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -60,9 +60,7 @@ export const WantedComics = (props): ReactElement => {
|
||||
}}
|
||||
>
|
||||
{downloads.length > 0 ? (
|
||||
<span className="tag is-warning">
|
||||
{downloads.length}
|
||||
</span>
|
||||
<span className="tag is-warning">{downloads.length}</span>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
@@ -72,11 +70,17 @@ export const WantedComics = (props): ReactElement => {
|
||||
header: "Download Details",
|
||||
id: "downloadDetails",
|
||||
accessorKey: "acquisition",
|
||||
cell: data => <ol>
|
||||
{data.getValue().directconnect.downloads.map((download, idx) => {
|
||||
return <li className="is-size-7" key={idx}>{download.name}</li>;
|
||||
})}
|
||||
</ol>
|
||||
cell: (data) => (
|
||||
<ol>
|
||||
{data.getValue().directconnect.downloads.map((download, idx) => {
|
||||
return (
|
||||
<li className="is-size-7" key={idx}>
|
||||
{download.name}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ol>
|
||||
),
|
||||
},
|
||||
{
|
||||
header: "Type",
|
||||
@@ -92,7 +96,7 @@ export const WantedComics = (props): ReactElement => {
|
||||
* @param {number} pageIndex
|
||||
* @param {number} pageSize
|
||||
* @returns void
|
||||
*
|
||||
*
|
||||
**/
|
||||
const nextPage = useCallback((pageIndex: number, pageSize: number) => {
|
||||
dispatch(
|
||||
@@ -112,7 +116,6 @@ export const WantedComics = (props): ReactElement => {
|
||||
);
|
||||
}, []);
|
||||
|
||||
|
||||
/**
|
||||
* Pagination control that fetches the previous x (pageSize) items
|
||||
* based on the y (pageIndex) offset from the Elasticsearch index
|
||||
@@ -138,7 +141,7 @@ export const WantedComics = (props): ReactElement => {
|
||||
from,
|
||||
},
|
||||
type: "wanted",
|
||||
trigger: "wantedComicsPage"
|
||||
trigger: "wantedComicsPage",
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -161,7 +164,7 @@ export const WantedComics = (props): ReactElement => {
|
||||
nextPage: nextPage,
|
||||
previousPage: previousPage,
|
||||
}}
|
||||
// rowClickHandler={navigateToComicDetail}
|
||||
// rowClickHandler={navigateToComicDetail}
|
||||
/>
|
||||
{/* pagination controls */}
|
||||
</div>
|
||||
|
||||
@@ -13,12 +13,14 @@ const Navbar: React.FunctionComponent = (props) => {
|
||||
airDCPPDisconnectionInfo,
|
||||
airDCPPSessionInformation,
|
||||
airDCPPDownloadTick,
|
||||
importJobQueue,
|
||||
} = useStore(
|
||||
useShallow((state) => ({
|
||||
airDCPPSocketConnected: state.airDCPPSocketConnected,
|
||||
airDCPPDisconnectionInfo: state.airDCPPDisconnectionInfo,
|
||||
airDCPPSessionInformation: state.airDCPPSessionInformation,
|
||||
airDCPPDownloadTick: state.airDCPPDownloadTick,
|
||||
importJobQueue: state.importJobQueue,
|
||||
})),
|
||||
);
|
||||
// const downloadProgressTick = useSelector(
|
||||
@@ -35,24 +37,6 @@ const Navbar: React.FunctionComponent = (props) => {
|
||||
// (state: RootState) => state.airdcpp.socketDisconnectionReason,
|
||||
// );
|
||||
|
||||
// Import-related selector hooks
|
||||
// const successfulImportJobCount = useSelector(
|
||||
// (state: RootState) => state.fileOps.successfulJobCount,
|
||||
// );
|
||||
// const failedImportJobCount = useSelector(
|
||||
// (state: RootState) => state.fileOps.failedJobCount,
|
||||
// );
|
||||
//
|
||||
// const lastQueueJob = useSelector(
|
||||
// (state: RootState) => state.fileOps.lastQueueJob,
|
||||
// );
|
||||
// const libraryQueueImportStatus = useSelector(
|
||||
// (state: RootState) => state.fileOps.LSQueueImportStatus,
|
||||
// );
|
||||
//
|
||||
// const allImportJobResults = useSelector(
|
||||
// (state: RootState) => state.fileOps.importJobStatistics,
|
||||
// );
|
||||
return (
|
||||
<nav className="navbar is-fixed-top">
|
||||
<div className="navbar-brand">
|
||||
@@ -128,6 +112,38 @@ const Navbar: React.FunctionComponent = (props) => {
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{!isUndefined(importJobQueue.status) &&
|
||||
location.hash !== "#/import" ? (
|
||||
<div className="navbar-item has-dropdown is-hoverable">
|
||||
<a className="navbar-link is-arrowless">
|
||||
<i className="fa-solid fa-file-import has-text-warning-dark"></i>
|
||||
</a>
|
||||
|
||||
<div className="navbar-dropdown is-right is-boxed">
|
||||
<a className="navbar-item">
|
||||
<ul>
|
||||
{importJobQueue.successfulJobCount > 0 ? (
|
||||
<li className="mb-2">
|
||||
<span className="tag is-success mr-2">
|
||||
{importJobQueue.successfulJobCount}
|
||||
</span>
|
||||
imported.
|
||||
</li>
|
||||
) : null}
|
||||
{importJobQueue.failedJobCount > 0 ? (
|
||||
<li>
|
||||
<span className="tag is-danger mr-2">
|
||||
{importJobQueue.failedJobCount}
|
||||
</span>
|
||||
failed to import.
|
||||
</li>
|
||||
) : null}
|
||||
</ul>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* AirDC++ socket connection status */}
|
||||
<div className="navbar-item has-dropdown is-hoverable">
|
||||
{airDCPPSocketConnected ? (
|
||||
|
||||
@@ -11,6 +11,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||
import Import from "./components/Import/Import";
|
||||
import Dashboard from "./components/Dashboard/Dashboard";
|
||||
import TabulatedContentContainer from "./components/Library/TabulatedContentContainer";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
@@ -22,6 +23,10 @@ const router = createBrowserRouter([
|
||||
children: [
|
||||
{ path: "dashboard", element: <Dashboard /> },
|
||||
{ path: "settings", element: <Settings /> },
|
||||
{
|
||||
path: "library",
|
||||
element: <TabulatedContentContainer category="library" />,
|
||||
},
|
||||
{ path: "import", element: <Import path={"./comics"} /> },
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user