diff --git a/frontend/src/features/settings/tabs/AnalyticsTab.tsx b/frontend/src/features/settings/tabs/AnalyticsTab.tsx index e266bba4..6b178977 100644 --- a/frontend/src/features/settings/tabs/AnalyticsTab.tsx +++ b/frontend/src/features/settings/tabs/AnalyticsTab.tsx @@ -15,6 +15,35 @@ interface AnalyticsTabProps { const PROVIDER_OPTIONS: TrackerProvider[] = ['none', 'umami', 'rybbit', 'custom']; +/** + * The shipped CSP `script-src` is a static allowlist that no configured + * tracker domain is ever added to, so a self-hosted Umami/Rybbit instance is + * blocked by the browser with nothing but a console error to show for it. + * Shown for every provider that loads a script from another origin. + */ +const CspWarning: React.FC = () => { + const { t } = useTranslation(); + + return ( +
+
+ +
+

+ {t('settings.analytics.customCspWarning', 'Content-Security-Policy reminder')} +

+

+ {t( + 'settings.analytics.customCspWarningText', + 'PicPeak ships with a strict CSP (`script-src \'self\'`). If your tracker loads from another domain, add that domain to your reverse-proxy or nginx CSP config — otherwise the browser silently blocks the script.', + )} +

+
+
+
+ ); +}; + export const AnalyticsTab: React.FC = ({ analyticsSettings, setAnalyticsSettings, @@ -128,6 +157,8 @@ export const AnalyticsTab: React.FC = ({ )}

+ + )} @@ -191,6 +222,8 @@ export const AnalyticsTab: React.FC = ({ )}

+ + )} @@ -222,22 +255,7 @@ export const AnalyticsTab: React.FC = ({

-
-
- -
-

- {t('settings.analytics.customCspWarning', 'Content-Security-Policy reminder')} -

-

- {t( - 'settings.analytics.customCspWarningText', - 'PicPeak ships with a strict CSP (`script-src \'self\'`). If your tracker loads from another domain, add that domain to your reverse-proxy or nginx CSP config — otherwise the browser silently blocks the script.', - )} -

-
-
-
+ )}