import React, { useEffect, useState, useContext } from "react"; import { FormattedMessage, useIntl } from "react-intl"; import { Alert, Button, Card, Container, Form, InputGroup, } from "react-bootstrap"; import * as GQL from "src/core/generated-graphql"; import { mutateSetup, useConfigureUI, useSystemStatus, } from "src/core/StashService"; import { Link, useHistory } from "react-router-dom"; import { ConfigurationContext } from "src/hooks/Config"; import StashConfiguration from "../Settings/StashConfiguration"; import { Icon } from "../Shared/Icon"; import { LoadingIndicator } from "../Shared/LoadingIndicator"; import { ModalComponent } from "../Shared/Modal"; import { FolderSelectDialog } from "../Shared/FolderSelect/FolderSelectDialog"; import { faEllipsisH, faExclamationTriangle, faQuestionCircle, } from "@fortawesome/free-solid-svg-icons"; import { releaseNotes } from "src/docs/en/ReleaseNotes"; export const Setup: React.FC = () => { const { configuration, loading: configLoading } = useContext(ConfigurationContext); const [saveUI] = useConfigureUI(); const [step, setStep] = useState(0); const [configLocation, setConfigLocation] = useState(""); const [stashes, setStashes] = useState([]); const [showStashAlert, setShowStashAlert] = useState(false); const [databaseFile, setDatabaseFile] = useState(""); const [generatedLocation, setGeneratedLocation] = useState(""); const [cacheLocation, setCacheLocation] = useState(""); const [storeBlobsInDatabase, setStoreBlobsInDatabase] = useState(false); const [blobsLocation, setBlobsLocation] = useState(""); const [loading, setLoading] = useState(false); const [setupError, setSetupError] = useState(""); const intl = useIntl(); const history = useHistory(); const [showGeneratedSelectDialog, setShowGeneratedSelectDialog] = useState(false); const [showCacheSelectDialog, setShowCacheSelectDialog] = useState(false); const [showBlobsDialog, setShowBlobsDialog] = useState(false); const { data: systemStatus, loading: statusLoading } = useSystemStatus(); useEffect(() => { if (systemStatus?.systemStatus.configPath) { setConfigLocation(systemStatus.systemStatus.configPath); } }, [systemStatus]); useEffect(() => { if (configuration) { const { stashes: configStashes, generatedPath } = configuration.general; if (configStashes.length > 0) { setStashes( configStashes.map((s) => { const { __typename, ...withoutTypename } = s; return withoutTypename; }) ); } if (generatedPath) { setGeneratedLocation(generatedPath); } } }, [configuration]); const discordLink = ( Discord ); const githubLink = ( ); function onConfigLocationChosen(loc: string) { setConfigLocation(loc); next(); } function goBack(n?: number) { let dec = n; if (!dec) { dec = 1; } setStep(Math.max(0, step - dec)); } function next() { setStep(step + 1); } function confirmPaths() { if (stashes.length > 0) { next(); return; } setShowStashAlert(true); } function maybeRenderStashAlert() { if (!showStashAlert) { return; } return ( { setShowStashAlert(false); next(); }, }} cancel={{ onClick: () => setShowStashAlert(false) }} >

); } function renderWelcomeSpecificConfig() { return ( <>

{chunks}, }} />

); } function renderWelcome() { return ( <>

{chunks}, }} />

{chunks}, }} />

); } function onGeneratedSelectClosed(d?: string) { if (d) { setGeneratedLocation(d); } setShowGeneratedSelectDialog(false); } function maybeRenderGeneratedSelectDialog() { if (!showGeneratedSelectDialog) { return; } return ; } function onBlobsClosed(d?: string) { if (d) { setBlobsLocation(d); } setShowBlobsDialog(false); } function maybeRenderBlobsSelectDialog() { if (!showBlobsDialog) { return; } return ; } function maybeRenderGenerated() { if (!configuration?.general.generatedPath) { return (

{chunks}, }} />

) => setGeneratedLocation(e.currentTarget.value) } />
); } } function onCacheSelectClosed(d?: string) { if (d) { setCacheLocation(d); } setShowCacheSelectDialog(false); } function maybeRenderCacheSelectDialog() { if (!showCacheSelectDialog) { return; } return ; } function maybeRenderCache() { if (!configuration?.general.cachePath) { return (

{chunks}, }} />

) => setCacheLocation(e.currentTarget.value) } />
); } } function maybeRenderBlobs() { if (!configuration?.general.blobsPath) { return (

{chunks}, }} />

{chunks}, strong: (chunks: string) => {chunks}, }} />

