import React, { useState, useEffect } from "react"; import { Button, Form, ProgressBar } from "react-bootstrap"; import { Link } from "react-router-dom"; import { useJobStatus, useMetadataUpdate, mutateMetadataImport, mutateMetadataClean, mutateMetadataScan, mutateMetadataAutoTag, mutateMetadataExport, mutateMigrateHashNaming, mutateStopJob, usePlugins, mutateRunPluginTask, } from "src/core/StashService"; import { useToast } from "src/hooks"; import * as GQL from "src/core/generated-graphql"; import { Modal } from "src/components/Shared"; import { GenerateButton } from "./GenerateButton"; type Plugin = Pick; type PluginTask = Pick; export const SettingsTasksPanel: React.FC = () => { const Toast = useToast(); const [isImportAlertOpen, setIsImportAlertOpen] = useState(false); const [isCleanAlertOpen, setIsCleanAlertOpen] = useState(false); const [useFileMetadata, setUseFileMetadata] = useState(false); const [status, setStatus] = useState(""); const [progress, setProgress] = useState(0); const [autoTagPerformers, setAutoTagPerformers] = useState(true); const [autoTagStudios, setAutoTagStudios] = useState(true); const [autoTagTags, setAutoTagTags] = useState(true); const jobStatus = useJobStatus(); const metadataUpdate = useMetadataUpdate(); const plugins = usePlugins(); function statusToText(s: string) { switch (s) { case "Idle": return "Idle"; case "Scan": return "Scanning for new content"; case "Generate": return "Generating supporting files"; case "Clean": return "Cleaning the database"; case "Export": return "Exporting to JSON"; case "Import": return "Importing from JSON"; case "Auto Tag": return "Auto tagging scenes"; case "Plugin Operation": return "Running Plugin Operation"; case "Migrate": return "Migrating"; default: return "Idle"; } } useEffect(() => { if (jobStatus?.data?.jobStatus) { setStatus(statusToText(jobStatus.data.jobStatus.status)); const newProgress = jobStatus.data.jobStatus.progress; if (newProgress < 0) { setProgress(-1); } else { setProgress(newProgress * 100); } } }, [jobStatus]); useEffect(() => { if (metadataUpdate?.data?.metadataUpdate) { setStatus(statusToText(metadataUpdate.data.metadataUpdate.status)); const newProgress = metadataUpdate.data.metadataUpdate.progress; if (newProgress < 0) { setProgress(-1); } else { setProgress(newProgress * 100); } } }, [metadataUpdate]); function onImport() { setIsImportAlertOpen(false); mutateMetadataImport().then(() => { jobStatus.refetch(); }); } function renderImportAlert() { return ( setIsImportAlertOpen(false) }} >

Are you sure you want to import? This will delete the database and re-import from your exported metadata.

); } function onClean() { setIsCleanAlertOpen(false); mutateMetadataClean().then(() => { jobStatus.refetch(); }); } function renderCleanAlert() { return ( setIsCleanAlertOpen(false) }} >

Are you sure you want to Clean? This will delete database information and generated content for all scenes and galleries that are no longer found in the filesystem.

); } async function onScan() { try { await mutateMetadataScan({ useFileMetadata }); Toast.success({ content: "Started scan" }); jobStatus.refetch(); } catch (e) { Toast.error(e); } } function getAutoTagInput() { const wildcard = ["*"]; return { performers: autoTagPerformers ? wildcard : [], studios: autoTagStudios ? wildcard : [], tags: autoTagTags ? wildcard : [], }; } async function onAutoTag() { try { await mutateMetadataAutoTag(getAutoTagInput()); Toast.success({ content: "Started auto tagging" }); jobStatus.refetch(); } catch (e) { Toast.error(e); } } function maybeRenderStop() { if (!status || status === "Idle") { return undefined; } return ( ); } function renderJobStatus() { return ( <>
Status: {status}
{!!status && status !== "Idle" ? ( -1 ? progress : 100} label={progress > -1 ? `${progress.toFixed(0)}%` : ""} /> ) : ( "" )}
{maybeRenderStop()} ); } async function onPluginTaskClicked(plugin: Plugin, operation: PluginTask) { await mutateRunPluginTask(plugin.id, operation.name); } function renderPluginTasks(plugin: Plugin, pluginTasks: PluginTask[]) { if (!pluginTasks) { return; } return pluginTasks.map((o) => { return (
{o.description ? ( {o.description} ) : undefined}
); }); } function renderPlugins() { if (!plugins.data || !plugins.data.plugins) { return; } return ( <>
Plugin Tasks
{plugins.data.plugins.map((o) => { return (
{o.name}
{renderPluginTasks(o, o.tasks ?? [])}
); })} ); } return ( <> {renderImportAlert()} {renderCleanAlert()}

Running Jobs

{renderJobStatus()}
Library
setUseFileMetadata(!useFileMetadata)} /> Scan for new content and add it to the database.
Auto Tagging
setAutoTagPerformers(!autoTagPerformers)} /> setAutoTagStudios(!autoTagStudios)} /> setAutoTagTags(!autoTagTags)} /> Auto-tag content based on filenames.
Generated Content
Check for missing files and remove them from the database. This is a destructive action.
Metadata
Export the database content into JSON format. Import from exported JSON. This is a destructive action. {renderPlugins()}
Migrations
Used after changing the Generated file naming hash to rename existing generated files to the new hash format. ); };