🔍 CV search metadata wrangling

This commit is contained in:
2024-04-14 00:25:17 -04:00
parent 6de8517bb5
commit 1de01e7dbd
6 changed files with 141 additions and 80 deletions

View File

@@ -21,13 +21,15 @@ export const Dashboard = (): ReactElement => {
limit: 5,
sort: { updatedAt: "-1" },
},
predicate: { "acquisition.source.wanted": false },
predicate: {
wanted: { $exists: false },
},
comicStatus: "recent",
},
}),
queryKey: ["recentComics"],
});
// Wanted Comics
const { data: wantedComics } = useQuery({
queryFn: async () =>
await axios({
@@ -39,7 +41,9 @@ export const Dashboard = (): ReactElement => {
limit: 5,
sort: { updatedAt: "-1" },
},
predicate: { "acquisition.source.wanted": true },
predicate: {
wanted: { $exists: true, $ne: null },
},
},
}),
queryKey: ["wantedComics"],

View File

@@ -18,6 +18,7 @@ type RecentlyImportedProps = {
export const RecentlyImported = (
comics: RecentlyImportedProps,
): ReactElement => {
console.log(comics);
return (
<div>
<Header
@@ -33,9 +34,7 @@ export const RecentlyImported = (
rawFileDetails,
sourcedMetadata: { comicvine, comicInfo, locg },
inferredMetadata,
acquisition: {
source: { name },
},
wanted: { source } = {},
},
idx,
) => {
@@ -45,11 +44,14 @@ export const RecentlyImported = (
comicInfo,
locg,
});
const { issue, coverURL, icon } = determineExternalMetadata(name, {
comicvine,
comicInfo,
locg,
});
const { issue, coverURL, icon } = determineExternalMetadata(
source,
{
comicvine,
comicInfo,
locg,
},
);
const isComicVineMetadataAvailable =
!isUndefined(comicvine) &&
!isUndefined(comicvine.volumeInformation);

View File

@@ -31,10 +31,9 @@ export const WantedComicsList = ({
_id,
rawFileDetails,
sourcedMetadata: { comicvine, comicInfo, locg },
wanted,
}) => {
const isComicBookMetadataAvailable =
!isUndefined(comicvine) &&
!isUndefined(comicvine.volumeInformation);
const isComicBookMetadataAvailable = !isUndefined(comicvine);
const consolidatedComicMetadata = {
rawFileDetails,
comicvine,
@@ -42,12 +41,15 @@ export const WantedComicsList = ({
locg,
};
const { issueName, url } = determineCoverFile(
consolidatedComicMetadata,
);
const {
issueName,
url,
publisher = null,
} = determineCoverFile(consolidatedComicMetadata);
const titleElement = (
<Link to={"/comic/details/" + _id}>
{ellipsize(issueName, 20)}
<p>{publisher}</p>
</Link>
);
return (
@@ -61,9 +63,7 @@ export const WantedComicsList = ({
<div className="pb-1">
{/* Issue type */}
{isComicBookMetadataAvailable &&
!isNil(
detectIssueTypes(comicvine.volumeInformation.description),
) ? (
!isNil(detectIssueTypes(comicvine.description)) ? (
<div className="my-2">
<span className="inline-flex items-center bg-slate-50 text-slate-800 text-xs font-medium px-2.5 py-0.5 rounded-md dark:text-slate-900 dark:bg-slate-400">
<span className="pr-1 pt-1">
@@ -71,11 +71,7 @@ export const WantedComicsList = ({
</span>
<span className="text-md text-slate-500 dark:text-slate-900">
{
detectIssueTypes(
comicvine.volumeInformation.description,
).displayName
}
{detectIssueTypes(comicvine.description).displayName}
</span>
</span>
</div>

View File

@@ -49,7 +49,7 @@ export const Search = ({}: ISearchProps): ReactElement => {
limit: "10",
offset: "0",
field_list:
"id,name,deck,api_detail_url,image,description,volume,cover_date,start_year,count_of_issues",
"id,name,deck,api_detail_url,image,description,volume,cover_date,start_year,count_of_issues,publisher",
resources: resource,
},
});
@@ -57,17 +57,49 @@ export const Search = ({}: ISearchProps): ReactElement => {
});
// add to library
const { data: additionResult } = useQuery({
queryFn: async () =>
await axios({
const { data: additionResult, mutate: addToWantedList } = useMutation({
mutationFn: async ({
source,
comicObject,
markEntireVolumeWanted,
resourceType,
}) => {
console.log("jigni", comicObject);
let volumeInformation = {};
let issues = [];
switch (resourceType) {
case "issue":
const { id, api_detail_url, image } = comicObject;
// Add issue metadata
issues.push({ id, api_detail_url, image });
// Get volume metadata from CV
console.log("volume", comicObject.volume.id);
const response = await axios({
url: `${COMICVINE_SERVICE_URI}/getVolumes`,
method: "POST",
data: {
volumeURI: comicObject.volume.api_detail_url,
fieldList:
"id,name,deck,api_detail_url,image,description,start_year,count_of_issues,publisher,first_issue,last_issue",
},
});
console.log("boogie", response.data);
volumeInformation = response.data?.results;
break;
case "volume":
volumeInformation = comicObject;
break;
default:
break;
}
return await axios({
url: `${LIBRARY_SERVICE_BASE_URI}/rawImportToDb`,
method: "POST",
data: {
importType: "new",
payload: {
rawFileDetails: {
name: "",
},
importStatus: {
isImported: true,
tagged: false,
@@ -75,14 +107,17 @@ export const Search = ({}: ISearchProps): ReactElement => {
score: "0",
},
},
sourcedMetadata:
{ comicvine: comicVineMetadata?.comicData } || null,
acquisition: { source: { wanted: true, name: "comicvine" } },
wanted: {
source,
markEntireVolumeWanted,
issues,
volume: {},
},
sourcedMetadata: { comicvine: volumeInformation } || null,
},
},
}),
queryKey: ["additionResult"],
enabled: !isNil(comicVineMetadata.comicData),
});
},
});
const addToLibrary = (sourceName: string, comicData) =>
@@ -93,11 +128,9 @@ export const Search = ({}: ISearchProps): ReactElement => {
};
const onSubmit = async (values) => {
// Include the selected resource value in the form data
const formData = { ...values, resource: selectedResource };
try {
mutate(formData);
// Handle response
} catch (error) {
// Handle error
}
@@ -260,13 +293,17 @@ export const Search = ({}: ISearchProps): ReactElement => {
)}
</p>
<div className="mt-2">
<button
className="flex space-x-1 sm:mt-0 sm:flex-row sm:items-center rounded-lg border border-green-400 dark:border-green-200 bg-green-200 px-2 py-2 text-gray-500 hover:bg-transparent hover:text-green-600 focus:outline-none focus:ring active:text-indigo-500"
onClick={() => addToLibrary("comicvine", result)}
>
<i className="icon-[solar--add-square-bold-duotone] w-6 h-6 mr-2"></i>{" "}
Mark as Wanted
</button>
<PopoverButton
content={`This will add ${result.volume.name} to your wanted list.`}
clickHandler={() =>
addToWantedList({
source: "comicvine",
comicObject: result,
markEntireVolumeWanted: false,
resourceType: "issue",
})
}
/>
</div>
</div>
</div>
@@ -365,8 +402,15 @@ export const Search = ({}: ISearchProps): ReactElement => {
count: result.count_of_issues,
},
)} to your wanted list.`}
clickHandler={() =>
addToWantedList({
source: "comicvine",
comicObject: result,
markEntireVolumeWanted: true,
resourceType: "volume",
})
}
/>
{/* onClick={() => addToLibrary("comicvine", result) */}
</div>
</div>
</div>

View File

@@ -3,7 +3,7 @@ import { useFloating, offset, flip } from "@floating-ui/react-dom";
import { useTranslation } from "react-i18next";
import "../../shared/utils/i18n.util"; // Ensure you import your i18n configuration
const PopoverButton = ({ content }) => {
const PopoverButton = ({ content, clickHandler }) => {
const [isVisible, setIsVisible] = useState(false);
// Use destructuring to obtain the reference and floating setters, among other values.
const { x, y, refs, strategy, floatingStyles } = useFloating({
@@ -23,6 +23,7 @@ const PopoverButton = ({ content }) => {
onBlur={() => setIsVisible(false)}
aria-describedby="popover"
className="flex space-x-1 sm:mt-0 sm:flex-row sm:items-center rounded-lg border border-green-400 dark:border-green-200 bg-green-200 px-2 py-2 text-gray-500 hover:bg-transparent hover:text-green-600 focus:outline-none focus:ring active:text-indigo-500"
onClick={clickHandler}
>
<i className="icon-[solar--add-square-bold-duotone] w-6 h-6 mr-2"></i>{" "}
Mark as Wanted

View File

@@ -1,11 +1,12 @@
import { filter, isEmpty, isUndefined, min, minBy } from "lodash";
import { filter, isEmpty, isNil, isUndefined, min, minBy } from "lodash";
import { LIBRARY_SERVICE_HOST } from "../../constants/endpoints";
import { escapePoundSymbol } from "./formatting.utils";
export const determineCoverFile = (data) => {
export const determineCoverFile = (data): any => {
/* For a payload like this:
const foo = {
rawFileDetails: {}, // #1
wanted: {},
comicInfo: {},
comicvine: {}, // #2
locg: {}, // #3
@@ -19,36 +20,44 @@ export const determineCoverFile = (data) => {
issueName: "",
publisher: "",
},
wanted: {
objectReference: "wanted",
priority: 2,
url: "",
issueName: "",
publisher: "",
},
comicvine: {
objectReference: "comicvine",
priority: 2,
priority: 3,
url: "",
issueName: "",
publisher: "",
},
locg: {
objectReference: "locg",
priority: 3,
priority: 4,
url: "",
issueName: "",
publisher: "",
},
};
if (
!isUndefined(data.comicvine) &&
!isUndefined(data.comicvine.volumeInformation)
) {
coverFile.comicvine.url = data.comicvine.image.small_url;
// comicvine
if (!isUndefined(data.comicvine)) {
coverFile.comicvine.url = data?.comicvine?.image.small_url;
coverFile.comicvine.issueName = data.comicvine.name;
coverFile.comicvine.publisher = data.comicvine.volumeInformation.publisher;
coverFile.comicvine.publisher = data.comicvine.publisher.name;
}
if (!isEmpty(data.rawFileDetails.cover)) {
// rawFileDetails
if (!isEmpty(data.rawFileDetails)) {
const encodedFilePath = encodeURI(
`${LIBRARY_SERVICE_HOST}/${data.rawFileDetails.cover.filePath}`,
);
coverFile.rawFile.url = escapePoundSymbol(encodedFilePath);
coverFile.rawFile.issueName = data.rawFileDetails.name;
}
// wanted
if (!isUndefined(data.locg)) {
coverFile.locg.url = data.locg.cover;
coverFile.locg.issueName = data.locg.name;
@@ -69,25 +78,30 @@ export const determineCoverFile = (data) => {
export const determineExternalMetadata = (
metadataSource: string,
source: any
) => {
switch (metadataSource) {
case "comicvine":
return {
coverURL: source.comicvine.image.small_url,
issue: source.comicvine.name,
icon: "cvlogo.svg",
};
case "locg":
return {
coverURL: source.locg.cover,
issue: source.locg.name,
icon: "locglogo.svg",
};
case undefined:
return {};
source: any,
): any => {
if (!isNil(source)) {
switch (metadataSource) {
case "comicvine":
return {
coverURL:
source.comicvine?.image.small_url ||
source.comicvine.volumeInformation?.image.small_url,
issue: source.comicvine.name,
icon: "cvlogo.svg",
};
case "locg":
return {
coverURL: source.locg.cover,
issue: source.locg.name,
icon: "locglogo.svg",
};
case undefined:
return {};
default:
break;
default:
break;
}
}
};
return null;
};