@actuate-media/cms-admin 0.36.0 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/views/appearance-settings.render.test.js +4 -4
- package/dist/__tests__/views/updates-tab.render.test.d.ts +2 -0
- package/dist/__tests__/views/updates-tab.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/updates-tab.render.test.js +132 -0
- package/dist/__tests__/views/updates-tab.render.test.js.map +1 -0
- package/dist/actuate-admin.css +1 -1
- package/dist/views/ApiKeys.d.ts.map +1 -1
- package/dist/views/ApiKeys.js +14 -13
- package/dist/views/ApiKeys.js.map +1 -1
- package/dist/views/Profile.d.ts.map +1 -1
- package/dist/views/Profile.js +1 -1
- package/dist/views/Profile.js.map +1 -1
- package/dist/views/Settings.d.ts.map +1 -1
- package/dist/views/Settings.js +16 -119
- package/dist/views/Settings.js.map +1 -1
- package/dist/views/Users.js +1 -1
- package/dist/views/Users.js.map +1 -1
- package/dist/views/settings/AISettingsTab.js +40 -42
- package/dist/views/settings/AISettingsTab.js.map +1 -1
- package/dist/views/settings/AdminThemeCard.js +1 -1
- package/dist/views/settings/AiFeaturesCard.d.ts.map +1 -1
- package/dist/views/settings/AiFeaturesCard.js +2 -3
- package/dist/views/settings/AiFeaturesCard.js.map +1 -1
- package/dist/views/settings/BrandPreviewCard.js +1 -1
- package/dist/views/settings/BrandVoiceCard.d.ts.map +1 -1
- package/dist/views/settings/BrandVoiceCard.js +2 -4
- package/dist/views/settings/BrandVoiceCard.js.map +1 -1
- package/dist/views/settings/BrandingCard.d.ts.map +1 -1
- package/dist/views/settings/BrandingCard.js +34 -19
- package/dist/views/settings/BrandingCard.js.map +1 -1
- package/dist/views/settings/GeneralSettingsTab.js +1 -1
- package/dist/views/settings/LanguageRegionCard.d.ts.map +1 -1
- package/dist/views/settings/LanguageRegionCard.js +2 -1
- package/dist/views/settings/LanguageRegionCard.js.map +1 -1
- package/dist/views/settings/MonthlyUsageCard.d.ts.map +1 -1
- package/dist/views/settings/MonthlyUsageCard.js +3 -3
- package/dist/views/settings/MonthlyUsageCard.js.map +1 -1
- package/dist/views/settings/ProviderConnectionCard.js +1 -1
- package/dist/views/settings/ProviderConnectionCard.js.map +1 -1
- package/dist/views/settings/SecurityStatusCard.d.ts.map +1 -1
- package/dist/views/settings/SecurityStatusCard.js +2 -3
- package/dist/views/settings/SecurityStatusCard.js.map +1 -1
- package/dist/views/settings/SecurityTab.js +1 -1
- package/dist/views/settings/SeoRobotsDefaultsCard.d.ts.map +1 -1
- package/dist/views/settings/SeoRobotsDefaultsCard.js +3 -4
- package/dist/views/settings/SeoRobotsDefaultsCard.js.map +1 -1
- package/dist/views/settings/SeoSettingsTab.d.ts.map +1 -1
- package/dist/views/settings/SeoSettingsTab.js +5 -8
- package/dist/views/settings/SeoSettingsTab.js.map +1 -1
- package/dist/views/settings/SiteIndexStatusCard.d.ts.map +1 -1
- package/dist/views/settings/SiteIndexStatusCard.js +3 -2
- package/dist/views/settings/SiteIndexStatusCard.js.map +1 -1
- package/dist/views/settings/SiteInformationCard.d.ts.map +1 -1
- package/dist/views/settings/SiteInformationCard.js +4 -4
- package/dist/views/settings/SiteInformationCard.js.map +1 -1
- package/dist/views/settings/TypographyMotionCard.js +1 -1
- package/dist/views/settings/UpdatesTab.d.ts +6 -0
- package/dist/views/settings/UpdatesTab.d.ts.map +1 -0
- package/dist/views/settings/UpdatesTab.js +80 -0
- package/dist/views/settings/UpdatesTab.js.map +1 -0
- package/dist/views/settings/components.d.ts +51 -1
- package/dist/views/settings/components.d.ts.map +1 -1
- package/dist/views/settings/components.js +33 -0
- package/dist/views/settings/components.js.map +1 -1
- package/dist/views/settings/securityPrimitives.d.ts +11 -3
- package/dist/views/settings/securityPrimitives.d.ts.map +1 -1
- package/dist/views/settings/securityPrimitives.js +10 -3
- package/dist/views/settings/securityPrimitives.js.map +1 -1
- package/dist/views/settings/useUpdates.d.ts +67 -0
- package/dist/views/settings/useUpdates.d.ts.map +1 -0
- package/dist/views/settings/useUpdates.js +127 -0
- package/dist/views/settings/useUpdates.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/views/appearance-settings.render.test.tsx +4 -4
- package/src/__tests__/views/updates-tab.render.test.tsx +161 -0
- package/src/views/ApiKeys.tsx +190 -154
- package/src/views/Profile.tsx +4 -2
- package/src/views/Settings.tsx +26 -451
- package/src/views/Users.tsx +1 -1
- package/src/views/settings/AISettingsTab.tsx +64 -76
- package/src/views/settings/AdminThemeCard.tsx +1 -1
- package/src/views/settings/AiFeaturesCard.tsx +6 -12
- package/src/views/settings/BrandPreviewCard.tsx +1 -1
- package/src/views/settings/BrandVoiceCard.tsx +6 -19
- package/src/views/settings/BrandingCard.tsx +179 -180
- package/src/views/settings/GeneralSettingsTab.tsx +1 -1
- package/src/views/settings/LanguageRegionCard.tsx +5 -7
- package/src/views/settings/MonthlyUsageCard.tsx +6 -10
- package/src/views/settings/ProviderConnectionCard.tsx +1 -1
- package/src/views/settings/SecurityStatusCard.tsx +8 -11
- package/src/views/settings/SecurityTab.tsx +1 -1
- package/src/views/settings/SeoRobotsDefaultsCard.tsx +7 -14
- package/src/views/settings/SeoSettingsTab.tsx +17 -26
- package/src/views/settings/SiteIndexStatusCard.tsx +10 -22
- package/src/views/settings/SiteInformationCard.tsx +3 -9
- package/src/views/settings/TypographyMotionCard.tsx +1 -1
- package/src/views/settings/UpdatesTab.tsx +545 -0
- package/src/views/settings/components.tsx +123 -1
- package/src/views/settings/securityPrimitives.tsx +14 -9
- package/src/views/settings/useUpdates.ts +183 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { AlertTriangle, ChevronDown, ChevronRight, ImageIcon, Loader2, Trash2, Upload, } from 'lucide-react';
|
|
4
4
|
import { useRef } from 'react';
|
|
5
|
+
import { SettingsCard, SettingsControlRow, SettingsSubsection } from './components.js';
|
|
5
6
|
const LOGO_ACCEPT = 'image/svg+xml,image/png';
|
|
6
7
|
function previewSurface(dark) {
|
|
7
8
|
return dark ? 'bg-foreground border-border' : 'bg-muted border-border';
|
|
@@ -12,27 +13,41 @@ function LogoField({ label, helper, field, accept, square, darkSurface, brand, a
|
|
|
12
13
|
const asset = assetId ? assets[assetId] : undefined;
|
|
13
14
|
const uploading = uploadingField === field;
|
|
14
15
|
const inputId = `brand-${field}`;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
const thumbnail = (_jsx("div", { className: `flex shrink-0 items-center justify-center overflow-hidden rounded-md border p-2 ${previewSurface(Boolean(darkSurface))} ${square ? 'h-12 w-12' : 'h-12 w-20'}`, "aria-hidden": !asset, children: asset?.url ? (
|
|
17
|
+
// Never stretch/crop — contain preserves aspect ratio + transparency.
|
|
18
|
+
_jsx("img", { src: asset.url, alt: `${label} preview`, className: "max-h-full max-w-full object-contain" })) : (_jsx(ImageIcon, { size: 18, className: "text-muted-foreground", "aria-hidden": "true" })) }));
|
|
19
|
+
const controls = (_jsxs(_Fragment, { children: [_jsx("input", { ref: inputRef, id: inputId, type: "file", accept: accept, "aria-label": label, className: "sr-only", disabled: !canEdit || uploading, onChange: (e) => {
|
|
20
|
+
const file = e.target.files?.[0];
|
|
21
|
+
if (file)
|
|
22
|
+
onUpload(field, file);
|
|
23
|
+
if (inputRef.current)
|
|
24
|
+
inputRef.current.value = '';
|
|
25
|
+
} }), asset && (_jsxs("button", { type: "button", onClick: () => onRemove(field), disabled: !canEdit, className: "text-muted-foreground hover:text-destructive inline-flex items-center gap-1.5 rounded-md px-2 py-1.5 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50", "aria-label": `Remove ${label.toLowerCase()}`, children: [_jsx(Trash2, { size: 14, "aria-hidden": "true" }), " Remove"] })), _jsxs("button", { type: "button", onClick: () => inputRef.current?.click(), disabled: !canEdit || uploading, "aria-label": `${asset ? 'Replace' : 'Upload'} ${label.toLowerCase()}`, className: "border-border text-foreground hover:bg-accent inline-flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50", children: [uploading ? (_jsx(Loader2, { size: 14, className: "animate-spin", "aria-hidden": "true" })) : (_jsx(Upload, { size: 14, "aria-hidden": "true" })), asset ? 'Replace' : 'Upload'] })] }));
|
|
26
|
+
return (_jsxs("div", { children: [_jsx(SettingsControlRow, { leading: thumbnail, label: label, description: helper, control: controls }), warning && (_jsxs("p", { className: "text-warning mt-2 flex items-start gap-1.5 text-sm", role: "status", "aria-live": "polite", children: [_jsx(AlertTriangle, { size: 14, className: "mt-0.5 shrink-0", "aria-hidden": "true" }), " ", warning] }))] }));
|
|
27
|
+
}
|
|
28
|
+
function AdminBrandSourceToggle({ mode, canEdit, onChange, }) {
|
|
29
|
+
return (_jsx("div", { role: "radiogroup", "aria-label": "Brand source", className: "border-border bg-muted inline-flex rounded-md border p-0.5", children: [
|
|
30
|
+
['inheritPublicBrand', 'Inherit public brand'],
|
|
31
|
+
['customAdminBrand', 'Custom admin logo'],
|
|
32
|
+
].map(([value, text]) => {
|
|
33
|
+
const active = mode === value;
|
|
34
|
+
return (_jsx("button", { type: "button", role: "radio", "aria-checked": active, disabled: !canEdit, onClick: () => onChange(value), className: `rounded px-3 py-1.5 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${active
|
|
35
|
+
? 'bg-card text-foreground shadow-sm'
|
|
36
|
+
: 'text-muted-foreground hover:text-foreground'}`, children: text }, value));
|
|
37
|
+
}) }));
|
|
24
38
|
}
|
|
25
39
|
export function BrandingCard({ s, canEdit }) {
|
|
26
40
|
const warningFor = (field) => s.issues.find((i) => i.field === field && i.severity === 'warning')?.message;
|
|
27
41
|
const custom = s.brand.mode === 'customAdminBrand';
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
const logoFieldProps = {
|
|
43
|
+
accept: LOGO_ACCEPT,
|
|
44
|
+
brand: s.brand,
|
|
45
|
+
assets: s.assets,
|
|
46
|
+
uploadingField: s.uploadingField,
|
|
47
|
+
canEdit,
|
|
48
|
+
onUpload: s.uploadAsset,
|
|
49
|
+
onRemove: s.removeAsset,
|
|
50
|
+
};
|
|
51
|
+
return (_jsxs(SettingsCard, { title: "Branding", description: "Logos shown in the admin sidebar and on the public site.", children: [_jsxs("div", { className: "space-y-5", children: [_jsx(LogoField, { label: "Primary logo", helper: "SVG or PNG, up to 1MB. Best for the public header and full admin sidebar.", field: "publicPrimaryLogoAssetId", warning: warningFor('publicPrimaryLogoAssetId'), ...logoFieldProps }), _jsx(LogoField, { label: "Favicon / app icon source", helper: "32\u00D732 PNG or SVG. A larger square image is fine \u2014 it scales down cleanly.", field: "faviconSourceAssetId", square: true, warning: warningFor('faviconSourceAssetId'), ...logoFieldProps }), _jsxs("div", { className: "border-border border-t pt-4", children: [_jsxs("button", { type: "button", onClick: () => s.setShowAdvanced(!s.showAdvanced), "aria-expanded": s.showAdvanced, className: "text-foreground hover:text-brand inline-flex items-center gap-1.5 text-sm font-medium transition-colors", children: [s.showAdvanced ? (_jsx(ChevronDown, { size: 16, "aria-hidden": "true" })) : (_jsx(ChevronRight, { size: 16, "aria-hidden": "true" })), "Advanced logo variants"] }), s.showAdvanced && (_jsxs("div", { className: "mt-4 space-y-5", children: [_jsx(LogoField, { label: "Logo mark", helper: "Square icon or mark. Used for the collapsed sidebar, compact UI, and app icons.", field: "publicLogoMarkAssetId", square: true, warning: warningFor('publicLogoMarkAssetId'), ...logoFieldProps }), _jsx(LogoField, { label: "Dark mode logo", helper: "Optional. Used on dark backgrounds or the dark admin theme.", field: "publicDarkLogoAssetId", darkSurface: true, warning: warningFor('publicDarkLogoAssetId'), ...logoFieldProps })] }))] }), _jsx(SettingsSubsection, { title: "Admin branding", description: "By default the admin reuses your public brand. Override it for a distinct internal look.", children: _jsxs("div", { className: "mt-4 space-y-5", children: [_jsx(SettingsControlRow, { label: "Brand source", description: "Choose whether the admin inherits the public brand or uses a custom logo.", control: _jsx(AdminBrandSourceToggle, { mode: s.brand.mode, canEdit: canEdit, onChange: s.setBrandingMode }) }), custom && (_jsxs("div", { className: "space-y-5", children: [_jsx(LogoField, { label: "Admin primary logo", helper: "Shown in the admin sidebar instead of the public logo.", field: "adminPrimaryLogoAssetId", warning: warningFor('adminPrimaryLogoAssetId'), ...logoFieldProps }), _jsx(LogoField, { label: "Admin logo mark", helper: "Square mark for the collapsed admin sidebar.", field: "adminLogoMarkAssetId", square: true, warning: warningFor('adminLogoMarkAssetId'), ...logoFieldProps })] }))] }) }), _jsxs("div", { className: "border-border border-t pt-4", children: [_jsx("label", { htmlFor: "brand-alt", className: "text-foreground block text-base font-medium", children: "Logo alt text" }), _jsx("p", { className: "text-muted-foreground mt-0.5 mb-2 text-sm", children: "Used by screen readers on the public site. Defaults to the Site Title when empty." }), _jsx("input", { id: "brand-alt", type: "text", value: s.brand.defaultLogoAltText ?? '', disabled: !canEdit, onChange: (e) => s.setAltText(e.target.value), placeholder: "Site Title", className: "border-border bg-input-background text-foreground focus-visible:ring-ring w-full max-w-md rounded-md border px-3 py-2 text-base focus-visible:ring-2 focus-visible:outline-none disabled:opacity-50" })] })] }), s.saveError && (_jsx("p", { className: "text-destructive mt-4 text-sm", role: "alert", children: s.saveError }))] }));
|
|
37
52
|
}
|
|
38
53
|
//# sourceMappingURL=BrandingCard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrandingCard.js","sourceRoot":"","sources":["../../../src/views/settings/BrandingCard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACZ,SAAS,EACT,OAAO,EACP,MAAM,EACN,MAAM,GACP,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"BrandingCard.js","sourceRoot":"","sources":["../../../src/views/settings/BrandingCard.tsx"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ export function GeneralSettingsTab({ onNavigate, role }) {
|
|
|
12
12
|
const settings = useGeneralSettings(canEdit);
|
|
13
13
|
const runAudit = () => onNavigate?.('/seo?tab=audit');
|
|
14
14
|
if (settings.loading) {
|
|
15
|
-
return (_jsxs("div", { className: "space-y-4", "aria-busy": "true", "aria-live": "polite", children: [_jsx("span", { className: "sr-only", children: "Loading settings\u2026" }), [0, 1, 2, 3].map((i) => (_jsxs("div", { className: "border-border bg-card rounded-lg border p-
|
|
15
|
+
return (_jsxs("div", { className: "space-y-4", "aria-busy": "true", "aria-live": "polite", children: [_jsx("span", { className: "sr-only", children: "Loading settings\u2026" }), [0, 1, 2, 3].map((i) => (_jsxs("div", { className: "border-border bg-card rounded-lg border p-6", children: [_jsx("div", { className: "bg-muted mb-4 h-4 w-40 animate-pulse rounded" }), _jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "bg-muted h-9 w-full animate-pulse rounded" }), _jsx("div", { className: "bg-muted h-9 w-full animate-pulse rounded" })] })] }, i)))] }));
|
|
16
16
|
}
|
|
17
17
|
return (_jsxs("div", { className: "space-y-4", children: [settings.loadError && (_jsxs("div", { role: "alert", className: "border-destructive/30 bg-destructive/10 text-destructive flex items-center gap-3 rounded-lg border p-3 text-sm", children: [_jsx(AlertTriangle, { size: 16, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { className: "flex-1", children: settings.loadError }), _jsx("button", { type: "button", onClick: settings.refetch, className: "border-destructive/40 rounded-md border px-3 py-1 transition-colors hover:opacity-80", children: "Retry" })] })), !canEdit && (_jsxs("div", { className: "border-border bg-muted text-muted-foreground flex items-center gap-2 rounded-lg border p-3 text-sm", children: [_jsx(Info, { size: 16, className: "shrink-0", "aria-hidden": "true" }), "You have read-only access to settings. Only administrators can make changes."] })), _jsx(SettingsValidationSummary, { issues: settings.issues }), _jsx(SiteIndexStatusCard, { status: settings.indexStatus, loading: settings.loading, onNavigate: onNavigate, onRunAudit: runAudit }), _jsx(SiteInformationCard, { form: settings.form, setField: settings.setField, sources: settings.sources, issues: settings.issues, canEdit: canEdit }), _jsx(LanguageRegionCard, { form: settings.form, setField: settings.setField, issues: settings.issues, canEdit: canEdit }), _jsx(SeoRobotsDefaultsCard, { form: settings.form, setField: settings.setField, isProduction: settings.isProduction, indexStatus: settings.indexStatus, canEdit: canEdit, onNavigate: onNavigate }), settings.saveState === 'error' && settings.saveError && (_jsxs("div", { role: "alert", className: "border-destructive/30 bg-destructive/10 text-destructive flex items-center gap-3 rounded-lg border p-3 text-sm", children: [_jsx(AlertTriangle, { size: 16, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { className: "flex-1", children: settings.saveError }), _jsx("button", { type: "button", onClick: settings.save, className: "border-destructive/40 rounded-md border px-3 py-1 transition-colors hover:opacity-80", children: "Retry" })] })), _jsx(SettingsSaveBar, { dirty: settings.dirty, canEdit: canEdit, hasErrors: settings.hasErrors, saveState: settings.saveState, onSave: settings.save, onReset: settings.reset })] }));
|
|
18
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LanguageRegionCard.d.ts","sourceRoot":"","sources":["../../../src/views/settings/LanguageRegionCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LanguageRegionCard.d.ts","sourceRoot":"","sources":["../../../src/views/settings/LanguageRegionCard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AA+BnF,UAAU,uBAAuB;IAC/B,IAAI,EAAE,mBAAmB,CAAA;IACzB,QAAQ,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IAC9F,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,uBAAuB,2CA0E9F"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useId, useMemo } from 'react';
|
|
4
|
+
import { SettingsCard } from './components.js';
|
|
4
5
|
const INPUT_CLASS = 'w-full rounded-md border border-border bg-input-background px-3 py-2 text-base text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-60';
|
|
5
6
|
const LABEL_CLASS = 'mb-1 block text-sm font-medium text-foreground';
|
|
6
7
|
const LANGUAGES = [
|
|
@@ -43,6 +44,6 @@ export function LanguageRegionCard({ form, setField, issues, canEdit }) {
|
|
|
43
44
|
return TIMEZONES;
|
|
44
45
|
return [form.timezone, ...TIMEZONES];
|
|
45
46
|
}, [form.timezone]);
|
|
46
|
-
return (
|
|
47
|
+
return (_jsx(SettingsCard, { title: "Language & Region", description: "Default language and timezone applied across the admin and public site.", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { htmlFor: langId, className: LABEL_CLASS, children: "Language" }), _jsx("select", { id: langId, value: form.language, disabled: !canEdit, "aria-invalid": Boolean(langIssue), onChange: (e) => setField('language', e.target.value), className: INPUT_CLASS, children: languageOptions.map((l) => (_jsx("option", { value: l.value, children: l.label }, l.value))) }), langIssue && _jsx("p", { className: "text-destructive mt-1 text-sm", children: langIssue.message })] }), _jsxs("div", { children: [_jsx("label", { htmlFor: tzId, className: LABEL_CLASS, children: "Timezone" }), _jsx("select", { id: tzId, value: form.timezone, disabled: !canEdit, "aria-invalid": Boolean(tzIssue), onChange: (e) => setField('timezone', e.target.value), className: INPUT_CLASS, children: timezoneOptions.map((tz) => (_jsx("option", { value: tz, children: tz }, tz))) }), tzIssue ? (_jsx("p", { className: "text-destructive mt-1 text-sm", children: tzIssue.message })) : (_jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: "Applied to dashboard dates, audit logs, scheduled publishing, and form submissions." }))] })] }) }));
|
|
47
48
|
}
|
|
48
49
|
//# sourceMappingURL=LanguageRegionCard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LanguageRegionCard.js","sourceRoot":"","sources":["../../../src/views/settings/LanguageRegionCard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"LanguageRegionCard.js","sourceRoot":"","sources":["../../../src/views/settings/LanguageRegionCard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAG9C,MAAM,WAAW,GACf,wNAAwN,CAAA;AAC1N,MAAM,WAAW,GAAG,gDAAgD,CAAA;AAEpE,MAAM,SAAS,GAA4C;IACzD,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE;IACzC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE;IACzC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE;IAC5C,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE;IAC7C,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE;IAC5C,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE;IAC7C,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE;CAClC,CAAA;AAED,MAAM,SAAS,GAAG;IAChB,KAAK;IACL,kBAAkB;IAClB,iBAAiB;IACjB,gBAAgB;IAChB,qBAAqB;IACrB,mBAAmB;IACnB,eAAe;IACf,cAAc;IACd,eAAe;IACf,YAAY;IACZ,gBAAgB;IAChB,kBAAkB;CACnB,CAAA;AASD,MAAM,UAAU,kBAAkB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAA2B;IAC7F,MAAM,MAAM,GAAG,KAAK,EAAE,CAAA;IACtB,MAAM,IAAI,GAAG,KAAK,EAAE,CAAA;IACpB,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,CAAA;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,UAAU,CAAC,CAAA;IAE1D,uEAAuE;IACvE,iEAAiE;IACjE,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,EAAE;QACnC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,SAAS,CAAA;QACtE,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,SAAS,CAAC,CAAA;IACvE,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEnB,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,EAAE;QACnC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,SAAS,CAAA;QACvD,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC,CAAA;IACtC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEnB,OAAO,CACL,KAAC,YAAY,IACX,KAAK,EAAC,mBAAmB,EACzB,WAAW,EAAC,yEAAyE,YAErF,eAAK,SAAS,EAAC,WAAW,aACxB,0BACE,gBAAO,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,yBAEtC,EACR,iBACE,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,IAAI,CAAC,QAAQ,EACpB,QAAQ,EAAE,CAAC,OAAO,kBACJ,OAAO,CAAC,SAAS,CAAC,EAChC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACrD,SAAS,EAAE,WAAW,YAErB,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAC1B,iBAAsB,KAAK,EAAE,CAAC,CAAC,KAAK,YACjC,CAAC,CAAC,KAAK,IADG,CAAC,CAAC,KAAK,CAEX,CACV,CAAC,GACK,EACR,SAAS,IAAI,YAAG,SAAS,EAAC,+BAA+B,YAAE,SAAS,CAAC,OAAO,GAAK,IAC9E,EAEN,0BACE,gBAAO,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,yBAEpC,EACR,iBACE,EAAE,EAAE,IAAI,EACR,KAAK,EAAE,IAAI,CAAC,QAAQ,EACpB,QAAQ,EAAE,CAAC,OAAO,kBACJ,OAAO,CAAC,OAAO,CAAC,EAC9B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACrD,SAAS,EAAE,WAAW,YAErB,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAC3B,iBAAiB,KAAK,EAAE,EAAE,YACvB,EAAE,IADQ,EAAE,CAEN,CACV,CAAC,GACK,EACR,OAAO,CAAC,CAAC,CAAC,CACT,YAAG,SAAS,EAAC,+BAA+B,YAAE,OAAO,CAAC,OAAO,GAAK,CACnE,CAAC,CAAC,CAAC,CACF,YAAG,SAAS,EAAC,oCAAoC,oGAE7C,CACL,IACG,IACF,GACO,CAChB,CAAA;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MonthlyUsageCard.d.ts","sourceRoot":"","sources":["../../../src/views/settings/MonthlyUsageCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MonthlyUsageCard.d.ts","sourceRoot":"","sources":["../../../src/views/settings/MonthlyUsageCard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAYrD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,OAAO,GACR,EAAE;IACD,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACzB,iBAAiB,EAAE,MAAM,CAAA;IACzB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,OAAO,EAAE,OAAO,CAAA;CACjB,2CAgFA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import {
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useId } from 'react';
|
|
4
|
+
import { SettingsCard } from './components.js';
|
|
4
5
|
const INPUT_CLASS = 'w-full rounded-md border border-border bg-input-background px-3 py-2 text-base text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-60';
|
|
5
6
|
const LABEL_CLASS = 'mb-1 flex items-center gap-2 text-sm font-medium text-foreground';
|
|
6
7
|
function formatTokens(n) {
|
|
@@ -16,7 +17,6 @@ function formatTokens(n) {
|
|
|
16
17
|
* fabricated number.
|
|
17
18
|
*/
|
|
18
19
|
export function MonthlyUsageCard({ usage, monthlyTokenLimit, onChangeLimit, budgetError, canEdit, }) {
|
|
19
|
-
const headingId = useId();
|
|
20
20
|
const limitId = useId();
|
|
21
21
|
const used = usage?.totalTokens ?? 0;
|
|
22
22
|
const limit = monthlyTokenLimit === '' ? undefined : Number(monthlyTokenLimit);
|
|
@@ -25,6 +25,6 @@ export function MonthlyUsageCard({ usage, monthlyTokenLimit, onChangeLimit, budg
|
|
|
25
25
|
const periodLabel = usage?.periodStart
|
|
26
26
|
? new Date(usage.periodStart).toLocaleDateString(undefined, { month: 'long', year: 'numeric' })
|
|
27
27
|
: 'This month';
|
|
28
|
-
return (
|
|
28
|
+
return (_jsx(SettingsCard, { title: "Monthly Usage", description: `Token usage for ${periodLabel}. Aggregated from completed AI runs.`, children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-center justify-between text-sm", children: [_jsxs("span", { className: "text-foreground font-medium", children: [formatTokens(used), " tokens used"] }), limit && limit > 0 && (_jsxs("span", { className: "text-muted-foreground", children: ["of ", formatTokens(limit)] }))] }), pct !== null ? (_jsx("div", { className: "bg-muted h-2 w-full overflow-hidden rounded-full", role: "progressbar", "aria-valuenow": pct, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuetext": `${pct}% of monthly token budget used`, children: _jsx("div", { className: `h-full rounded-full transition-all ${over ? 'bg-destructive' : 'bg-brand'}`, style: { width: `${pct}%` } }) })) : (_jsx("p", { className: "text-muted-foreground text-sm", children: "No monthly limit set. Usage is tracked but not capped." })), over && (_jsx("p", { className: "text-destructive mt-1 text-sm", role: "status", children: "Usage has exceeded the monthly limit." }))] }), _jsxs("div", { children: [_jsx("label", { htmlFor: limitId, className: LABEL_CLASS, children: "Monthly token limit" }), _jsx("input", { id: limitId, type: "text", inputMode: "numeric", value: monthlyTokenLimit, disabled: !canEdit, placeholder: "No limit", "aria-invalid": Boolean(budgetError), "aria-describedby": budgetError ? `${limitId}-error` : undefined, onChange: (e) => onChangeLimit(e.target.value), className: INPUT_CLASS }), budgetError ? (_jsx("p", { id: `${limitId}-error`, className: "text-destructive mt-1 text-sm", children: budgetError })) : (_jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: "Leave blank for no limit. Enforcement and alerts arrive with usage metering." }))] })] }) }));
|
|
29
29
|
}
|
|
30
30
|
//# sourceMappingURL=MonthlyUsageCard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MonthlyUsageCard.js","sourceRoot":"","sources":["../../../src/views/settings/MonthlyUsageCard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"MonthlyUsageCard.js","sourceRoot":"","sources":["../../../src/views/settings/MonthlyUsageCard.tsx"],"names":[],"mappings":"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"}
|
|
@@ -38,7 +38,7 @@ export function ProviderConnectionCard({ provider, canEdit, busy, onTest, onSync
|
|
|
38
38
|
await onUpdateKey(keyInput.trim() === '' ? null : keyInput.trim());
|
|
39
39
|
setKeyInput('');
|
|
40
40
|
}
|
|
41
|
-
return (_jsxs("div", { className: "border-border bg-
|
|
41
|
+
return (_jsxs("div", { className: "border-border bg-background rounded-lg border p-4", children: [_jsxs("div", { className: "mb-3 flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-foreground text-base font-medium", children: provider.displayName }), _jsx(StatusPill, { status: provider.status })] }), _jsx("p", { className: "text-muted-foreground mt-0.5 text-sm capitalize", children: provider.provider })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { type: "button", onClick: onTest, disabled: !canEdit || busy, className: "border-border text-foreground hover:bg-accent inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-60", children: [busy ? (_jsx(Loader2, { size: 14, className: "animate-spin", "aria-hidden": "true" })) : (_jsx(Plug, { size: 14, "aria-hidden": "true" })), "Test connection"] }), _jsxs("button", { type: "button", onClick: onSyncModels, disabled: !canEdit || busy, "aria-label": `Refresh models for ${provider.displayName}`, className: "border-border text-foreground hover:bg-accent inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-60", children: [_jsx(RefreshCw, { size: 14, "aria-hidden": "true" }), "Refresh models"] }), _jsx("button", { type: "button", onClick: () => setConfirmDisconnect(true), disabled: !canEdit || busy, "aria-label": `Disconnect ${provider.displayName}`, className: "text-muted-foreground hover:text-destructive inline-flex items-center rounded-md p-1.5 transition-colors disabled:cursor-not-allowed disabled:opacity-60", children: _jsx(Trash2, { size: 16, "aria-hidden": "true" }) })] })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsxs("label", { htmlFor: keyId, className: LABEL_CLASS, children: [_jsx(KeyRound, { size: 13, "aria-hidden": "true" }), "API key", envManaged && (_jsxs("span", { className: "text-muted-foreground border-border bg-muted inline-flex items-center gap-1 rounded-md border px-1.5 py-0.5 text-xs", children: [_jsx(Lock, { size: 11, "aria-hidden": "true" }), "Managed by environment"] }))] }), envManaged ? (_jsxs("p", { className: "text-muted-foreground text-sm", children: ["This key is set via an environment variable and can't be edited here.", provider.apiKeyLast4 ? ` Ends in ••••${provider.apiKeyLast4}.` : ''] })) : (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("input", { id: keyId, type: "password", autoComplete: "off", spellCheck: false, value: keyInput, disabled: !keyEditable || busy, placeholder: provider.hasKey
|
|
42
42
|
? `Key set ••••${provider.apiKeyLast4 ?? ''} — enter a new key to replace`
|
|
43
43
|
: 'Paste API key', onChange: (e) => setKeyInput(e.target.value), className: INPUT_CLASS }), _jsx("button", { type: "button", onClick: () => setConfirmKey(true), disabled: !keyEditable || busy || keyInput.trim() === '', className: "bg-brand text-brand-foreground inline-flex shrink-0 items-center rounded-md px-3 py-2 text-sm font-medium transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50", children: "Save key" })] }))] }), provider.provider === 'custom' && (_jsxs("div", { children: [_jsx("label", { htmlFor: baseUrlId, className: LABEL_CLASS, children: "Base URL" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("input", { id: baseUrlId, type: "url", value: baseUrlInput, disabled: !canEdit || busy, placeholder: "https://api.example.com/v1", onChange: (e) => setBaseUrlInput(e.target.value), className: INPUT_CLASS }), _jsx("button", { type: "button", onClick: () => onUpdateBaseUrl(baseUrlInput.trim()), disabled: !canEdit || busy || baseUrlInput.trim() === (provider.baseUrl ?? ''), className: "border-border text-foreground hover:bg-accent inline-flex shrink-0 items-center rounded-md border px-3 py-2 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-60", children: "Save" })] })] })), provider.lastTestedAt && (_jsxs("p", { className: "text-muted-foreground text-sm", children: ["Last tested ", new Date(provider.lastTestedAt).toLocaleString(), "."] }))] }), _jsx(ConfirmDangerousSettingDialog, { open: confirmKey, title: "Replace the stored API key?", description: "The new key is encrypted and replaces the existing one. Existing AI features will use it immediately.", confirmLabel: "Save key", onConfirm: applyKey, onCancel: () => setConfirmKey(false) }), _jsx(ConfirmDangerousSettingDialog, { open: confirmDisconnect, title: `Disconnect ${provider.displayName}?`, description: "This removes the stored key and model catalog for this provider. AI features that rely on it will stop working until you reconnect.", confirmLabel: "Disconnect", onConfirm: () => {
|
|
44
44
|
setConfirmDisconnect(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderConnectionCard.js","sourceRoot":"","sources":["../../../src/views/settings/ProviderConnectionCard.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ProviderConnectionCard.js","sourceRoot":"","sources":["../../../src/views/settings/ProviderConnectionCard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EACL,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,MAAM,GACP,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACvC,OAAO,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAA;AAG/D,MAAM,WAAW,GACf,wNAAwN,CAAA;AAC1N,MAAM,WAAW,GAAG,kEAAkE,CAAA;AAEtF,MAAM,WAAW,GAGb;IACF,SAAS,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;IAC7C,WAAW,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE;IACpD,YAAY,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE;IACrD,aAAa,EAAE,EAAE,KAAK,EAAE,sBAAsB,EAAE,IAAI,EAAE,MAAM,EAAE;IAC9D,WAAW,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE;IACrD,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE;CAC/C,CAAA;AAED,SAAS,UAAU,CAAC,EAAE,MAAM,EAAkC;IAC5D,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;IAChC,MAAM,SAAS,GACb,IAAI,CAAC,IAAI,KAAK,IAAI;QAChB,CAAC,CAAC,8CAA8C;QAChD,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO;YACrB,CAAC,CAAC,0DAA0D;YAC5D,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM;gBACpB,CAAC,CAAC,8CAA8C;gBAChD,CAAC,CAAC,8CAA8C,CAAA;IACxD,OAAO,CACL,gBACE,SAAS,EAAE,0FAA0F,SAAS,EAAE,aAE/G,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CACpB,KAAC,YAAY,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,CAC9C,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAC1B,KAAC,aAAa,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,CAC/C,CAAC,CAAC,CAAC,CACF,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,CACtC,EACA,IAAI,CAAC,KAAK,IACN,CACR,CAAA;AACH,CAAC;AAaD,MAAM,UAAU,sBAAsB,CAAC,EACrC,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,WAAW,EACX,eAAe,EACf,YAAY,GACgB;IAC5B,MAAM,KAAK,GAAG,KAAK,EAAE,CAAA;IACrB,MAAM,SAAS,GAAG,KAAK,EAAE,CAAA;IACzB,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAC5C,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;IACxE,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACnD,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEjE,MAAM,UAAU,GAAG,QAAQ,CAAC,oBAAoB,CAAA;IAChD,MAAM,WAAW,GAAG,OAAO,IAAI,CAAC,UAAU,CAAA;IAE1C,KAAK,UAAU,QAAQ;QACrB,aAAa,CAAC,KAAK,CAAC,CAAA;QACpB,MAAM,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;QAClE,WAAW,CAAC,EAAE,CAAC,CAAA;IACjB,CAAC;IAED,OAAO,CACL,eAAK,SAAS,EAAC,mDAAmD,aAChE,eAAK,SAAS,EAAC,6CAA6C,aAC1D,0BACE,eAAK,SAAS,EAAC,yBAAyB,aACtC,eAAM,SAAS,EAAC,uCAAuC,YAAE,QAAQ,CAAC,WAAW,GAAQ,EACrF,KAAC,UAAU,IAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAI,IACnC,EACN,YAAG,SAAS,EAAC,iDAAiD,YAAE,QAAQ,CAAC,QAAQ,GAAK,IAClF,EACN,eAAK,SAAS,EAAC,yBAAyB,aACtC,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,OAAO,IAAI,IAAI,EAC1B,SAAS,EAAC,wLAAwL,aAEjM,IAAI,CAAC,CAAC,CAAC,CACN,KAAC,OAAO,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,cAAc,iBAAa,MAAM,GAAG,CAClE,CAAC,CAAC,CAAC,CACF,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,CACtC,uBAEM,EACT,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,CAAC,OAAO,IAAI,IAAI,gBACd,sBAAsB,QAAQ,CAAC,WAAW,EAAE,EACxD,SAAS,EAAC,wLAAwL,aAElM,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,sBAEnC,EACT,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,EACzC,QAAQ,EAAE,CAAC,OAAO,IAAI,IAAI,gBACd,cAAc,QAAQ,CAAC,WAAW,EAAE,EAChD,SAAS,EAAC,0JAA0J,YAEpK,KAAC,MAAM,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,GAChC,IACL,IACF,EAEN,eAAK,SAAS,EAAC,WAAW,aAExB,0BACE,iBAAO,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,aAC3C,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,aAExC,UAAU,IAAI,CACb,gBAAM,SAAS,EAAC,qHAAqH,aACnI,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,8BAEhC,CACR,IACK,EACP,UAAU,CAAC,CAAC,CAAC,CACZ,aAAG,SAAS,EAAC,+BAA+B,sFAEzC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,gBAAgB,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,IAClE,CACL,CAAC,CAAC,CAAC,CACF,eAAK,SAAS,EAAC,yBAAyB,aACtC,gBACE,EAAE,EAAE,KAAK,EACT,IAAI,EAAC,UAAU,EACf,YAAY,EAAC,KAAK,EAClB,UAAU,EAAE,KAAK,EACjB,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,CAAC,WAAW,IAAI,IAAI,EAC9B,WAAW,EACT,QAAQ,CAAC,MAAM;4CACb,CAAC,CAAC,eAAe,QAAQ,CAAC,WAAW,IAAI,EAAE,+BAA+B;4CAC1E,CAAC,CAAC,eAAe,EAErB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC5C,SAAS,EAAE,WAAW,GACtB,EACF,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAClC,QAAQ,EAAE,CAAC,WAAW,IAAI,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EACxD,SAAS,EAAC,+LAA+L,yBAGlM,IACL,CACP,IACG,EAGL,QAAQ,CAAC,QAAQ,KAAK,QAAQ,IAAI,CACjC,0BACE,gBAAO,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,yBAEzC,EACR,eAAK,SAAS,EAAC,yBAAyB,aACtC,gBACE,EAAE,EAAE,SAAS,EACb,IAAI,EAAC,KAAK,EACV,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,CAAC,OAAO,IAAI,IAAI,EAC1B,WAAW,EAAC,4BAA4B,EACxC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAChD,SAAS,EAAE,WAAW,GACtB,EACF,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,EACnD,QAAQ,EAAE,CAAC,OAAO,IAAI,IAAI,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,EAC9E,SAAS,EAAC,uLAAuL,qBAG1L,IACL,IACF,CACP,EAEA,QAAQ,CAAC,YAAY,IAAI,CACxB,aAAG,SAAS,EAAC,+BAA+B,6BAC7B,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,cAAc,EAAE,SAC3D,CACL,IACG,EAEN,KAAC,6BAA6B,IAC5B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAC,6BAA6B,EACnC,WAAW,EAAC,uGAAuG,EACnH,YAAY,EAAC,UAAU,EACvB,SAAS,EAAE,QAAQ,EACnB,QAAQ,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,GACpC,EACF,KAAC,6BAA6B,IAC5B,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,cAAc,QAAQ,CAAC,WAAW,GAAG,EAC5C,WAAW,EAAC,qIAAqI,EACjJ,YAAY,EAAC,YAAY,EACzB,SAAS,EAAE,GAAG,EAAE;oBACd,oBAAoB,CAAC,KAAK,CAAC,CAAA;oBAC3B,YAAY,EAAE,CAAA;gBAChB,CAAC,EACD,QAAQ,EAAE,GAAG,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,GAC3C,IACE,CACP,CAAA;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecurityStatusCard.d.ts","sourceRoot":"","sources":["../../../src/views/settings/SecurityStatusCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SecurityStatusCard.d.ts","sourceRoot":"","sources":["../../../src/views/settings/SecurityStatusCard.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,yCAAyC,CAAA;AAgC9F,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,UAAU,GACX,EAAE;IACD,MAAM,EAAE,cAAc,CAAA;IACtB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC,2CAiEA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useId } from 'react';
|
|
4
3
|
import { Shield, ShieldAlert, ShieldCheck, ShieldX } from 'lucide-react';
|
|
4
|
+
import { SettingsCard } from './components.js';
|
|
5
5
|
import { CheckIcon } from './securityPrimitives.js';
|
|
6
6
|
const LEVEL_STYLES = {
|
|
7
7
|
secure: {
|
|
@@ -27,9 +27,8 @@ const SEVERITY_STYLES = {
|
|
|
27
27
|
info: 'border-border bg-muted text-muted-foreground',
|
|
28
28
|
};
|
|
29
29
|
export function SecurityStatusCard({ status, onNavigate, }) {
|
|
30
|
-
const headingId = useId();
|
|
31
30
|
const style = LEVEL_STYLES[status.status];
|
|
32
31
|
const { Icon } = style;
|
|
33
|
-
return (_jsxs(
|
|
32
|
+
return (_jsxs(SettingsCard, { title: "Security Status", description: status.description, actions: _jsxs("span", { className: `inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-sm font-medium ${style.pill}`, children: [_jsx(Icon, { size: 15, "aria-hidden": "true" }), style.word] }), children: [_jsx("div", { className: "grid grid-cols-1 gap-x-6 gap-y-1 sm:grid-cols-2", children: status.checks.map((check) => (_jsxs("button", { type: "button", disabled: !check.actionHref || !onNavigate, onClick: () => check.actionHref && onNavigate?.(check.actionHref), className: "enabled:hover:bg-accent/50 flex items-center justify-between gap-3 rounded-md py-1.5 text-left text-sm disabled:cursor-default", children: [_jsxs("span", { className: "flex items-center gap-2", children: [_jsx(CheckIcon, { status: check.status }), _jsx("span", { className: "text-foreground", children: check.label })] }), check.value !== undefined && (_jsx("span", { className: "text-muted-foreground text-right", children: check.value }))] }, check.key))) }), status.warnings.length > 0 && (_jsx("div", { className: "mt-4 space-y-2", "aria-live": "polite", children: status.warnings.map((w) => (_jsxs("div", { role: "note", className: `flex items-start justify-between gap-3 rounded-lg border p-3 text-sm ${SEVERITY_STYLES[w.severity]}`, children: [_jsxs("div", { children: [_jsx("p", { className: "font-medium", children: w.title }), _jsx("p", { className: "mt-0.5 opacity-90", children: w.description })] }), w.actionHref && w.actionLabel && onNavigate && (_jsx("button", { type: "button", onClick: () => onNavigate(w.actionHref), className: "shrink-0 self-center rounded-md border border-current/30 px-2.5 py-1 text-xs font-medium hover:opacity-80", children: w.actionLabel }))] }, w.id))) }))] }));
|
|
34
33
|
}
|
|
35
34
|
//# sourceMappingURL=SecurityStatusCard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecurityStatusCard.js","sourceRoot":"","sources":["../../../src/views/settings/SecurityStatusCard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"SecurityStatusCard.js","sourceRoot":"","sources":["../../../src/views/settings/SecurityStatusCard.tsx"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ import { SecurityStatusCard } from './SecurityStatusCard.js';
|
|
|
10
10
|
import { SessionPolicyCard } from './SessionPolicyCard.js';
|
|
11
11
|
import { useSecuritySettings } from './useSecuritySettings.js';
|
|
12
12
|
function CardSkeleton() {
|
|
13
|
-
return (_jsxs("div", { className: "border-border bg-card animate-pulse rounded-lg border p-
|
|
13
|
+
return (_jsxs("div", { className: "border-border bg-card animate-pulse rounded-lg border p-6", children: [_jsx("div", { className: "bg-muted mb-3 h-4 w-40 rounded" }), _jsx("div", { className: "bg-muted mb-4 h-3 w-72 rounded" }), _jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "bg-muted h-3 w-full rounded" }), _jsx("div", { className: "bg-muted h-3 w-2/3 rounded" })] })] }));
|
|
14
14
|
}
|
|
15
15
|
export function SecurityTab({ role, onNavigate, }) {
|
|
16
16
|
const canEdit = role === 'ADMIN';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SeoRobotsDefaultsCard.d.ts","sourceRoot":"","sources":["../../../src/views/settings/SeoRobotsDefaultsCard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAEnF,UAAU,0BAA0B;IAClC,IAAI,EAAE,mBAAmB,CAAA;IACzB,QAAQ,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IAC9F,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,eAAe,GAAG,IAAI,CAAA;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC;AAUD,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,OAAO,EACP,UAAU,GACX,EAAE,0BAA0B,
|
|
1
|
+
{"version":3,"file":"SeoRobotsDefaultsCard.d.ts","sourceRoot":"","sources":["../../../src/views/settings/SeoRobotsDefaultsCard.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAEnF,UAAU,0BAA0B;IAClC,IAAI,EAAE,mBAAmB,CAAA;IACzB,QAAQ,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IAC9F,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,eAAe,GAAG,IAAI,CAAA;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC;AAUD,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,OAAO,EACP,UAAU,GACX,EAAE,0BAA0B,2CAoG5B"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
import { ConfirmDangerousSettingDialog, SettingsToggleRow } from './components.js';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { ConfirmDangerousSettingDialog, SettingsCard, SettingsToggleRow } from './components.js';
|
|
5
5
|
export function SeoRobotsDefaultsCard({ form, setField, isProduction, indexStatus, canEdit, onNavigate, }) {
|
|
6
|
-
const headingId = useId();
|
|
7
6
|
const [pending, setPending] = useState(null);
|
|
8
7
|
// Some toggles can take the whole production site out of search results, so
|
|
9
8
|
// they route through a confirmation step before being applied.
|
|
@@ -33,7 +32,7 @@ export function SeoRobotsDefaultsCard({ form, setField, isProduction, indexStatu
|
|
|
33
32
|
const effectiveProd = form.defaultNoIndex ? 'Blocked' : 'Indexable';
|
|
34
33
|
const sitemapCheck = indexStatus?.checks.find((c) => c.key === 'sitemap');
|
|
35
34
|
const sitemapStatus = sitemapCheck ? (sitemapCheck.value === 'Yes' ? 'Enabled' : 'Disabled') : '—';
|
|
36
|
-
return (_jsxs(
|
|
35
|
+
return (_jsxs(SettingsCard, { title: "SEO & Robots Defaults", description: "Set the site-wide default for search engine indexing. Individual pages can inherit or override these rules in their SEO panel. These share the same configuration as the SEO section.", children: [_jsxs("div", { className: "space-y-4", children: [_jsx(SettingsToggleRow, { label: "Default No Index", description: "Ask search engines not to index pages unless a page explicitly allows indexing.", checked: form.defaultNoIndex, disabled: !canEdit, onChange: (v) => requestToggle('defaultNoIndex', v) }), _jsx(SettingsToggleRow, { label: "Default No Follow", description: "Ask search engines not to follow page links unless a page explicitly allows following.", checked: form.defaultNoFollow, disabled: !canEdit, onChange: (v) => requestToggle('defaultNoFollow', v) }), _jsx(SettingsToggleRow, { label: "Noindex Non-Production Environments", description: "Force noindex when the deployed environment is not production.", checked: form.noIndexNonProduction, disabled: !canEdit, onChange: (v) => requestToggle('noIndexNonProduction', v) })] }), _jsxs("div", { className: "border-border mt-4 space-y-2 border-t pt-4", children: [_jsx(SummaryRow, { label: "Effective production indexing", value: effectiveProd, danger: form.defaultNoIndex }), _jsx(SummaryRow, { label: "Effective current environment", value: indexStatus?.label ?? '—', danger: indexStatus?.severity === 'danger' }), _jsx(SummaryRow, { label: "Sitemap status", value: sitemapStatus }), onNavigate && (_jsx("button", { type: "button", onClick: () => onNavigate('/seo?tab=technical'), className: "text-brand mt-1 text-sm hover:underline", children: "Manage advanced robots.txt & sitemap in SEO \u2192" }))] }), _jsx(ConfirmDangerousSettingDialog, { open: pending !== null, title: pending?.title ?? '', description: pending?.description ?? '', confirmLabel: pending?.confirmLabel, onConfirm: () => {
|
|
37
36
|
if (pending)
|
|
38
37
|
setField(pending.field, pending.value);
|
|
39
38
|
setPending(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SeoRobotsDefaultsCard.js","sourceRoot":"","sources":["../../../src/views/settings/SeoRobotsDefaultsCard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"SeoRobotsDefaultsCard.js","sourceRoot":"","sources":["../../../src/views/settings/SeoRobotsDefaultsCard.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SeoSettingsTab.d.ts","sourceRoot":"","sources":["../../../src/views/settings/SeoSettingsTab.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SeoSettingsTab.d.ts","sourceRoot":"","sources":["../../../src/views/settings/SeoSettingsTab.tsx"],"names":[],"mappings":"AAsEA,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wBAAgB,cAAc,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,mBAAmB,2CAmGvE"}
|
|
@@ -4,7 +4,7 @@ import { useId, useState } from 'react';
|
|
|
4
4
|
import { AlertTriangle, CheckCircle2, ExternalLink, ImageIcon, Info, Loader2, RefreshCw, Search, Upload, X, } from 'lucide-react';
|
|
5
5
|
import { MediaPickerModal } from '../../components/MediaPickerModal.js';
|
|
6
6
|
import { SEOConfigPanel } from '../../components/SEOConfigPanel.js';
|
|
7
|
-
import { ConfirmDangerousSettingDialog, SettingsSaveBar, SettingsSourceBadge, SettingsToggleRow, SettingsValidationSummary, } from './components.js';
|
|
7
|
+
import { ConfirmDangerousSettingDialog, SettingsCard, SettingsSaveBar, SettingsSourceBadge, SettingsToggleRow, SettingsValidationSummary, } from './components.js';
|
|
8
8
|
import { META_DESCRIPTION_MAX, META_DESCRIPTION_MIN, useSeoSettings, validateTitleTemplateClient, } from './useSeoSettings.js';
|
|
9
9
|
const INPUT_CLASS = 'w-full rounded-md border border-border bg-input-background px-3 py-2 text-base text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-60';
|
|
10
10
|
const LABEL_CLASS = 'mb-1 flex items-center gap-2 text-sm font-medium text-foreground';
|
|
@@ -42,7 +42,7 @@ export function SeoSettingsTab({ onNavigate, role }) {
|
|
|
42
42
|
const canEdit = role === 'ADMIN';
|
|
43
43
|
const seo = useSeoSettings(canEdit);
|
|
44
44
|
if (seo.loading) {
|
|
45
|
-
return (_jsxs("div", { className: "space-y-4", "aria-busy": "true", "aria-live": "polite", children: [_jsx("span", { className: "sr-only", children: "Loading SEO settings\u2026" }), [0, 1, 2, 3].map((i) => (_jsxs("div", { className: "border-border bg-card rounded-lg border p-
|
|
45
|
+
return (_jsxs("div", { className: "space-y-4", "aria-busy": "true", "aria-live": "polite", children: [_jsx("span", { className: "sr-only", children: "Loading SEO settings\u2026" }), [0, 1, 2, 3].map((i) => (_jsxs("div", { className: "border-border bg-card rounded-lg border p-6", children: [_jsx("div", { className: "bg-muted mb-4 h-4 w-40 animate-pulse rounded" }), _jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "bg-muted h-9 w-full animate-pulse rounded" }), _jsx("div", { className: "bg-muted h-9 w-full animate-pulse rounded" })] })] }, i)))] }));
|
|
46
46
|
}
|
|
47
47
|
return (_jsxs("div", { className: "space-y-4", children: [_jsx(SeoWorkspaceCallout, { onNavigate: onNavigate }), seo.loadError && (_jsxs("div", { role: "alert", className: "border-destructive/30 bg-destructive/10 text-destructive flex items-center gap-3 rounded-lg border p-3 text-sm", children: [_jsx(AlertTriangle, { size: 16, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { className: "flex-1", children: seo.loadError }), _jsx("button", { type: "button", onClick: seo.refetch, className: "border-destructive/40 rounded-md border px-3 py-1 transition-colors hover:opacity-80", children: "Retry" })] })), !canEdit && (_jsxs("div", { className: "border-border bg-muted text-muted-foreground flex items-center gap-2 rounded-lg border p-3 text-sm", children: [_jsx(Info, { size: 16, className: "shrink-0", "aria-hidden": "true" }), "You have read-only access to SEO defaults. Only administrators can make changes."] })), _jsx(SettingsValidationSummary, { issues: seo.issues }), _jsx(MetaDefaultsCard, { seo: seo, canEdit: canEdit }), _jsx(SearchEngineVerificationCard, { seo: seo, canEdit: canEdit }), _jsx(SitemapDefaultsCard, { seo: seo, canEdit: canEdit, onNavigate: onNavigate }), _jsxs("details", { className: "border-border bg-card group rounded-lg border", children: [_jsxs("summary", { className: "text-foreground flex cursor-pointer list-none items-center justify-between p-4 text-base font-medium", children: [_jsx("span", { children: "Advanced & per-collection SEO" }), _jsx("span", { className: "text-muted-foreground text-sm font-normal group-open:hidden", children: "Show" }), _jsx("span", { className: "text-muted-foreground hidden text-sm font-normal group-open:inline", children: "Hide" })] }), _jsxs("div", { className: "border-border border-t p-4", children: [_jsx("p", { className: "text-muted-foreground mb-4 text-sm", children: "Site name, social handle, per-collection schema, and route toggles. These share the same SEO configuration as the defaults above." }), _jsx(SEOConfigPanel, {})] })] }), seo.saveState === 'error' && seo.saveError && (_jsxs("div", { role: "alert", className: "border-destructive/30 bg-destructive/10 text-destructive flex items-center gap-3 rounded-lg border p-3 text-sm", children: [_jsx(AlertTriangle, { size: 16, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { className: "flex-1", children: seo.saveError }), _jsx("button", { type: "button", onClick: seo.save, className: "border-destructive/40 rounded-md border px-3 py-1 transition-colors hover:opacity-80", children: "Retry" })] })), _jsx(SettingsSaveBar, { dirty: seo.dirty, canEdit: canEdit, hasErrors: seo.hasErrors, saveState: seo.saveState, onSave: seo.save, onReset: seo.reset })] }));
|
|
48
48
|
}
|
|
@@ -56,7 +56,6 @@ function SeoWorkspaceCallout({ onNavigate }) {
|
|
|
56
56
|
// Meta Defaults
|
|
57
57
|
// ---------------------------------------------------------------------------
|
|
58
58
|
function MetaDefaultsCard({ seo, canEdit }) {
|
|
59
|
-
const headingId = useId();
|
|
60
59
|
const templateId = useId();
|
|
61
60
|
const descId = useId();
|
|
62
61
|
const [pickerOpen, setPickerOpen] = useState(false);
|
|
@@ -71,7 +70,7 @@ function MetaDefaultsCard({ seo, canEdit }) {
|
|
|
71
70
|
const templateEditable = sources.titleTemplate?.editable !== false && canEdit;
|
|
72
71
|
const descEditable = sources.defaultMetaDescription?.editable !== false && canEdit;
|
|
73
72
|
const imageEditable = sources.defaultOgImage?.editable !== false && canEdit;
|
|
74
|
-
return (_jsxs(
|
|
73
|
+
return (_jsxs(SettingsCard, { title: "Meta Defaults", description: "Fallback page title, description, and social image applied when a page defines none of its own.", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsxs("label", { htmlFor: templateId, className: LABEL_CLASS, children: ["Title template", _jsx(SettingsSourceBadge, { meta: sources.titleTemplate })] }), _jsx("input", { id: templateId, type: "text", value: form.titleTemplate, disabled: !templateEditable, placeholder: "%page% \u2014 %site%", "aria-invalid": templateIssue?.severity === 'error', onChange: (e) => setField('titleTemplate', e.target.value), className: INPUT_CLASS }), _jsxs("p", { className: "text-muted-foreground mt-1 text-sm", children: ["Tokens: ", SUPPORTED_TOKENS.join(' '), ". Applied to all pages without a custom SEO title."] }), templateIssue ? (_jsx("p", { className: "text-destructive mt-1 text-sm", children: templateIssue.message })) : (tplValidation.valid && (_jsxs("p", { className: "text-muted-foreground mt-1 text-sm", children: ["Preview:", ' ', _jsx("span", { className: "text-foreground font-medium", children: previewTitle(form.titleTemplate, seo.siteName) })] })))] }), _jsxs("div", { children: [_jsxs("label", { htmlFor: descId, className: LABEL_CLASS, children: ["Default meta description", _jsx(SettingsSourceBadge, { meta: sources.defaultMetaDescription })] }), _jsx("textarea", { id: descId, rows: 3, value: form.defaultMetaDescription, disabled: !descEditable, "aria-describedby": `${descId}-count`, onChange: (e) => setField('defaultMetaDescription', e.target.value), className: `${INPUT_CLASS} resize-y` }), _jsxs("div", { className: "mt-1 flex items-center justify-between gap-2", children: [_jsx("p", { className: "text-muted-foreground text-sm", children: "Used when a page or post defines no description of its own." }), _jsxs("span", { id: `${descId}-count`, className: `text-sm ${descCountClass}`, children: [descLen, "/", META_DESCRIPTION_MAX] })] }), descIssue && _jsx("p", { className: "text-warning mt-1 text-sm", children: descIssue.message })] }), _jsxs("div", { children: [_jsxs("span", { className: LABEL_CLASS, children: ["Default social share image", _jsx(SettingsSourceBadge, { meta: sources.defaultOgImage })] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "border-border bg-muted flex h-16 w-28 shrink-0 items-center justify-center overflow-hidden rounded-md border", children: form.defaultOgImage ? (
|
|
75
74
|
// eslint-disable-next-line @next/next/no-img-element
|
|
76
75
|
_jsx("img", { src: form.defaultOgImage, alt: "Default social share preview", className: "h-full w-full object-cover" })) : (_jsx(ImageIcon, { size: 20, className: "text-muted-foreground", "aria-hidden": "true" })) }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { type: "button", onClick: () => setPickerOpen(true), disabled: !imageEditable, className: "border-border text-foreground hover:bg-accent inline-flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-60", children: [_jsx(Upload, { size: 14, "aria-hidden": "true" }), form.defaultOgImage ? 'Replace' : 'Choose image'] }), form.defaultOgImage && imageEditable && (_jsxs("button", { type: "button", onClick: () => {
|
|
77
76
|
setField('defaultOgImage', '');
|
|
@@ -92,16 +91,14 @@ function VerificationField({ label, field, placeholder, value, onChange, disable
|
|
|
92
91
|
return (_jsxs("div", { children: [_jsxs("label", { htmlFor: id, className: LABEL_CLASS, children: [label, hasValue && (_jsxs("span", { className: "text-muted-foreground border-border bg-muted inline-flex items-center gap-1 rounded-md border px-1.5 py-0.5 text-xs", children: [_jsx(CheckCircle2, { size: 11, className: "text-success", "aria-hidden": "true" }), "Saved"] }))] }), _jsx("input", { id: id, type: "text", autoComplete: "off", spellCheck: false, value: value, disabled: disabled, placeholder: placeholder, onChange: (e) => onChange(field, e.target.value), className: INPUT_CLASS })] }));
|
|
93
92
|
}
|
|
94
93
|
function SearchEngineVerificationCard({ seo, canEdit }) {
|
|
95
|
-
const headingId = useId();
|
|
96
94
|
const { form, setField } = seo;
|
|
97
95
|
const onChange = (key, value) => setField(key, value);
|
|
98
|
-
return (_jsxs(
|
|
96
|
+
return (_jsxs(SettingsCard, { title: "Search Engine Verification", description: "Paste the verification token from each provider. We render only safe meta tags into your site's head \u2014 never arbitrary HTML.", children: [_jsxs("div", { className: "space-y-4", children: [_jsx(VerificationField, { label: "Google Search Console", field: "googleVerification", placeholder: "google-site-verification\u2026", value: form.googleVerification, onChange: onChange, disabled: !canEdit }), _jsx(VerificationField, { label: "Bing Webmaster Tools", field: "bingVerification", placeholder: "msvalidate.01\u2026", value: form.bingVerification, onChange: onChange, disabled: !canEdit })] }), _jsxs("details", { className: "group mt-4", children: [_jsxs("summary", { className: "text-brand cursor-pointer list-none text-sm hover:underline", children: [_jsx("span", { className: "group-open:hidden", children: "More providers" }), _jsx("span", { className: "hidden group-open:inline", children: "Fewer providers" })] }), _jsxs("div", { className: "mt-4 space-y-4", children: [_jsx(VerificationField, { label: "Yandex", field: "yandexVerification", placeholder: "yandex-verification\u2026", value: form.yandexVerification, onChange: onChange, disabled: !canEdit }), _jsx(VerificationField, { label: "Pinterest", field: "pinterestVerification", placeholder: "p:domain_verify\u2026", value: form.pinterestVerification, onChange: onChange, disabled: !canEdit }), _jsx(VerificationField, { label: "Facebook domain verification", field: "facebookDomainVerification", placeholder: "facebook-domain-verification\u2026", value: form.facebookDomainVerification, onChange: onChange, disabled: !canEdit })] })] })] }));
|
|
99
97
|
}
|
|
100
98
|
// ---------------------------------------------------------------------------
|
|
101
99
|
// Sitemap Defaults
|
|
102
100
|
// ---------------------------------------------------------------------------
|
|
103
101
|
function SitemapDefaultsCard({ seo, canEdit, onNavigate, }) {
|
|
104
|
-
const headingId = useId();
|
|
105
102
|
const [pendingDisable, setPendingDisable] = useState(false);
|
|
106
103
|
const { form, setField, sitemap, siteUrl, isProduction, regenerateSitemap, regenerating } = seo;
|
|
107
104
|
function requestAutoGenerate(value) {
|
|
@@ -115,7 +112,7 @@ function SitemapDefaultsCard({ seo, canEdit, onNavigate, }) {
|
|
|
115
112
|
const lastGenerated = sitemap?.lastGeneratedAt
|
|
116
113
|
? new Date(sitemap.lastGeneratedAt).toLocaleString()
|
|
117
114
|
: 'Never';
|
|
118
|
-
return (_jsxs(
|
|
115
|
+
return (_jsxs(SettingsCard, { title: "Sitemap", description: "Control XML sitemap generation and whether search engines are pinged on publish.", children: [!siteUrl && (_jsxs("div", { className: "border-warning/30 bg-warning/10 text-warning mb-4 flex items-start gap-2 rounded-md border p-3 text-sm", children: [_jsx(AlertTriangle, { size: 16, className: "mt-0.5 shrink-0", "aria-hidden": "true" }), "Site URL is not set \u2014 sitemap URLs may be incorrect. Set it in Settings \u2192 General."] })), _jsxs("div", { className: "space-y-4", children: [_jsx(SettingsToggleRow, { label: "Auto-generate XML sitemap", description: "Rebuild the sitemap whenever content is published.", checked: form.autoGenerateSitemap, disabled: !canEdit, onChange: requestAutoGenerate }), _jsx(SettingsToggleRow, { label: "Ping search engines on publish", description: "Notify Google and Bing when the sitemap changes.", checked: form.pingOnPublish, disabled: !canEdit || !form.autoGenerateSitemap, onChange: (v) => setField('pingOnPublish', v) })] }), _jsxs("div", { className: "border-border mt-4 space-y-2 border-t pt-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Sitemap URL" }), sitemap?.sitemapUrl ? (_jsxs("a", { href: sitemap.sitemapUrl, target: "_blank", rel: "noreferrer", className: "text-brand inline-flex items-center gap-1 font-medium hover:underline", children: ["View sitemap", _jsx(ExternalLink, { size: 13, "aria-hidden": "true" })] })) : (_jsx("span", { className: "text-foreground font-medium", children: "/sitemap.xml" }))] }), _jsx(SummaryRow, { label: "Last generated", value: lastGenerated }), _jsx(SummaryRow, { label: "Included URLs", value: String(sitemap?.pagesIncluded ?? '—') }), _jsx(SummaryRow, { label: "Excluded URLs", value: String(sitemap?.pagesExcluded ?? '—') }), _jsxs("div", { className: "flex items-center justify-between gap-2 pt-1", children: [_jsxs("button", { type: "button", onClick: regenerateSitemap, disabled: !canEdit || regenerating, className: "border-border text-foreground hover:bg-accent inline-flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-60", children: [regenerating ? (_jsx(Loader2, { size: 14, className: "animate-spin", "aria-hidden": "true" })) : (_jsx(RefreshCw, { size: 14, "aria-hidden": "true" })), "Regenerate now"] }), onNavigate && (_jsx("button", { type: "button", onClick: () => onNavigate('/seo?tab=technical'), className: "text-brand text-sm hover:underline", children: "Manage in SEO Technical \u2192" }))] })] }), _jsx(ConfirmDangerousSettingDialog, { open: pendingDisable, title: "Stop auto-generating the sitemap on production?", description: "Your sitemap may go stale as content changes, which can hurt how quickly search engines discover new pages.", confirmLabel: "Turn Off", onConfirm: () => {
|
|
119
116
|
setField('autoGenerateSitemap', false);
|
|
120
117
|
setPendingDisable(false);
|
|
121
118
|
}, onCancel: () => setPendingDisable(false) })] }));
|