Added local file chip for local metadata
This commit is contained in:
@@ -96,7 +96,8 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
const hasAnyMetadata =
|
const hasAnyMetadata =
|
||||||
isComicBookMetadataAvailable ||
|
isComicBookMetadataAvailable ||
|
||||||
!isEmpty(comicInfo) ||
|
!isEmpty(comicInfo) ||
|
||||||
!isNil(locg);
|
!isNil(locg) ||
|
||||||
|
areRawFileDetailsAvailable;
|
||||||
|
|
||||||
const areRawFileDetailsAvailable =
|
const areRawFileDetailsAvailable =
|
||||||
!isUndefined(rawFileDetails) && !isEmpty(rawFileDetails);
|
!isUndefined(rawFileDetails) && !isEmpty(rawFileDetails);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { ReconcilerDrawer } from "./ReconcilerDrawer";
|
|||||||
import { fetcher } from "../../../graphql/fetcher";
|
import { fetcher } from "../../../graphql/fetcher";
|
||||||
import { useGetComicByIdQuery } from "../../../graphql/generated";
|
import { useGetComicByIdQuery } from "../../../graphql/generated";
|
||||||
import type { CanonicalRecord } from "./useReconciler";
|
import type { CanonicalRecord } from "./useReconciler";
|
||||||
|
import type { RawFileDetails as RawFileDetailsType } from "../../../graphql/generated";
|
||||||
|
|
||||||
interface ComicVineMetadata {
|
interface ComicVineMetadata {
|
||||||
volumeInformation?: Record<string, unknown>;
|
volumeInformation?: Record<string, unknown>;
|
||||||
@@ -28,6 +29,8 @@ interface VolumeInformationData {
|
|||||||
id?: string;
|
id?: string;
|
||||||
sourcedMetadata?: SourcedMetadata;
|
sourcedMetadata?: SourcedMetadata;
|
||||||
inferredMetadata?: { issue?: unknown };
|
inferredMetadata?: { issue?: unknown };
|
||||||
|
rawFileDetails?: RawFileDetailsType;
|
||||||
|
createdAt?: string;
|
||||||
updatedAt?: string;
|
updatedAt?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,34 +169,37 @@ export const VolumeInformation = (
|
|||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (
|
const hasLocalFile =
|
||||||
!isNil(data?.inferredMetadata?.issue) &&
|
(!isNil(data?.rawFileDetails) && !isEmpty(data?.rawFileDetails)) ||
|
||||||
!isEmpty(data?.inferredMetadata?.issue)
|
(!isNil(data?.inferredMetadata?.issue) && !isEmpty(data?.inferredMetadata?.issue));
|
||||||
) {
|
if (hasLocalFile) {
|
||||||
sources.push("inferredMetadata");
|
sources.push("inferredMetadata");
|
||||||
}
|
}
|
||||||
return sources;
|
return sources;
|
||||||
}, [data?.sourcedMetadata, data?.inferredMetadata]);
|
}, [data?.sourcedMetadata, data?.inferredMetadata, data?.rawFileDetails]);
|
||||||
|
|
||||||
|
const onlyComicvine =
|
||||||
|
presentSources.length === 1 &&
|
||||||
|
!!data.sourcedMetadata?.comicvine?.volumeInformation;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={1}>
|
<div key={1}>
|
||||||
{presentSources.length > 1 && (
|
{(presentSources.length > 1 || (presentSources.length === 1 && !onlyComicvine)) && (
|
||||||
<MetadataSourceChips
|
<MetadataSourceChips
|
||||||
sources={presentSources}
|
sources={presentSources}
|
||||||
onOpenReconciler={() => setReconcilerOpen(true)}
|
onOpenReconciler={() => setReconcilerOpen(true)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{presentSources.length === 1 &&
|
{onlyComicvine && (
|
||||||
data.sourcedMetadata?.comicvine?.volumeInformation && (
|
|
||||||
<ComicVineDetails
|
<ComicVineDetails
|
||||||
data={data.sourcedMetadata.comicvine}
|
data={data.sourcedMetadata!.comicvine!}
|
||||||
updatedAt={data.updatedAt}
|
updatedAt={data.updatedAt}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<ReconcilerDrawer
|
<ReconcilerDrawer
|
||||||
open={isReconcilerOpen}
|
open={isReconcilerOpen}
|
||||||
onOpenChange={setReconcilerOpen}
|
onOpenChange={setReconcilerOpen}
|
||||||
sourcedMetadata={(data.sourcedMetadata ?? {}) as import("./useReconciler").RawSourcedMetadata}
|
sourcedMetadata={(data.sourcedMetadata ?? {}) as unknown as import("./useReconciler").RawSourcedMetadata}
|
||||||
inferredMetadata={data.inferredMetadata as import("./useReconciler").RawInferredMetadata | undefined}
|
inferredMetadata={data.inferredMetadata as import("./useReconciler").RawInferredMetadata | undefined}
|
||||||
onSave={saveCanonical}
|
onSave={saveCanonical}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -145,7 +145,14 @@ export const Import = (): ReactElement => {
|
|||||||
}, [getSocket, queryClient]);
|
}, [getSocket, queryClient]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles force re-import - re-imports all files to fix indexing issues
|
* Initiates a force re-import of all library files.
|
||||||
|
*
|
||||||
|
* When the queue is already drained, disconnects and reconnects the socket
|
||||||
|
* before triggering the import — ensures the backend receives a fresh session
|
||||||
|
* rather than reusing a stale one that would be ignored.
|
||||||
|
*
|
||||||
|
* Validates directory availability and active session state before proceeding
|
||||||
|
* to prevent duplicate or broken imports.
|
||||||
*/
|
*/
|
||||||
const handleForceReImport = async () => {
|
const handleForceReImport = async () => {
|
||||||
setImportError(null);
|
setImportError(null);
|
||||||
@@ -194,6 +201,7 @@ export const Import = (): ReactElement => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `undefined` covers the initial state before any import has ever run in this session
|
||||||
const canStartImport =
|
const canStartImport =
|
||||||
!hasActiveSession &&
|
!hasActiveSession &&
|
||||||
(importJobQueue.status === "drained" || importJobQueue.status === undefined);
|
(importJobQueue.status === "drained" || importJobQueue.status === undefined);
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* @fileoverview Weekly Pull List page — displays comics releasing this week
|
||||||
|
* that the user has marked to follow.
|
||||||
|
* @module components/PullList/PullList
|
||||||
|
*/
|
||||||
|
|
||||||
import React, { ReactElement, useEffect, useMemo, useState } from "react";
|
import React, { ReactElement, useEffect, useMemo, useState } from "react";
|
||||||
import T2Table from "../shared/T2Table";
|
import T2Table from "../shared/T2Table";
|
||||||
import Card from "../shared/Carda";
|
import Card from "../shared/Carda";
|
||||||
@@ -16,6 +22,15 @@ interface PullListComic {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Weekly Pull List page component.
|
||||||
|
*
|
||||||
|
* Displays comics releasing this week that the user tracks.
|
||||||
|
* Fetching is not yet implemented — state is initialised to `null`
|
||||||
|
* so the table renders only when data is available, avoiding an empty-table flash.
|
||||||
|
*
|
||||||
|
* @returns {ReactElement} The pull list page UI
|
||||||
|
*/
|
||||||
export const PullList = (): ReactElement => {
|
export const PullList = (): ReactElement => {
|
||||||
// Placeholder for pull list comics - would come from API/store
|
// Placeholder for pull list comics - would come from API/store
|
||||||
const [pullListComics, setPullListComics] = useState<PullListComic[] | null>(null);
|
const [pullListComics, setPullListComics] = useState<PullListComic[] | null>(null);
|
||||||
@@ -32,6 +47,7 @@ export const PullList = (): ReactElement => {
|
|||||||
}, []);
|
}, []);
|
||||||
const nextPageHandler = () => {};
|
const nextPageHandler = () => {};
|
||||||
const previousPageHandler = () => {};
|
const previousPageHandler = () => {};
|
||||||
|
// Column def memoised — shape is static, no deps needed
|
||||||
const columnData = useMemo(
|
const columnData = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user