Allow tabs to save state
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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} />
|
||||
|
||||
47
frontend/src/lib/components/common/tabs/tabsState.svelte.ts
Normal file
47
frontend/src/lib/components/common/tabs/tabsState.svelte.ts
Normal 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)
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user