🦟 Fixed 404s upon page refresh

This commit is contained in:
2022-03-01 23:01:57 -08:00
parent 769e2e3edc
commit 9ec5040bd7
10 changed files with 238 additions and 189 deletions

View File

@@ -5,6 +5,7 @@ import {
IMAGETRANSFORMATION_SERVICE_BASE_URI,
LIBRARY_SERVICE_BASE_URI,
LIBRARY_SERVICE_HOST,
SEARCH_SERVICE_BASE_URI,
} from "../constants/endpoints";
import {
IMS_COMIC_BOOK_GROUPS_FETCHED,
@@ -257,7 +258,14 @@ export const extractComicArchive =
});
};
export const searchIssue = (options) => async (dispatch) => {};
export const searchIssue = (query) => async (dispatch) => {
const foo = await axios({
url: `${SEARCH_SERVICE_BASE_URI}/searchIssue`,
method: "POST",
data: query,
});
console.log(foo);
};
export const analyzeImage =
(imageFilePath: string | Buffer) => async (dispatch) => {
dispatch({

View File

@@ -12,7 +12,7 @@ import DownloadsPanel from "./ComicDetail/DownloadsPanel";
import { EditMetadataPanel } from "./ComicDetail/EditMetadataPanel";
import { Menu } from "./ComicDetail/ActionMenu/Menu";
import { isEmpty, isUndefined, isNil, findIndex } from "lodash";
import { isEmpty, isUndefined, isNil } from "lodash";
import { RootState } from "threetwo-ui-typings";
import { getComicBookDetailById } from "../actions/comicinfo.actions";
@@ -117,6 +117,7 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
},
};
// check for the availability of CV metadata
const isComicBookMetadataAvailable =
comicBookDetailData.sourcedMetadata &&
!isUndefined(comicBookDetailData.sourcedMetadata.comicvine) &&
@@ -125,6 +126,29 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
) &&
!isEmpty(comicBookDetailData.sourcedMetadata);
// check for the availability of rawFileDetails
const areRawFileDetailsAvailable =
!isUndefined(comicBookDetailData.rawFileDetails) &&
!isEmpty(comicBookDetailData.rawFileDetails.cover);
// query for airdc++
const airDCPPQuery = {};
if (isComicBookMetadataAvailable) {
Object.assign(airDCPPQuery, {
issue: {
name: comicBookDetailData.sourcedMetadata.comicvine.volumeInformation
.name,
},
});
} else if (areRawFileDetailsAvailable) {
Object.assign(airDCPPQuery, {
issue: {
name: comicBookDetailData.inferredMetadata.issue.name,
number: comicBookDetailData.inferredMetadata.issue.number,
},
});
}
// Tab content and header details
const tabGroup = [
{
@@ -134,7 +158,7 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
content: isComicBookMetadataAvailable ? (
<VolumeInformation data={comicBookDetailData} key={1} />
) : null,
include: isComicBookMetadataAvailable,
shouldShow: isComicBookMetadataAvailable,
},
{
id: 2,
@@ -156,8 +180,8 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
</div>
</div>
),
include:
!isNil(comicBookDetailData.sourcedMetadata) &&
shouldShow:
!isUndefined(comicBookDetailData.sourcedMetadata) &&
!isEmpty(comicBookDetailData.sourcedMetadata.comicInfo),
},
{
@@ -165,18 +189,14 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
icon: <i className="fa-regular fa-file-archive"></i>,
name: "Archive Operations",
content: <ArchiveOperations data={comicBookDetailData} key={3} />,
include:
!isUndefined(comicBookDetailData.rawFileDetails) &&
!isEmpty(comicBookDetailData.rawFileDetails.cover),
shouldShow: areRawFileDetailsAvailable,
},
{
id: 4,
icon: <i className="fa-solid fa-floppy-disk"></i>,
name: "Acquisition",
content: (
<AcquisitionPanel comicBookMetadata={comicBookDetailData} key={4} />
),
include: !isNil(comicBookDetailData.rawFileDetails),
content: <AcquisitionPanel query={airDCPPQuery} key={4} />,
shouldShow: true,
},
{
id: 5,
@@ -194,12 +214,11 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
key={5}
/>
),
include: !isNil(comicBookDetailData.rawFileDetails),
shouldShow: true,
},
];
// filtered Tabs
const filteredTabs = tabGroup.filter((tab) => tab.include);
const filteredTabs = tabGroup.filter((tab) => tab.shouldShow);
// Tabs
const MetadataTabGroup = () => {
@@ -245,10 +264,7 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
// 2. from the CV-scraped version
let imagePath = "";
let comicBookTitle = "";
if (
!isUndefined(comicBookDetailData.rawFileDetails) &&
!isEmpty(comicBookDetailData.rawFileDetails.cover)
) {
if (areRawFileDetailsAvailable) {
const encodedFilePath = encodeURI(
`${LIBRARY_SERVICE_HOST}/${comicBookDetailData.rawFileDetails.cover.filePath}`,
);

View File

@@ -16,16 +16,15 @@ import ellipsize from "ellipsize";
import { isEmpty, isNil, map } from "lodash";
import { AirDCPPSocketContext } from "../../context/AirDCPPSocket";
interface IAcquisitionPanelProps {
comicBookMetadata: any;
query: any;
}
export const AcquisitionPanel = (
props: IAcquisitionPanelProps,
): ReactElement => {
const volumeName =
props.comicBookMetadata.sourcedMetadata.comicvine.volumeInformation.name;
const sanitizedVolumeName = volumeName.replace(/[^a-zA-Z0-9 ]/g, " ");
const issueName = props.comicBookMetadata.sourcedMetadata.comicvine.name;
console.log(props);
const issueName = props.query.issue.name;
const sanitizedIssueName = issueName.replace(/[^a-zA-Z0-9 ]/g, " ");
// Selectors for picking state
const airDCPPSearchResults = useSelector((state: RootState) => {
@@ -51,7 +50,7 @@ export const AcquisitionPanel = (
// AirDC++ search query
const dcppSearchQuery = {
query: {
pattern: `${sanitizedVolumeName.replace(/#/g, "")}`,
pattern: `${sanitizedIssueName.replace(/#/g, "")}`,
extensions: ["cbz", "cbr"],
},
hub_urls: map(

View File

@@ -191,6 +191,7 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
<h1 className="title">Library</h1>
{/* Search bar */}
<SearchBar />
{!isUndefined(data) ? (
<div>
<div className="library">
<table {...getTableProps()} className="table is-hoverable">
@@ -306,7 +307,8 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
{/* page size selector */}
<div
className={
"dropdown " + (isPageSizeDropdownCollapsed ? "is-active" : "")
"dropdown " +
(isPageSizeDropdownCollapsed ? "is-active" : "")
}
onBlur={() => togglePageSizeDropdown()}
>
@@ -336,6 +338,7 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
</nav>
</div>
</div>
) : null}
</div>
</section>
);

View File

@@ -1,16 +1,29 @@
import React, { ReactElement } from "react";
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 foo = () => {};
const dispatch = useDispatch();
const handleSubmit = useCallback((e) => {
console.log(e);
dispatch(
searchIssue({
queryObject: {
volumeName: e.search,
},
}),
);
}, []);
return (
<div className="box sticky">
<Form
onSubmit={foo}
onSubmit={handleSubmit}
initialValues={{}}
render={({ handleSubmit, form, submitting, pristine, values }) => (
<form onSubmit={handleSubmit}>
<div className="column is-three-quarters search">
<label>Search</label>
<Field name="search">
@@ -24,7 +37,11 @@ export const SearchBar = (): ReactElement => {
);
}}
</Field>
<button className="button" type="submit">
Search
</button>
</div>
</form>
)}
/>
<div className="column one-fifth">

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect, useMemo, ReactElement } from "react";
import PropTypes from "prop-types";
import { useHistory } from "react-router";
import { useNavigate } from "react-router";
import {
removeLeadingPeriod,
escapePoundSymbol,
@@ -10,7 +10,7 @@ import prettyBytes from "pretty-bytes";
import ellipsize from "ellipsize";
import { useDispatch, useSelector } from "react-redux";
import { getComicBooks } from "../actions/fileops.actions";
import { isNil, isEmpty } from "lodash";
import { isNil, isEmpty, isUndefined } from "lodash";
import Masonry from "react-masonry-css";
import Card from "./Carda";
import { detectIssueTypes } from "../shared/utils/tradepaperback.utils";
@@ -45,7 +45,7 @@ export const LibraryGrid = (libraryGridProps: ILibraryGridProps) => {
{data.map(({ _id, rawFileDetails, sourcedMetadata }) => {
let imagePath = "";
let comicName = "";
if (!isNil(rawFileDetails)) {
if (!isEmpty(rawFileDetails.cover)) {
const encodedFilePath = encodeURI(
`${LIBRARY_SERVICE_HOST}/${removeLeadingPeriod(
rawFileDetails.cover.filePath,
@@ -71,7 +71,7 @@ export const LibraryGrid = (libraryGridProps: ILibraryGridProps) => {
title={comicName ? titleElement : null}
>
<div className="content is-flex is-flex-direction-row">
{!isNil(sourcedMetadata.comicvine) && (
{!isEmpty(sourcedMetadata.comicvine) && (
<span className="icon cv-icon is-small">
<img src="/dist/img/cvlogo.svg" />
</span>
@@ -81,13 +81,13 @@ export const LibraryGrid = (libraryGridProps: ILibraryGridProps) => {
<i className="fas fa-adjust" />
</span>
)}
{!isNil(sourcedMetadata.comicvine) &&
{!isUndefined(sourcedMetadata.comicvine.volumeInformation) &&
!isEmpty(
detectIssueTypes(
sourcedMetadata.comicvine.volumeInformation.description,
),
) ? (
<span className="tag is-warning">
<span className="tag is-warning ml-1">
{
detectIssueTypes(
sourcedMetadata.comicvine.volumeInformation

View File

@@ -161,7 +161,7 @@ const VolumeDetails = (props): ReactElement => {
if (
!isUndefined(comicBookDetails.sourcedMetadata) &&
!isUndefined(comicBookDetails.sourcedMetadata.comicvine)
!isUndefined(comicBookDetails.sourcedMetadata.comicvine.volumeInformation)
) {
return (
<div className="container volume-details">

View File

@@ -49,6 +49,12 @@ export const LIBRARY_SERVICE_BASE_URI = hostURIBuilder({
port: "3000",
apiPath: "/api/library",
});
export const SEARCH_SERVICE_BASE_URI = hostURIBuilder({
protocol: "http",
host: process.env.UNDERLYING_HOSTNAME || "localhost",
port: "3000",
apiPath: "/api/search",
});
export const SETTINGS_SERVICE_BASE_URI = hostURIBuilder({
protocol: "http",

View File

@@ -1,5 +1,5 @@
import { createStore, combineReducers, applyMiddleware } from "redux";
import { createBrowserHistory } from "history";
import { createHashHistory } from "history";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from "redux-thunk";
import { createReduxHistoryContext } from "redux-first-history";
@@ -12,7 +12,7 @@ const socketConnection = io(SOCKET_BASE_URI, { transports: ["websocket"] });
const { createReduxHistory, routerMiddleware, routerReducer } =
createReduxHistoryContext({
history: createBrowserHistory(),
history: createHashHistory(),
});
export const store = createStore(

View File

@@ -73,9 +73,9 @@ module.exports = () => {
aliasFields: ["browser", "browser.esm"],
},
devServer: {
hot: true,
port: 3050,
open: true,
hot: true,
proxy: {
"/api/**": {
target: "http://localhost:8050",