setStoreBlobsInDatabase(!storeBlobsInDatabase)} />

{!storeBlobsInDatabase && ( ) => setBlobsLocation(e.currentTarget.value) } disabled={storeBlobsInDatabase} /> )}
); } } function renderSetPaths() { return ( <> {maybeRenderStashAlert()}

setStashes(s)} />

{chunks}, }} />
{chunks}, }} />

) => setDatabaseFile(e.currentTarget.value) } />
{maybeRenderGenerated()} {maybeRenderCache()} {maybeRenderBlobs()}
); } function renderConfigLocation() { if (configLocation === "config.yml") { return <current working directory>/config.yml; } if (configLocation === "") { return $HOME/.stash/config.yml; } return {configLocation}; } function maybeRenderExclusions(s: GQL.StashConfig) { if (!s.excludeImage && !s.excludeVideo) { return; } const excludes = []; if (s.excludeVideo) { excludes.push("videos"); } if (s.excludeImage) { excludes.push("images"); } return `(excludes ${excludes.join(" and ")})`; } function renderStashLibraries() { return (
    {stashes.map((s) => (
  • {s.path} {maybeRenderExclusions(s)}
  • ))}
); } async function onSave() { try { setLoading(true); await mutateSetup({ configLocation, databaseFile, generatedLocation, cacheLocation, storeBlobsInDatabase, blobsLocation, stashes, }); // Set lastNoteSeen to hide release notes dialog await saveUI({ variables: { input: { ...configuration?.ui, lastNoteSeen: releaseNotes[0].date, }, }, }); } catch (e) { if (e instanceof Error) setSetupError(e.message ?? e.toString()); } finally { setLoading(false); next(); } } function renderConfirm() { return ( <>

{renderConfigLocation()}
{renderStashLibraries()}
{databaseFile !== "" ? databaseFile : intl.formatMessage({ id: "setup.confirm.default_db_location", })}
{generatedLocation !== "" ? generatedLocation : intl.formatMessage({ id: "setup.confirm.default_generated_content_location", })}
{cacheLocation !== "" ? cacheLocation : intl.formatMessage({ id: "setup.confirm.default_cache_location", })}
{storeBlobsInDatabase ? intl.formatMessage({ id: "setup.confirm.blobs_use_database", }) : blobsLocation !== "" ? blobsLocation : intl.formatMessage({ id: "setup.confirm.default_blobs_location", })}
); } function renderError() { return ( <>

{setupError} }} />

); } function renderSuccess() { return ( <>

{chunks}, localized_task: intl.formatMessage({ id: "config.categories.tasks", }), localized_scan: intl.formatMessage({ id: "actions.scan" }), }} />

}} />

{" "} OpenCollective{" "} ), }} />

); } function renderFinish() { if (setupError) { return renderError(); } return renderSuccess(); } // only display setup wizard if system is not setup if (statusLoading || configLoading) { return ; } if ( step === 0 && systemStatus && systemStatus.systemStatus.status !== GQL.SystemStatusEnum.Setup ) { // redirect to main page history.push("/"); return ; } const welcomeStep = systemStatus && systemStatus.systemStatus.configPath !== "" ? renderWelcomeSpecificConfig : renderWelcome; const steps = [welcomeStep, renderSetPaths, renderConfirm, renderFinish]; function renderCreating() { return ( {chunks}, }} /> ); } return ( {maybeRenderGeneratedSelectDialog()} {maybeRenderCacheSelectDialog()} {maybeRenderBlobsSelectDialog()}

{loading ? renderCreating() : {steps[step]()}}
); }; export default Setup;