feat: let every EE instance set the announcement banner (#11238)

* feat: let every EE instance set the announcement banner, not only cloud

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat: move the announcement banner setting to the bottom of the general tab

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-09-18 21:03:00 +02:00
committed by GitHub
co-authored by Claude Opus 5
parent f00b2fcb1e
commit 87761d1797
4 changed files with 23 additions and 23 deletions
@@ -10,10 +10,10 @@
} from './instanceBanner'
import { instanceSettingsSaved } from './instanceSettings'
// Mounted only on the managed cloud (see the render site in the logged layout), so the
// poll costs nothing anywhere else. An announcement is only worth broadcasting while it
// is current, hence polling rather than waiting for the next full page load: a session
// left open all day is exactly the one that needs to hear about the maintenance window.
// Mounted only on EE (see the render site in the logged layout), so the poll costs
// nothing on CE. An announcement is only worth broadcasting while it is current, hence
// polling rather than waiting for the next full page load: a session left open all day
// is exactly the one that needs to hear about the maintenance window.
const POLL_MS = 60_000
let banner = $state<ResolvedInstanceBanner | undefined>(undefined)
@@ -871,7 +871,7 @@
{:else if setting.fieldType == 'ws_connectivity'}
<WsConnectivityTest {values} />
{:else if setting.fieldType == 'instance_banner'}
<InstanceBannerSetting {values} disabled={loading} />
<InstanceBannerSetting {values} disabled={loading || !$enterpriseLicense} />
{/if}
{#if hasError}
<span class="text-red-600 dark:text-red-400 text-xs">
+13 -13
View File
@@ -240,19 +240,6 @@ export const settings: Record<string, Setting[]> = {
placeholder: 'only for EE',
storage: 'setting'
},
{
label: 'Announcement banner',
description:
'Message shown above every page of the instance, for maintenance windows and incidents.',
key: 'instance_banner',
fieldType: 'instance_banner',
storage: 'setting',
// The banner only renders on the managed cloud, so only offer it there.
cloudonly: true,
hideInQuickSetup: true,
// Gates Save. The card renders the specific message itself, so no `error` here.
isValid: (value: any) => instanceBannerFormError(value) == undefined
},
{
label: 'Non-prod instance',
description:
@@ -334,6 +321,19 @@ export const settings: Record<string, Setting[]> = {
fieldType: 'boolean',
storage: 'setting',
hideInQuickSetup: true
},
{
label: 'Announcement banner',
description:
'Message shown above every page of the instance, for maintenance windows and incidents.',
key: 'instance_banner',
fieldType: 'instance_banner',
storage: 'setting',
// The banner only renders on EE, so the card is disabled without a license.
ee_only: '',
hideInQuickSetup: true,
// Gates Save. The card renders the specific message itself, so no `error` here.
isValid: (value: any) => instanceBannerFormError(value) == undefined
}
],
Jobs: [
@@ -1414,11 +1414,11 @@
</div>
{/if}
<div class="flex flex-col h-full w-full">
{#if isCloudHosted() && !menuHidden}
<!-- Announcements are a managed-cloud operations tool, so the component never
mounts elsewhere: no fetch, no poll, no listener on a self-hosted instance.
Also skipped when the menu is hidden — that is an embed or an OAuth
callback, where the announcement would land inside someone else's page. -->
{#if $enterpriseLicense && !menuHidden}
<!-- Announcements are an EE feature, so the component never mounts on CE: no
fetch, no poll, no listener there. Also skipped when the menu is hidden —
that is an embed or an OAuth callback, where the announcement would land
inside someone else's page. -->
<InstanceBanner />
{/if}
{#if $userStore?.is_service_account}