🔧 🏗️ Massive tables refactor

Abstracted a table component that can be configured to display issues, volumes or pull list items
This commit is contained in:
2022-11-15 17:22:50 -08:00
parent 1e39daeda2
commit 7babf9f73d
11 changed files with 134 additions and 102 deletions

View File

@@ -32,6 +32,8 @@ import {
SS_SEARCH_FAILED,
SS_SEARCH_RESULTS_FETCHED_SPECIAL,
WANTED_COMICS_FETCHED,
VOLUMES_FETCHED,
CV_WEEKLY_PULLLIST_FETCHED,
} from "../constants/action-types";
import { success } from "react-notification-system-redux";
import { removeLeadingPeriod } from "../shared/utils/formatting.utils";
@@ -316,12 +318,16 @@ export const searchIssue = (query, options) => async (dispatch) => {
data: response.data.body,
});
break;
case "volumesPage":
dispatch({
type: VOLUMES_FETCHED,
data: response.data.body,
});
break;
default:
break;
}
};
export const analyzeImage =
(imageFilePath: string | Buffer) => async (dispatch) => {

View File

@@ -3,7 +3,7 @@ import Dashboard from "./Dashboard/Dashboard";
import Import from "./Import";
import { ComicDetailContainer } from "./ComicDetail/ComicDetailContainer";
import LibraryContainer from "./Library/LibraryContainer";
import TabulatedContentContainer from "./Library/TabulatedContentContainer";
import LibraryGrid from "./Library/LibraryGrid";
import Search from "./Search";
import Settings from "./Settings";
@@ -92,7 +92,7 @@ export const App = (): ReactElement => {
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/import" element={<Import path={"./comics"} />} />
<Route path="/library" element={<LibraryContainer />} />
<Route path="/library" element={<TabulatedContentContainer category="library" />} />
<Route path="/library-grid" element={<LibraryGrid />} />
<Route path="/downloads" element={<Downloads data={{}} />} />
<Route path="/search" element={<Search />} />
@@ -105,9 +105,9 @@ export const App = (): ReactElement => {
element={<VolumeDetail />}
/>
<Route path="/settings" element={<Settings />} />
<Route path="/pull-list/all" element={<PullList />} />
<Route path="/wanted/all" element={<WantedComics />} />
<Route path="/volumes/all" element={<Volumes />} />
<Route path="/pull-list/all" element={<TabulatedContentContainer category="pullList" />} />
<Route path="/wanted/all" element={<TabulatedContentContainer category="wanted" />} />
<Route path="/volumes/all" element={<TabulatedContentContainer category="volumes" />} />
</Routes>
</div>
</AirDCPPSocketContextProvider>

View File

@@ -20,7 +20,7 @@ export const PullList = ({ issues }: PullListProps): ReactElement => {
useEffect(() => {
dispatch(
getWeeklyPullList({
startDate: "2022-11-9",
startDate: "2022-11-15",
pageSize: "15",
currentPage: "1",
}),
@@ -127,7 +127,7 @@ export const PullList = ({ issues }: PullListProps): ReactElement => {
<Slider {...settings} ref={(c) => (sliderRef = c)}>
{!isNil(pullList) &&
pullList &&
map(pullList, (issue, idx) => {
map(pullList, ({issue}, idx) => {
return (
<Card
key={idx}

View File

@@ -81,7 +81,7 @@ export const Library = (): ReactElement => {
const WantedStatus = ({ value }) => {
return !value ? <span className="tag is-info is-light">Wanted</span> : null;
};
const columns = React.useMemo(() => [
const columns = useMemo(() => [
{
header: "Comic Metadata",
footer: 1,

View File

@@ -1,39 +1,34 @@
import { isEmpty, isUndefined } from "lodash";
import React, { ReactElement, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { searchIssue } from "../../actions/fileops.actions";
import React, { ReactElement } from "react";
import PullList from "../PullList/PullList";
import { Volumes } from "../Volumes/Volumes";
import WantedComics from "../WantedComics/WantedComics";
import { Library } from "./Library";
const LibraryContainer = (): ReactElement => {
// const dispatch = useDispatch();
// useEffect(() => {
// dispatch(
// searchIssue(
// {
// query: {},
// },
// {
// pagination: {
// size: 25,
// from: 0,
// },
// type: "all",
// trigger: "libraryPage"
// },
// ),
// );
// }, []);
interface ITabulatedContentContainerProps {
category: string;
}
// const searchResults = useSelector(
// (state: RootState) => state.fileOps.libraryComics,
// );
// const searchError = useSelector(
// (state: RootState) => state.fileOps.librarySearchError,
// );
const TabulatedContentContainer = (
props: ITabulatedContentContainerProps,
): ReactElement => {
const { category } = props;
const renderTabulatedContent = () => {
switch (category) {
case "library":
return <Library />;
case "pullList":
return <PullList />;
case "wanted":
return <WantedComics />;
case "volumes":
return <Volumes />;
default:
return <></>;
}
};
return (
<Library />)
// : (
return renderTabulatedContent();
// : (
// <div className="container">
// <section className="section is-small">
// <div className="columns">
@@ -59,4 +54,4 @@ const LibraryContainer = (): ReactElement => {
// );
};
export default LibraryContainer;
export default TabulatedContentContainer;

View File

@@ -4,18 +4,19 @@ import { getWeeklyPullList } from "../../actions/comicinfo.actions";
import { useDispatch, useSelector } from "react-redux";
import Card from "../Carda";
import ellipsize from "ellipsize";
import { isNil, isUndefined } from "lodash";
export const PullList = (): ReactElement => {
const pullListComics = useSelector(
(state: RootState) => state.comicInfo.pullList,
);
console.log(pullListComics);
const dispatch = useDispatch();
useEffect(() => {
dispatch(
getWeeklyPullList({
startDate: "2022-6-1",
pageSize: "100",
startDate: "2022-11-15",
pageSize: "15",
currentPage: "1",
}),
);
@@ -25,24 +26,25 @@ export const PullList = (): ReactElement => {
const columnData = useMemo(
() => [
{
Header: "Comic Information",
header: "Comic Information",
columns: [
{
Header: "Details",
header: "Details",
id: "comicDetails",
minWidth: 450,
accessor: (row) => {
console.log(row);
accessorKey: "issue",
cell: (row) => {
const item = row.getValue();
return (
<div className="columns">
<div className="column">
<div className="column is-three-quarters">
<div className="comic-detail issue-metadata">
<dl>
<dd>
<div className="columns mt-2">
<div className="column is-3">
<Card
imageUrl={row.cover}
imageUrl={item.cover}
orientation={"vertical"}
hasDetails={false}
// cardContainerStyle={{ maxWidth: 200 }}
@@ -52,18 +54,20 @@ export const PullList = (): ReactElement => {
<dl>
<dt>
<h6 className="name has-text-weight-medium mb-1">
{row.name}
{item.name}
</h6>
</dt>
<dd className="is-size-7">
published by{" "}
<span className="has-text-weight-semibold">
{row.publisher}
{item.publisher}
</span>
</dd>
<dd className="is-size-7">
<span>{ellipsize(row.description, 190)}</span>
<span>
{ellipsize(item.description, 190)}
</span>
</dd>
<dd className="is-size-7 mt-2">
@@ -71,10 +75,10 @@ export const PullList = (): ReactElement => {
<div className="control">
<span className="tags">
<span className="tag is-success is-light has-text-weight-semibold">
{row.price}
{item.price}
</span>
<span className="tag is-success is-light">
{row.pulls}
{item.pulls}
</span>
</span>
</div>
@@ -99,16 +103,24 @@ export const PullList = (): ReactElement => {
return (
<section className="container">
<div className="section">
<h1 className="title">Weekly Pull List</h1>
<T2Table
rowData={pullListComics}
columns={columnData}
totalPages={pullListComics.length}
paginationHandlers={{
nextPage: nextPageHandler,
previousPage: previousPageHandler,
}}
/>
<div className="header-area">
<h1 className="title">Weekly Pull List</h1>
</div>
{!isNil(pullListComics) && (
<div>
<div className="library">
<T2Table
sourceData={pullListComics}
columns={columnData}
totalPages={pullListComics.length}
paginationHandlers={{
nextPage: nextPageHandler,
previousPage: previousPageHandler,
}}
/>
</div>
</div>
)}
</div>
</section>
);

View File

@@ -2,16 +2,13 @@ import React, { ReactElement, useEffect, useMemo } from "react";
import { useDispatch, useSelector } from "react-redux";
import { searchIssue } from "../../actions/fileops.actions";
import Card from "../Carda";
import SearchBar from "../Library/SearchBar";
import T2Table from "../shared/T2Table";
import ellipsize from "ellipsize";
import { isUndefined } from "lodash";
import { convert } from "html-to-text";
import { isUndefined } from "lodash";
export const Volumes = (props): ReactElement => {
const volumes = useSelector(
(state: RootState) => state.fileOps.librarySearchResults,
);
const volumes = useSelector((state: RootState) => state.fileOps.volumes);
const dispatch = useDispatch();
useEffect(() => {
dispatch(
@@ -25,19 +22,20 @@ export const Volumes = (props): ReactElement => {
from: 0,
},
type: "volumes",
trigger: "volumesPage",
},
),
);
}, []);
console.log(volumes);
const columnData = useMemo(
() => [
{
Header: "Volume Details",
header: "Volume Details",
id: "volumeDetails",
minWidth: 450,
accessor: (row) => {
accessorKey: "_source",
cell: (row) => {
const foo = row.getValue();
return (
<div className="columns">
<div className="column">
@@ -45,11 +43,11 @@ export const Volumes = (props): ReactElement => {
<dl>
<dd>
<div className="columns mt-2">
<div className="column is-3">
<div className="">
<Card
imageUrl={
row._source.sourcedMetadata.comicvine
.volumeInformation.image.thumb_url
foo.sourcedMetadata.comicvine.volumeInformation
.image.thumb_url
}
orientation={"vertical"}
hasDetails={false}
@@ -61,7 +59,7 @@ export const Volumes = (props): ReactElement => {
<dt>
<h6 className="name has-text-weight-medium mb-1">
{
row._source.sourcedMetadata.comicvine
foo.sourcedMetadata.comicvine
.volumeInformation.name
}
</h6>
@@ -70,7 +68,7 @@ export const Volumes = (props): ReactElement => {
published by{" "}
<span className="has-text-weight-semibold">
{
row._source.sourcedMetadata.comicvine
foo.sourcedMetadata.comicvine
.volumeInformation.publisher.name
}
</span>
@@ -80,7 +78,7 @@ export const Volumes = (props): ReactElement => {
<span>
{ellipsize(
convert(
row._source.sourcedMetadata.comicvine
foo.sourcedMetadata.comicvine
.volumeInformation.description,
{
baseElements: {
@@ -102,7 +100,7 @@ export const Volumes = (props): ReactElement => {
</span>
<span className="tag is-success is-light">
{
row._source.sourcedMetadata.comicvine
foo.sourcedMetadata.comicvine
.volumeInformation.count_of_issues
}
</span>
@@ -122,36 +120,35 @@ export const Volumes = (props): ReactElement => {
},
},
{
Header: "Download Status",
header: "Download Status",
columns: [
{
Header: "Files",
accessor: "_source.acquisition.directconnect",
header: "Files",
accessorKey: "_source.acquisition.directconnect",
align: "right",
Cell: (props) => {
cell: (props) => {
const row = props.getValue();
return (
<div
style={{
display: "flex",
// flexDirection: "column",
flexDirection: "column",
justifyContent: "center",
}}
>
{props.cell.value.length > 0 ? (
<span className="tag is-warning">
{props.cell.value.length}
</span>
{row.length > 0 ? (
<span className="tag is-warning">{row.length}</span>
) : null}
</div>
);
},
},
{
Header: "Type",
header: "Type",
id: "Air",
},
{
Header: "Type",
header: "Type",
id: "dcc",
},
],
@@ -162,16 +159,24 @@ export const Volumes = (props): ReactElement => {
return (
<section className="container">
<div className="section">
{volumes.hits ? (
<div className="header-area">
<h1 className="title">Volumes</h1>
</div>
{!isUndefined(volumes.hits) && (
<div>
<div className="library">
<h1 className="title">Volumes</h1>
{/* Search bar */}
<SearchBar />
<T2Table rowData={volumes.hits.hits} columns={columnData} />
<T2Table
sourceData={volumes?.hits?.hits}
totalPages={volumes.hits.hits.length}
paginationHandlers={{
nextPage: () => {},
previousPage: () => {},
}}
columns={columnData}
/>
</div>
</div>
) : null}
)}
</div>
</section>
);

View File

@@ -20,6 +20,7 @@ export const T2Table = (tableOptions): ReactElement => {
pageIndex: 1,
pageSize: 15,
});
console.log(sourceData)
const pagination = useMemo(

View File

@@ -51,6 +51,7 @@ export const IMS_COMIC_BOOK_GROUPS_CALL_IN_PROGRESS =
"IMS_COMIC_BOOK_GROUPS_CALL_IN_PROGRESS";
export const IMS_COMIC_BOOK_GROUPS_CALL_FAILED =
"IMS_COMIC_BOOK_GROUPS_CALL_FAILED";
export const VOLUMES_FETCHED="VOLUMES_FETCHED";
// search results from the Search service
export const SS_SEARCH_RESULTS_FETCHED = "SS_SEARCH_RESULTS_FETCHED";

View File

@@ -109,10 +109,14 @@ function comicinfoReducer(state = initialState, action) {
...state,
};
case CV_WEEKLY_PULLLIST_FETCHED: {
const foo = [];
action.data.map((item) => {
foo.push({issue: item})
});
return {
...state,
inProgress: false,
pullList: [...action.data],
pullList: foo,
};
}
case LIBRARY_STATISTICS_CALL_IN_PROGRESS:

View File

@@ -28,6 +28,7 @@ import {
LS_IMPORT_CALL_IN_PROGRESS,
SS_SEARCH_FAILED,
SS_SEARCH_RESULTS_FETCHED_SPECIAL,
VOLUMES_FETCHED,
} from "../constants/action-types";
const initialState = {
IMSCallInProgress: false,
@@ -45,6 +46,7 @@ const initialState = {
recentComics: [],
wantedComics: [],
libraryComics: [],
volumes: [],
librarySearchResultsFormatted: [],
librarySearchResultCount: 0,
libraryQueueResults: [],
@@ -188,7 +190,6 @@ function fileOpsReducer(state = initialState, action) {
}
case SS_SEARCH_RESULTS_FETCHED: {
console.log(action.data);
return {
...state,
libraryComics: action.data,
@@ -221,6 +222,13 @@ function fileOpsReducer(state = initialState, action) {
SSCallInProgress: false,
};
}
case VOLUMES_FETCHED:
return {
...state,
volumes: action.data,
SSCallInProgress: false,
};
case SS_SEARCH_FAILED: {
return {