🔨 Fixes to ComicDetail container
This commit is contained in:
@@ -17,16 +17,11 @@ import DownloadsPanel from "./DownloadsPanel";
|
|||||||
import { VolumeInformation } from "./Tabs/VolumeInformation";
|
import { VolumeInformation } from "./Tabs/VolumeInformation";
|
||||||
|
|
||||||
import { isEmpty, isUndefined, isNil, filter } from "lodash";
|
import { isEmpty, isUndefined, isNil, filter } from "lodash";
|
||||||
import { components } from "react-select";
|
import { components, PlaceholderProps, GroupBase, StylesConfig } from "react-select";
|
||||||
import { RootState } from "threetwo-ui-typings";
|
|
||||||
|
|
||||||
import "react-sliding-pane/dist/react-sliding-pane.css";
|
import "react-sliding-pane/dist/react-sliding-pane.css";
|
||||||
import Loader from "react-loader-spinner";
|
|
||||||
import SlidingPane from "react-sliding-pane";
|
import SlidingPane from "react-sliding-pane";
|
||||||
import Modal from "react-modal";
|
|
||||||
import ComicViewer from "react-comic-viewer";
|
|
||||||
|
|
||||||
import { extractComicArchive } from "../../actions/fileops.actions";
|
|
||||||
import { determineCoverFile } from "../../shared/utils/metadata.utils";
|
import { determineCoverFile } from "../../shared/utils/metadata.utils";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { styled } from "styled-components";
|
import { styled } from "styled-components";
|
||||||
@@ -38,23 +33,82 @@ const StyledSlidingPanel = styled(SlidingPane)`
|
|||||||
background: #ccc;
|
background: #ccc;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
interface RawFileDetails {
|
||||||
|
name: string;
|
||||||
|
cover?: {
|
||||||
|
filePath?: string;
|
||||||
|
};
|
||||||
|
containedIn?: string;
|
||||||
|
fileSize?: number;
|
||||||
|
path?: string;
|
||||||
|
extension?: string;
|
||||||
|
mimeType?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InferredIssue {
|
||||||
|
name?: string;
|
||||||
|
number?: number;
|
||||||
|
year?: string;
|
||||||
|
subtitle?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ComicVineMetadata {
|
||||||
|
name?: string;
|
||||||
|
volumeInformation?: any;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Acquisition {
|
||||||
|
directconnect?: {
|
||||||
|
downloads?: any[];
|
||||||
|
};
|
||||||
|
torrent?: any[];
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
interface ComicDetailProps {
|
interface ComicDetailProps {
|
||||||
data: {
|
data: {
|
||||||
_id: string;
|
_id: string;
|
||||||
rawFileDetails: {};
|
rawFileDetails?: RawFileDetails;
|
||||||
inferredMetadata: {
|
inferredMetadata: {
|
||||||
issue: {};
|
issue?: InferredIssue;
|
||||||
};
|
};
|
||||||
sourcedMetadata: {
|
sourcedMetadata: {
|
||||||
comicvine: {};
|
comicvine?: ComicVineMetadata;
|
||||||
locg: {};
|
locg?: any;
|
||||||
comicInfo: {};
|
comicInfo?: any;
|
||||||
};
|
};
|
||||||
acquisition: {};
|
acquisition?: Acquisition;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
};
|
||||||
userSettings: {};
|
userSettings?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ComicVineSearchQuery {
|
||||||
|
inferredIssueDetails: {
|
||||||
|
name: string;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ComicVineMatch {
|
||||||
|
score: number;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ActionOption {
|
||||||
|
value: string;
|
||||||
|
label: React.ReactElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ContentForSlidingPanel {
|
||||||
|
[key: string]: {
|
||||||
|
content: (props?: any) => React.ReactElement;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Component for displaying the metadata for a comic in greater detail.
|
* Component for displaying the metadata for a comic in greater detail.
|
||||||
@@ -83,7 +137,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [slidingPanelContentId, setSlidingPanelContentId] = useState("");
|
const [slidingPanelContentId, setSlidingPanelContentId] = useState("");
|
||||||
const [modalIsOpen, setIsOpen] = useState(false);
|
const [modalIsOpen, setIsOpen] = useState(false);
|
||||||
const [comicVineMatches, setComicVineMatches] = useState([]);
|
const [comicVineMatches, setComicVineMatches] = useState<ComicVineMatch[]>([]);
|
||||||
|
|
||||||
const { comicObjectId } = useParams<{ comicObjectId: string }>();
|
const { comicObjectId } = useParams<{ comicObjectId: string }>();
|
||||||
|
|
||||||
@@ -113,9 +167,9 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// sliding panel init
|
// sliding panel init
|
||||||
const contentForSlidingPanel = {
|
const contentForSlidingPanel: ContentForSlidingPanel = {
|
||||||
CVMatches: {
|
CVMatches: {
|
||||||
content: (props) => (
|
content: (props?: any) => (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
<ComicVineSearchForm data={rawFileDetails} />
|
<ComicVineSearchForm data={rawFileDetails} />
|
||||||
@@ -125,8 +179,8 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
<p className="">Searching for:</p>
|
<p className="">Searching for:</p>
|
||||||
{inferredMetadata.issue ? (
|
{inferredMetadata.issue ? (
|
||||||
<>
|
<>
|
||||||
<span className="">{inferredMetadata.issue.name} </span>
|
<span className="">{inferredMetadata.issue?.name} </span>
|
||||||
<span className=""> # {inferredMetadata.issue.number} </span>
|
<span className=""> # {inferredMetadata.issue?.number} </span>
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
@@ -148,9 +202,9 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
const fetchComicVineMatches = async (
|
const fetchComicVineMatches = async (
|
||||||
searchPayload,
|
searchPayload: any,
|
||||||
issueSearchQuery,
|
issueSearchQuery: ComicVineSearchQuery,
|
||||||
seriesSearchQuery,
|
seriesSearchQuery: ComicVineSearchQuery,
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
const response = await axios({
|
const response = await axios({
|
||||||
@@ -176,13 +230,13 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
// return sortBy(matches, (match) => -match.score);
|
// return sortBy(matches, (match) => -match.score);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
let matches: any = [];
|
let matches: ComicVineMatch[] = [];
|
||||||
if (!isNil(response.data.results) && response.data.results.length === 1) {
|
if (!isNil(response.data.results) && response.data.results.length === 1) {
|
||||||
matches = response.data.results;
|
matches = response.data.results;
|
||||||
} else {
|
} else {
|
||||||
matches = response.data.map((match) => match);
|
matches = response.data.map((match: ComicVineMatch) => match);
|
||||||
}
|
}
|
||||||
const scoredMatches = matches.sort((a, b) => b.score - a.score);
|
const scoredMatches = matches.sort((a: ComicVineMatch, b: ComicVineMatch) => b.score - a.score);
|
||||||
setComicVineMatches(scoredMatches);
|
setComicVineMatches(scoredMatches);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -191,13 +245,13 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
|
|
||||||
// Action event handlers
|
// Action event handlers
|
||||||
const openDrawerWithCVMatches = () => {
|
const openDrawerWithCVMatches = () => {
|
||||||
let seriesSearchQuery: IComicVineSearchQuery = {} as IComicVineSearchQuery;
|
let seriesSearchQuery: ComicVineSearchQuery = {} as ComicVineSearchQuery;
|
||||||
let issueSearchQuery: IComicVineSearchQuery = {} as IComicVineSearchQuery;
|
let issueSearchQuery: ComicVineSearchQuery = {} as ComicVineSearchQuery;
|
||||||
|
|
||||||
if (!isUndefined(rawFileDetails)) {
|
if (!isUndefined(rawFileDetails)) {
|
||||||
issueSearchQuery = refineQuery(rawFileDetails.name);
|
issueSearchQuery = refineQuery(rawFileDetails.name) as ComicVineSearchQuery;
|
||||||
} else if (!isEmpty(comicvine)) {
|
} else if (!isEmpty(comicvine) && comicvine?.name) {
|
||||||
issueSearchQuery = refineQuery(comicvine.name);
|
issueSearchQuery = refineQuery(comicvine.name) as ComicVineSearchQuery;
|
||||||
}
|
}
|
||||||
fetchComicVineMatches(rawFileDetails, issueSearchQuery, seriesSearchQuery);
|
fetchComicVineMatches(rawFileDetails, issueSearchQuery, seriesSearchQuery);
|
||||||
setSlidingPanelContentId("CVMatches");
|
setSlidingPanelContentId("CVMatches");
|
||||||
@@ -234,9 +288,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
<div>Delete Comic</div>
|
<div>Delete Comic</div>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
const Placeholder = (props) => {
|
const Placeholder = components.Placeholder;
|
||||||
return <components.Placeholder {...props} />;
|
|
||||||
};
|
|
||||||
const actionOptions = [
|
const actionOptions = [
|
||||||
{ value: "match-on-comic-vine", label: CVMatchLabel },
|
{ value: "match-on-comic-vine", label: CVMatchLabel },
|
||||||
{ value: "edit-metdata", label: editLabel },
|
{ value: "edit-metdata", label: editLabel },
|
||||||
@@ -249,7 +301,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
const handleActionSelection = (action) => {
|
const handleActionSelection = (action: ActionOption) => {
|
||||||
switch (action.value) {
|
switch (action.value) {
|
||||||
case "match-on-comic-vine":
|
case "match-on-comic-vine":
|
||||||
openDrawerWithCVMatches();
|
openDrawerWithCVMatches();
|
||||||
@@ -262,24 +314,24 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const customStyles = {
|
const customStyles: StylesConfig<ActionOption, false> = {
|
||||||
menu: (base) => ({
|
menu: (base: any) => ({
|
||||||
...base,
|
...base,
|
||||||
backgroundColor: "rgb(156, 163, 175)",
|
backgroundColor: "rgb(156, 163, 175)",
|
||||||
}),
|
}),
|
||||||
placeholder: (base) => ({
|
placeholder: (base: any) => ({
|
||||||
...base,
|
...base,
|
||||||
color: "black",
|
color: "black",
|
||||||
}),
|
}),
|
||||||
option: (base, { data, isDisabled, isFocused, isSelected }) => ({
|
option: (base: any, { isFocused }: any) => ({
|
||||||
...base,
|
...base,
|
||||||
backgroundColor: isFocused ? "gray" : "rgb(156, 163, 175)",
|
backgroundColor: isFocused ? "gray" : "rgb(156, 163, 175)",
|
||||||
}),
|
}),
|
||||||
singleValue: (base) => ({
|
singleValue: (base: any) => ({
|
||||||
...base,
|
...base,
|
||||||
paddingTop: "0.4rem",
|
paddingTop: "0.4rem",
|
||||||
}),
|
}),
|
||||||
control: (base) => ({
|
control: (base: any) => ({
|
||||||
...base,
|
...base,
|
||||||
backgroundColor: "rgb(156, 163, 175)",
|
backgroundColor: "rgb(156, 163, 175)",
|
||||||
color: "black",
|
color: "black",
|
||||||
@@ -289,7 +341,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
|
|
||||||
// check for the availability of CV metadata
|
// check for the availability of CV metadata
|
||||||
const isComicBookMetadataAvailable =
|
const isComicBookMetadataAvailable =
|
||||||
!isUndefined(comicvine) && !isUndefined(comicvine.volumeInformation);
|
!isUndefined(comicvine) && !isUndefined(comicvine?.volumeInformation);
|
||||||
|
|
||||||
// check for the availability of rawFileDetails
|
// check for the availability of rawFileDetails
|
||||||
const areRawFileDetailsAvailable =
|
const areRawFileDetailsAvailable =
|
||||||
@@ -354,7 +406,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
query={airDCPPQuery}
|
query={airDCPPQuery}
|
||||||
comicObjectId={_id}
|
comicObjectId={_id}
|
||||||
comicObject={data.data}
|
comicObject={data.data}
|
||||||
userSettings={userSettings}
|
settings={userSettings}
|
||||||
key={4}
|
key={4}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -376,8 +428,8 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
name: "Downloads",
|
name: "Downloads",
|
||||||
icon: (
|
icon: (
|
||||||
<>
|
<>
|
||||||
{acquisition?.directconnect?.downloads?.length +
|
{(acquisition?.directconnect?.downloads?.length || 0) +
|
||||||
acquisition?.torrent.length}
|
(acquisition?.torrent?.length || 0)}
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
content:
|
content:
|
||||||
@@ -404,7 +456,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
// 2. from the CV-scraped version
|
// 2. from the CV-scraped version
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="container mx-auto px-4 sm:px-6 lg:px-8">
|
<section className="mx-auto max-w-screen-xl px-4 py-4 sm:px-6 sm:py-8 lg:px-8">
|
||||||
<div className="section">
|
<div className="section">
|
||||||
{!isNil(data) && !isEmpty(data) && (
|
{!isNil(data) && !isEmpty(data) && (
|
||||||
<>
|
<>
|
||||||
@@ -418,7 +470,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
|
|
||||||
{/* raw file details */}
|
{/* raw file details */}
|
||||||
{!isUndefined(rawFileDetails) &&
|
{!isUndefined(rawFileDetails) &&
|
||||||
!isEmpty(rawFileDetails.cover) && (
|
!isEmpty(rawFileDetails?.cover) && (
|
||||||
<div className="grid">
|
<div className="grid">
|
||||||
<RawFileDetails
|
<RawFileDetails
|
||||||
data={{
|
data={{
|
||||||
@@ -468,7 +520,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
|
|
||||||
<TabControls
|
<TabControls
|
||||||
filteredTabs={filteredTabs}
|
filteredTabs={filteredTabs}
|
||||||
downloadCount={acquisition?.directconnect?.downloads?.length}
|
downloadCount={acquisition?.directconnect?.downloads?.length || 0}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<StyledSlidingPanel
|
<StyledSlidingPanel
|
||||||
@@ -478,7 +530,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
width={"600px"}
|
width={"600px"}
|
||||||
>
|
>
|
||||||
{slidingPanelContentId !== "" &&
|
{slidingPanelContentId !== "" &&
|
||||||
contentForSlidingPanel[slidingPanelContentId].content()}
|
contentForSlidingPanel[slidingPanelContentId]?.content()}
|
||||||
</StyledSlidingPanel>
|
</StyledSlidingPanel>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import React, { ReactElement } from "react";
|
|||||||
export const ComicInfoXML = (data: { json: any }): ReactElement => {
|
export const ComicInfoXML = (data: { json: any }): ReactElement => {
|
||||||
const { json } = data;
|
const { json } = data;
|
||||||
return (
|
return (
|
||||||
<div className="flex md:w-4/5 lg:w-78">
|
<div className="flex w-3/4">
|
||||||
<dl className="dark:bg-yellow-600 bg-yellow-200 p-3 rounded-lg">
|
<dl className="dark:bg-yellow-600 bg-yellow-200 p-3 rounded-lg w-full">
|
||||||
<dt>
|
<dt>
|
||||||
<p className="text-lg">{json.series?.[0]}</p>
|
<p className="text-lg">{json.series?.[0]}</p>
|
||||||
</dt>
|
</dt>
|
||||||
|
|||||||
Reference in New Issue
Block a user