mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-25 16:03:47 +00:00
fix: remove URL-hash sync from script editor (already marked TEMP)
This commit is contained in:
@@ -4,12 +4,7 @@
|
||||
import { initialArgsStore, userStore, workspaceStore } from '$lib/stores'
|
||||
import ScriptBuilder from '$lib/components/ScriptBuilder.svelte'
|
||||
import { editPathFor, invalidate } from '$lib/components/workspacePicker'
|
||||
import {
|
||||
cleanValueProperties,
|
||||
encodeState,
|
||||
orderedJsonStringify,
|
||||
readFieldsRecursively
|
||||
} from '$lib/utils'
|
||||
import { cleanValueProperties, orderedJsonStringify } from '$lib/utils'
|
||||
import { goto } from '$lib/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import DiffDrawer from '$lib/components/DiffDrawer.svelte'
|
||||
@@ -80,28 +75,6 @@
|
||||
return () => UserDraft.clearLiveEditorDraft('script', { workspace, storagePath: draftPath })
|
||||
})
|
||||
|
||||
/** Some pages base64-JSON-encode a NewScript-like payload into the URL
|
||||
* hash on `/scripts/edit/<path>#…`. Treat it as a one-shot seed that
|
||||
* wins over local autosave + backend draft + deployed: apply, toast,
|
||||
* strip from the URL. Same logic as /scripts/add, kept in this file for
|
||||
* a faithful mirror of its decoder.
|
||||
*
|
||||
* Can't reuse `decodeState` from utils.ts — it fires its own error toast
|
||||
* on parse failure, which would noise up the UI for unrelated anchors.
|
||||
*/
|
||||
function decodeUrlScriptSeed(): Partial<EditableScript> | undefined {
|
||||
const fragment = page.url.hash.startsWith('#') ? page.url.hash.slice(1) : ''
|
||||
if (!fragment) return undefined
|
||||
try {
|
||||
const decoded = JSON.parse(decodeURIComponent(atob(fragment)))
|
||||
if (decoded && typeof decoded === 'object') return decoded as Partial<EditableScript>
|
||||
} catch {
|
||||
// Hash isn't a valid encoded script — ignore.
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
let urlScriptSeed = decodeUrlScriptSeed()
|
||||
|
||||
// Seed from the URL so ScriptBuilder mounts with a populated `initialPath`
|
||||
// even when `scriptHandle.draft` is already defined synchronously from a
|
||||
// local autosave. An empty initialPath flips ScriptBuilder's
|
||||
@@ -127,18 +100,6 @@
|
||||
let staleModalCause = $state<'draft' | 'version'>('version')
|
||||
let pendingBaseline: { baseline: EditableScript; revs: UserDraftMeta } | undefined = undefined
|
||||
|
||||
// === BEGIN TEMP URL-HASH SYNC (remove with future PR) ===
|
||||
// Legacy behavior: URL hash both seeds the editor and stays in sync with
|
||||
// edits. Asks the user via modal when the URL value would clobber an
|
||||
// existing local autosave that differs from it.
|
||||
let urlConflictModalOpen = $state(false)
|
||||
let urlConflictPending: { seed: EditableScript; revs: UserDraftMeta } | undefined = undefined
|
||||
// Gates the URL-sync effect until the initial URL-seed has been resolved
|
||||
// (silent apply OR modal closed) so it doesn't overwrite the URL payload
|
||||
// before the user has decided.
|
||||
let initialUrlSeedResolved = $state(!urlScriptSeed)
|
||||
// === END TEMP URL-HASH SYNC ===
|
||||
|
||||
function applyBaseline(baseline: EditableScript): void {
|
||||
initialPath = baseline.path
|
||||
scriptBuilder?.setDraftTriggers(baseline.draft_triggers)
|
||||
@@ -170,26 +131,6 @@
|
||||
staleModalOpen = false
|
||||
}
|
||||
|
||||
// === BEGIN TEMP URL-HASH SYNC (remove with future PR) ===
|
||||
function onUrlConflictUseUrl(): void {
|
||||
if (urlConflictPending) {
|
||||
const { seed, revs } = urlConflictPending
|
||||
UserDraft.remove('script', draftPath)
|
||||
scriptHandle.setDraftAndMeta(seed, revs)
|
||||
applyBaseline(seed)
|
||||
sendUserToast('Loaded from URL')
|
||||
}
|
||||
urlConflictPending = undefined
|
||||
urlConflictModalOpen = false
|
||||
initialUrlSeedResolved = true
|
||||
}
|
||||
function onUrlConflictKeepLocal(): void {
|
||||
urlConflictPending = undefined
|
||||
urlConflictModalOpen = false
|
||||
initialUrlSeedResolved = true
|
||||
}
|
||||
// === END TEMP URL-HASH SYNC ===
|
||||
|
||||
/** Increments per `loadScript` call. Stale loads (e.g. when picker
|
||||
* navigation races a draft-discard reload) bail at the next checkpoint
|
||||
* after their captured token no longer matches. */
|
||||
@@ -262,32 +203,7 @@
|
||||
parent_hash: topHash ?? backendScript.hash
|
||||
}
|
||||
|
||||
if (urlScriptSeed) {
|
||||
// === TEMP URL-HASH SYNC branch (remove with future PR) ===
|
||||
// URL hash seed competes with the local autosave on load.
|
||||
// When they differ, defer to a user-facing modal instead of
|
||||
// silently overwriting.
|
||||
const seeded = { ...bakedBaseline, ...urlScriptSeed } as EditableScript
|
||||
if (localDraft != undefined) {
|
||||
const localClean = orderedJsonStringify(cleanValueProperties(localDraft))
|
||||
const seededClean = orderedJsonStringify(cleanValueProperties(seeded))
|
||||
if (localClean === seededClean) {
|
||||
UserDraft.remove('script', draftPath)
|
||||
scriptHandle.setDraftAndMeta(seeded, newRevs)
|
||||
initialUrlSeedResolved = true
|
||||
} else {
|
||||
urlConflictPending = { seed: seeded, revs: newRevs }
|
||||
urlConflictModalOpen = true
|
||||
}
|
||||
} else {
|
||||
UserDraft.remove('script', draftPath)
|
||||
scriptHandle.setDraftAndMeta(seeded, newRevs)
|
||||
sendUserToast('Loaded from URL')
|
||||
initialUrlSeedResolved = true
|
||||
}
|
||||
urlScriptSeed = undefined
|
||||
// === END TEMP URL-HASH SYNC branch ===
|
||||
} else if (localDraft != undefined) {
|
||||
if (localDraft != undefined) {
|
||||
const referenceClean = cleanValueProperties(backendScript)
|
||||
const localClean = cleanValueProperties(localDraft)
|
||||
if (orderedJsonStringify(referenceClean) === orderedJsonStringify(localClean)) {
|
||||
@@ -362,31 +278,6 @@
|
||||
}
|
||||
})
|
||||
|
||||
// === BEGIN TEMP URL-HASH SYNC (remove with future PR) ===
|
||||
// Mirror the current draft to the URL hash on every edit (debounced).
|
||||
let _urlHashSyncTimeout: number | undefined
|
||||
$effect(() => {
|
||||
const draft = scriptHandle.draft
|
||||
if (!draft) return
|
||||
// Wait until the initial URL-seed has been resolved (silent apply or
|
||||
// modal closed) so we don't clobber the URL payload prematurely.
|
||||
if (!initialUrlSeedResolved) {
|
||||
if (_urlHashSyncTimeout) clearTimeout(_urlHashSyncTimeout)
|
||||
return
|
||||
}
|
||||
readFieldsRecursively(draft)
|
||||
if (typeof window === 'undefined') return
|
||||
if (_urlHashSyncTimeout) clearTimeout(_urlHashSyncTimeout)
|
||||
_urlHashSyncTimeout = setTimeout(() => {
|
||||
const snapshot = $state.snapshot(scriptHandle.draft)
|
||||
if (!snapshot) return
|
||||
const url = new URL(window.location.href)
|
||||
url.hash = encodeState(snapshot)
|
||||
window.history.replaceState(window.history.state, '', url.toString())
|
||||
}, 500)
|
||||
})
|
||||
// === END TEMP URL-HASH SYNC ===
|
||||
|
||||
let diffDrawer: DiffDrawer | undefined = $state()
|
||||
|
||||
async function restoreDeployed() {
|
||||
@@ -424,13 +315,6 @@
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
<!-- TEMP URL-HASH SYNC: conflict modal (remove with future PR) -->
|
||||
<LocalDraftStaleModal
|
||||
open={urlConflictModalOpen}
|
||||
cause="url"
|
||||
onLoadLatest={onUrlConflictUseUrl}
|
||||
onKeepDraft={onUrlConflictKeepLocal}
|
||||
/>
|
||||
{#if scriptHandle.draft && renderEditor}
|
||||
<ScriptBuilder
|
||||
bind:this={scriptBuilder}
|
||||
|
||||
Reference in New Issue
Block a user