🤼♀️ Wiring up ES-powered issue detection
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
|||||||
IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS,
|
IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS,
|
||||||
CV_ISSUES_METADATA_CALL_IN_PROGRESS,
|
CV_ISSUES_METADATA_CALL_IN_PROGRESS,
|
||||||
CV_ISSUES_METADATA_FETCH_SUCCESS,
|
CV_ISSUES_METADATA_FETCH_SUCCESS,
|
||||||
|
CV_CLEANUP,
|
||||||
} from "../constants/action-types";
|
} from "../constants/action-types";
|
||||||
import {
|
import {
|
||||||
COMICBOOKINFO_SERVICE_URI,
|
COMICBOOKINFO_SERVICE_URI,
|
||||||
@@ -64,24 +65,24 @@ export const comicinfoAPICall = (options) => async (dispatch) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const getIssuesForSeries = (comicObjectID: any) => async (dispatch) => {
|
export const findIssuesForSeriesInLibrary =
|
||||||
dispatch({
|
(comicObjectID: any) => async (dispatch) => {
|
||||||
type: CV_ISSUES_METADATA_CALL_IN_PROGRESS,
|
dispatch({
|
||||||
});
|
type: CV_ISSUES_METADATA_CALL_IN_PROGRESS,
|
||||||
|
});
|
||||||
|
dispatch({
|
||||||
|
type: CV_CLEANUP,
|
||||||
|
});
|
||||||
|
|
||||||
|
await axios({
|
||||||
|
url: `${IMPORT_SERVICE_BASE_URI}/findIssuesForSeriesInLibrary`,
|
||||||
|
method: "POST",
|
||||||
|
params: {
|
||||||
|
comicObjectID,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const issues = await axios({
|
|
||||||
url: `${IMPORT_SERVICE_BASE_URI}/getIssuesForSeries`,
|
|
||||||
method: "POST",
|
|
||||||
params: {
|
|
||||||
comicObjectID,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
console.log(issues);
|
|
||||||
dispatch({
|
|
||||||
type: CV_ISSUES_METADATA_FETCH_SUCCESS,
|
|
||||||
issues,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
export const getComicBookDetailById =
|
export const getComicBookDetailById =
|
||||||
(comicBookObjectId: string) => async (dispatch) => {
|
(comicBookObjectId: string) => async (dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|||||||
@@ -128,6 +128,11 @@ $size-8: 0.9rem;
|
|||||||
border-bottom-right-radius: 0.3rem;
|
border-bottom-right-radius: 0.3rem;
|
||||||
box-shadow: 1px 8px 23px 7px rgba(0, 0, 0, 0.12);
|
box-shadow: 1px 8px 23px 7px rgba(0, 0, 0, 0.12);
|
||||||
|
|
||||||
|
.green-border {
|
||||||
|
border:2px dotted #999;
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
.truncate {
|
.truncate {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ interface ICardProps {
|
|||||||
hasDetails: boolean;
|
hasDetails: boolean;
|
||||||
title?: PropTypes.ReactElementLike | null;
|
title?: PropTypes.ReactElementLike | null;
|
||||||
children?: PropTypes.ReactNodeLike;
|
children?: PropTypes.ReactNodeLike;
|
||||||
|
borderColorClass?: string;
|
||||||
|
backgroundColor?: string;
|
||||||
|
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderCard = (props): ReactElement => {
|
const renderCard = (props): ReactElement => {
|
||||||
@@ -16,9 +19,15 @@ const renderCard = (props): ReactElement => {
|
|||||||
return <>horiztonal</>;
|
return <>horiztonal</>;
|
||||||
case "vertical":
|
case "vertical":
|
||||||
return (
|
return (
|
||||||
<div>
|
<div onClick={props.onClick}>
|
||||||
<div className="generic-card">
|
<div className="generic-card">
|
||||||
<div>
|
<div
|
||||||
|
className={
|
||||||
|
!isNil(props.borderColorClass)
|
||||||
|
? `${props.borderColorClass}`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
props.hasDetails
|
props.hasDetails
|
||||||
@@ -31,10 +40,15 @@ const renderCard = (props): ReactElement => {
|
|||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
{props.hasDetails && (
|
{props.hasDetails && (
|
||||||
<div className="card-content">
|
<div
|
||||||
<div className="card-title is-size-8 is-family-secondary">
|
className="card-content"
|
||||||
{isNil(props.title) ? "No Name" : props.title}
|
style={{ backgroundColor: props.backgroundColor }}
|
||||||
</div>
|
>
|
||||||
|
{!isNil(props.title) ? (
|
||||||
|
<div className="card-title is-size-8 is-family-secondary">
|
||||||
|
{props.title}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { isEmpty, isNil, isUndefined } from "lodash";
|
import { isEmpty, isNil, isUndefined, map } from "lodash";
|
||||||
import React, { useEffect, ReactElement } from "react";
|
import React, { useEffect, ReactElement, useState, useCallback } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { useParams } from "react-router";
|
import { useParams } from "react-router";
|
||||||
import {
|
import {
|
||||||
getComicBookDetailById,
|
getComicBookDetailById,
|
||||||
getIssuesForSeries,
|
findIssuesForSeriesInLibrary,
|
||||||
} from "../../actions/comicinfo.actions";
|
} from "../../actions/comicinfo.actions";
|
||||||
import Masonry from "react-masonry-css";
|
import Masonry from "react-masonry-css";
|
||||||
import { Card } from "../Carda";
|
import { Card } from "../Carda";
|
||||||
|
import SlidingPane from "react-sliding-pane";
|
||||||
|
|
||||||
const VolumeDetails = (props): ReactElement => {
|
const VolumeDetails = (props): ReactElement => {
|
||||||
const breakpointColumnsObj = {
|
const breakpointColumnsObj = {
|
||||||
@@ -16,15 +17,45 @@ const VolumeDetails = (props): ReactElement => {
|
|||||||
700: 2,
|
700: 2,
|
||||||
600: 1,
|
600: 1,
|
||||||
};
|
};
|
||||||
|
// sliding panel config
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const [slidingPanelContentId, setSlidingPanelContentId] = useState("");
|
||||||
|
const [matches, setMatches] = useState([]);
|
||||||
|
|
||||||
|
// sliding panel init
|
||||||
|
const contentForSlidingPanel = {
|
||||||
|
potentialMatchesInLibrary: {
|
||||||
|
content: () => {
|
||||||
|
console.log(matches);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-10">
|
||||||
|
{map(matches, (match) => (
|
||||||
|
<pre>{JSON.stringify(match, undefined, 2)}</pre>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// sliding panel handlers
|
||||||
|
const openPotentialLibraryMatchesPanel = useCallback((potentialMatches) => {
|
||||||
|
setSlidingPanelContentId("potentialMatchesInLibrary");
|
||||||
|
setMatches(potentialMatches);
|
||||||
|
setVisible(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const comicBookDetails = useSelector(
|
const comicBookDetails = useSelector(
|
||||||
(state: RootState) => state.comicInfo.comicBookDetail,
|
(state: RootState) => state.comicInfo.comicBookDetail,
|
||||||
);
|
);
|
||||||
const issues = useSelector(
|
const issuesForVolume = useSelector(
|
||||||
(state: RootState) => state.comicInfo.issuesForVolume,
|
(state: RootState) => state.comicInfo.issuesForVolume,
|
||||||
);
|
);
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(getIssuesForSeries(comicObjectId));
|
dispatch(findIssuesForSeriesInLibrary(comicObjectId));
|
||||||
dispatch(getComicBookDetailById(comicObjectId));
|
dispatch(getComicBookDetailById(comicObjectId));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -56,27 +87,50 @@ const VolumeDetails = (props): ReactElement => {
|
|||||||
className="issues-container"
|
className="issues-container"
|
||||||
columnClassName="issues-column"
|
columnClassName="issues-column"
|
||||||
>
|
>
|
||||||
{!isUndefined(issues) && !isEmpty(issues)
|
{!isUndefined(issuesForVolume) && !isEmpty(issuesForVolume)
|
||||||
? issues.map((issue) => {
|
? issuesForVolume.map((issue) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card
|
<Card
|
||||||
key={issue.id}
|
key={issue.issue.id}
|
||||||
imageUrl={issue.image.thumb_url}
|
imageUrl={issue.issue.image.thumb_url}
|
||||||
orientation={"vertical"}
|
orientation={"vertical"}
|
||||||
hasDetails={false}
|
hasDetails={!isEmpty(issue.matches) ? true : false}
|
||||||
/>
|
borderColorClass={
|
||||||
{!isEmpty(issue.potentialMatches)
|
!isEmpty(issue.matches) ? "green-border" : ""
|
||||||
? "matches available"
|
}
|
||||||
: null}
|
backgroundColor={
|
||||||
|
!isEmpty(issue.matches) ? "#e0f5d0" : ""
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
openPotentialLibraryMatchesPanel(issue.matches)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{!isEmpty(issue.matches) ? (
|
||||||
|
<span className="icon is-success">
|
||||||
|
<i className="fa-solid fa-hands-asl-interpreting"></i>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</Card>
|
||||||
|
{/* { JSON.stringify(issue, undefined, 2)} */}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
: "loading"}
|
: "loading"}
|
||||||
</Masonry>
|
</Masonry>
|
||||||
{/* <pre>{JSON.stringify(comicBookDetails, undefined, 2)}</pre> */}
|
{/* <pre>{JSON.stringify(issuesForVolume, undefined, 2)}</pre> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<SlidingPane
|
||||||
|
isOpen={visible}
|
||||||
|
onRequestClose={() => setVisible(false)}
|
||||||
|
title={"Potential Matches in Library"}
|
||||||
|
width={"600px"}
|
||||||
|
>
|
||||||
|
{slidingPanelContentId !== "" &&
|
||||||
|
contentForSlidingPanel[slidingPanelContentId].content()}
|
||||||
|
</SlidingPane>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -41,9 +41,13 @@ export const IMS_COMIC_BOOK_GROUPS_CALL_FAILED =
|
|||||||
|
|
||||||
// issues for a given volume
|
// issues for a given volume
|
||||||
export const CV_ISSUES_METADATA_CALL_IN_PROGRESS =
|
export const CV_ISSUES_METADATA_CALL_IN_PROGRESS =
|
||||||
"ISSUES_METADATA_CALL_IN_PROGRESS";
|
"CV_ISSUES_METADATA_CALL_IN_PROGRESS";
|
||||||
export const CV_ISSUES_METADATA_FETCH_SUCCESS = "ISSUES_METADATA_FETCH_SUCCESS";
|
export const CV_ISSUES_METADATA_FETCH_SUCCESS =
|
||||||
export const CV_ISSUES_METADATA_FETCH_FAILED = "ISSUES_METADATA_FETCH_FAILED";
|
"CV_ISSUES_METADATA_FETCH_SUCCESS";
|
||||||
|
export const CV_ISSUES_METADATA_FETCH_FAILED =
|
||||||
|
"CV_ISSUES_METADATA_FETCH_FAILED";
|
||||||
|
export const CV_ISSUES_FOR_VOLUME_IN_LIBRARY_SUCCESS =
|
||||||
|
"CV_ISSUES_FOR_VOLUME_IN_LIBRARY_SUCCESS";
|
||||||
|
|
||||||
// extracted comic archive
|
// extracted comic archive
|
||||||
export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS =
|
export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS =
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ import {
|
|||||||
CV_CLEANUP,
|
CV_CLEANUP,
|
||||||
IMS_COMIC_BOOK_DB_OBJECT_FETCHED,
|
IMS_COMIC_BOOK_DB_OBJECT_FETCHED,
|
||||||
IMS_COMIC_BOOK_DB_OBJECT_CALL_IN_PROGRESS,
|
IMS_COMIC_BOOK_DB_OBJECT_CALL_IN_PROGRESS,
|
||||||
IMS_COMIC_BOOK_DB_OBJECT_CALL_FAILED,
|
|
||||||
CV_ISSUES_METADATA_CALL_IN_PROGRESS,
|
CV_ISSUES_METADATA_CALL_IN_PROGRESS,
|
||||||
CV_ISSUES_METADATA_FETCH_SUCCESS,
|
CV_ISSUES_METADATA_FETCH_SUCCESS,
|
||||||
|
CV_ISSUES_FOR_VOLUME_IN_LIBRARY_SUCCESS,
|
||||||
} from "../constants/action-types";
|
} from "../constants/action-types";
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
searchQuery: {},
|
searchQuery: {},
|
||||||
@@ -48,17 +49,20 @@ function comicinfoReducer(state = initialState, action) {
|
|||||||
...state,
|
...state,
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
searchQuery: {},
|
searchQuery: {},
|
||||||
|
issuesForVolume: [],
|
||||||
};
|
};
|
||||||
case CV_ISSUES_METADATA_CALL_IN_PROGRESS:
|
case CV_ISSUES_METADATA_CALL_IN_PROGRESS:
|
||||||
return {
|
return {
|
||||||
inProgress: true,
|
inProgress: true,
|
||||||
...state,
|
...state,
|
||||||
};
|
};
|
||||||
case CV_ISSUES_METADATA_FETCH_SUCCESS:
|
|
||||||
console.log(action);
|
case CV_ISSUES_FOR_VOLUME_IN_LIBRARY_SUCCESS:
|
||||||
|
console.log("jagan", action);
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
issuesForVolume: action.issues.data,
|
issuesForVolume: [...state.issuesForVolume, action.result],
|
||||||
|
inProgress: false,
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
|||||||
@@ -12857,10 +12857,10 @@ text-table@^0.2.0, text-table@~0.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||||
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
|
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
|
||||||
|
|
||||||
threetwo-ui-typings@^1.0.11:
|
threetwo-ui-typings@^1.0.12:
|
||||||
version "1.0.11"
|
version "1.0.12"
|
||||||
resolved "https://registry.yarnpkg.com/threetwo-ui-typings/-/threetwo-ui-typings-1.0.11.tgz#796f58230ce1cb15a654bbc1d8dbcc400fd8335b"
|
resolved "https://registry.yarnpkg.com/threetwo-ui-typings/-/threetwo-ui-typings-1.0.12.tgz#9f05542d7fa67b2349e20b0555ab196521fa8448"
|
||||||
integrity sha512-jRI1rUttoJDqsKFUPd4MM56NErftl2NSEo8MkeqllOtVf38Wy+wVvAT+OW6AoSguA5cLxSpOiA25c31FWjOvOw==
|
integrity sha512-lKADNpD2Oa3Wmf6tdZhaPSNfIFa0KtstsZLE0yalTjqKmtQZM7Ct2OnlCkH7aonDuVn+jgcRMwkcP9krCqa2fw==
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript "^4.3.2"
|
typescript "^4.3.2"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user