release: v0.20.0
This commit is contained in:
@@ -30,6 +30,7 @@ import SeoSection from './settings/SeoSection';
|
||||
import SecuritySection from './settings/SecuritySection';
|
||||
import AboutSection, { useAboutEditor } from './settings/AboutSection';
|
||||
import PageHeader from './PageHeader';
|
||||
import { sameDraft } from './sameDraft';
|
||||
|
||||
const SETTINGS_SECTIONS = [
|
||||
{ id: 'general', label: 'General' },
|
||||
@@ -71,6 +72,8 @@ export default function SettingsEditor() {
|
||||
} | null>(null);
|
||||
/** Fields an environment variable overrides, path to variable name (#605). */
|
||||
const [envLocks, setEnvLocks] = useState<EnvLocks>({});
|
||||
/** SITE_TITLE, the first fallback for an empty title (QA A-15). */
|
||||
const [siteTitleEnv, setSiteTitleEnv] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
/**
|
||||
* Set when the settings could not be fetched. It blocks saving, because an
|
||||
@@ -79,7 +82,8 @@ export default function SettingsEditor() {
|
||||
*/
|
||||
const [loadError, setLoadError] = useState<string | null>(null);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [dirty, setDirty] = useState(false);
|
||||
/** Set by any edit; `dirty` below also asks whether the edits changed anything. */
|
||||
const [edited, setDirty] = useState(false);
|
||||
const [saveStatus, setSaveStatus] = useState<SaveStatus>(null);
|
||||
|
||||
const about = useAboutEditor(activeSection === 'about');
|
||||
@@ -88,6 +92,8 @@ export default function SettingsEditor() {
|
||||
// builder's and the journal's do (#592) — useUnsavedGuard only covers
|
||||
// leaving the browser.
|
||||
const [serverSettings, setServerSettings] = useState<Settings>({});
|
||||
// Typing a value back to what was saved is not an unsaved change (QA A-19).
|
||||
const dirty = edited && !sameDraft(settings, serverSettings);
|
||||
// The draft never sees `sitePassword`: sessionStorage is readable by any
|
||||
// script on the admin origin, and until it is saved (and hashed) the field
|
||||
// holds the password as typed. A restored draft takes the password from the
|
||||
@@ -160,7 +166,13 @@ export default function SettingsEditor() {
|
||||
: `The server answered ${res.status}.`,
|
||||
);
|
||||
}
|
||||
const { settings: data, siteUrl, envLocks: locks, version } = await res.json();
|
||||
const {
|
||||
settings: data,
|
||||
siteUrl,
|
||||
envLocks: locks,
|
||||
version,
|
||||
siteTitleEnv: titleEnv,
|
||||
} = await res.json();
|
||||
const loaded: Settings = data || {};
|
||||
versionRef.current = typeof version === 'string' ? version : null;
|
||||
setServerSettings(loaded);
|
||||
@@ -170,6 +182,7 @@ export default function SettingsEditor() {
|
||||
setDirty(restored !== null);
|
||||
setSiteUrlInfo(siteUrl ?? null);
|
||||
setEnvLocks(locks ?? {});
|
||||
setSiteTitleEnv(typeof titleEnv === 'string' ? titleEnv : null);
|
||||
} catch (err) {
|
||||
console.error('Failed to load settings:', err);
|
||||
setLoadError(err instanceof Error ? err.message : 'The settings could not be loaded.');
|
||||
@@ -407,7 +420,7 @@ export default function SettingsEditor() {
|
||||
|
||||
{/* Content */}
|
||||
<div className="settings-content">
|
||||
{activeSection === 'general' && <GeneralSection {...props} />}
|
||||
{activeSection === 'general' && <GeneralSection {...props} siteTitleEnv={siteTitleEnv} />}
|
||||
{activeSection === 'theme' && <ThemeSection {...props} />}
|
||||
{activeSection === 'grid' && <GridSection {...props} />}
|
||||
{activeSection === 'footer' && <FooterSection {...props} />}
|
||||
|
||||
Reference in New Issue
Block a user