diff --git a/graphql/schema/types/config.graphql b/graphql/schema/types/config.graphql
index 359229a4a..88ffb36dd 100644
--- a/graphql/schema/types/config.graphql
+++ b/graphql/schema/types/config.graphql
@@ -6,6 +6,8 @@ input SetupInput {
databaseFile: String!
"""Empty to indicate default"""
generatedLocation: String!
+ """Empty to indicate default"""
+ cacheLocation: String!
}
enum StreamingResolutionEnum {
diff --git a/internal/manager/manager.go b/internal/manager/manager.go
index 53a00c1ba..d12930c2f 100644
--- a/internal/manager/manager.go
+++ b/internal/manager/manager.go
@@ -100,6 +100,8 @@ type SetupInput struct {
DatabaseFile string `json:"databaseFile"`
// Empty to indicate default
GeneratedLocation string `json:"generatedLocation"`
+ // Empty to indicate default
+ CacheLocation string `json:"cacheLocation"`
}
type Manager struct {
@@ -588,6 +590,9 @@ func setSetupDefaults(input *SetupInput) {
if input.GeneratedLocation == "" {
input.GeneratedLocation = filepath.Join(configDir, "generated")
}
+ if input.CacheLocation == "" {
+ input.CacheLocation = filepath.Join(configDir, "cache")
+ }
if input.DatabaseFile == "" {
input.DatabaseFile = filepath.Join(configDir, "stash-go.sqlite")
@@ -633,6 +638,17 @@ func (s *Manager) Setup(ctx context.Context, input SetupInput) error {
s.Config.Set(config.Generated, input.GeneratedLocation)
}
+ // create the cache directory if it does not exist
+ if !c.HasOverride(config.Cache) {
+ if exists, _ := fsutil.DirExists(input.CacheLocation); !exists {
+ if err := os.Mkdir(input.CacheLocation, 0755); err != nil {
+ return fmt.Errorf("error creating cache directory: %v", err)
+ }
+ }
+
+ s.Config.Set(config.Cache, input.CacheLocation)
+ }
+
// set the configuration
if !c.HasOverride(config.Database) {
s.Config.Set(config.Database, input.DatabaseFile)
diff --git a/ui/v2.5/src/App.tsx b/ui/v2.5/src/App.tsx
index 10660e884..0833452ba 100644
--- a/ui/v2.5/src/App.tsx
+++ b/ui/v2.5/src/App.tsx
@@ -1,5 +1,11 @@
import React, { Suspense, useEffect, useState } from "react";
-import { Route, Switch, useRouteMatch } from "react-router-dom";
+import {
+ Route,
+ Switch,
+ useHistory,
+ useLocation,
+ useRouteMatch,
+} from "react-router-dom";
import { IntlProvider, CustomFormats } from "react-intl";
import { Helmet } from "react-helmet";
import cloneDeep from "lodash-es/cloneDeep";
@@ -30,7 +36,7 @@ import { InteractiveProvider } from "./hooks/Interactive/context";
import { ReleaseNotesDialog } from "./components/Dialogs/ReleaseNotesDialog";
import { IUIConfig } from "./core/config";
import { releaseNotes } from "./docs/en/ReleaseNotes";
-import { getPlatformURL, getBaseURL } from "./core/createClient";
+import { getPlatformURL } from "./core/createClient";
import { lazyComponent } from "./utils/lazyComponent";
const Performers = lazyComponent(
@@ -126,6 +132,8 @@ export const App: React.FC = () => {
setLocale();
}, [language]);
+ const location = useLocation();
+ const history = useHistory();
const setupMatch = useRouteMatch(["/setup", "/migrate"]);
// redirect to setup or migrate as needed
@@ -134,27 +142,24 @@ export const App: React.FC = () => {
return;
}
- const baseURL = getBaseURL();
+ const { status } = systemStatusData.systemStatus;
if (
- window.location.pathname !== baseURL + "setup" &&
- systemStatusData.systemStatus.status === GQL.SystemStatusEnum.Setup
+ location.pathname !== "/setup" &&
+ status === GQL.SystemStatusEnum.Setup
) {
// redirect to setup page
- const newURL = new URL("setup", window.location.origin + baseURL);
- window.location.href = newURL.toString();
+ history.push("/setup");
}
if (
- window.location.pathname !== baseURL + "migrate" &&
- systemStatusData.systemStatus.status ===
- GQL.SystemStatusEnum.NeedsMigration
+ location.pathname !== "/migrate" &&
+ status === GQL.SystemStatusEnum.NeedsMigration
) {
- // redirect to setup page
- const newURL = new URL("migrate", window.location.origin + baseURL);
- window.location.href = newURL.toString();
+ // redirect to migrate page
+ history.push("/migrate");
}
- }, [systemStatusData]);
+ }, [systemStatusData, setupMatch, history, location]);
function maybeRenderNavbar() {
// don't render navbar for setup views
@@ -200,7 +205,7 @@ export const App: React.FC = () => {
}
function maybeRenderReleaseNotes() {
- if (setupMatch || config.loading || config.error) {
+ if (setupMatch || !systemStatusData || config.loading || config.error) {
return;
}
diff --git a/ui/v2.5/src/components/Settings/SettingsSystemPanel.tsx b/ui/v2.5/src/components/Settings/SettingsSystemPanel.tsx
index 108f9652b..b23f72027 100644
--- a/ui/v2.5/src/components/Settings/SettingsSystemPanel.tsx
+++ b/ui/v2.5/src/components/Settings/SettingsSystemPanel.tsx
@@ -116,6 +116,14 @@ export const SettingsConfigurationPanel: React.FC = () => {
onChange={(v) => saveGeneral({ generatedPath: v })}
/>
+ saveGeneral({ cachePath: v })}
+ />
+
{
onChange={(v) => saveGeneral({ metadataPath: v })}
/>
- saveGeneral({ cachePath: v })}
- />
-
{
const [migrateError, setMigrateError] = useState("");
const intl = useIntl();
+ const history = useHistory();
// if database path includes path separators, then this is passed through
// to the migration path. Extract the base name of the database file.
@@ -109,8 +110,7 @@ export const Migrate: React.FC = () => {
systemStatus.systemStatus.status !== GQL.SystemStatusEnum.NeedsMigration
) {
// redirect to main page
- const newURL = new URL("/", window.location.toString());
- window.location.href = newURL.toString();
+ history.push("/");
return ;
}
@@ -122,8 +122,7 @@ export const Migrate: React.FC = () => {
backupPath: backupPath ?? "",
});
- const newURL = new URL("", window.location.origin + getBaseURL());
- window.location.href = newURL.toString();
+ history.push("/");
} catch (e) {
if (e instanceof Error) setMigrateError(e.message ?? e.toString());
setMigrateLoading(false);
diff --git a/ui/v2.5/src/components/Setup/Setup.tsx b/ui/v2.5/src/components/Setup/Setup.tsx
index f8b116a14..d7b8e5c6f 100644
--- a/ui/v2.5/src/components/Setup/Setup.tsx
+++ b/ui/v2.5/src/components/Setup/Setup.tsx
@@ -14,7 +14,7 @@ import {
useConfigureUI,
useSystemStatus,
} from "src/core/StashService";
-import { Link } from "react-router-dom";
+import { Link, useHistory } from "react-router-dom";
import { ConfigurationContext } from "src/hooks/Config";
import StashConfiguration from "../Settings/StashConfiguration";
import { Icon } from "../Shared/Icon";
@@ -37,14 +37,18 @@ export const Setup: React.FC = () => {
const [configLocation, setConfigLocation] = useState("");
const [stashes, setStashes] = useState([]);
const [showStashAlert, setShowStashAlert] = useState(false);
- const [generatedLocation, setGeneratedLocation] = useState("");
const [databaseFile, setDatabaseFile] = useState("");
+ const [generatedLocation, setGeneratedLocation] = useState("");
+ const [cacheLocation, setCacheLocation] = useState("");
const [loading, setLoading] = useState(false);
const [setupError, setSetupError] = useState("");
const intl = useIntl();
+ const history = useHistory();
- const [showGeneratedDialog, setShowGeneratedDialog] = useState(false);
+ const [showGeneratedSelectDialog, setShowGeneratedSelectDialog] =
+ useState(false);
+ const [showCacheSelectDialog, setShowCacheSelectDialog] = useState(false);
const { data: systemStatus, loading: statusLoading } = useSystemStatus();
@@ -233,20 +237,20 @@ export const Setup: React.FC = () => {
);
}
- function onGeneratedClosed(d?: string) {
+ function onGeneratedSelectClosed(d?: string) {
if (d) {
setGeneratedLocation(d);
}
- setShowGeneratedDialog(false);
+ setShowGeneratedSelectDialog(false);
}
function maybeRenderGeneratedSelectDialog() {
- if (!showGeneratedDialog) {
+ if (!showGeneratedSelectDialog) {
return;
}
- return ;
+ return ;
}
function maybeRenderGenerated() {
@@ -279,7 +283,64 @@ export const Setup: React.FC = () => {
+
+
+
+ );
+ }
+ }
+
+ 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)
+ }
+ />
+
+
@@ -328,6 +389,13 @@ export const Setup: React.FC = () => {
code: (chunks: string) => {chunks},
}}
/>
+
+ {chunks},
+ }}
+ />
{
/>
{maybeRenderGenerated()}
+ {maybeRenderCache()}
@@ -404,6 +473,7 @@ export const Setup: React.FC = () => {
configLocation,
databaseFile,
generatedLocation,
+ cacheLocation,
stashes,
});
// Set lastNoteSeen to hide release notes dialog
@@ -473,6 +543,20 @@ export const Setup: React.FC = () => {
+
+ -
+
+
+ -
+
+ {cacheLocation !== ""
+ ? cacheLocation
+ : intl.formatMessage({
+ id: "setup.confirm.default_cache_location",
+ })}
+
+
+
@@ -592,7 +676,7 @@ export const Setup: React.FC = () => {
-