Allow tabs to save state

This commit is contained in:
Guilhem
2025-05-28 17:55:04 +02:00
parent d600cd0ec7
commit 44aba60614
5 changed files with 89 additions and 4 deletions

View File

@@ -88,6 +88,7 @@
setSplitPanesLayoutContext,
type PanesLayout
} from './splitPanes/SplitPanesLayout.svelte'
import { setTabStateContext, TabsState } from './common/tabs/tabsState.svelte'
export let initialPath: string = ''
export let pathStoreInit: string | undefined = undefined
@@ -108,6 +109,7 @@
export let draftTriggersFromUrl: Trigger[] | undefined = undefined
export let selectedTriggerIndexFromUrl: number | undefined = undefined
export let savedSplitPanesLayout: Record<string, PanesLayout> | undefined = undefined
export let tabsStateFromUrl: Record<string, string> | undefined = undefined
let initialPathStore = writable(initialPath)
$: initialPathStore.set(initialPath)
@@ -143,12 +145,21 @@
const splitPanesLayout = new SplitPanesLayout(savedSplitPanesLayout ?? {}, saveSessionDraft)
setSplitPanesLayoutContext(splitPanesLayout)
const tabsState = new TabsState(tabsStateFromUrl ?? {}, saveSessionDraft)
setTabStateContext(tabsState)
export function setSplitPanesLayout(layout: Record<string, PanesLayout> | undefined) {
if (layout !== undefined) {
splitPanesLayout.layout = layout
}
}
export function setTabsState(newTabsState: Record<string, string> | undefined) {
if (newTabsState !== undefined) {
tabsState.selected = newTabsState
}
}
export function getInitialAndModifiedValues(): SavedAndModifiedValue {
return {
savedValue: savedFlow,
@@ -506,7 +517,8 @@
selectedId: $selectedIdStore,
draft_triggers: triggersState.getDraftTriggersSnapshot(),
selected_trigger: triggersState.getSelectedTriggerSnapshot(),
split_panes_layout: splitPanesLayout.getLayoutSnapshot()
split_panes_layout: splitPanesLayout.getLayoutSnapshot(),
tabs_state: tabsState.getTabsStateSnapshot()
})
)
} catch (err) {

View File

@@ -12,6 +12,7 @@
import { createEventDispatcher } from 'svelte'
import { twMerge } from 'tailwind-merge'
import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted'
import { getTabStateContext, type TabsState } from './tabsState.svelte'
const dispatch = createEventDispatcher()
const dispatchIfMounted = createDispatcherIfMounted(dispatch)
@@ -25,11 +26,14 @@
export let style = ''
export let hashNavigation = false
export let values: string[] | undefined = undefined
export let id: string | undefined = undefined // if provided, the tabs state will be stored in a parent context
$: selected && updateSelected()
const selectedStore = writable(selected)
let tabsState: TabsState | undefined = undefined
$: $selectedStore && dispatchIfMounted('selected', $selectedStore)
$: hashValues = values ? values.map((x) => '#' + x) : undefined
@@ -44,6 +48,9 @@
function updateSelected() {
selectedStore.set(selected)
if (tabsState && id) {
tabsState.setSelected(id, selected)
}
}
function hashChange() {
@@ -56,6 +63,15 @@
}
}
}
if (id) {
tabsState = getTabStateContext()
console.log('dbg tabsState', tabsState)
const tabState = tabsState?.getSelected(id)
if (tabState) {
selected = tabState
}
}
</script>
<svelte:window on:hashchange={hashChange} />

View File

@@ -0,0 +1,47 @@
import { getContext, setContext } from 'svelte'
const KEY = 'tabsState'
export class TabsState {
#selected: Record<string, string> = $state({})
#changeCb: (() => void) | undefined = undefined
constructor(selected: Record<string, string>, changeCb?: () => void) {
this.#selected = selected
this.#changeCb = changeCb
}
get selected() {
return this.#selected
}
set selected(value: Record<string, string>) {
this.#selected = value
this.#changeCb?.()
}
setChangeCb(cb: () => void) {
this.#changeCb = cb
}
getSelected(id: string) {
return this.#selected[id]
}
setSelected(id: string, value: string) {
this.#selected[id] = value
this.#changeCb?.()
}
getTabsStateSnapshot() {
return $state.snapshot(this.#selected)
}
}
export function setTabStateContext(tabsState: TabsState) {
setContext<TabsState>(KEY, tabsState)
}
export function getTabStateContext(): TabsState | undefined {
return getContext<TabsState>(KEY)
}

View File

@@ -456,7 +456,7 @@
<Pane minSize={20} index={1} defaultSize={panesSizes[1]}>
<Splitpanes id={`flow-editor-step-input-${flowModule.id}`}>
<Pane minSize={36} index={0} defaultSize={selected === 'inputs' ? 100 : 50}>
<Tabs bind:selected>
<Tabs bind:selected id={`flow-editor-step-input-${flowModule.id}`}>
{#if !preprocessorModule}
<Tab value="inputs">Step Input</Tab>
{/if}
@@ -512,7 +512,10 @@
bind:scriptProgress
/>
{:else if selected === 'advanced'}
<Tabs bind:selected={advancedSelected}>
<Tabs
bind:selected={advancedSelected}
id={`flow-editor-step-advanced-${flowModule.id}`}
>
<Tab value="retries" active={flowModule.retry !== undefined}>Retries</Tab>
{#if !$selectedId.includes('failure')}
<Tab value="runtime">Runtime</Tab>
@@ -536,7 +539,10 @@
{/if}
</Tabs>
{#if advancedSelected === 'runtime'}
<Tabs bind:selected={advancedRuntimeSelected}>
<Tabs
bind:selected={advancedRuntimeSelected}
id={`flow-editor-step-advanced-runtime-${flowModule.id}`}
>
<Tab value="concurrency">Concurrency</Tab>
<Tab value="timeout">Timeout</Tab>
<Tab value="priority">Priority</Tab>

View File

@@ -65,6 +65,7 @@
let draftTriggersFromUrl: Trigger[] | undefined = undefined
let selectedTriggerIndexFromUrl: number | undefined = undefined
let splitPanesLayoutFromUrl: Record<string, PanesLayout> | undefined = undefined
let tabsStateFromUrl: Record<string, string> | undefined = undefined
let flowBuilder: FlowBuilder | undefined = undefined
@@ -96,9 +97,11 @@
draftTriggersFromUrl = stateLoadedFromUrl.draft_triggers
selectedTriggerIndexFromUrl = stateLoadedFromUrl.selected_trigger
splitPanesLayoutFromUrl = stateLoadedFromUrl.split_panes_layout
tabsStateFromUrl = stateLoadedFromUrl.tabs_state
flowBuilder?.setSplitPanesLayout(splitPanesLayoutFromUrl)
flowBuilder?.setDraftTriggers(draftTriggersFromUrl)
flowBuilder?.setSelectedTriggerIndex(selectedTriggerIndexFromUrl)
flowBuilder?.setTabsState(stateLoadedFromUrl.tabs_state)
const selectedId = stateLoadedFromUrl?.selectedId ?? 'settings-metadata'
const reloadAction = () => {
stateLoadedFromUrl = undefined
@@ -275,6 +278,7 @@
{savedPrimarySchedule}
{draftTriggersFromUrl}
{selectedTriggerIndexFromUrl}
{tabsStateFromUrl}
bind:version
bind:getInitialAndModifiedValues
>