mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 00:02:03 +00:00
improve app editor behavior when hiding right panel
This commit is contained in:
@@ -30,10 +30,10 @@
|
||||
|
||||
import ItemPicker from '$lib/components/ItemPicker.svelte'
|
||||
import VariableEditor from '$lib/components/VariableEditor.svelte'
|
||||
import { VariableService, type Job, type Policy } from '$lib/gen'
|
||||
import { VariableService, type Policy } from '$lib/gen'
|
||||
import { initHistory } from '$lib/history'
|
||||
import { Component, Minus, Paintbrush, Plus, Smartphone, Scan, Hand, Grab } from 'lucide-svelte'
|
||||
import { findGridItem, findGridItemParentGrid } from './appUtils'
|
||||
import { animateTo, findGridItem, findGridItemParentGrid } from './appUtils'
|
||||
import ComponentNavigation from './component/ComponentNavigation.svelte'
|
||||
import CssSettings from './componentsPanel/CssSettings.svelte'
|
||||
import SettingsPanel from './SettingsPanel.svelte'
|
||||
@@ -49,7 +49,6 @@
|
||||
import { getTheme } from './componentsPanel/themeUtils'
|
||||
import StylePanel from './settingsPanel/StylePanel.svelte'
|
||||
import type DiffDrawer from '$lib/components/DiffDrawer.svelte'
|
||||
import RunnableJobPanel from './RunnableJobPanel.svelte'
|
||||
import HideButton from './settingsPanel/HideButton.svelte'
|
||||
import AppEditorBottomPanel from './AppEditorBottomPanel.svelte'
|
||||
import panzoom from 'panzoom'
|
||||
@@ -386,27 +385,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function animateTo(start: number, end: number, onUpdate: (newValue: number) => void) {
|
||||
const duration = 400
|
||||
const startTime = performance.now()
|
||||
|
||||
function animate(time: number) {
|
||||
const elapsed = time - startTime
|
||||
const progress = Math.min(elapsed / duration, 1)
|
||||
const currentValue = start + (end - start) * easeInOut(progress)
|
||||
onUpdate(currentValue)
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(animate)
|
||||
}
|
||||
}
|
||||
|
||||
requestAnimationFrame(animate)
|
||||
}
|
||||
|
||||
function easeInOut(t: number) {
|
||||
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
|
||||
}
|
||||
|
||||
$: $cssEditorOpen && selectCss()
|
||||
|
||||
function selectCss() {
|
||||
@@ -583,13 +561,11 @@
|
||||
} else {
|
||||
leftPanelSize = storedLeftPanelSize
|
||||
}
|
||||
storedLeftPanelSize = 0
|
||||
}
|
||||
|
||||
function showRightPanel() {
|
||||
rightPanelSize = storedRightPanelSize
|
||||
centerPanelSize = centerPanelSize - storedRightPanelSize
|
||||
storedRightPanelSize = 0
|
||||
}
|
||||
|
||||
function showBottomPanel(animate: boolean = false) {
|
||||
@@ -611,7 +587,6 @@
|
||||
runnablePanelSize = storedBottomPanelSize
|
||||
gridPanelSize = gridPanelSize - storedBottomPanelSize
|
||||
}
|
||||
storedBottomPanelSize = 0
|
||||
}
|
||||
|
||||
function keydown(event: KeyboardEvent) {
|
||||
@@ -705,9 +680,6 @@
|
||||
|
||||
$: $connectingInput.opened, updatePannelInConnecting()
|
||||
|
||||
let testJob: Job | undefined = undefined
|
||||
let jobToWatch: { componentId: string; job: string } | undefined = undefined
|
||||
|
||||
$: updateCursorStyle(!!$connectingInput.opened && !$panzoomActive)
|
||||
|
||||
function updateCursorStyle(disabled: boolean) {
|
||||
@@ -1125,14 +1097,7 @@
|
||||
{rightPanelSize}
|
||||
{centerPanelWidth}
|
||||
{runnablePanelSize}
|
||||
>
|
||||
<RunnableJobPanel
|
||||
float={rightPanelSize !== 0}
|
||||
hidden={runnablePanelSize === 0}
|
||||
bind:testJob
|
||||
bind:jobToWatch
|
||||
/>
|
||||
</AppEditorBottomPanel>
|
||||
/>
|
||||
</Pane>
|
||||
{/if}
|
||||
</Splitpanes>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import InlineScriptsPanel from './inlineScriptsPanel/InlineScriptsPanel.svelte'
|
||||
import RunnableJobPanel from './RunnableJobPanel.svelte'
|
||||
|
||||
@@ -10,15 +9,13 @@
|
||||
|
||||
{#if rightPanelSize !== 0}
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class={twMerge('relative h-full w-full overflow-x-visible')} on:mouseenter on:mouseleave>
|
||||
<div class="relative h-full w-full overflow-x-visible" on:mouseenter on:mouseleave>
|
||||
<InlineScriptsPanel on:hidePanel />
|
||||
<RunnableJobPanel hidden={runnablePanelSize === 0} />
|
||||
<slot />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-row relative w-full h-full">
|
||||
<InlineScriptsPanel width={centerPanelWidth - 400} on:hidePanel />
|
||||
|
||||
<slot />
|
||||
<InlineScriptsPanel width={centerPanelWidth * 0.66} on:hidePanel />
|
||||
<RunnableJobPanel float={false} hidden={runnablePanelSize === 0} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
export let hidden: boolean = false
|
||||
export let testJob: Job | undefined = undefined
|
||||
export let jobToWatch: { componentId: string; job: string } | undefined = undefined
|
||||
export let width: number | undefined = undefined
|
||||
|
||||
const { runnableJobEditorPanel, selectedComponentInEditor } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
@@ -16,7 +17,7 @@
|
||||
|
||||
let testJobLoader: TestJobLoader
|
||||
|
||||
$: $runnableJobEditorPanel.focused &&
|
||||
$: ($runnableJobEditorPanel.focused || !float) &&
|
||||
$selectedComponentInEditor &&
|
||||
$runnableJobEditorPanel.jobs &&
|
||||
updateSelectedJob()
|
||||
@@ -59,7 +60,10 @@
|
||||
<RunnableJobPanelInner {testIsLoading} {frontendJob} {testJob} />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-col w-full">
|
||||
<div
|
||||
class="flex flex-col min-w-0 grow h-full"
|
||||
style={width !== undefined ? `width:${width}px;` : ''}
|
||||
>
|
||||
{#if $selectedComponentInEditor}
|
||||
<RunnableJobPanelInner {testIsLoading} {frontendJob} {testJob} />
|
||||
{:else if !hidden}
|
||||
|
||||
@@ -1281,3 +1281,24 @@ export function areShadowsTheSame(
|
||||
shadow1.h === shadow2.h
|
||||
)
|
||||
}
|
||||
|
||||
export function animateTo(start: number, end: number, onUpdate: (newValue: number) => void) {
|
||||
const duration = 400
|
||||
const startTime = performance.now()
|
||||
|
||||
function animate(time: number) {
|
||||
const elapsed = time - startTime
|
||||
const progress = Math.min(elapsed / duration, 1)
|
||||
const currentValue = start + (end - start) * easeInOut(progress)
|
||||
onUpdate(currentValue)
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(animate)
|
||||
}
|
||||
}
|
||||
|
||||
requestAnimationFrame(animate)
|
||||
}
|
||||
|
||||
function easeInOut(t: number) {
|
||||
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
|
||||
}
|
||||
|
||||
+53
-56
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext, AppViewerContext, HiddenRunnable } from '../../types'
|
||||
import SplitPanesWrapper from '$lib/components/splitPanes/SplitPanesWrapper.svelte'
|
||||
import { Pane, Splitpanes } from 'svelte-splitpanes'
|
||||
import InlineScriptsPanelList from './InlineScriptsPanelList.svelte'
|
||||
import InlineScriptEditor from './InlineScriptEditor.svelte'
|
||||
@@ -105,60 +104,58 @@
|
||||
export let width: number | undefined = undefined
|
||||
</script>
|
||||
|
||||
<SplitPanesWrapper>
|
||||
<Splitpanes
|
||||
class={twMerge('!overflow-visible')}
|
||||
style={width !== undefined ? `width:${width}px;` : ''}
|
||||
>
|
||||
<Pane size={25}>
|
||||
<InlineScriptsPanelList on:hidePanel />
|
||||
</Pane>
|
||||
<Pane size={75}>
|
||||
{#if !$selectedComponentInEditor}
|
||||
<div class="text-sm text-secondary text-center py-8 px-2">
|
||||
Select a script on the left panel
|
||||
</div>
|
||||
{:else if gridItem}
|
||||
{#key gridItem?.id}
|
||||
<InlineScriptsPanelWithTable
|
||||
<Splitpanes
|
||||
class={twMerge('!overflow-visible')}
|
||||
style={width !== undefined ? `width:${width}px;` : 'width: 100%;'}
|
||||
>
|
||||
<Pane size={25}>
|
||||
<InlineScriptsPanelList on:hidePanel />
|
||||
</Pane>
|
||||
<Pane size={75}>
|
||||
{#if !$selectedComponentInEditor}
|
||||
<div class="text-sm text-secondary text-center py-8 px-2">
|
||||
Select a script on the left panel
|
||||
</div>
|
||||
{:else if gridItem}
|
||||
{#key gridItem?.id}
|
||||
<InlineScriptsPanelWithTable
|
||||
on:createScriptFromInlineScript={(e) => {
|
||||
createScriptFromInlineScript(gridItem?.id ?? 'unknown', e.detail)
|
||||
}}
|
||||
bind:gridItem
|
||||
/>
|
||||
{/key}
|
||||
{:else if unusedInlineScript > -1 && $app.unusedInlineScripts?.[unusedInlineScript]}
|
||||
{#key unusedInlineScript}
|
||||
<InlineScriptEditor
|
||||
on:createScriptFromInlineScript={() =>
|
||||
sendUserToast('Cannot save to workspace unused scripts', true)}
|
||||
id={`unused-${unusedInlineScript}`}
|
||||
bind:name={$app.unusedInlineScripts[unusedInlineScript].name}
|
||||
bind:inlineScript={$app.unusedInlineScripts[unusedInlineScript].inlineScript}
|
||||
on:delete={() => {
|
||||
// remove the script from the array at the index
|
||||
$app.unusedInlineScripts.splice(unusedInlineScript, 1)
|
||||
$app.unusedInlineScripts = [...$app.unusedInlineScripts]
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
{:else if hiddenInlineScript > -1}
|
||||
{#key hiddenInlineScript}
|
||||
{#if $app.hiddenInlineScripts?.[hiddenInlineScript]}
|
||||
<InlineScriptHiddenRunnable
|
||||
on:createScriptFromInlineScript={(e) => {
|
||||
createScriptFromInlineScript(gridItem?.id ?? 'unknown', e.detail)
|
||||
createScriptFromInlineScript(BG_PREFIX + hiddenInlineScript, e.detail)
|
||||
}}
|
||||
bind:gridItem
|
||||
/>
|
||||
{/key}
|
||||
{:else if unusedInlineScript > -1 && $app.unusedInlineScripts?.[unusedInlineScript]}
|
||||
{#key unusedInlineScript}
|
||||
<InlineScriptEditor
|
||||
on:createScriptFromInlineScript={() =>
|
||||
sendUserToast('Cannot save to workspace unused scripts', true)}
|
||||
id={`unused-${unusedInlineScript}`}
|
||||
bind:name={$app.unusedInlineScripts[unusedInlineScript].name}
|
||||
bind:inlineScript={$app.unusedInlineScripts[unusedInlineScript].inlineScript}
|
||||
on:delete={() => {
|
||||
// remove the script from the array at the index
|
||||
$app.unusedInlineScripts.splice(unusedInlineScript, 1)
|
||||
$app.unusedInlineScripts = [...$app.unusedInlineScripts]
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
{:else if hiddenInlineScript > -1}
|
||||
{#key hiddenInlineScript}
|
||||
{#if $app.hiddenInlineScripts?.[hiddenInlineScript]}
|
||||
<InlineScriptHiddenRunnable
|
||||
on:createScriptFromInlineScript={(e) => {
|
||||
createScriptFromInlineScript(BG_PREFIX + hiddenInlineScript, e.detail)
|
||||
}}
|
||||
transformer={$selectedComponentInEditor?.endsWith('_transformer')}
|
||||
on:delete={() => deleteBackgroundScript(hiddenInlineScript)}
|
||||
id={BG_PREFIX + hiddenInlineScript}
|
||||
bind:runnable={$app.hiddenInlineScripts[hiddenInlineScript]}
|
||||
/>{/if}{/key}
|
||||
{:else}
|
||||
<div class="text-sm text-tertiary text-center py-8 px-2">
|
||||
No script found at id {$selectedComponentInEditor}
|
||||
</div>
|
||||
{/if}
|
||||
</Pane>
|
||||
</Splitpanes>
|
||||
</SplitPanesWrapper>
|
||||
transformer={$selectedComponentInEditor?.endsWith('_transformer')}
|
||||
on:delete={() => deleteBackgroundScript(hiddenInlineScript)}
|
||||
id={BG_PREFIX + hiddenInlineScript}
|
||||
bind:runnable={$app.hiddenInlineScripts[hiddenInlineScript]}
|
||||
/>{/if}{/key}
|
||||
{:else}
|
||||
<div class="text-sm text-tertiary text-center py-8 px-2">
|
||||
No script found at id {$selectedComponentInEditor}
|
||||
</div>
|
||||
{/if}
|
||||
</Pane>
|
||||
</Splitpanes>
|
||||
|
||||
+18
-11
@@ -18,13 +18,18 @@
|
||||
export let defaultUserInput = false
|
||||
export let hideCreateScript = false
|
||||
export let onlyFlow = false
|
||||
|
||||
let tab: Tab = onlyFlow ? 'workspaceflows' : 'inlinescripts'
|
||||
let filter: string = ''
|
||||
let picker: Drawer
|
||||
export let rawApps = false
|
||||
|
||||
const { app, workspace } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let tab: Tab = onlyFlow
|
||||
? 'workspaceflows'
|
||||
: $app?.unusedInlineScripts?.length > 0
|
||||
? 'inlinescripts'
|
||||
: 'workspacescripts'
|
||||
let filter: string = ''
|
||||
let picker: Drawer
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
pick: {
|
||||
runnable: Runnable
|
||||
@@ -138,15 +143,17 @@
|
||||
<div class="max-w-6xl">
|
||||
<Tabs bind:selected={tab}>
|
||||
{#if !onlyFlow}
|
||||
<Tab size="sm" value="inlinescripts">
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
<Building size={18} strokeWidth={1.5} />
|
||||
Detached Inline Scripts
|
||||
</div>
|
||||
</Tab>
|
||||
{#if !rawApps}
|
||||
<Tab size="sm" value="inlinescripts">
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
<Building size={18} strokeWidth={1.5} />
|
||||
Detached Inline Scripts
|
||||
</div>
|
||||
</Tab>
|
||||
{/if}
|
||||
<Tab size="sm" value="workspacescripts">
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
<Building size={18} strokeWidth={1.5}/>
|
||||
<Building size={18} strokeWidth={1.5} />
|
||||
Workspace Scripts
|
||||
</div>
|
||||
</Tab>
|
||||
|
||||
Reference in New Issue
Block a user