diff --git a/frontend/src/lib/components/CompareDrafts.svelte b/frontend/src/lib/components/CompareDrafts.svelte index 28cd3fd17a..88107f8bba 100644 --- a/frontend/src/lib/components/CompareDrafts.svelte +++ b/frontend/src/lib/components/CompareDrafts.svelte @@ -29,7 +29,8 @@ useWorkspaceDrafts } from '$lib/workspaceDrafts.svelte' import type { Kind as LayoutKind } from '$lib/utils_deployable' - import { userStore } from '$lib/stores' + import { userStore, userWorkspaces } from '$lib/stores' + import { childWorkspaceNoun } from '$lib/utils/devWorkspaceLabel' interface Props { currentWorkspaceId: string @@ -161,6 +162,10 @@ // (unrelated to the fork's own work) are the common case worth hiding. let hideUnchanged = $state(true) + const currentNoun = $derived( + childWorkspaceNoun($userWorkspaces.find((w) => w.id === currentWorkspaceId)) + ) + // The list (and, in the default view, the Draft Count) come from the Workspace // Drafts module; deploy/discard invalidate the resource, so the list refetches // and deployed items drop off without a manual reload here. @@ -663,8 +668,7 @@ size="xs" options={{ right: 'Hide unchanged drafts', - rightTooltip: - "Hide drafts identical to the parent workspace. A fork inherits the parent's drafts when it's created; those are unrelated to the changes made in this fork." + rightTooltip: `Hide drafts identical to the parent workspace. A ${currentNoun} inherits the parent's drafts when it's created; those are unrelated to the changes made in this ${currentNoun}.` }} /> {/if} diff --git a/frontend/src/lib/components/CompareWorkspaces.svelte b/frontend/src/lib/components/CompareWorkspaces.svelte index 2b644e900d..875eda25ce 100644 --- a/frontend/src/lib/components/CompareWorkspaces.svelte +++ b/frontend/src/lib/components/CompareWorkspaces.svelte @@ -68,6 +68,7 @@ import CompareModeToggle, { type CompareMode } from './CompareModeToggle.svelte' import CompareTargetPicker from './CompareTargetPicker.svelte' import { displayDate } from '$lib/utils' + import { childWorkspaceNoun } from '$lib/utils/devWorkspaceLabel' import { editUrlFor } from './sessions/forkEditUrl' import { diffInMask } from './sessions/modifiedItemsMask' import DatatableSchemaDiff from './DatatableSchemaDiff.svelte' @@ -400,6 +401,8 @@ let currentWorkspaceInfo = $derived($userWorkspaces.find((w) => w.id == currentWorkspaceId)) let parentWorkspaceInfo = $derived($userWorkspaces.find((w) => w.id == parentWorkspaceId)) + let currentNoun = $derived(childWorkspaceNoun(currentWorkspaceInfo)) + // An arbitrary target is one-way: the pair has no tally, so nothing distinguishes // a change made here from one made there, and the "update current" direction // would list every difference as an incoming change. @@ -448,7 +451,7 @@ ? `No changes between this workspace and ${parentWorkspaceId}.` : mergeIntoParent ? `Nothing to deploy — ${parentWorkspaceId} already has every change from this workspace.` - : `Nothing to update — this fork is up to date with ${parentWorkspaceId}.` + : `Nothing to update — this ${currentNoun} is up to date with ${parentWorkspaceId}.` ) let conflictingDiffs = $derived( @@ -1437,7 +1440,8 @@ {#if mergeIntoParent} This workspace has {draftCount} undeployed draft{draftCount !== 1 ? 's' : ''}. - Only deployed versions in this fork can be sent to {parentWorkspaceId} — deploy + Only deployed versions in this {currentNoun} can be sent to {parentWorkspaceId} — + deploy {draftCount !== 1 ? 'them' : 'it'} first, otherwise those changes won't be included. {:else} This workspace has {draftCount} undeployed draft{draftCount !== 1 ? 's' : ''}. @@ -1461,14 +1465,14 @@ {conflictingDiffs.length} item{conflictingDiffs.length !== 1 ? 's have' : ' has'} conflicting - changes, it was modified on the original workspace while changes were made on this fork. - Make sure to resolve these before merging. + changes, it was modified on the original workspace while changes were made on this + {currentNoun}. Make sure to resolve these before merging. {/if} {#if hasBehindChanges && hasAheadChanges && !(mergeIntoParent && !canDeployToParent)} diff --git a/frontend/src/lib/components/DatatableSchemaDiff.svelte b/frontend/src/lib/components/DatatableSchemaDiff.svelte index c660b122b5..579b7a1923 100644 --- a/frontend/src/lib/components/DatatableSchemaDiff.svelte +++ b/frontend/src/lib/components/DatatableSchemaDiff.svelte @@ -13,6 +13,7 @@ import SimpleEditor from '$lib/components/SimpleEditor.svelte' import { sendUserToast } from '$lib/toast' import { userWorkspaces } from '$lib/stores' + import { childWorkspaceNoun } from '$lib/utils/devWorkspaceLabel' import { runScriptAndPollResult } from '$lib/components/jobs/utils' import { writingJobOptions } from '$lib/components/jobs/writingJob' import YAML from 'yaml' @@ -34,6 +35,11 @@ let { currentWorkspaceId, parentWorkspaceId }: Props = $props() + let currentNoun = $derived( + childWorkspaceNoun($userWorkspaces.find((w) => w.id === currentWorkspaceId)) + ) + let currentNounCap = $derived(currentNoun.charAt(0).toUpperCase() + currentNoun.slice(1)) + let loading = $state(true) let error: string | undefined = $state(undefined) let diffs: DatatableDiff[] = $state([]) @@ -321,8 +327,9 @@
{#if diff.aheadChanges.length > 0}
-
Fork changes (ahead)
+
+ {currentNounCap} changes (ahead) +
{#each diff.aheadChanges as change}
{#if change.kind === 'added'} @@ -393,8 +400,8 @@ (drawerOpen = false)} title="{drawerChange.schemaName}.{drawerChange.tableName} ({drawerDirection === 'ahead' - ? 'Fork → Parent' - : 'Parent → Fork'})" + ? `${currentNounCap} → Parent` + : `Parent → ${currentNounCap}`})" > {#snippet actions()}
diff --git a/frontend/src/lib/utils/devWorkspaceLabel.ts b/frontend/src/lib/utils/devWorkspaceLabel.ts index e1b3e6604e..e12e490261 100644 --- a/frontend/src/lib/utils/devWorkspaceLabel.ts +++ b/frontend/src/lib/utils/devWorkspaceLabel.ts @@ -41,3 +41,14 @@ export function devLabelWord(label: string | null | undefined): string { export function devLabelNoun(label: string | null | undefined): string { return `${devLabelKey(label)} workspace` } + +/** + * How to name a child workspace in prose: its environment noun when it is a dev workspace + * ("dev workspace", "staging workspace"), "fork" otherwise. A dev workspace is a standing + * environment its whole team works in, so calling it a fork misreads it as throwaway. + */ +export function childWorkspaceNoun( + workspace: { is_dev_workspace?: boolean; dev_workspace_label?: string | null } | undefined +): string { + return workspace?.is_dev_workspace ? devLabelNoun(workspace.dev_workspace_label) : 'fork' +} diff --git a/frontend/src/routes/(root)/(logged)/forks/compare/+page.svelte b/frontend/src/routes/(root)/(logged)/forks/compare/+page.svelte index d5ff28ccca..a21fa36835 100644 --- a/frontend/src/routes/(root)/(logged)/forks/compare/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/forks/compare/+page.svelte @@ -51,6 +51,10 @@ // prefix. Distinct from having a compare target: a root workspace has no parent // yet can still be pointed at an arbitrary one. const isFork = $derived(!!parentWorkspaceId) + // A dev workspace is a standing environment, torn down by detaching it in the + // dev-workspace settings — never by an archive/delete button sitting next to the + // merge it is here to perform. + const isDevWorkspace = $derived(!!currentWorkspaceData?.is_dev_workspace) const hasCompareTarget = $derived(!!compareTargetId) // Mode is seeded from the URL (?mode=draft|fork). `draft` is valid for any @@ -389,10 +393,10 @@
- - {#if isFork} + + {#if isFork && !isDevWorkspace}