Compare commits
3 Commits
wmill-scri
...
rf/whitela
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57b02e6103 | ||
|
|
a7ed1c83c5 | ||
|
|
360a371d0e |
3
frontend/package-lock.json
generated
3
frontend/package-lock.json
generated
@@ -7,7 +7,6 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "windmill-components",
|
"name": "windmill-components",
|
||||||
"version": "1.496.3",
|
"version": "1.496.3",
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-crypto/sha256-js": "^4.0.0",
|
"@aws-crypto/sha256-js": "^4.0.0",
|
||||||
@@ -151,7 +150,7 @@
|
|||||||
"fsevents": "^2.3.3"
|
"fsevents": "^2.3.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"svelte": "^4.0.0"
|
"svelte": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@alloc/quick-lru": {
|
"node_modules/@alloc/quick-lru": {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"postinstall": "node scripts/untar_ui_builder.js && node scripts/patch_files.js",
|
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --threshold warning",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --threshold warning",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
|
"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
|
||||||
@@ -161,7 +160,7 @@
|
|||||||
"zod-to-json-schema": "^3.24.5"
|
"zod-to-json-schema": "^3.24.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"svelte": "^4.0.0"
|
"svelte": "^5.0.0"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
"./package.json": "./package.json",
|
"./package.json": "./package.json",
|
||||||
@@ -381,11 +380,16 @@
|
|||||||
"./tailwindUtils": {
|
"./tailwindUtils": {
|
||||||
"types": "./package/components/apps/editor/componentsPanel/tailwindUtils.d.ts",
|
"types": "./package/components/apps/editor/componentsPanel/tailwindUtils.d.ts",
|
||||||
"default": "./package/components/apps/editor/componentsPanel/tailwindUtils.js"
|
"default": "./package/components/apps/editor/componentsPanel/tailwindUtils.js"
|
||||||
|
},
|
||||||
|
"./components/custom_ui": {
|
||||||
|
"types": "./package/components/custom_ui.d.ts",
|
||||||
|
"default": "./package/components/custom_ui.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
"package"
|
"package",
|
||||||
|
"scripts"
|
||||||
],
|
],
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"svelte": "./dist/index.js",
|
"svelte": "./dist/index.js",
|
||||||
@@ -519,6 +523,9 @@
|
|||||||
],
|
],
|
||||||
"tailwindUtils": [
|
"tailwindUtils": [
|
||||||
"./package/components/apps/editor/componentsPanel/tailwindUtils.d.ts"
|
"./package/components/apps/editor/componentsPanel/tailwindUtils.d.ts"
|
||||||
|
],
|
||||||
|
"components/custom_ui": [
|
||||||
|
"./package/components/custom_ui.d.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
|
// Check if this script is being run from the package root
|
||||||
|
const isTopLevel = !process.env.npm_config_global && process.env.INIT_CWD === process.cwd()
|
||||||
|
|
||||||
|
if (isTopLevel) {
|
||||||
|
console.log('Running postinstall: direct install')
|
||||||
|
// Your postinstall logic here
|
||||||
|
} else {
|
||||||
|
console.log('Skipping postinstall: installed as dependency')
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
@@ -18,17 +29,6 @@ const response = await fetch(tarUrl)
|
|||||||
const buffer = await response.arrayBuffer()
|
const buffer = await response.arrayBuffer()
|
||||||
await fs.promises.writeFile(outputTarPath, Buffer.from(buffer))
|
await fs.promises.writeFile(outputTarPath, Buffer.from(buffer))
|
||||||
|
|
||||||
// Check if this script is being run from the package root
|
|
||||||
const isRootInstall = process.cwd() + '/scripts' === __dirname
|
|
||||||
|
|
||||||
if (isRootInstall) {
|
|
||||||
console.log('Running postinstall: direct install')
|
|
||||||
// Your postinstall logic here
|
|
||||||
} else {
|
|
||||||
console.log('Skipping postinstall: installed as dependency')
|
|
||||||
process.exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create extract directory if it doesn't exist
|
// Create extract directory if it doesn't exist
|
||||||
try {
|
try {
|
||||||
await fs.promises.mkdir(extractTo, { recursive: true })
|
await fs.promises.mkdir(extractTo, { recursive: true })
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
<script context="module" lang="ts">
|
<script module lang="ts">
|
||||||
export const EDITOR_BAR_WIDTH_THRESHOLD = 1044
|
export const EDITOR_BAR_WIDTH_THRESHOLD = 1044
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { run } from 'svelte/legacy'
|
||||||
|
|
||||||
import { ResourceService, VariableService, type Script } from '$lib/gen'
|
import { ResourceService, VariableService, type Script } from '$lib/gen'
|
||||||
|
|
||||||
import { workspaceStore } from '$lib/stores'
|
import { workspaceStore } from '$lib/stores'
|
||||||
@@ -47,110 +49,145 @@
|
|||||||
import type { EditorBarUi } from './custom_ui'
|
import type { EditorBarUi } from './custom_ui'
|
||||||
import EditorSettings from './EditorSettings.svelte'
|
import EditorSettings from './EditorSettings.svelte'
|
||||||
|
|
||||||
export let lang: SupportedLanguage | 'bunnative' | undefined
|
interface Props {
|
||||||
export let editor: Editor | undefined
|
lang: SupportedLanguage | 'bunnative' | undefined
|
||||||
export let websocketAlive: {
|
editor: Editor | undefined
|
||||||
pyright: boolean
|
websocketAlive: {
|
||||||
ruff: boolean
|
pyright: boolean
|
||||||
deno: boolean
|
ruff: boolean
|
||||||
go: boolean
|
deno: boolean
|
||||||
shellcheck: boolean
|
go: boolean
|
||||||
|
shellcheck: boolean
|
||||||
|
}
|
||||||
|
iconOnly?: boolean
|
||||||
|
validCode?: boolean
|
||||||
|
kind?: 'script' | 'trigger' | 'approval'
|
||||||
|
template?: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell' | 'bunnative'
|
||||||
|
collabMode?: boolean
|
||||||
|
collabLive?: boolean
|
||||||
|
collabUsers?: { name: string }[]
|
||||||
|
scriptPath?: string | undefined
|
||||||
|
diffEditor?: DiffEditor | undefined
|
||||||
|
args: Record<string, any>
|
||||||
|
noHistory?: boolean
|
||||||
|
saveToWorkspace?: boolean
|
||||||
|
customUi?: EditorBarUi
|
||||||
|
lastDeployedCode?: string | undefined
|
||||||
|
diffMode?: boolean
|
||||||
|
showHistoryDrawer?: boolean
|
||||||
|
right?: import('svelte').Snippet
|
||||||
}
|
}
|
||||||
export let iconOnly: boolean = false
|
|
||||||
export let validCode: boolean = true
|
|
||||||
export let kind: 'script' | 'trigger' | 'approval' = 'script'
|
|
||||||
export let template: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell' | 'bunnative' =
|
|
||||||
'script'
|
|
||||||
export let collabMode = false
|
|
||||||
export let collabLive = false
|
|
||||||
export let collabUsers: { name: string }[] = []
|
|
||||||
export let scriptPath: string | undefined = undefined
|
|
||||||
export let diffEditor: DiffEditor | undefined = undefined
|
|
||||||
export let args: Record<string, any>
|
|
||||||
export let noHistory = false
|
|
||||||
export let saveToWorkspace = false
|
|
||||||
export let customUi: EditorBarUi = {}
|
|
||||||
export let lastDeployedCode: string | undefined = undefined
|
|
||||||
export let diffMode: boolean = false
|
|
||||||
export let showHistoryDrawer: boolean = false
|
|
||||||
|
|
||||||
let contextualVariablePicker: ItemPicker
|
let {
|
||||||
let variablePicker: ItemPicker
|
lang,
|
||||||
let resourcePicker: ItemPicker
|
editor,
|
||||||
let resourceTypePicker: ItemPicker
|
websocketAlive,
|
||||||
let variableEditor: VariableEditor
|
iconOnly = false,
|
||||||
let resourceEditor: ResourceEditorDrawer
|
validCode = true,
|
||||||
let showContextVarPicker = false
|
kind = 'script',
|
||||||
let showVarPicker = false
|
template = 'script',
|
||||||
let showResourcePicker = false
|
collabMode = false,
|
||||||
let showResourceTypePicker = false
|
collabLive = false,
|
||||||
|
collabUsers = [],
|
||||||
|
scriptPath = undefined,
|
||||||
|
diffEditor = undefined,
|
||||||
|
args,
|
||||||
|
noHistory = false,
|
||||||
|
saveToWorkspace = false,
|
||||||
|
customUi = {},
|
||||||
|
lastDeployedCode = undefined,
|
||||||
|
diffMode = false,
|
||||||
|
showHistoryDrawer = $bindable(false),
|
||||||
|
right
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
$: showContextVarPicker = [
|
let contextualVariablePicker: ItemPicker | undefined = $state()
|
||||||
'python3',
|
let variablePicker: ItemPicker | undefined = $state()
|
||||||
'bash',
|
let resourcePicker: ItemPicker | undefined = $state()
|
||||||
'powershell',
|
let resourceTypePicker: ItemPicker | undefined = $state()
|
||||||
'go',
|
let variableEditor: VariableEditor | undefined = $state()
|
||||||
'deno',
|
let resourceEditor: ResourceEditorDrawer | undefined = $state()
|
||||||
'bun',
|
let showContextVarPicker = $state(false)
|
||||||
'bunnative',
|
let showVarPicker = $state(false)
|
||||||
'nativets',
|
let showResourcePicker = $state(false)
|
||||||
'php',
|
let showResourceTypePicker = $state(false)
|
||||||
'rust',
|
|
||||||
'csharp',
|
|
||||||
'nu',
|
|
||||||
'java'
|
|
||||||
// for related places search: ADD_NEW_LANG
|
|
||||||
].includes(lang ?? '')
|
|
||||||
$: showVarPicker = [
|
|
||||||
'python3',
|
|
||||||
'bash',
|
|
||||||
'powershell',
|
|
||||||
'go',
|
|
||||||
'deno',
|
|
||||||
'bun',
|
|
||||||
'bunnative',
|
|
||||||
'nativets',
|
|
||||||
'php',
|
|
||||||
'rust',
|
|
||||||
'csharp',
|
|
||||||
'nu',
|
|
||||||
'java'
|
|
||||||
// for related places search: ADD_NEW_LANG
|
|
||||||
].includes(lang ?? '')
|
|
||||||
$: showResourcePicker = [
|
|
||||||
'python3',
|
|
||||||
'bash',
|
|
||||||
'powershell',
|
|
||||||
'go',
|
|
||||||
'deno',
|
|
||||||
'bun',
|
|
||||||
'bunnative',
|
|
||||||
'nativets',
|
|
||||||
'php',
|
|
||||||
'rust',
|
|
||||||
'csharp',
|
|
||||||
'nu',
|
|
||||||
'java'
|
|
||||||
// for related places search: ADD_NEW_LANG
|
|
||||||
].includes(lang ?? '')
|
|
||||||
$: showResourceTypePicker =
|
|
||||||
['typescript', 'javascript'].includes(scriptLangToEditorLang(lang)) ||
|
|
||||||
lang === 'python3' ||
|
|
||||||
lang === 'php'
|
|
||||||
|
|
||||||
let codeViewer: Drawer
|
run(() => {
|
||||||
let codeObj: { language: SupportedLanguage; content: string } | undefined = undefined
|
showContextVarPicker = [
|
||||||
|
'python3',
|
||||||
|
'bash',
|
||||||
|
'powershell',
|
||||||
|
'go',
|
||||||
|
'deno',
|
||||||
|
'bun',
|
||||||
|
'bunnative',
|
||||||
|
'nativets',
|
||||||
|
'php',
|
||||||
|
'rust',
|
||||||
|
'csharp',
|
||||||
|
'nu',
|
||||||
|
'java'
|
||||||
|
// for related places search: ADD_NEW_LANG
|
||||||
|
].includes(lang ?? '')
|
||||||
|
})
|
||||||
|
run(() => {
|
||||||
|
showVarPicker = [
|
||||||
|
'python3',
|
||||||
|
'bash',
|
||||||
|
'powershell',
|
||||||
|
'go',
|
||||||
|
'deno',
|
||||||
|
'bun',
|
||||||
|
'bunnative',
|
||||||
|
'nativets',
|
||||||
|
'php',
|
||||||
|
'rust',
|
||||||
|
'csharp',
|
||||||
|
'nu',
|
||||||
|
'java'
|
||||||
|
// for related places search: ADD_NEW_LANG
|
||||||
|
].includes(lang ?? '')
|
||||||
|
})
|
||||||
|
run(() => {
|
||||||
|
showResourcePicker = [
|
||||||
|
'python3',
|
||||||
|
'bash',
|
||||||
|
'powershell',
|
||||||
|
'go',
|
||||||
|
'deno',
|
||||||
|
'bun',
|
||||||
|
'bunnative',
|
||||||
|
'nativets',
|
||||||
|
'php',
|
||||||
|
'rust',
|
||||||
|
'csharp',
|
||||||
|
'nu',
|
||||||
|
'java'
|
||||||
|
// for related places search: ADD_NEW_LANG
|
||||||
|
].includes(lang ?? '')
|
||||||
|
})
|
||||||
|
run(() => {
|
||||||
|
showResourceTypePicker =
|
||||||
|
['typescript', 'javascript'].includes(scriptLangToEditorLang(lang)) ||
|
||||||
|
lang === 'python3' ||
|
||||||
|
lang === 'php'
|
||||||
|
})
|
||||||
|
|
||||||
|
let codeViewer: Drawer | undefined = $state()
|
||||||
|
let codeObj: { language: SupportedLanguage; content: string } | undefined = $state(undefined)
|
||||||
|
|
||||||
function addEditorActions() {
|
function addEditorActions() {
|
||||||
editor?.addAction('insert-variable', 'Windmill: Insert variable', () => {
|
editor?.addAction('insert-variable', 'Windmill: Insert variable', () => {
|
||||||
variablePicker.openDrawer()
|
variablePicker?.openDrawer()
|
||||||
})
|
})
|
||||||
editor?.addAction('insert-resource', 'Windmill: Insert resource', () => {
|
editor?.addAction('insert-resource', 'Windmill: Insert resource', () => {
|
||||||
resourcePicker.openDrawer()
|
resourcePicker?.openDrawer()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$: editor && addEditorActions()
|
run(() => {
|
||||||
|
editor && addEditorActions()
|
||||||
|
})
|
||||||
|
|
||||||
async function loadVariables() {
|
async function loadVariables() {
|
||||||
return await VariableService.listVariable({ workspace: $workspaceStore ?? '' })
|
return await VariableService.listVariable({ workspace: $workspaceStore ?? '' })
|
||||||
@@ -162,9 +199,9 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let scriptPicker: Drawer
|
let scriptPicker: Drawer | undefined = $state()
|
||||||
let pick_existing: 'hub' | 'workspace' = 'hub'
|
let pick_existing: 'hub' | 'workspace' = $state('hub')
|
||||||
let filter = ''
|
let filter = $state('')
|
||||||
|
|
||||||
async function onScriptPick(e: { detail: { path: string } }) {
|
async function onScriptPick(e: { detail: { path: string } }) {
|
||||||
codeObj = undefined
|
codeObj = undefined
|
||||||
@@ -462,21 +499,23 @@ string ${windmillPathToCamelCaseName(path)} = await client.GetStringAsync(uri);
|
|||||||
itemName="Variable"
|
itemName="Variable"
|
||||||
extraField="path"
|
extraField="path"
|
||||||
loadItems={loadVariables}
|
loadItems={loadVariables}
|
||||||
buttons={{ 'Edit/View': (x) => variableEditor.editVariable(x) }}
|
buttons={{ 'Edit/View': (x) => variableEditor?.editVariable(x) }}
|
||||||
>
|
>
|
||||||
<div slot="submission" class="flex flex-row">
|
{#snippet submission()}
|
||||||
<Button
|
<div class="flex flex-row">
|
||||||
variant="border"
|
<Button
|
||||||
color="blue"
|
variant="border"
|
||||||
size="sm"
|
color="blue"
|
||||||
startIcon={{ icon: Plus }}
|
size="sm"
|
||||||
on:click={() => {
|
startIcon={{ icon: Plus }}
|
||||||
variableEditor.initNew()
|
on:click={() => {
|
||||||
}}
|
variableEditor?.initNew()
|
||||||
>
|
}}
|
||||||
New variable
|
>
|
||||||
</Button>
|
New variable
|
||||||
</div>
|
</Button>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
</ItemPicker>
|
</ItemPicker>
|
||||||
|
|
||||||
<ItemPicker
|
<ItemPicker
|
||||||
@@ -548,24 +587,26 @@ JsonNode ${windmillPathToCamelCaseName(path)} = JsonNode.Parse(await client.GetS
|
|||||||
tooltip="Resources represent connections to third party systems. Resources are a good way to define a connection to a frequently used third party system such as a database."
|
tooltip="Resources represent connections to third party systems. Resources are a good way to define a connection to a frequently used third party system such as a database."
|
||||||
documentationLink="https://www.windmill.dev/docs/core_concepts/resources_and_types"
|
documentationLink="https://www.windmill.dev/docs/core_concepts/resources_and_types"
|
||||||
itemName="Resource"
|
itemName="Resource"
|
||||||
buttons={{ 'Edit/View': (x) => resourceEditor.initEdit(x) }}
|
buttons={{ 'Edit/View': (x) => resourceEditor?.initEdit(x) }}
|
||||||
extraField="description"
|
extraField="description"
|
||||||
extraField2="resource_type"
|
extraField2="resource_type"
|
||||||
loadItems={async () =>
|
loadItems={async () =>
|
||||||
await ResourceService.listResource({ workspace: $workspaceStore ?? 'NO_W' })}
|
await ResourceService.listResource({ workspace: $workspaceStore ?? 'NO_W' })}
|
||||||
>
|
>
|
||||||
<div slot="submission" class="flex flex-row gap-x-1 mr-2">
|
{#snippet submission()}
|
||||||
<Button
|
<div class="flex flex-row gap-x-1 mr-2">
|
||||||
startIcon={{ icon: Plus }}
|
<Button
|
||||||
target="_blank"
|
startIcon={{ icon: Plus }}
|
||||||
variant="border"
|
target="_blank"
|
||||||
color="blue"
|
variant="border"
|
||||||
size="sm"
|
color="blue"
|
||||||
href="{base}/resources?connect_app=undefined"
|
size="sm"
|
||||||
>
|
href="{base}/resources?connect_app=undefined"
|
||||||
Add resource
|
>
|
||||||
</Button>
|
Add resource
|
||||||
</div>
|
</Button>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
</ItemPicker>
|
</ItemPicker>
|
||||||
|
|
||||||
{#if showResourceTypePicker}
|
{#if showResourceTypePicker}
|
||||||
@@ -650,7 +691,7 @@ JsonNode ${windmillPathToCamelCaseName(path)} = JsonNode.Parse(await client.GetS
|
|||||||
size="xs"
|
size="xs"
|
||||||
spacingSize="md"
|
spacingSize="md"
|
||||||
color="light"
|
color="light"
|
||||||
on:click={resourceTypePicker.openDrawer}
|
on:click={() => resourceTypePicker?.openDrawer}
|
||||||
{iconOnly}
|
{iconOnly}
|
||||||
startIcon={{ icon: Package }}
|
startIcon={{ icon: Package }}
|
||||||
>
|
>
|
||||||
@@ -724,7 +765,9 @@ JsonNode ${windmillPathToCamelCaseName(path)} = JsonNode.Parse(await client.GetS
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Popover>
|
<Popover>
|
||||||
<svelte:fragment slot="text">Toggle diff mode</svelte:fragment>
|
{#snippet text()}
|
||||||
|
Toggle diff mode
|
||||||
|
{/snippet}
|
||||||
<DiffIcon class="ml-1 text-tertiary" size={14} />
|
<DiffIcon class="ml-1 text-tertiary" size={14} />
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
@@ -739,14 +782,16 @@ JsonNode ${windmillPathToCamelCaseName(path)} = JsonNode.Parse(await client.GetS
|
|||||||
on:change={() => dispatch('toggleCollabMode')}
|
on:change={() => dispatch('toggleCollabMode')}
|
||||||
/>
|
/>
|
||||||
<Popover>
|
<Popover>
|
||||||
<svelte:fragment slot="text">Multiplayer</svelte:fragment>
|
{#snippet text()}
|
||||||
|
Multiplayer
|
||||||
|
{/snippet}
|
||||||
<Users class="ml-1 text-tertiary" size={14} />
|
<Users class="ml-1 text-tertiary" size={14} />
|
||||||
</Popover>
|
</Popover>
|
||||||
{#if collabLive}
|
{#if collabLive}
|
||||||
<button
|
<button
|
||||||
title="Show invite link"
|
title="Show invite link"
|
||||||
class="p-1 rounded hover:bg-gray-400 mx-1 border"
|
class="p-1 rounded hover:bg-gray-400 mx-1 border"
|
||||||
on:click={() => dispatch('collabPopup')}><Link size={14} /></button
|
onclick={() => dispatch('collabPopup')}><Link size={14} /></button
|
||||||
>
|
>
|
||||||
<div class="isolate flex -space-x-2 pl-2">
|
<div class="isolate flex -space-x-2 pl-2">
|
||||||
{#each collabUsers as user}
|
{#each collabUsers as user}
|
||||||
@@ -773,7 +818,7 @@ JsonNode ${windmillPathToCamelCaseName(path)} = JsonNode.Parse(await client.GetS
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-row items-center gap-2">
|
<div class="flex flex-row items-center gap-2">
|
||||||
<slot name="right" />
|
{@render right?.()}
|
||||||
{#if scriptPath && !noHistory}
|
{#if scriptPath && !noHistory}
|
||||||
<Button
|
<Button
|
||||||
btnClasses="!font-medium text-tertiary"
|
btnClasses="!font-medium text-tertiary"
|
||||||
|
|||||||
@@ -43,7 +43,6 @@
|
|||||||
import type { FlowEditorContext, FlowInput, FlowInputEditorState } from './flows/types'
|
import type { FlowEditorContext, FlowInput, FlowInputEditorState } from './flows/types'
|
||||||
import { cleanInputs } from './flows/utils'
|
import { cleanInputs } from './flows/utils'
|
||||||
import { Calendar, Pen, Save, DiffIcon, HistoryIcon, FileJson, type Icon } from 'lucide-svelte'
|
import { Calendar, Pen, Save, DiffIcon, HistoryIcon, FileJson, type Icon } from 'lucide-svelte'
|
||||||
import { createEventDispatcher } from 'svelte'
|
|
||||||
import Awareness from './Awareness.svelte'
|
import Awareness from './Awareness.svelte'
|
||||||
import { getAllModules } from './flows/flowExplorer'
|
import { getAllModules } from './flows/flowExplorer'
|
||||||
import { type FlowCopilotContext } from './copilot/flow'
|
import { type FlowCopilotContext } from './copilot/flow'
|
||||||
@@ -89,6 +88,24 @@
|
|||||||
export let setSavedraftCb: ((cb: () => void) => void) | undefined = undefined
|
export let setSavedraftCb: ((cb: () => void) => void) | undefined = undefined
|
||||||
export let draftTriggersFromUrl: Trigger[] | undefined = undefined
|
export let draftTriggersFromUrl: Trigger[] | undefined = undefined
|
||||||
export let selectedTriggerIndexFromUrl: number | undefined = undefined
|
export let selectedTriggerIndexFromUrl: number | undefined = undefined
|
||||||
|
export let onevent: {
|
||||||
|
deploy?: (path: string) => void
|
||||||
|
deployError?: (error: Error) => void
|
||||||
|
saveInitial?: (path: string) => void
|
||||||
|
saveDraft?: ({
|
||||||
|
path,
|
||||||
|
savedAtNewPath,
|
||||||
|
newFlow
|
||||||
|
}: {
|
||||||
|
path: string
|
||||||
|
savedAtNewPath: boolean
|
||||||
|
newFlow: boolean
|
||||||
|
}) => void
|
||||||
|
saveDraftError?: (error: Error) => void
|
||||||
|
saveDraftOnlyAtNewPath?: ({ path, selectedId }: { path: string; selectedId: string }) => void
|
||||||
|
seeDetails?: (path: string) => void
|
||||||
|
historyRestore?: () => void
|
||||||
|
} = {}
|
||||||
|
|
||||||
let initialPathStore = writable(initialPath)
|
let initialPathStore = writable(initialPath)
|
||||||
$: initialPathStore.set(initialPath)
|
$: initialPathStore.set(initialPath)
|
||||||
@@ -152,8 +169,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
|
||||||
|
|
||||||
const primaryScheduleStore = writable<ScheduleTrigger | undefined | false>(savedPrimarySchedule) // kept for legacy reasons
|
const primaryScheduleStore = writable<ScheduleTrigger | undefined | false>(savedPrimarySchedule) // kept for legacy reasons
|
||||||
const triggersCount = writable<TriggersCount | undefined>(undefined)
|
const triggersCount = writable<TriggersCount | undefined>(undefined)
|
||||||
const simplifiedPoll = writable(false)
|
const simplifiedPoll = writable(false)
|
||||||
@@ -275,18 +290,19 @@
|
|||||||
|
|
||||||
let savedAtNewPath = false
|
let savedAtNewPath = false
|
||||||
if (newFlow) {
|
if (newFlow) {
|
||||||
dispatch('saveInitial', $pathStore)
|
onevent.saveInitial?.($pathStore)
|
||||||
} else if (savedFlow?.draft_only && $pathStore !== initialPath) {
|
} else if (savedFlow?.draft_only && $pathStore !== initialPath) {
|
||||||
savedAtNewPath = true
|
savedAtNewPath = true
|
||||||
initialPath = $pathStore
|
initialPath = $pathStore
|
||||||
// this is so we can use the flow builder outside of sveltekit
|
// this is so we can use the flow builder outside of sveltekit
|
||||||
dispatch('saveDraftOnlyAtNewPath', { path: $pathStore, selectedId: getSelectedId() })
|
onevent.saveDraftOnlyAtNewPath?.({ path: $pathStore, selectedId: getSelectedId() })
|
||||||
}
|
}
|
||||||
dispatch('saveDraft', { path: $pathStore, savedAtNewPath, newFlow })
|
|
||||||
|
onevent.saveDraft?.({ path: $pathStore, savedAtNewPath, newFlow })
|
||||||
sendUserToast('Saved as draft')
|
sendUserToast('Saved as draft')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
sendUserToast(`Error while saving the flow as a draft: ${error.body || error.message}`, true)
|
sendUserToast(`Error while saving the flow as a draft: ${error.body || error.message}`, true)
|
||||||
dispatch('saveDraftError', error)
|
onevent.saveDraftError?.(error)
|
||||||
}
|
}
|
||||||
loadingDraft = false
|
loadingDraft = false
|
||||||
}
|
}
|
||||||
@@ -450,9 +466,9 @@
|
|||||||
} as Flow
|
} as Flow
|
||||||
setDraftTriggers([])
|
setDraftTriggers([])
|
||||||
loadingSave = false
|
loadingSave = false
|
||||||
dispatch('deploy', $pathStore)
|
onevent.deploy?.($pathStore)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
dispatch('deployError', err)
|
onevent.deployError?.(err)
|
||||||
sendUserToast(`The flow could not be saved: ${err.body}`, true)
|
sendUserToast(`The flow could not be saved: ${err.body}`, true)
|
||||||
loadingSave = false
|
loadingSave = false
|
||||||
}
|
}
|
||||||
@@ -651,7 +667,7 @@
|
|||||||
if (savedFlow?.draft_only === false || savedFlow?.draft_only === undefined) {
|
if (savedFlow?.draft_only === false || savedFlow?.draft_only === undefined) {
|
||||||
dropdownItems.push({
|
dropdownItems.push({
|
||||||
label: 'Exit & see details',
|
label: 'Exit & see details',
|
||||||
onClick: () => dispatch('details', $pathStore)
|
onClick: () => onevent.seeDetails?.($pathStore)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,7 +793,11 @@
|
|||||||
{#key renderCount}
|
{#key renderCount}
|
||||||
{#if !$userStore?.operator}
|
{#if !$userStore?.operator}
|
||||||
{#if $pathStore}
|
{#if $pathStore}
|
||||||
<FlowHistory bind:this={flowHistory} path={$pathStore} on:historyRestore />
|
<FlowHistory
|
||||||
|
bind:this={flowHistory}
|
||||||
|
path={$pathStore}
|
||||||
|
onHistoryRestore={() => onevent.historyRestore?.()}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<FlowYamlEditor bind:drawer={yamlEditorDrawer} />
|
<FlowYamlEditor bind:drawer={yamlEditorDrawer} />
|
||||||
<FlowImportExportMenu bind:drawer={jsonViewerDrawer} />
|
<FlowImportExportMenu bind:drawer={jsonViewerDrawer} />
|
||||||
|
|||||||
@@ -7,23 +7,41 @@
|
|||||||
import SearchItems from './SearchItems.svelte'
|
import SearchItems from './SearchItems.svelte'
|
||||||
|
|
||||||
type Item = Record<string, any>
|
type Item = Record<string, any>
|
||||||
export let pickCallback: (path: string, f: string) => void
|
|
||||||
export let loadItems: () => Promise<Item[] | undefined>
|
|
||||||
export let extraField: string = 'path'
|
|
||||||
export let extraField2: string | undefined = undefined
|
|
||||||
export let itemName: string
|
|
||||||
export let closeOnClick = true
|
|
||||||
/** Displayed if the load function returns no items. */
|
|
||||||
export let noItemMessage = 'There are no items in the list'
|
|
||||||
/** Displayed if the search returns no items. */
|
|
||||||
export let buttons: Record<string, (x: string) => void> = {}
|
|
||||||
export let tooltip: string = ''
|
|
||||||
export let documentationLink: string | undefined = undefined
|
|
||||||
|
|
||||||
let loading = false
|
interface Props {
|
||||||
let items: Item[] | undefined = []
|
pickCallback: (path: string, f: string) => void
|
||||||
let filteredItems: Item[] | undefined = []
|
loadItems: () => Promise<Item[] | undefined>
|
||||||
let filter = ''
|
extraField?: string
|
||||||
|
extraField2?: string | undefined
|
||||||
|
itemName: string
|
||||||
|
closeOnClick?: boolean
|
||||||
|
/** Displayed if the load function returns no items. */
|
||||||
|
noItemMessage?: string
|
||||||
|
/** Displayed if the search returns no items. */
|
||||||
|
buttons?: Record<string, (x: string) => void>
|
||||||
|
tooltip?: string
|
||||||
|
documentationLink?: string | undefined
|
||||||
|
submission?: import('svelte').Snippet
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
pickCallback,
|
||||||
|
loadItems,
|
||||||
|
extraField = 'path',
|
||||||
|
extraField2 = undefined,
|
||||||
|
itemName,
|
||||||
|
closeOnClick = true,
|
||||||
|
noItemMessage = 'There are no items in the list',
|
||||||
|
buttons = {},
|
||||||
|
tooltip = '',
|
||||||
|
documentationLink = undefined,
|
||||||
|
submission
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
|
let loading = $state(false)
|
||||||
|
let items: Item[] | undefined = $state([])
|
||||||
|
let filteredItems: Item[] | undefined = $state([])
|
||||||
|
let filter = $state('')
|
||||||
|
|
||||||
export function openDrawer() {
|
export function openDrawer() {
|
||||||
loading = true
|
loading = true
|
||||||
@@ -34,12 +52,12 @@
|
|||||||
.finally(() => {
|
.finally(() => {
|
||||||
loading = false
|
loading = false
|
||||||
})
|
})
|
||||||
drawer.openDrawer?.()
|
drawer?.openDrawer?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
let drawer: Drawer
|
let drawer: Drawer | undefined = $state()
|
||||||
|
|
||||||
let refreshing = false
|
let refreshing = $state(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SearchItems
|
<SearchItems
|
||||||
@@ -65,7 +83,7 @@
|
|||||||
>
|
>
|
||||||
<div class="w-full h-full flex flex-col">
|
<div class="w-full h-full flex flex-col">
|
||||||
<div class="flex flex-row gap-2 pb-4">
|
<div class="flex flex-row gap-2 pb-4">
|
||||||
<!-- svelte-ignore a11y-autofocus -->
|
<!-- svelte-ignore a11y_autofocus -->
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Search {itemName}s"
|
placeholder="Search {itemName}s"
|
||||||
@@ -110,9 +128,9 @@
|
|||||||
<button
|
<button
|
||||||
class="py-2 px-1 gap-1 flex grow border-gray-300 border-opacity-0
|
class="py-2 px-1 gap-1 flex grow border-gray-300 border-opacity-0
|
||||||
text-primary"
|
text-primary"
|
||||||
on:click={() => {
|
onclick={() => {
|
||||||
if (closeOnClick) {
|
if (closeOnClick) {
|
||||||
drawer.closeDrawer()
|
drawer?.closeDrawer()
|
||||||
}
|
}
|
||||||
pickCallback(obj['path'], obj[extraField])
|
pickCallback(obj['path'], obj[extraField])
|
||||||
}}
|
}}
|
||||||
@@ -174,8 +192,8 @@
|
|||||||
<NoItemFound />
|
<NoItemFound />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<svelte:fragment slot="actions">
|
{#snippet actions()}
|
||||||
<slot name="submission" />
|
{@render submission?.()}
|
||||||
</svelte:fragment>
|
{/snippet}
|
||||||
</DrawerContent>
|
</DrawerContent>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
import { writable } from 'svelte/store'
|
import { writable } from 'svelte/store'
|
||||||
import { defaultScriptLanguages, processLangs } from '$lib/scripts'
|
import { defaultScriptLanguages, processLangs } from '$lib/scripts'
|
||||||
import DefaultScripts from './DefaultScripts.svelte'
|
import DefaultScripts from './DefaultScripts.svelte'
|
||||||
import { createEventDispatcher, onMount, setContext } from 'svelte'
|
import { onMount, setContext } from 'svelte'
|
||||||
import Summary from './Summary.svelte'
|
import Summary from './Summary.svelte'
|
||||||
import type { ScriptBuilderWhitelabelCustomUi } from './custom_ui'
|
import type { ScriptBuilderWhitelabelCustomUi } from './custom_ui'
|
||||||
import DeployOverrideConfirmationModal from '$lib/components/common/confirmationModal/DeployOverrideConfirmationModal.svelte'
|
import DeployOverrideConfirmationModal from '$lib/components/common/confirmationModal/DeployOverrideConfirmationModal.svelte'
|
||||||
@@ -112,6 +112,22 @@
|
|||||||
export let savedPrimarySchedule: ScheduleTrigger | undefined = undefined
|
export let savedPrimarySchedule: ScheduleTrigger | undefined = undefined
|
||||||
export let functionExports: ((exports: ScriptBuilderFunctionExports) => void) | undefined =
|
export let functionExports: ((exports: ScriptBuilderFunctionExports) => void) | undefined =
|
||||||
undefined
|
undefined
|
||||||
|
export let onevent: {
|
||||||
|
deploy?: (newHash: string) => void
|
||||||
|
deployError?: (error: Error) => void
|
||||||
|
saveInitial?: (path: string) => void
|
||||||
|
saveDraft?: ({
|
||||||
|
path,
|
||||||
|
savedAtNewPath,
|
||||||
|
script
|
||||||
|
}: {
|
||||||
|
path: string
|
||||||
|
savedAtNewPath: boolean
|
||||||
|
script: NewScript
|
||||||
|
}) => void
|
||||||
|
saveDraftError?: (error: Error) => void
|
||||||
|
seeDetails?: (path: string) => void
|
||||||
|
} = {}
|
||||||
|
|
||||||
export function getInitialAndModifiedValues(): SavedAndModifiedValue {
|
export function getInitialAndModifiedValues(): SavedAndModifiedValue {
|
||||||
return {
|
return {
|
||||||
@@ -183,8 +199,6 @@
|
|||||||
loadTriggers()
|
loadTriggers()
|
||||||
}
|
}
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
|
||||||
|
|
||||||
$: initialPath != '' && loadTriggers()
|
$: initialPath != '' && loadTriggers()
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
@@ -566,10 +580,10 @@
|
|||||||
script.parent_hash = newHash
|
script.parent_hash = newHash
|
||||||
sendUserToast('Deployed')
|
sendUserToast('Deployed')
|
||||||
} else {
|
} else {
|
||||||
dispatch('deploy', newHash)
|
onevent.deploy?.(newHash)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch('deployError', error)
|
onevent.deployError?.(error)
|
||||||
sendUserToast(`Error while saving the script: ${error.body || error.message}`, true)
|
sendUserToast(`Error while saving the script: ${error.body || error.message}`, true)
|
||||||
}
|
}
|
||||||
loadingSave = false
|
loadingSave = false
|
||||||
@@ -701,9 +715,9 @@
|
|||||||
if (initialPath == '' || (savedScript?.draft_only && script.path !== initialPath)) {
|
if (initialPath == '' || (savedScript?.draft_only && script.path !== initialPath)) {
|
||||||
savedAtNewPath = true
|
savedAtNewPath = true
|
||||||
initialPath = script.path
|
initialPath = script.path
|
||||||
dispatch('saveInitial', script.path)
|
onevent.saveInitial?.(script.path)
|
||||||
}
|
}
|
||||||
dispatch('saveDraft', { path: script.path, savedAtNewPath, script })
|
onevent.saveDraft?.({ path: script.path, savedAtNewPath, script })
|
||||||
|
|
||||||
sendUserToast('Saved as draft')
|
sendUserToast('Saved as draft')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -711,7 +725,7 @@
|
|||||||
`Error while saving the script as a draft: ${error.body || error.message}`,
|
`Error while saving the script as a draft: ${error.body || error.message}`,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
dispatch('saveDraftError', error)
|
onevent.saveDraftError?.(error)
|
||||||
}
|
}
|
||||||
loadingDraft = false
|
loadingDraft = false
|
||||||
}
|
}
|
||||||
@@ -769,7 +783,7 @@
|
|||||||
{
|
{
|
||||||
label: 'Exit & See details',
|
label: 'Exit & See details',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
dispatch('seeDetails', initialPath)
|
onevent.seeDetails?.(initialPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -1686,12 +1700,8 @@
|
|||||||
{customUi}
|
{customUi}
|
||||||
collabMode
|
collabMode
|
||||||
edit={initialPath != ''}
|
edit={initialPath != ''}
|
||||||
on:format={() => {
|
onFormat={() => saveDraft()}
|
||||||
saveDraft()
|
onSaveDraft={() => saveDraft()}
|
||||||
}}
|
|
||||||
on:saveDraft={() => {
|
|
||||||
saveDraft()
|
|
||||||
}}
|
|
||||||
on:openTriggers={openTriggers}
|
on:openTriggers={openTriggers}
|
||||||
on:applyArgs={applyArgs}
|
on:applyArgs={applyArgs}
|
||||||
on:addPreprocessor={addPreprocessor}
|
on:addPreprocessor={addPreprocessor}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
import EditorBar, { EDITOR_BAR_WIDTH_THRESHOLD } from './EditorBar.svelte'
|
import EditorBar, { EDITOR_BAR_WIDTH_THRESHOLD } from './EditorBar.svelte'
|
||||||
import TestJobLoader from './TestJobLoader.svelte'
|
import TestJobLoader from './TestJobLoader.svelte'
|
||||||
import JobProgressBar from '$lib/components/jobs/JobProgressBar.svelte'
|
import JobProgressBar from '$lib/components/jobs/JobProgressBar.svelte'
|
||||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
|
import { onDestroy, onMount } from 'svelte'
|
||||||
import { Button } from './common'
|
import { Button } from './common'
|
||||||
import SplitPanesWrapper from './splitPanes/SplitPanesWrapper.svelte'
|
import SplitPanesWrapper from './splitPanes/SplitPanesWrapper.svelte'
|
||||||
import WindmillIcon from './icons/WindmillIcon.svelte'
|
import WindmillIcon from './icons/WindmillIcon.svelte'
|
||||||
@@ -42,78 +42,114 @@
|
|||||||
import HideButton from './apps/editor/settingsPanel/HideButton.svelte'
|
import HideButton from './apps/editor/settingsPanel/HideButton.svelte'
|
||||||
import { base } from '$lib/base'
|
import { base } from '$lib/base'
|
||||||
import { SUPPORTED_CHAT_SCRIPT_LANGUAGES } from './copilot/chat/script/core'
|
import { SUPPORTED_CHAT_SCRIPT_LANGUAGES } from './copilot/chat/script/core'
|
||||||
import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted'
|
|
||||||
import { getStringError } from './copilot/chat/utils'
|
import { getStringError } from './copilot/chat/utils'
|
||||||
import type { ScriptOptions } from './copilot/chat/ContextManager.svelte'
|
import type { ScriptOptions } from './copilot/chat/ContextManager.svelte'
|
||||||
import { aiChatManager, AIMode } from './copilot/chat/AIChatManager.svelte'
|
import { aiChatManager, AIMode } from './copilot/chat/AIChatManager.svelte'
|
||||||
import TriggerableByAI from './TriggerableByAI.svelte'
|
import TriggerableByAI from './TriggerableByAI.svelte'
|
||||||
|
|
||||||
// Exported
|
interface Props {
|
||||||
export let schema: Schema | any = emptySchema()
|
// Exported
|
||||||
export let code: string
|
schema?: Schema | any
|
||||||
export let path: string | undefined
|
code: string
|
||||||
export let lang: Preview['language']
|
path: string | undefined
|
||||||
export let kind: string | undefined = undefined
|
lang: Preview['language']
|
||||||
export let template: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell' | 'bunnative' =
|
kind?: string | undefined
|
||||||
'script'
|
template?: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell' | 'bunnative'
|
||||||
export let tag: string | undefined
|
tag: string | undefined
|
||||||
export let initialArgs: Record<string, any> = {}
|
initialArgs?: Record<string, any>
|
||||||
export let fixedOverflowWidgets = true
|
fixedOverflowWidgets?: boolean
|
||||||
export let noSyncFromGithub = false
|
noSyncFromGithub?: boolean
|
||||||
export let editor: Editor | undefined = undefined
|
editor?: Editor | undefined
|
||||||
export let diffEditor: DiffEditor | undefined = undefined
|
diffEditor?: DiffEditor | undefined
|
||||||
export let collabMode = false
|
collabMode?: boolean
|
||||||
export let edit = true
|
edit?: boolean
|
||||||
export let noHistory = false
|
noHistory?: boolean
|
||||||
export let saveToWorkspace = false
|
saveToWorkspace?: boolean
|
||||||
export let watchChanges = false
|
watchChanges?: boolean
|
||||||
export let customUi: ScriptEditorWhitelabelCustomUi | undefined = undefined
|
customUi?: ScriptEditorWhitelabelCustomUi | undefined
|
||||||
export let args: Record<string, any> = initialArgs
|
args?: Record<string, any>
|
||||||
export let selectedTab: 'main' | 'preprocessor' = 'main'
|
selectedTab?: 'main' | 'preprocessor'
|
||||||
export let hasPreprocessor = false
|
hasPreprocessor?: boolean
|
||||||
export let captureTable: CaptureTable | undefined = undefined
|
captureTable?: CaptureTable | undefined
|
||||||
export let showCaptures: boolean = true
|
showCaptures?: boolean
|
||||||
export let stablePathForCaptures: string = ''
|
stablePathForCaptures?: string
|
||||||
export let lastSavedCode: string | undefined = undefined
|
lastSavedCode?: string | undefined
|
||||||
export let lastDeployedCode: string | undefined = undefined
|
lastDeployedCode?: string | undefined
|
||||||
|
editor_bar_right?: import('svelte').Snippet
|
||||||
|
onChange?: (code: string, schema: Schema) => void
|
||||||
|
onFormat?: () => void
|
||||||
|
onSaveDraft?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
let showHistoryDrawer = false
|
let {
|
||||||
|
schema = $bindable(emptySchema()),
|
||||||
|
code = $bindable(),
|
||||||
|
path,
|
||||||
|
lang,
|
||||||
|
kind = undefined,
|
||||||
|
template = 'script',
|
||||||
|
tag,
|
||||||
|
initialArgs = {},
|
||||||
|
fixedOverflowWidgets = true,
|
||||||
|
noSyncFromGithub = false,
|
||||||
|
editor = $bindable(undefined),
|
||||||
|
diffEditor = $bindable(undefined),
|
||||||
|
collabMode = false,
|
||||||
|
edit = true,
|
||||||
|
noHistory = false,
|
||||||
|
saveToWorkspace = false,
|
||||||
|
watchChanges = false,
|
||||||
|
customUi = undefined,
|
||||||
|
args = $bindable(initialArgs),
|
||||||
|
selectedTab = $bindable('main'),
|
||||||
|
hasPreprocessor = $bindable(false),
|
||||||
|
captureTable = $bindable(undefined),
|
||||||
|
showCaptures = true,
|
||||||
|
stablePathForCaptures = '',
|
||||||
|
lastSavedCode = undefined,
|
||||||
|
lastDeployedCode = undefined,
|
||||||
|
editor_bar_right,
|
||||||
|
onChange,
|
||||||
|
onFormat,
|
||||||
|
onSaveDraft
|
||||||
|
}: Props = $props()
|
||||||
|
// export let onC
|
||||||
|
|
||||||
let jobProgressReset: () => void
|
let showHistoryDrawer = $state(false)
|
||||||
let diffMode = false
|
|
||||||
|
|
||||||
let websocketAlive = {
|
let jobProgressReset: (() => void) | undefined = $state()
|
||||||
|
let diffMode = $state(false)
|
||||||
|
|
||||||
|
let websocketAlive = $state({
|
||||||
pyright: false,
|
pyright: false,
|
||||||
deno: false,
|
deno: false,
|
||||||
go: false,
|
go: false,
|
||||||
ruff: false,
|
ruff: false,
|
||||||
shellcheck: false
|
shellcheck: false
|
||||||
}
|
})
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
$effect(() => {
|
||||||
const dispatchIfMounted = createDispatcherIfMounted(dispatch)
|
watchChanges && (code != undefined || schema != undefined) && onChange?.(code, schema)
|
||||||
|
})
|
||||||
|
|
||||||
$: watchChanges &&
|
let width = $state(1200)
|
||||||
(code != undefined || schema != undefined) &&
|
|
||||||
dispatchIfMounted('change', { code, schema })
|
|
||||||
|
|
||||||
let width = 1200
|
let testJobLoader: TestJobLoader | undefined = $state()
|
||||||
|
|
||||||
let testJobLoader: TestJobLoader
|
let isValid: boolean = $state(true)
|
||||||
|
let scriptProgress = $state(undefined)
|
||||||
let isValid: boolean = true
|
|
||||||
let scriptProgress = undefined
|
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
let testIsLoading = false
|
let testIsLoading = $state(false)
|
||||||
let testJob: Job | undefined
|
let testJob: Job | undefined = $state()
|
||||||
let pastPreviews: CompletedJob[] = []
|
let pastPreviews: CompletedJob[] = $state([])
|
||||||
let validCode = true
|
let validCode = $state(true)
|
||||||
|
let logPanel: LogPanel | undefined = $state()
|
||||||
|
|
||||||
let wsProvider: WebsocketProvider | undefined = undefined
|
let wsProvider: WebsocketProvider | undefined = $state(undefined)
|
||||||
let yContent: Y.Text | undefined = undefined
|
let yContent: Y.Text | undefined = $state(undefined)
|
||||||
let peers: { name: string }[] = []
|
let peers: { name: string }[] = $state([])
|
||||||
let showCollabPopup = false
|
let showCollabPopup = $state(false)
|
||||||
|
|
||||||
const url = new URL(window.location.toString())
|
const url = new URL(window.location.toString())
|
||||||
let initialCollab = /true|1/i.test(url.searchParams.get('collab') ?? '0')
|
let initialCollab = /true|1/i.test(url.searchParams.get('collab') ?? '0')
|
||||||
@@ -292,11 +328,15 @@
|
|||||||
return `${url}?collab=1` + (edit ? '' : `&path=${path}`)
|
return `${url}?collab=1` + (edit ? '' : `&path=${path}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
$: showTabs = hasPreprocessor
|
let showTabs = $derived(hasPreprocessor)
|
||||||
$: !hasPreprocessor && (selectedTab = 'main')
|
$effect(() => {
|
||||||
$: selectedTab && inferSchema(code)
|
!hasPreprocessor && (selectedTab = 'main')
|
||||||
|
})
|
||||||
|
$effect(() => {
|
||||||
|
selectedTab && inferSchema(code)
|
||||||
|
})
|
||||||
|
|
||||||
let argsRender = 0
|
let argsRender = $state(0)
|
||||||
export async function updateArgs(newArgs: Record<string, any>) {
|
export async function updateArgs(newArgs: Record<string, any>) {
|
||||||
if (Object.keys(newArgs).length > 0) {
|
if (Object.keys(newArgs).length > 0) {
|
||||||
args = { ...newArgs }
|
args = { ...newArgs }
|
||||||
@@ -304,17 +344,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let setFocusToLogs = () => {}
|
function setFocusToLogs() {
|
||||||
|
logPanel?.setFocusToLogs()
|
||||||
|
}
|
||||||
|
|
||||||
setContext('disableTooltips', customUi?.disableTooltips === true)
|
setContext('disableTooltips', customUi?.disableTooltips === true)
|
||||||
|
|
||||||
let codePanelSize = 70
|
let codePanelSize = $state(70)
|
||||||
let testPanelSize = 30
|
let testPanelSize = $state(30)
|
||||||
let storedTestPanelSize = testPanelSize
|
let storedTestPanelSize = testPanelSize
|
||||||
|
|
||||||
$: !SUPPORTED_CHAT_SCRIPT_LANGUAGES.includes(lang ?? '') &&
|
$effect(() => {
|
||||||
!aiChatManager.open &&
|
!SUPPORTED_CHAT_SCRIPT_LANGUAGES.includes(lang ?? '') &&
|
||||||
aiChatManager.toggleOpen()
|
!aiChatManager.open &&
|
||||||
|
aiChatManager.toggleOpen()
|
||||||
|
})
|
||||||
|
|
||||||
function toggleTestPanel() {
|
function toggleTestPanel() {
|
||||||
if (testPanelSize > 0) {
|
if (testPanelSize > 0) {
|
||||||
@@ -348,9 +392,9 @@
|
|||||||
editor?.show()
|
editor?.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
$: error = getError(testJob)
|
let error = $derived(getError(testJob))
|
||||||
|
|
||||||
$: {
|
$effect(() => {
|
||||||
const options: ScriptOptions = {
|
const options: ScriptOptions = {
|
||||||
code,
|
code,
|
||||||
lang: lang as ScriptLang,
|
lang: lang as ScriptLang,
|
||||||
@@ -367,7 +411,7 @@
|
|||||||
editor?.reviewAndApplyCode(code)
|
editor?.reviewAndApplyCode(code)
|
||||||
}
|
}
|
||||||
aiChatManager.scriptEditorShowDiffMode = showDiffMode
|
aiChatManager.scriptEditorShowDiffMode = showDiffMode
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<TestJobLoader
|
<TestJobLoader
|
||||||
@@ -378,7 +422,7 @@
|
|||||||
bind:job={testJob}
|
bind:job={testJob}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<svelte:window on:keydown={onKeyDown} />
|
<svelte:window onkeydown={onKeyDown} />
|
||||||
|
|
||||||
<TriggerableByAI id="script-editor" description="Component to edit a script" />
|
<TriggerableByAI id="script-editor" description="Component to edit a script" />
|
||||||
|
|
||||||
@@ -431,7 +475,9 @@
|
|||||||
{diffMode}
|
{diffMode}
|
||||||
bind:showHistoryDrawer
|
bind:showHistoryDrawer
|
||||||
>
|
>
|
||||||
<slot name="editor-bar-right" slot="right" />
|
{#snippet right()}
|
||||||
|
{@render editor_bar_right?.()}
|
||||||
|
{/snippet}
|
||||||
</EditorBar>
|
</EditorBar>
|
||||||
{#if !noSyncFromGithub && customUi?.editorBar?.useVsCode != false}
|
{#if !noSyncFromGithub && customUi?.editorBar?.useVsCode != false}
|
||||||
<div class="py-1">
|
<div class="py-1">
|
||||||
@@ -490,7 +536,7 @@
|
|||||||
aiChatManager.toggleOpen()
|
aiChatManager.toggleOpen()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="popoverOverride">
|
{#snippet popoverOverride()}
|
||||||
<div class="text-sm">
|
<div class="text-sm">
|
||||||
Enable Windmill AI in the <a
|
Enable Windmill AI in the <a
|
||||||
href="{base}/workspace_settings?tab=ai"
|
href="{base}/workspace_settings?tab=ai"
|
||||||
@@ -500,7 +546,7 @@
|
|||||||
workspace settings <ExternalLink size={16} />
|
workspace settings <ExternalLink size={16} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</svelte:fragment>
|
{/snippet}
|
||||||
</HideButton>
|
</HideButton>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -518,7 +564,7 @@
|
|||||||
on:change={(e) => {
|
on:change={(e) => {
|
||||||
inferSchema(e.detail)
|
inferSchema(e.detail)
|
||||||
}}
|
}}
|
||||||
on:saveDraft
|
on:saveDraft={() => onSaveDraft?.()}
|
||||||
on:toggleAiPanel={() => aiChatManager.toggleOpen()}
|
on:toggleAiPanel={() => aiChatManager.toggleOpen()}
|
||||||
on:addSelectedLinesToAiChat={(e) => {
|
on:addSelectedLinesToAiChat={(e) => {
|
||||||
const { lines, startLine, endLine } = e.detail
|
const { lines, startLine, endLine } = e.detail
|
||||||
@@ -536,7 +582,7 @@
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Could not save last_save to local storage', e)
|
console.error('Could not save last_save to local storage', e)
|
||||||
}
|
}
|
||||||
dispatch('format')
|
onFormat?.()
|
||||||
}}
|
}}
|
||||||
class="flex flex-1 h-full !overflow-visible"
|
class="flex flex-1 h-full !overflow-visible"
|
||||||
scriptLang={lang}
|
scriptLang={lang}
|
||||||
@@ -670,7 +716,7 @@
|
|||||||
</Pane>
|
</Pane>
|
||||||
<Pane size={67} class="relative">
|
<Pane size={67} class="relative">
|
||||||
<LogPanel
|
<LogPanel
|
||||||
bind:setFocusToLogs
|
bind:this={logPanel}
|
||||||
{lang}
|
{lang}
|
||||||
previewJob={testJob}
|
previewJob={testJob}
|
||||||
{pastPreviews}
|
{pastPreviews}
|
||||||
@@ -690,7 +736,7 @@
|
|||||||
compact={true}
|
compact={true}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<svelte:fragment slot="capturesTab">
|
{#snippet capturesTab()}
|
||||||
<div class="h-full p-2">
|
<div class="h-full p-2">
|
||||||
<CaptureTable
|
<CaptureTable
|
||||||
bind:this={captureTable}
|
bind:this={captureTable}
|
||||||
@@ -704,7 +750,7 @@
|
|||||||
on:addPreprocessor
|
on:addPreprocessor
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</svelte:fragment>
|
{/snippet}
|
||||||
</LogPanel>
|
</LogPanel>
|
||||||
</Pane>
|
</Pane>
|
||||||
</Splitpanes>
|
</Splitpanes>
|
||||||
|
|||||||
@@ -79,6 +79,10 @@
|
|||||||
path: string,
|
path: string,
|
||||||
opt?: Record<string, any>
|
opt?: Record<string, any>
|
||||||
) => window.history.pushState(null, '', path)
|
) => window.history.pushState(null, '', path)
|
||||||
|
export let onevent: {
|
||||||
|
savedNewAppPath?: (path: string) => void
|
||||||
|
restore?: (app: App) => void
|
||||||
|
} = {}
|
||||||
|
|
||||||
migrateApp(app)
|
migrateApp(app)
|
||||||
|
|
||||||
@@ -805,7 +809,7 @@
|
|||||||
<AppEditorHeader
|
<AppEditorHeader
|
||||||
{newPath}
|
{newPath}
|
||||||
{newApp}
|
{newApp}
|
||||||
on:restore
|
on:restore={(e) => onevent.restore?.(e.detail)}
|
||||||
{policy}
|
{policy}
|
||||||
{fromHub}
|
{fromHub}
|
||||||
bind:this={appEditorHeader}
|
bind:this={appEditorHeader}
|
||||||
@@ -815,7 +819,7 @@
|
|||||||
leftPanelHidden={leftPanelSize === 0}
|
leftPanelHidden={leftPanelSize === 0}
|
||||||
rightPanelHidden={rightPanelSize === 0}
|
rightPanelHidden={rightPanelSize === 0}
|
||||||
bottomPanelHidden={runnablePanelSize === 0}
|
bottomPanelHidden={runnablePanelSize === 0}
|
||||||
on:savedNewAppPath
|
on:savedNewAppPath={(e) => onevent.savedNewAppPath?.(e.detail)}
|
||||||
on:showLeftPanel={() => showLeftPanel()}
|
on:showLeftPanel={() => showLeftPanel()}
|
||||||
on:showRightPanel={() => showRightPanel()}
|
on:showRightPanel={() => showRightPanel()}
|
||||||
on:hideLeftPanel={() => hideLeftPanel()}
|
on:hideLeftPanel={() => hideLeftPanel()}
|
||||||
|
|||||||
@@ -13,17 +13,33 @@
|
|||||||
} from 'lucide-svelte'
|
} from 'lucide-svelte'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
export let btnClasses: string | undefined = undefined
|
interface Props {
|
||||||
export let size: ButtonType.Size = 'xs'
|
btnClasses?: string | undefined
|
||||||
|
size?: ButtonType.Size
|
||||||
|
variant?: ButtonType.Variant
|
||||||
|
color?: ButtonType.Color
|
||||||
|
direction?: 'left' | 'right' | 'bottom'
|
||||||
|
hidden?: boolean
|
||||||
|
shortcut?: string | undefined
|
||||||
|
panelName?: string | undefined
|
||||||
|
customHiddenIcon?: ButtonType.Icon | undefined
|
||||||
|
usePopoverOverride?: boolean
|
||||||
|
popoverOverride?: import('svelte').Snippet
|
||||||
|
}
|
||||||
|
|
||||||
export let variant: ButtonType.Variant = 'contained'
|
let {
|
||||||
export let color: ButtonType.Color = 'light'
|
btnClasses = undefined,
|
||||||
export let direction: 'left' | 'right' | 'bottom' = 'right'
|
size = 'xs',
|
||||||
export let hidden: boolean = false
|
variant = 'contained',
|
||||||
export let shortcut: string | undefined = undefined
|
color = 'light',
|
||||||
export let panelName: string | undefined = undefined
|
direction = 'right',
|
||||||
export let customHiddenIcon: ButtonType.Icon | undefined = undefined
|
hidden = false,
|
||||||
export let usePopoverOverride: boolean = false
|
shortcut = undefined,
|
||||||
|
panelName = undefined,
|
||||||
|
customHiddenIcon = undefined,
|
||||||
|
usePopoverOverride = false,
|
||||||
|
popoverOverride
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
const OpenIconMap = {
|
const OpenIconMap = {
|
||||||
left: PanelLeftOpen,
|
left: PanelLeftOpen,
|
||||||
@@ -45,9 +61,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Popover>
|
<Popover>
|
||||||
<svelte:fragment slot="text">
|
{#snippet text()}
|
||||||
{#if usePopoverOverride && $$slots.popoverOverride}
|
{#if usePopoverOverride && popoverOverride}
|
||||||
<slot name="popoverOverride" />
|
{@render popoverOverride?.()}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="flex flex-row gap-1">
|
<div class="flex flex-row gap-1">
|
||||||
{hidden ? 'Show' : 'Hide '} the {panelName ?? direction} panel.
|
{hidden ? 'Show' : 'Hide '} the {panelName ?? direction} panel.
|
||||||
@@ -57,7 +73,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</svelte:fragment>
|
{/snippet}
|
||||||
<Button
|
<Button
|
||||||
iconOnly
|
iconOnly
|
||||||
startIcon={hidden
|
startIcon={hidden
|
||||||
|
|||||||
@@ -5,17 +5,35 @@
|
|||||||
import TriggerableByAI from '$lib/components/TriggerableByAI.svelte'
|
import TriggerableByAI from '$lib/components/TriggerableByAI.svelte'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
|
||||||
export let aiId: string | undefined = undefined
|
interface Props {
|
||||||
export let aiDescription: string | undefined = undefined
|
aiId?: string | undefined
|
||||||
export let title: string | undefined = undefined
|
aiDescription?: string | undefined
|
||||||
export let overflow_y = true
|
title?: string | undefined
|
||||||
export let noPadding = false
|
overflow_y?: boolean
|
||||||
export let forceOverflowVisible = false
|
noPadding?: boolean
|
||||||
export let tooltip: string = ''
|
forceOverflowVisible?: boolean
|
||||||
export let documentationLink: string | undefined = undefined
|
tooltip?: string
|
||||||
export let CloseIcon: any | undefined = undefined
|
documentationLink?: string | undefined
|
||||||
|
CloseIcon?: any | undefined
|
||||||
|
fullScreen?: boolean
|
||||||
|
actions?: import('svelte').Snippet
|
||||||
|
children?: import('svelte').Snippet
|
||||||
|
}
|
||||||
|
|
||||||
export let fullScreen: boolean = true
|
let {
|
||||||
|
aiId = undefined,
|
||||||
|
aiDescription = undefined,
|
||||||
|
title = undefined,
|
||||||
|
overflow_y = true,
|
||||||
|
noPadding = false,
|
||||||
|
forceOverflowVisible = false,
|
||||||
|
tooltip = '',
|
||||||
|
documentationLink = undefined,
|
||||||
|
CloseIcon = undefined,
|
||||||
|
fullScreen = true,
|
||||||
|
actions,
|
||||||
|
children
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
</script>
|
</script>
|
||||||
@@ -39,9 +57,9 @@
|
|||||||
{/if}</span
|
{/if}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
{#if $$slots.actions}
|
{#if actions}
|
||||||
<div class="flex gap-2 items-center justify-end">
|
<div class="flex gap-2 items-center justify-end">
|
||||||
<slot name="actions" />
|
{@render actions?.()}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@@ -54,6 +72,6 @@
|
|||||||
)}
|
)}
|
||||||
class:overflow-y-auto={overflow_y}
|
class:overflow-y-auto={overflow_y}
|
||||||
>
|
>
|
||||||
<slot />
|
{@render children?.()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
76
frontend/src/lib/components/common/tabs/TabsV2.svelte
Normal file
76
frontend/src/lib/components/common/tabs/TabsV2.svelte
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { setContext } from 'svelte'
|
||||||
|
import { writable } from 'svelte/store'
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
import type { TabsContext } from './tabs.svelte'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
selected: string
|
||||||
|
hideTabs?: boolean
|
||||||
|
class?: string
|
||||||
|
wrapperClass?: string
|
||||||
|
style?: string
|
||||||
|
hashNavigation?: boolean
|
||||||
|
values?: string[] | undefined
|
||||||
|
children?: import('svelte').Snippet<[any]>
|
||||||
|
content?: import('svelte').Snippet
|
||||||
|
onSelectedChange?: (value: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
selected = $bindable(),
|
||||||
|
hideTabs = false,
|
||||||
|
class: c = '',
|
||||||
|
wrapperClass = '',
|
||||||
|
style = '',
|
||||||
|
hashNavigation = false,
|
||||||
|
values = undefined,
|
||||||
|
children,
|
||||||
|
content,
|
||||||
|
onSelectedChange
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
|
const selectedStore = writable(selected)
|
||||||
|
|
||||||
|
setContext<TabsContext>('Tabs', {
|
||||||
|
selected: selectedStore,
|
||||||
|
update: (value: string) => {
|
||||||
|
selectedStore.set(value)
|
||||||
|
selected = value
|
||||||
|
},
|
||||||
|
hashNavigation
|
||||||
|
})
|
||||||
|
|
||||||
|
function updateSelected() {
|
||||||
|
selectedStore.set(selected)
|
||||||
|
}
|
||||||
|
|
||||||
|
function hashChange() {
|
||||||
|
if (hashNavigation) {
|
||||||
|
const hash = window.location.hash
|
||||||
|
if (hash && hashValues?.includes(hash)) {
|
||||||
|
const id = hash.replace('#', '')
|
||||||
|
selectedStore.set(id)
|
||||||
|
selected = id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$effect(() => {
|
||||||
|
selected && updateSelected()
|
||||||
|
})
|
||||||
|
$effect(() => {
|
||||||
|
$selectedStore && onSelectedChange?.($selectedStore)
|
||||||
|
})
|
||||||
|
|
||||||
|
let hashValues = $derived(values ? values.map((x) => '#' + x) : undefined)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:window onhashchange={hashChange} />
|
||||||
|
{#if !hideTabs}
|
||||||
|
<div class="overflow-x-auto {wrapperClass}">
|
||||||
|
<div class={twMerge('border-b flex flex-row whitespace-nowrap scrollbar-hidden', c)} {style}>
|
||||||
|
{@render children?.({ selected })}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{@render content?.()}
|
||||||
7
frontend/src/lib/components/common/tabs/tabs.svelte.ts
Normal file
7
frontend/src/lib/components/common/tabs/tabs.svelte.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import type { Writable } from 'svelte/store'
|
||||||
|
|
||||||
|
export type TabsContext = {
|
||||||
|
selected: Writable<string>
|
||||||
|
update: (value: string) => void
|
||||||
|
hashNavigation: boolean
|
||||||
|
}
|
||||||
@@ -1,18 +1,20 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from 'svelte'
|
|
||||||
import Drawer from '../common/drawer/Drawer.svelte'
|
import Drawer from '../common/drawer/Drawer.svelte'
|
||||||
import DrawerContent from '../common/drawer/DrawerContent.svelte'
|
import DrawerContent from '../common/drawer/DrawerContent.svelte'
|
||||||
|
|
||||||
import FlowHistoryInner from './FlowHistoryInner.svelte'
|
import FlowHistoryInner from './FlowHistoryInner.svelte'
|
||||||
|
|
||||||
export let path: string
|
interface Props {
|
||||||
let drawer: Drawer
|
path: string
|
||||||
|
onHistoryRestore: () => void
|
||||||
export function open() {
|
|
||||||
drawer.openDrawer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
let { path, onHistoryRestore }: Props = $props()
|
||||||
|
let drawer: Drawer | undefined = undefined
|
||||||
|
|
||||||
|
export function open() {
|
||||||
|
drawer?.openDrawer()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Drawer bind:this={drawer} size="1200px">
|
<Drawer bind:this={drawer} size="1200px">
|
||||||
@@ -26,8 +28,8 @@
|
|||||||
<FlowHistoryInner
|
<FlowHistoryInner
|
||||||
allowFork
|
allowFork
|
||||||
on:historyRestore={() => {
|
on:historyRestore={() => {
|
||||||
drawer.closeDrawer()
|
drawer?.closeDrawer()
|
||||||
dispatch('historyRestore')
|
onHistoryRestore()
|
||||||
}}
|
}}
|
||||||
{path}
|
{path}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -198,9 +198,7 @@
|
|||||||
{#key script.hash}
|
{#key script.hash}
|
||||||
<ScriptEditor
|
<ScriptEditor
|
||||||
showCaptures={false}
|
showCaptures={false}
|
||||||
on:saveDraft={() => {
|
onSaveDraft={() => saveScript()}
|
||||||
saveScript()
|
|
||||||
}}
|
|
||||||
noSyncFromGithub
|
noSyncFromGithub
|
||||||
lang={script.language}
|
lang={script.language}
|
||||||
path={script.path}
|
path={script.path}
|
||||||
@@ -209,7 +207,7 @@
|
|||||||
bind:code={script.content}
|
bind:code={script.content}
|
||||||
bind:schema={script.schema}
|
bind:schema={script.schema}
|
||||||
>
|
>
|
||||||
<div slot="editor-bar-right">
|
<div slot="editor_bar_right">
|
||||||
<WorkerTagSelect bind:tag={script.tag} />
|
<WorkerTagSelect bind:tag={script.tag} />
|
||||||
</div>
|
</div>
|
||||||
</ScriptEditor>
|
</ScriptEditor>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { preventDefault } from 'svelte/legacy'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type CompletedJob,
|
type CompletedJob,
|
||||||
type Job,
|
type Job,
|
||||||
@@ -10,11 +12,9 @@
|
|||||||
import { workspaceStore } from '$lib/stores'
|
import { workspaceStore } from '$lib/stores'
|
||||||
import { base } from '$lib/base'
|
import { base } from '$lib/base'
|
||||||
import { displayDate } from '$lib/utils'
|
import { displayDate } from '$lib/utils'
|
||||||
import Tabs from '../common/tabs/Tabs.svelte'
|
|
||||||
import Tab from '../common/tabs/Tab.svelte'
|
import Tab from '../common/tabs/Tab.svelte'
|
||||||
import DisplayResult from '../DisplayResult.svelte'
|
import DisplayResult from '../DisplayResult.svelte'
|
||||||
import Drawer from '../common/drawer/Drawer.svelte'
|
import Drawer from '../common/drawer/Drawer.svelte'
|
||||||
import DrawerContent from '../common/drawer/DrawerContent.svelte'
|
|
||||||
import HighlightCode from '../HighlightCode.svelte'
|
import HighlightCode from '../HighlightCode.svelte'
|
||||||
import LogViewer from '../LogViewer.svelte'
|
import LogViewer from '../LogViewer.svelte'
|
||||||
import { Pane, Splitpanes } from 'svelte-splitpanes'
|
import { Pane, Splitpanes } from 'svelte-splitpanes'
|
||||||
@@ -30,33 +30,54 @@
|
|||||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||||
import type { PreviewPanelUi } from '../custom_ui'
|
import type { PreviewPanelUi } from '../custom_ui'
|
||||||
import { getStringError } from '../copilot/chat/utils'
|
import { getStringError } from '../copilot/chat/utils'
|
||||||
|
import { DrawerContent } from '../common'
|
||||||
|
import TabsV2 from '../common/tabs/TabsV2.svelte'
|
||||||
|
|
||||||
export let lang: Preview['language'] | undefined
|
interface Props {
|
||||||
export let previewIsLoading = false
|
lang: Preview['language'] | undefined
|
||||||
export let previewJob: Job | undefined
|
previewIsLoading?: boolean
|
||||||
export let pastPreviews: CompletedJob[] = []
|
previewJob: Job | undefined
|
||||||
export let editor: Editor | undefined = undefined
|
pastPreviews?: CompletedJob[]
|
||||||
export let diffEditor: DiffEditor | undefined = undefined
|
editor?: Editor | undefined
|
||||||
export let args: Record<string, any> | undefined = undefined
|
diffEditor?: DiffEditor | undefined
|
||||||
export let workspace: string | undefined = undefined
|
args?: Record<string, any> | undefined
|
||||||
export let showCaptures: boolean = false
|
workspace?: string | undefined
|
||||||
export let customUi: PreviewPanelUi | undefined = undefined
|
showCaptures?: boolean
|
||||||
|
customUi?: PreviewPanelUi | undefined
|
||||||
|
children?: import('svelte').Snippet
|
||||||
|
capturesTab?: import('svelte').Snippet
|
||||||
|
}
|
||||||
|
|
||||||
type DrawerContent = {
|
let {
|
||||||
|
lang,
|
||||||
|
previewIsLoading = false,
|
||||||
|
previewJob,
|
||||||
|
pastPreviews = [],
|
||||||
|
editor = undefined,
|
||||||
|
diffEditor = undefined,
|
||||||
|
args = undefined,
|
||||||
|
workspace = undefined,
|
||||||
|
showCaptures = false,
|
||||||
|
customUi = undefined,
|
||||||
|
children,
|
||||||
|
capturesTab
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
|
type DContent = {
|
||||||
mode: 'json' | Preview['language'] | 'plain'
|
mode: 'json' | Preview['language'] | 'plain'
|
||||||
title: string
|
title: string
|
||||||
content: any
|
content: any
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectedTab = 'logs'
|
let selectedTab = $state('logs')
|
||||||
let drawerOpen: boolean = false
|
let drawerOpen: boolean = $state(false)
|
||||||
let drawerContent: DrawerContent | undefined = undefined
|
let drawerContent: DContent | undefined = $state(undefined)
|
||||||
|
|
||||||
export function setFocusToLogs() {
|
export function setFocusToLogs() {
|
||||||
selectedTab = 'logs'
|
selectedTab = 'logs'
|
||||||
}
|
}
|
||||||
|
|
||||||
function openDrawer(newContent: DrawerContent) {
|
function openDrawer(newContent: DContent) {
|
||||||
drawerContent = newContent
|
drawerContent = newContent
|
||||||
drawerOpen = true
|
drawerOpen = true
|
||||||
}
|
}
|
||||||
@@ -69,7 +90,7 @@
|
|||||||
return x as Record<string, WorkflowStatus>
|
return x as Record<string, WorkflowStatus>
|
||||||
}
|
}
|
||||||
|
|
||||||
let forceJson = false
|
let forceJson = $state(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Drawer bind:open={drawerOpen} size="800px">
|
<Drawer bind:open={drawerOpen} size="800px">
|
||||||
@@ -94,7 +115,7 @@
|
|||||||
</Drawer>
|
</Drawer>
|
||||||
|
|
||||||
<div class="h-full flex flex-col">
|
<div class="h-full flex flex-col">
|
||||||
<Tabs bind:selected={selectedTab} class="pt-1" wrapperClass="flex-none">
|
<TabsV2 bind:selected={selectedTab} class="pt-1" wrapperClass="flex-none">
|
||||||
<Tab value="logs" size="xs">Logs & Result</Tab>
|
<Tab value="logs" size="xs">Logs & Result</Tab>
|
||||||
{#if customUi?.disableHistory !== true}
|
{#if customUi?.disableHistory !== true}
|
||||||
<Tab value="history" size="xs">History</Tab>
|
<Tab value="history" size="xs">History</Tab>
|
||||||
@@ -103,7 +124,7 @@
|
|||||||
<Tab value="captures" size="xs">Trigger captures</Tab>
|
<Tab value="captures" size="xs">Trigger captures</Tab>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<svelte:fragment slot="content">
|
{#snippet content()}
|
||||||
<div class="grow min-h-0">
|
<div class="grow min-h-0">
|
||||||
{#if selectedTab === 'logs'}
|
{#if selectedTab === 'logs'}
|
||||||
<SplitPanesWrapper>
|
<SplitPanesWrapper>
|
||||||
@@ -128,7 +149,7 @@
|
|||||||
/>
|
/>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane>
|
<Pane>
|
||||||
<slot />
|
{@render children?.()}
|
||||||
{#if previewJob != undefined && 'result' in previewJob}
|
{#if previewJob != undefined && 'result' in previewJob}
|
||||||
<div class="relative w-full h-full p-2">
|
<div class="relative w-full h-full p-2">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
@@ -140,6 +161,7 @@
|
|||||||
customUi={customUi?.displayResult}
|
customUi={customUi?.displayResult}
|
||||||
language={lang}
|
language={lang}
|
||||||
>
|
>
|
||||||
|
<!-- @migration-task: migrate this slot by hand, `copilot-fix` is an invalid identifier -->
|
||||||
<svelte:fragment slot="copilot-fix">
|
<svelte:fragment slot="copilot-fix">
|
||||||
{#if lang && editor && diffEditor && args && previewJob && !previewJob.success && getStringError(previewJob.result)}
|
{#if lang && editor && diffEditor && args && previewJob && !previewJob.success && getStringError(previewJob.result)}
|
||||||
<ScriptFix {lang} />
|
<ScriptFix {lang} />
|
||||||
@@ -203,7 +225,7 @@
|
|||||||
<Cell>
|
<Cell>
|
||||||
<button
|
<button
|
||||||
class="text-xs"
|
class="text-xs"
|
||||||
on:click|preventDefault={() => {
|
onclick={preventDefault(() => {
|
||||||
openDrawer({ mode: 'json', content: undefined, title: 'Result' })
|
openDrawer({ mode: 'json', content: undefined, title: 'Result' })
|
||||||
JobService.getCompletedJobResult({
|
JobService.getCompletedJobResult({
|
||||||
workspace: workspace ?? $workspaceStore ?? 'NO_W',
|
workspace: workspace ?? $workspaceStore ?? 'NO_W',
|
||||||
@@ -211,7 +233,7 @@
|
|||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
drawerContent && (drawerContent.content = res)
|
drawerContent && (drawerContent.content = res)
|
||||||
})
|
})
|
||||||
}}
|
})}
|
||||||
>
|
>
|
||||||
See Result
|
See Result
|
||||||
</button>
|
</button>
|
||||||
@@ -219,7 +241,7 @@
|
|||||||
<Cell>
|
<Cell>
|
||||||
<button
|
<button
|
||||||
class="text-xs"
|
class="text-xs"
|
||||||
on:click|preventDefault={async () => {
|
onclick={preventDefault(async () => {
|
||||||
const code = (
|
const code = (
|
||||||
await JobService.getCompletedJob({
|
await JobService.getCompletedJob({
|
||||||
workspace: workspace ?? $workspaceStore ?? 'NO_W',
|
workspace: workspace ?? $workspaceStore ?? 'NO_W',
|
||||||
@@ -231,7 +253,7 @@
|
|||||||
content: String(code),
|
content: String(code),
|
||||||
title: `Code ${lang}`
|
title: `Code ${lang}`
|
||||||
})
|
})
|
||||||
}}
|
})}
|
||||||
>
|
>
|
||||||
View code
|
View code
|
||||||
</button>
|
</button>
|
||||||
@@ -239,7 +261,7 @@
|
|||||||
<Cell last>
|
<Cell last>
|
||||||
<button
|
<button
|
||||||
class="text-xs"
|
class="text-xs"
|
||||||
on:click|preventDefault={async () => {
|
onclick={preventDefault(async () => {
|
||||||
const logs = await (
|
const logs = await (
|
||||||
await fetch(
|
await fetch(
|
||||||
OpenAPI.BASE +
|
OpenAPI.BASE +
|
||||||
@@ -252,7 +274,7 @@
|
|||||||
content: String(logs),
|
content: String(logs),
|
||||||
title: `Logs for ${id}`
|
title: `Logs for ${id}`
|
||||||
})
|
})
|
||||||
}}
|
})}
|
||||||
>
|
>
|
||||||
View logs
|
View logs
|
||||||
</button>
|
</button>
|
||||||
@@ -264,9 +286,9 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if selectedTab === 'captures'}
|
{#if selectedTab === 'captures'}
|
||||||
<slot name="capturesTab" />
|
{@render capturesTab?.()}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</svelte:fragment>
|
{/snippet}
|
||||||
</Tabs>
|
</TabsV2>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -165,14 +165,16 @@
|
|||||||
<!-- <div id="monaco-widgets-root" class="monaco-editor" style="z-index: 1200;" /> -->
|
<!-- <div id="monaco-widgets-root" class="monaco-editor" style="z-index: 1200;" /> -->
|
||||||
|
|
||||||
<FlowBuilder
|
<FlowBuilder
|
||||||
on:saveInitial={(e) => {
|
onevent={{
|
||||||
goto(`/flows/edit/${e.detail}?selected=${getSelectedId?.()}`)
|
saveInitial: (path) => {
|
||||||
}}
|
goto(`/flows/edit/${path}?selected=${getSelectedId?.()}`)
|
||||||
on:deploy={(e) => {
|
},
|
||||||
goto(`/flows/get/${e.detail}?workspace=${$workspaceStore}`)
|
deploy: (path) => {
|
||||||
}}
|
goto(`/flows/get/${path}?workspace=${$workspaceStore}`)
|
||||||
on:details={(e) => {
|
},
|
||||||
goto(`/flows/get/${e.detail}?workspace=${$workspaceStore}`)
|
seeDetails: (path) => {
|
||||||
|
goto(`/flows/get/${path}?workspace=${$workspaceStore}`)
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
{initialPath}
|
{initialPath}
|
||||||
{pathStoreInit}
|
{pathStoreInit}
|
||||||
|
|||||||
@@ -244,18 +244,19 @@
|
|||||||
|
|
||||||
<DiffDrawer bind:this={diffDrawer} {restoreDeployed} {restoreDraft} />
|
<DiffDrawer bind:this={diffDrawer} {restoreDeployed} {restoreDraft} />
|
||||||
<FlowBuilder
|
<FlowBuilder
|
||||||
on:deploy={(e) => {
|
onevent={{
|
||||||
goto(`/flows/get/${e.detail}?workspace=${$workspaceStore}`)
|
deploy: (path) => {
|
||||||
}}
|
goto(`/flows/get/${path}?workspace=${$workspaceStore}`)
|
||||||
on:details={(e) => {
|
},
|
||||||
goto(`/flows/get/${e.detail}?workspace=${$workspaceStore}`)
|
seeDetails: (path) => {
|
||||||
}}
|
goto(`/flows/get/${path}?workspace=${$workspaceStore}`)
|
||||||
on:saveDraftOnlyAtNewPath={(e) => {
|
},
|
||||||
const { path, selectedId } = e.detail
|
saveDraftOnlyAtNewPath: ({ path, selectedId }) => {
|
||||||
goto(`/flows/edit/${path}?selected=${selectedId}`)
|
goto(`/flows/edit/${path}?selected=${selectedId}`)
|
||||||
}}
|
},
|
||||||
on:historyRestore={() => {
|
historyRestore: () => {
|
||||||
loadFlow()
|
loadFlow()
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
{flowStore}
|
{flowStore}
|
||||||
{flowStateStore}
|
{flowStateStore}
|
||||||
|
|||||||
@@ -108,13 +108,13 @@
|
|||||||
{initialArgs}
|
{initialArgs}
|
||||||
bind:this={scriptBuilder}
|
bind:this={scriptBuilder}
|
||||||
lockedLanguage={templatePath != null || hubPath != null}
|
lockedLanguage={templatePath != null || hubPath != null}
|
||||||
on:deploy={(e) => {
|
onevent={{
|
||||||
let newHash = e.detail
|
deploy: (newHash) => {
|
||||||
goto(`/scripts/get/${newHash}?workspace=${$workspaceStore}`)
|
goto(`/scripts/get/${newHash}?workspace=${$workspaceStore}`)
|
||||||
}}
|
},
|
||||||
on:saveInitial={(e) => {
|
saveInitial: (path) => {
|
||||||
let path = e.detail
|
goto(`/scripts/edit/${path}`)
|
||||||
goto(`/scripts/edit/${path}`)
|
}
|
||||||
}}
|
}}
|
||||||
bind:getInitialAndModifiedValues
|
bind:getInitialAndModifiedValues
|
||||||
searchParams={$page.url.searchParams}
|
searchParams={$page.url.searchParams}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
let scriptLoadedFromUrl = initialState != undefined ? decodeState(initialState) : undefined
|
let scriptLoadedFromUrl = initialState != undefined ? decodeState(initialState) : undefined
|
||||||
|
|
||||||
|
|
||||||
let script: (NewScript & { draft_triggers?: Trigger[] }) | undefined = undefined
|
let script: (NewScript & { draft_triggers?: Trigger[] }) | undefined = undefined
|
||||||
|
|
||||||
let initialPath: string = ''
|
let initialPath: string = ''
|
||||||
@@ -218,19 +217,18 @@
|
|||||||
{diffDrawer}
|
{diffDrawer}
|
||||||
{savedPrimarySchedule}
|
{savedPrimarySchedule}
|
||||||
searchParams={$page.url.searchParams}
|
searchParams={$page.url.searchParams}
|
||||||
on:deploy={(e) => {
|
onevent={{
|
||||||
let newHash = e.detail
|
deploy: (newHash) => {
|
||||||
goto(`/scripts/get/${newHash}?workspace=${$workspaceStore}`)
|
goto(`/scripts/get/${newHash}?workspace=${$workspaceStore}`)
|
||||||
|
},
|
||||||
|
saveInitial: (path) => {
|
||||||
|
goto(`/scripts/edit/${path}`)
|
||||||
|
},
|
||||||
|
saveDraft: ({ path, savedAtNewPath, script }) => {
|
||||||
|
goto(`/scripts/edit/${path}`)
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
bind:getInitialAndModifiedValues
|
bind:getInitialAndModifiedValues
|
||||||
on:saveInitial={(e) => {
|
|
||||||
let path = e.detail
|
|
||||||
goto(`/scripts/edit/${path}`)
|
|
||||||
}}
|
|
||||||
on:seeDetails={(e) => {
|
|
||||||
let path = e.detail
|
|
||||||
goto(`/scripts/get/${path}?workspace=${$workspaceStore}`)
|
|
||||||
}}
|
|
||||||
replaceStateFn={(path) => {
|
replaceStateFn={(path) => {
|
||||||
replaceState(path, $page.state)
|
replaceState(path, $page.state)
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user