mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-05 16:03:47 +00:00
refactor(drafts): extract DraftEditorModals trailer block
The four editor routes (scripts/flows/apps/apps_raw) mounted an
identical pair of trailer modals — DraftSyncConflictModal +
OtherUsersDraftsModal — wrapped in the same guard chain and {#key path}
remount. Lift the markup into one component; routes thread their
itemKind, path, editPathFor, and loader callback.
Pure markup extraction, no state ownership change. Drops the unused
userStore import where the trailer was the only consumer.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
<script lang="ts">
|
||||
/**
|
||||
* The two modals every editor route mounts at its trailer:
|
||||
* - DraftSyncConflictModal: surfaces a 409 from the autosave pipeline.
|
||||
* The route supplies `onLoadFromServer` (re-fetches the deployed-overlay
|
||||
* response and re-seeds editor state) and a `getLocalDraft` getter that
|
||||
* snapshots the cell value for the overwrite branch.
|
||||
* - OtherUsersDraftsModal: surfaces the list of other workspace users (or
|
||||
* the legacy NULL-email row) with a draft at the same path, offered for
|
||||
* forking. Open-gated on `otherDraftsUsers.length > 0`.
|
||||
*
|
||||
* Gates the whole block on `enabled` (defaults to true) — the scripts
|
||||
* route uses this to suppress when viewing a specific hash.
|
||||
*
|
||||
* Wrap the OtherUsersDraftsModal in `{#key path}` so navigating between
|
||||
* editor paths fully remounts the modal (carrying its `jsonOpen` /
|
||||
* fork-target state with it) instead of trying to recompute its
|
||||
* `forkPath` derivation for a new path mid-flight.
|
||||
*/
|
||||
import { userStore } from '$lib/stores'
|
||||
import type { UserDraftItemKind } from '$lib/gen'
|
||||
import DraftSyncConflictModal from './DraftSyncConflictModal.svelte'
|
||||
import OtherUsersDraftsModal, { type OtherDraftUser } from './OtherUsersDraftsModal.svelte'
|
||||
|
||||
type Props = {
|
||||
workspace: string
|
||||
itemKind: UserDraftItemKind
|
||||
path: string
|
||||
otherDraftsUsers: OtherDraftUser[]
|
||||
editPathFor: (forkedPath: string) => string
|
||||
onLoadFromServer: () => void | Promise<void>
|
||||
getLocalDraft: () => unknown
|
||||
/** Defaults to true; set to false to suppress both modals. */
|
||||
enabled?: boolean
|
||||
}
|
||||
|
||||
let {
|
||||
workspace,
|
||||
itemKind,
|
||||
path,
|
||||
otherDraftsUsers,
|
||||
editPathFor,
|
||||
onLoadFromServer,
|
||||
getLocalDraft,
|
||||
enabled = true
|
||||
}: Props = $props()
|
||||
</script>
|
||||
|
||||
{#if enabled && workspace && path}
|
||||
<DraftSyncConflictModal
|
||||
query={{ workspace, itemKind, path }}
|
||||
{onLoadFromServer}
|
||||
{getLocalDraft}
|
||||
/>
|
||||
{#if otherDraftsUsers.length > 0}
|
||||
{#key path}
|
||||
<OtherUsersDraftsModal
|
||||
{workspace}
|
||||
{itemKind}
|
||||
{path}
|
||||
currentUserUsername={$userStore?.username}
|
||||
{otherDraftsUsers}
|
||||
{editPathFor}
|
||||
/>
|
||||
{/key}
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -1,17 +1,15 @@
|
||||
<script lang="ts">
|
||||
import AppEditor from '$lib/components/apps/editor/AppEditor.svelte'
|
||||
import { AppService, type AppWithLastVersion } from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { replaceState } from '$app/navigation'
|
||||
import { goto } from '$lib/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import DiffDrawer from '$lib/components/DiffDrawer.svelte'
|
||||
import type { App } from '$lib/components/apps/types'
|
||||
import DraftSyncConflictModal from '$lib/components/common/confirmationModal/DraftSyncConflictModal.svelte'
|
||||
import DraftEditorModals from '$lib/components/common/confirmationModal/DraftEditorModals.svelte'
|
||||
import { UserDraftDbSyncer } from '$lib/userDraftDbSyncer.svelte'
|
||||
import OtherUsersDraftsModal, {
|
||||
type OtherDraftUser
|
||||
} from '$lib/components/common/confirmationModal/OtherUsersDraftsModal.svelte'
|
||||
import { type OtherDraftUser } from '$lib/components/common/confirmationModal/OtherUsersDraftsModal.svelte'
|
||||
import { stateSnapshot } from '$lib/svelte5Utils.svelte'
|
||||
import { emptyApp } from '$lib/components/apps/editor/appUtils'
|
||||
import { untrack } from 'svelte'
|
||||
@@ -221,25 +219,15 @@
|
||||
</script>
|
||||
|
||||
<DiffDrawer bind:this={diffDrawer} {restoreDeployed} />
|
||||
{#if $workspaceStore && path}
|
||||
<DraftSyncConflictModal
|
||||
query={{ workspace: $workspaceStore, itemKind: 'app', path }}
|
||||
onLoadFromServer={() => loadApp()}
|
||||
getLocalDraft={() => app?.value}
|
||||
/>
|
||||
{/if}
|
||||
{#if $workspaceStore && path && otherDraftsUsers.length > 0}
|
||||
{#key path}
|
||||
<OtherUsersDraftsModal
|
||||
workspace={$workspaceStore}
|
||||
itemKind="app"
|
||||
{path}
|
||||
currentUserUsername={$userStore?.username}
|
||||
{otherDraftsUsers}
|
||||
editPathFor={(forkedPath) => `/apps/edit/${forkedPath}`}
|
||||
/>
|
||||
{/key}
|
||||
{/if}
|
||||
<DraftEditorModals
|
||||
workspace={$workspaceStore ?? ''}
|
||||
itemKind="app"
|
||||
{path}
|
||||
{otherDraftsUsers}
|
||||
editPathFor={(forkedPath) => `/apps/edit/${forkedPath}`}
|
||||
onLoadFromServer={() => loadApp()}
|
||||
getLocalDraft={() => app?.value}
|
||||
/>
|
||||
|
||||
{#key redraw}
|
||||
{#if app}
|
||||
|
||||
@@ -15,11 +15,9 @@
|
||||
import { type RawAppData, DEFAULT_DATA } from '$lib/components/raw_apps/dataTableRefUtils'
|
||||
import { UserDraft } from '$lib/userDraft.svelte'
|
||||
import { notifyDraftLoaded } from '$lib/userDraftToast'
|
||||
import DraftSyncConflictModal from '$lib/components/common/confirmationModal/DraftSyncConflictModal.svelte'
|
||||
import DraftEditorModals from '$lib/components/common/confirmationModal/DraftEditorModals.svelte'
|
||||
import { UserDraftDbSyncer } from '$lib/userDraftDbSyncer.svelte'
|
||||
import OtherUsersDraftsModal, {
|
||||
type OtherDraftUser
|
||||
} from '$lib/components/common/confirmationModal/OtherUsersDraftsModal.svelte'
|
||||
import { type OtherDraftUser } from '$lib/components/common/confirmationModal/OtherUsersDraftsModal.svelte'
|
||||
import RawAppTemplatePicker, {
|
||||
type RawAppTemplatePickerResult
|
||||
} from '$lib/components/raw_apps/RawAppTemplatePicker.svelte'
|
||||
@@ -382,25 +380,15 @@
|
||||
</script>
|
||||
|
||||
<DiffDrawer bind:this={diffDrawer} {restoreDeployed} />
|
||||
{#if $workspaceStore && path}
|
||||
<DraftSyncConflictModal
|
||||
query={{ workspace: $workspaceStore, itemKind: 'raw_app', path }}
|
||||
onLoadFromServer={() => loadApp()}
|
||||
getLocalDraft={() => draftHandle.draft}
|
||||
/>
|
||||
{/if}
|
||||
{#if $workspaceStore && path && otherDraftsUsers.length > 0}
|
||||
{#key path}
|
||||
<OtherUsersDraftsModal
|
||||
workspace={$workspaceStore}
|
||||
itemKind="raw_app"
|
||||
{path}
|
||||
currentUserUsername={$userStore?.username}
|
||||
{otherDraftsUsers}
|
||||
editPathFor={(forkedPath) => `/apps_raw/edit/${forkedPath}`}
|
||||
/>
|
||||
{/key}
|
||||
{/if}
|
||||
<DraftEditorModals
|
||||
workspace={$workspaceStore ?? ''}
|
||||
itemKind="raw_app"
|
||||
{path}
|
||||
{otherDraftsUsers}
|
||||
editPathFor={(forkedPath) => `/apps_raw/edit/${forkedPath}`}
|
||||
onLoadFromServer={() => loadApp()}
|
||||
getLocalDraft={() => draftHandle.draft}
|
||||
/>
|
||||
|
||||
<RawAppTemplatePicker bind:open={templatePicker} onStart={onTemplatePickerStart} />
|
||||
|
||||
|
||||
@@ -3,18 +3,16 @@
|
||||
|
||||
import FlowBuilder from '$lib/components/FlowBuilder.svelte'
|
||||
import { editPathFor, invalidate } from '$lib/components/workspacePicker'
|
||||
import { initialArgsStore, userStore, workspaceStore } from '$lib/stores'
|
||||
import { initialArgsStore, workspaceStore } from '$lib/stores'
|
||||
import { decodeState, emptySchema, type StateStore } from '$lib/utils'
|
||||
import { initFlow } from '$lib/components/flows/flowStore.svelte'
|
||||
import { goto } from '$lib/navigation'
|
||||
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import DiffDrawer from '$lib/components/DiffDrawer.svelte'
|
||||
import DraftSyncConflictModal from '$lib/components/common/confirmationModal/DraftSyncConflictModal.svelte'
|
||||
import DraftEditorModals from '$lib/components/common/confirmationModal/DraftEditorModals.svelte'
|
||||
import { UserDraftDbSyncer } from '$lib/userDraftDbSyncer.svelte'
|
||||
import OtherUsersDraftsModal, {
|
||||
type OtherDraftUser
|
||||
} from '$lib/components/common/confirmationModal/OtherUsersDraftsModal.svelte'
|
||||
import { type OtherDraftUser } from '$lib/components/common/confirmationModal/OtherUsersDraftsModal.svelte'
|
||||
import type { ScheduleTrigger } from '$lib/components/triggers'
|
||||
import type { Trigger } from '$lib/components/triggers/utils'
|
||||
import { tick, untrack } from 'svelte'
|
||||
@@ -317,25 +315,15 @@
|
||||
<!-- <div id="monaco-widgets-root" class="monaco-editor" style="z-index: 1200;" /> -->
|
||||
|
||||
<DiffDrawer bind:this={diffDrawer} {restoreDeployed} isFlow />
|
||||
{#if $workspaceStore && flowDraftPath}
|
||||
<DraftSyncConflictModal
|
||||
query={{ workspace: $workspaceStore, itemKind: 'flow', path: flowDraftPath }}
|
||||
onLoadFromServer={() => loadFlow()}
|
||||
getLocalDraft={() => flowHandle.draft}
|
||||
/>
|
||||
{/if}
|
||||
{#if $workspaceStore && flowDraftPath && otherDraftsUsers.length > 0}
|
||||
{#key flowDraftPath}
|
||||
<OtherUsersDraftsModal
|
||||
workspace={$workspaceStore}
|
||||
itemKind="flow"
|
||||
path={flowDraftPath}
|
||||
currentUserUsername={$userStore?.username}
|
||||
{otherDraftsUsers}
|
||||
editPathFor={(forkedPath) => `/flows/edit/${forkedPath}`}
|
||||
/>
|
||||
{/key}
|
||||
{/if}
|
||||
<DraftEditorModals
|
||||
workspace={$workspaceStore ?? ''}
|
||||
itemKind="flow"
|
||||
path={flowDraftPath}
|
||||
{otherDraftsUsers}
|
||||
editPathFor={(forkedPath) => `/flows/edit/${forkedPath}`}
|
||||
onLoadFromServer={() => loadFlow()}
|
||||
getLocalDraft={() => flowHandle.draft}
|
||||
/>
|
||||
{#if notFound}
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-2xl font-bold">Flow not found at path {page.params.path}</h1>
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { ScriptService, type NewScript, type Script } from '$lib/gen'
|
||||
|
||||
import { initialArgsStore, userStore, workspaceStore } from '$lib/stores'
|
||||
import { initialArgsStore, workspaceStore } from '$lib/stores'
|
||||
import ScriptBuilder from '$lib/components/ScriptBuilder.svelte'
|
||||
import { editPathFor, invalidate } from '$lib/components/workspacePicker'
|
||||
import { emptySchema } from '$lib/utils'
|
||||
import { goto } from '$lib/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import DiffDrawer from '$lib/components/DiffDrawer.svelte'
|
||||
import OtherUsersDraftsModal, {
|
||||
type OtherDraftUser
|
||||
} from '$lib/components/common/confirmationModal/OtherUsersDraftsModal.svelte'
|
||||
import { type OtherDraftUser } from '$lib/components/common/confirmationModal/OtherUsersDraftsModal.svelte'
|
||||
import DraftEditorModals from '$lib/components/common/confirmationModal/DraftEditorModals.svelte'
|
||||
import type { ScheduleTrigger } from '$lib/components/triggers'
|
||||
import type { Trigger } from '$lib/components/triggers/utils'
|
||||
import { get } from 'svelte/store'
|
||||
@@ -19,7 +18,6 @@
|
||||
import { UserDraft, type UserDraftHandle } from '$lib/userDraft.svelte'
|
||||
import { notifyDraftLoaded } from '$lib/userDraftToast'
|
||||
import { UserDraftDbSyncer } from '$lib/userDraftDbSyncer.svelte'
|
||||
import DraftSyncConflictModal from '$lib/components/common/confirmationModal/DraftSyncConflictModal.svelte'
|
||||
|
||||
type EditableScript = NewScript & { draft_triggers?: Trigger[] }
|
||||
|
||||
@@ -250,25 +248,16 @@
|
||||
</script>
|
||||
|
||||
<DiffDrawer bind:this={diffDrawer} {restoreDeployed} />
|
||||
{#if !hash && $workspaceStore && page.params.path}
|
||||
<DraftSyncConflictModal
|
||||
query={{ workspace: $workspaceStore, itemKind: 'script', path: page.params.path }}
|
||||
onLoadFromServer={() => loadScript()}
|
||||
getLocalDraft={() => scriptHandle.draft}
|
||||
/>
|
||||
{/if}
|
||||
{#if !hash && $workspaceStore && page.params.path && otherDraftsUsers.length > 0}
|
||||
{#key page.params.path}
|
||||
<OtherUsersDraftsModal
|
||||
workspace={$workspaceStore}
|
||||
itemKind="script"
|
||||
path={page.params.path}
|
||||
currentUserUsername={$userStore?.username}
|
||||
{otherDraftsUsers}
|
||||
editPathFor={(forkedPath) => `/scripts/edit/${forkedPath}`}
|
||||
/>
|
||||
{/key}
|
||||
{/if}
|
||||
<DraftEditorModals
|
||||
enabled={!hash}
|
||||
workspace={$workspaceStore ?? ''}
|
||||
itemKind="script"
|
||||
path={page.params.path ?? ''}
|
||||
{otherDraftsUsers}
|
||||
editPathFor={(forkedPath) => `/scripts/edit/${forkedPath}`}
|
||||
onLoadFromServer={() => loadScript()}
|
||||
getLocalDraft={() => scriptHandle.draft}
|
||||
/>
|
||||
{#if scriptHandle.draft && renderEditor}
|
||||
<ScriptBuilder
|
||||
bind:this={scriptBuilder}
|
||||
|
||||
Reference in New Issue
Block a user