From e90490ada46ba0a5e13ca3b7fc4b6dc471b40e2f Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 14 Nov 2025 08:58:32 -0600 Subject: [PATCH 1/6] Add new ENVIRONMENT_NAME env var to set for unique color of left nav --- server/config/docker.yaml | 3 +- server/server/api/handler.go | 8 +++ server/server/config/config.go | 5 ++ src/lib/components/side-nav.svelte | 19 ++++-- .../navigation/navigation-container.svelte | 65 +++++++++++++++---- src/lib/services/settings-service.ts | 3 + src/lib/theme/plugin.ts | 12 ++++ src/lib/theme/variables.ts | 12 ++++ src/lib/types/index.ts | 1 + src/routes/(app)/+layout.svelte | 4 +- 10 files changed, 115 insertions(+), 17 deletions(-) diff --git a/server/config/docker.yaml b/server/config/docker.yaml index e661b8ba3f..e475638ec1 100644 --- a/server/config/docker.yaml +++ b/server/config/docker.yaml @@ -71,7 +71,8 @@ codec: includeCredentials: {{ env "TEMPORAL_CODEC_INCLUDE_CREDENTIALS" | default "false" }} defaultErrorMessage: {{ env "TEMPORAL_CODEC_DEFAULT_ERROR_MESSAGE" | default "" }} defaultErrorLink: {{ env "TEMPORAL_CODEC_DEFAULT_ERROR_LINK" | default "" }} - +environment: + name: {{ env "TEMPORAL_ENVIRONMENT_NAME" | default "" }} forwardHeaders: {{- if env "TEMPORAL_FORWARD_HEADERS" }} {{- range env "TEMPORAL_FORWARD_HEADERS" | split "," }} diff --git a/server/server/api/handler.go b/server/server/api/handler.go index 1dc7ac039d..5adf83fccf 100644 --- a/server/server/api/handler.go +++ b/server/server/api/handler.go @@ -57,6 +57,10 @@ type CodecResponse struct { DefaultErrorLink string } +type Environment struct { + Name string +} + type SettingsResponse struct { Auth *Auth BannerText string @@ -65,6 +69,7 @@ type SettingsResponse struct { FeedbackURL string NotifyOnNewVersion bool Codec *CodecResponse + Environment *Environment Version string DisableWriteActions bool WorkflowTerminateDisabled bool @@ -143,6 +148,9 @@ func GetSettings(cfgProvider *config.ConfigProviderWithRefresh) func(echo.Contex DefaultErrorMessage: cfg.Codec.DefaultErrorMessage, DefaultErrorLink: cfg.Codec.DefaultErrorLink, }, + Environment: &Environment{ + Name: cfg.Environment.Name, + }, Version: version.UIVersion, DisableWriteActions: cfg.DisableWriteActions, WorkflowTerminateDisabled: cfg.WorkflowTerminateDisabled, diff --git a/server/server/config/config.go b/server/server/config/config.go index d0cc562b0f..67c18e88ce 100644 --- a/server/server/config/config.go +++ b/server/server/config/config.go @@ -51,6 +51,7 @@ type ( // How often to reload the config RefreshInterval time.Duration `yaml:"refreshInterval"` Codec Codec `yaml:"codec"` + Environment Environment `yaml:"environment"` DisableWriteActions bool `yaml:"disableWriteActions"` // Discrete configuration for Workflow Actions in the UI WorkflowTerminateDisabled bool `yaml:"workflowTerminateDisabled"` @@ -136,6 +137,10 @@ type ( DefaultErrorLink string `yaml:"defaultErrorLink"` } + Environment struct { + Name string `yaml:"name"` + } + Filesystem struct { Path string `yaml:"path"` } diff --git a/src/lib/components/side-nav.svelte b/src/lib/components/side-nav.svelte index 9adf662c78..68be4b549f 100644 --- a/src/lib/components/side-nav.svelte +++ b/src/lib/components/side-nav.svelte @@ -1,14 +1,25 @@ - + {#each linkList as item} {#if !item?.hidden} {#if item.divider} @@ -26,6 +37,6 @@ {/if} {/each} - + {@render bottom?.()} diff --git a/src/lib/holocene/navigation/navigation-container.svelte b/src/lib/holocene/navigation/navigation-container.svelte index c0f1f62d00..06fac8e3ce 100644 --- a/src/lib/holocene/navigation/navigation-container.svelte +++ b/src/lib/holocene/navigation/navigation-container.svelte @@ -1,18 +1,36 @@ + + diff --git a/src/lib/services/settings-service.ts b/src/lib/services/settings-service.ts index 7f40e3a0c0..33e473f069 100644 --- a/src/lib/services/settings-service.ts +++ b/src/lib/services/settings-service.ts @@ -37,6 +37,9 @@ export const fetchSettings = async (request = fetch): Promise => { }, defaultNamespace: settingsResponse?.DefaultNamespace || 'default', // API returns an empty string if default namespace is not configured disableWriteActions: !!settingsResponse?.DisableWriteActions || false, + buildEnvironment: { + name: settingsResponse?.Environment?.Name || '', + }, workflowTerminateDisabled: !!settingsResponse?.WorkflowTerminateDisabled, workflowCancelDisabled: !!settingsResponse?.WorkflowCancelDisabled, workflowSignalDisabled: !!settingsResponse?.WorkflowSignalDisabled, diff --git a/src/lib/theme/plugin.ts b/src/lib/theme/plugin.ts index 9097c73524..0eee615a6d 100644 --- a/src/lib/theme/plugin.ts +++ b/src/lib/theme/plugin.ts @@ -162,6 +162,18 @@ const temporal = plugin( backgroundColor: css('--color-surface-black'), color: css('--color-text-white'), }, + '.surface-development': { + backgroundColor: css('--color-surface-development'), + color: css('--color-text-white'), + }, + '.surface-test': { + backgroundColor: css('--color-surface-test'), + color: css('--color-text-white'), + }, + '.surface-staging': { + backgroundColor: css('--color-surface-staging'), + color: css('--color-text-white'), + }, }); }, { diff --git a/src/lib/theme/variables.ts b/src/lib/theme/variables.ts index 7ef913c015..df867f5142 100644 --- a/src/lib/theme/variables.ts +++ b/src/lib/theme/variables.ts @@ -173,6 +173,18 @@ export const variables = { light: 'indigo.100', dark: 'slate.900', }, + '--color-surface-development': { + light: 'green.700', + dark: 'green.700', + }, + '--color-surface-staging': { + light: 'blue.600', + dark: 'blue.600', + }, + '--color-surface-test': { + light: 'yellow.700', + dark: 'yellow.700', + }, // Border '--color-border-primary': { light: 'space-black', diff --git a/src/lib/types/index.ts b/src/lib/types/index.ts index 17c34f4f88..a85dd149f4 100644 --- a/src/lib/types/index.ts +++ b/src/lib/types/index.ts @@ -284,6 +284,7 @@ export type SettingsResponse = { DefaultErrorMessage?: string; DefaultErrorLink?: string; }; + Environment: { Name: string }; DefaultNamespace: string; DisableWriteActions: boolean; WorkflowTerminateDisabled: boolean; diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index fae37206af..ac4be62dac 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -45,6 +45,8 @@ let { children }: Props = $props(); let isCloud = $derived(page.data?.settings?.runtimeEnvironment?.isCloud); + let environmentName = $derived(page.data?.settings?.buildEnvironment?.name); + let activeNamespaceName = $derived( page.params?.namespace ?? $lastUsedNamespace, ); @@ -252,7 +254,7 @@ position={toaster.position} /> {/if} @@ -110,7 +126,7 @@ 'focus-visible:[&_a]:outline-none focus-visible:[&_a]:ring-2 focus-visible:[&_a]:ring-primary/70 focus-visible:[&_button]:outline-none focus-visible:[&_button]:ring-2 focus-visible:[&_button]:ring-primary/70', isCloud ? 'bg-gradient-to-b from-indigo-600 to-indigo-900 text-off-white focus-visible:[&_a]:ring-success focus-visible:[&_button]:ring-success' - : 'surface-black border-t border-subtle', + : environmentName || 'surface-black border-t border-subtle', )} data-testid="top-nav" aria-label={translate('common.main')} @@ -120,7 +136,7 @@ data-testid="nav-menu-button" class:active-shadow={viewLinks} type="button" - on:click={onLinksClick} + onclick={onLinksClick} > {#if viewLinks} @@ -153,7 +169,7 @@ data-testid="nav-profile-button" class:active-shadow={viewSettings} type="button" - on:click={onSettingsClick} + onclick={onSettingsClick} > {#if viewSettings} @@ -161,13 +177,7 @@
- - {translate('common.user-profile')} - + {@render avatar()}
{/if} @@ -181,4 +191,16 @@ .nav-button { @apply relative select-none p-1 text-center align-middle text-xs font-medium uppercase transition-all; } + + .development { + @apply surface-development border-t border-subtle; + } + + .staging { + @apply surface-staging border-t border-subtle; + } + + .test { + @apply surface-test border-t border-subtle; + } diff --git a/src/lib/holocene/main-content-container.svelte b/src/lib/holocene/main-content-container.svelte index f70f44802f..39c7729a79 100644 --- a/src/lib/holocene/main-content-container.svelte +++ b/src/lib/holocene/main-content-container.svelte @@ -1,10 +1,21 @@ + +
- + {@render children()}
- + {@render main()}
- + {@render footer()}
diff --git a/src/lib/holocene/navigation/navigation-container.svelte b/src/lib/holocene/navigation/navigation-container.svelte index 06fac8e3ce..28d22f5ca7 100644 --- a/src/lib/holocene/navigation/navigation-container.svelte +++ b/src/lib/holocene/navigation/navigation-container.svelte @@ -77,7 +77,7 @@
{@render bottom?.()}
{translate('common.version')} {version} @@ -97,8 +97,4 @@ .test { @apply surface-test; } - - .production { - @apply surface-black; - } diff --git a/src/lib/theme/variables.ts b/src/lib/theme/variables.ts index df867f5142..43db2191e7 100644 --- a/src/lib/theme/variables.ts +++ b/src/lib/theme/variables.ts @@ -173,6 +173,7 @@ export const variables = { light: 'indigo.100', dark: 'slate.900', }, + // Environment Surfaces '--color-surface-development': { light: 'green.700', dark: 'green.700', diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index 589cf38014..1111acb9ec 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -4,6 +4,7 @@ import { afterNavigate, goto } from '$app/navigation'; import { page, updated } from '$app/state'; + import BottomNavNamespaces from '$lib/components/bottom-nav-namespaces.svelte'; import BottomNavigation from '$lib/components/bottom-nav.svelte'; import DataEncoderSettings from '$lib/components/data-encoder-settings.svelte'; import NamespacePicker from '$lib/components/namespace-picker.svelte'; @@ -277,22 +278,33 @@ {/snippet} -
- - {@render children()} - -
- - - + {#snippet main()} +
+ + {@render children()} + +
+ {/snippet} + {#snippet footer()} + + + {#snippet namespacePicker({ open })} + + {/snippet} + {#snippet avatar()} + {translate('common.user-profile')} + {/snippet} + + {/snippet}
From f1cbd320ba1aa14a8f91d7e607a0695454344c2e Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 14 Nov 2025 12:05:33 -0600 Subject: [PATCH 4/6] Remove enviroment name from developmet.yaml --- server/config/development.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/config/development.yaml b/server/config/development.yaml index 6623b36582..0b44b32ef5 100644 --- a/server/config/development.yaml +++ b/server/config/development.yaml @@ -61,5 +61,3 @@ codec: defaultErrorLink: forwardHeaders: # can be used to pass additional HTTP headers from HTTP requests to Temporal gRPC backend - X-Forwarded-For -environment: - name: test From 139ae7c508dbd262516bb41600b315462976a054 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 14 Nov 2025 12:27:04 -0600 Subject: [PATCH 5/6] Make namespaceList optional with default --- src/lib/components/bottom-nav.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/bottom-nav.svelte b/src/lib/components/bottom-nav.svelte index 533e101f1a..8d17ef76ae 100644 --- a/src/lib/components/bottom-nav.svelte +++ b/src/lib/components/bottom-nav.svelte @@ -23,7 +23,7 @@ children: Snippet; namespacePicker: Snippet<[{ open: boolean; closeMenu: () => void }]>; avatar: Snippet; - namespaceList: NamespaceListItem[]; + namespaceList?: NamespaceListItem[]; isCloud: boolean; linkList: NavLinkListItem[]; showNamespacePicker?: boolean; @@ -34,7 +34,7 @@ children, namespacePicker, avatar, - namespaceList, + namespaceList = [], isCloud = false, linkList, showNamespacePicker = true, From ad0cf15ae6f389705fe47bca193e89f072c84264 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 14 Nov 2025 13:14:07 -0600 Subject: [PATCH 6/6] Allow list of valid environment names --- src/lib/utilities/environment-name.ts | 6 ++++++ src/routes/(app)/+layout.svelte | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 src/lib/utilities/environment-name.ts diff --git a/src/lib/utilities/environment-name.ts b/src/lib/utilities/environment-name.ts new file mode 100644 index 0000000000..b64f75d192 --- /dev/null +++ b/src/lib/utilities/environment-name.ts @@ -0,0 +1,6 @@ +export const setValidEnvironmentName = (name: string | undefined): string => { + const env = name.toLowerCase(); + const validEnvs = ['development', 'test', 'staging']; + if (name && name.trim().length > 0 && validEnvs.includes(env)) return env; + return ''; +}; diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index 1111acb9ec..9c4abb0473 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -25,6 +25,7 @@ import type { NamespaceListItem, NavLinkListItem } from '$lib/types/global'; import { setCoreContext } from '$lib/utilities/core-context'; import DarkMode from '$lib/utilities/dark-mode'; + import { setValidEnvironmentName } from '$lib/utilities/environment-name'; import { routeForArchivalWorkfows, routeForBatchOperations, @@ -46,7 +47,9 @@ let { children }: Props = $props(); let isCloud = $derived(page.data?.settings?.runtimeEnvironment?.isCloud); - let environmentName = $derived(page.data?.settings?.buildEnvironment?.name); + let environmentName = $derived( + setValidEnvironmentName(page.data?.settings?.buildEnvironment?.name), + ); let activeNamespaceName = $derived( page.params?.namespace ?? $lastUsedNamespace,