diff --git a/frontend/src/lib/components/CliHelpBox.svelte b/frontend/src/lib/components/CliHelpBox.svelte index 000a6ee181..1e758ba7e3 100644 --- a/frontend/src/lib/components/CliHelpBox.svelte +++ b/frontend/src/lib/components/CliHelpBox.svelte @@ -1,35 +1,14 @@ -
- - -
- -{#if opened} - {/each} diff --git a/frontend/src/lib/components/apps/editor/DeploymentHistory.svelte b/frontend/src/lib/components/apps/editor/DeploymentHistory.svelte index 692637081e..911b44af9b 100644 --- a/frontend/src/lib/components/apps/editor/DeploymentHistory.svelte +++ b/frontend/src/lib/components/apps/editor/DeploymentHistory.svelte @@ -11,6 +11,8 @@ export let versions: number[] + debugger + let selectedVersion: number | undefined = undefined let selected: AppWithLastVersion | undefined = undefined diff --git a/frontend/src/lib/components/common/table/AppRow.svelte b/frontend/src/lib/components/common/table/AppRow.svelte index 52aaab1a5c..ee0146fcc9 100644 --- a/frontend/src/lib/components/common/table/AppRow.svelte +++ b/frontend/src/lib/components/common/table/AppRow.svelte @@ -100,16 +100,6 @@ {/if} {/if} - - goto('/schedules')} bind:this={scheduleEditor} /> {/if} {/if} - - {#if !draft_only} - - - {/if}
- - - -
- {#if marked} - {@html marked} - {:else} - {!summary || summary.length == 0 ? path : summary} - {/if} + +
+
-
- {path} +
+
+ {#if marked} + {@html marked} + {:else} + {!summary || summary.length == 0 ? path : summary} + {/if} +
+
+ {path} +
{#if $$slots.badges} diff --git a/frontend/src/lib/components/common/table/ScriptRow.svelte b/frontend/src/lib/components/common/table/ScriptRow.svelte index 8bdbf4e3c8..85a27191dd 100644 --- a/frontend/src/lib/components/common/table/ScriptRow.svelte +++ b/frontend/src/lib/components/common/table/ScriptRow.svelte @@ -13,10 +13,8 @@ faCalendarAlt, faCodeFork, faEdit, - faEye, faFileExport, faList, - faPlay, faShare, faTrashAlt } from '@fortawesome/free-solid-svg-icons' @@ -86,7 +84,7 @@ goto('/schedules')} bind:this={scheduleEditor} /> {/if} {/if} - - {#if !draft_only} - - - {/if} + import { copyToClipboard } from '$lib/utils' + import { Clipboard } from 'lucide-svelte' + + export let content: string + export let title: string + + +
{title}
+ + +
{ + e.preventDefault() + copyToClipboard(content) + }} +> +
{content}
+ +
diff --git a/frontend/src/lib/components/details/DetailPageHeader.svelte b/frontend/src/lib/components/details/DetailPageHeader.svelte new file mode 100644 index 0000000000..96909f65f0 --- /dev/null +++ b/frontend/src/lib/components/details/DetailPageHeader.svelte @@ -0,0 +1,70 @@ + + +
+
+
+
+ {title} +
+
+ + + {#each menuItems as { label, Icon, onclick, color } (label)} + { + const div = document.querySelector('[id^="headlessui-menu-items"]') + div?.parentElement?.remove() + + onclick() + }} + > +
+ + {label} +
+
+ {/each} +
+
+ {#each mainButtons as btn} + + {/each} +
+
+
+
diff --git a/frontend/src/lib/components/details/DetailPageLayout.svelte b/frontend/src/lib/components/details/DetailPageLayout.svelte new file mode 100644 index 0000000000..e7b44928d6 --- /dev/null +++ b/frontend/src/lib/components/details/DetailPageLayout.svelte @@ -0,0 +1,83 @@ + + +
+
+ + + + + + + + + + + Saved inputs + {#if !isOperator} + Details & Triggers + {/if} + +
+ + + + + + + + + + + + + + Webhooks + + + + + + Schedule + + + + + + CLI + + + + +
+
+ {#if triggerSelected === 'webhooks'} + + {:else if triggerSelected === 'schedule'} + + {:else if triggerSelected === 'cli'} + + {/if} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/lib/components/details/Menu.svelte b/frontend/src/lib/components/details/Menu.svelte new file mode 100644 index 0000000000..18c93a9422 --- /dev/null +++ b/frontend/src/lib/components/details/Menu.svelte @@ -0,0 +1,57 @@ + + + + + + + + + + +
+ + +
+ +
+
+
+
+
+
diff --git a/frontend/src/lib/components/details/WebhooksPanel.svelte b/frontend/src/lib/components/details/WebhooksPanel.svelte new file mode 100644 index 0000000000..d5c86be7c6 --- /dev/null +++ b/frontend/src/lib/components/details/WebhooksPanel.svelte @@ -0,0 +1,246 @@ + + + + +
+ {#if SCRIPT_VIEW_SHOW_CREATE_TOKEN_BUTTON} +
+ + +
+ {/if} + +
+
+
Request type
+ + + + +
+ {#if !isFlow} +
+
Call method
+ + + + + + +
+ {/if} +
+
Token configuration
+ + + + +
+
+ + + + REST + {#if SCRIPT_VIEW_SHOW_EXAMPLE_CURL} + Curl + {/if} + Fetch + + + +
+ + + {#if requestType !== 'get_path'} + + {/if} + + +
+
+ +
+ + + +
+
+ + response.json() +).then(data => { + ${ + webhookType === 'sync' + ? 'console.log(data)' + : `let UUID = data.uuid; + let checkCompletion = setInterval(() => { + fetch(\`${$page.url.protocol}//${$page.url.hostname}/api/w/${$workspaceStore}/jobs_u/completed/get_result_maybe/\$\{UUID\}\`, { + method: 'GET', + headers: { + 'Authorization': 'Bearer ${token}' + } + }).then(response => response.json()) + .then(data => { + if (data.completed) { + console.log('Job result: ', data); + clearInterval(checkCompletion); + } + }); + }, 1000);` + } +});`} + /> + +
+
+
diff --git a/frontend/src/lib/components/details/utils.ts b/frontend/src/lib/components/details/utils.ts new file mode 100644 index 0000000000..a79b48cd00 --- /dev/null +++ b/frontend/src/lib/components/details/utils.ts @@ -0,0 +1,65 @@ +import { ScriptService, JobService, Script } from '$lib/gen' + +export async function deleteScript(hash: string, workspace: string) { + return await ScriptService.deleteScriptByHash({ workspace: workspace, hash }) +} + +export async function archiveScript(hash: string, workspace: string) { + return await ScriptService.archiveScriptByHash({ workspace: workspace, hash }) +} + +export async function unarchiveScript(hash: string, workspace: string) { + const r = await ScriptService.getScriptByHash({ workspace: workspace, hash }) + const ns = await ScriptService.createScript({ + workspace: workspace, + requestBody: { + ...r, + parent_hash: hash, + lock: r.lock?.split('\n') + } + }) + return ns +} + +export async function getScriptDeploymentStatus(hash: string, workspace: string): Promise { + return await ScriptService.getScriptDeploymentStatus({ + workspace: workspace, + hash: hash + }) +} + +export async function loadScript(hash: string, workspace: string): Promise { + let script: Script + try { + script = await ScriptService.getScriptByHash({ workspace: workspace, hash }) + } catch { + script = await ScriptService.getScriptByPath({ workspace: workspace, path: hash }) + hash = script.hash + } + return { script, hash } +} + +export async function runScript( + scheduledForStr: string | undefined, + args: Record, + hash: string, + workspace: string, + invisibleToOwner?: boolean +) { + const scheduledFor = scheduledForStr ? new Date(scheduledForStr).toISOString() : undefined + let run = await JobService.runScriptByHash({ + workspace: workspace, + hash: hash, + requestBody: args, + scheduledFor, + invisibleToOwner + }) + return run +} +export function curlCommand(async: boolean, args: any, $page: any, workspace: string, script: any) { + return `curl -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" -X POST -d '${JSON.stringify( + args + )}' ${$page.url.protocol}//${$page.url.hostname}/api/w/${workspace}/jobs/run${ + async ? '' : '_wait_result' + }/p/${script?.path}` +} diff --git a/frontend/src/routes/(root)/(logged)/flows/get/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/flows/get/[...path]/+page.svelte index 6bc1afede1..b9aca66140 100644 --- a/frontend/src/routes/(root)/(logged)/flows/get/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/flows/get/[...path]/+page.svelte @@ -3,56 +3,47 @@ import { FlowService, JobService, ScheduleService, type Flow, type Schedule } from '$lib/gen' import { canWrite, - copyToClipboard, defaultIfEmptyString, displayDaysAgo, emptyString, encodeState } from '$lib/utils' - import { - faArchive, - faCalendar, - faChevronDown, - faChevronUp, - faClipboard, - faCodeFork, - faEdit, - faFileExport, - faList, - faPlay, - faShare, - faTrash - } from '@fortawesome/free-solid-svg-icons' + import { faCalendar, faCodeFork, faEdit } from '@fortawesome/free-solid-svg-icons' + import { Pane, Splitpanes } from 'svelte-splitpanes' + import DetailPageLayout from '$lib/components/details/DetailPageLayout.svelte' import { goto } from '$app/navigation' - import CenteredPage from '$lib/components/CenteredPage.svelte' - import { Alert, Badge, Button, Skeleton, Tab, TabContent, Tabs } from '$lib/components/common' - import CronInput from '$lib/components/CronInput.svelte' - import FlowViewer from '$lib/components/FlowViewer.svelte' + import { Alert, Button, Skeleton } from '$lib/components/common' import JobArgs from '$lib/components/JobArgs.svelte' import MoveDrawer from '$lib/components/MoveDrawer.svelte' import RunForm from '$lib/components/RunForm.svelte' import ScheduleEditor from '$lib/components/ScheduleEditor.svelte' import ShareModal from '$lib/components/ShareModal.svelte' import Toggle from '$lib/components/Toggle.svelte' - import Tooltip from '$lib/components/Tooltip.svelte' - import UserSettings from '$lib/components/UserSettings.svelte' import { userStore, workspaceStore } from '$lib/stores' - import Icon from 'svelte-awesome' - import { slide } from 'svelte/transition' import { sendUserToast } from '$lib/toast' import Urlize from '$lib/components/Urlize.svelte' import DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte' + import SavedInputs from '$lib/components/SavedInputs.svelte' + import { FolderOpen, Archive, Trash, Server, Share, PenBox, ListOrdered } from 'lucide-svelte' - let userSettings: UserSettings + import DetailPageHeader from '$lib/components/details/DetailPageHeader.svelte' + import WebhooksPanel from '$lib/components/details/WebhooksPanel.svelte' + import Badge from '$lib/components/common/badge/Badge.svelte' + import CliHelpBox from '$lib/components/CliHelpBox.svelte' + import InlineCodeCopy from '$lib/components/InlineCodeCopy.svelte' + import FlowGraphViewer from '$lib/components/FlowGraphViewer.svelte' + import SplitPanesWrapper from '$lib/components/splitPanes/SplitPanesWrapper.svelte' + import SchemaViewer from '$lib/components/SchemaViewer.svelte' let flow: Flow | undefined let schedule: Schedule | undefined let can_write = false - let path = $page.params.path let shareModal: ShareModal + $: cliCommand = `wmill flow run ${flow?.path} -d '${JSON.stringify(args)}'` + $: { if ($workspaceStore && $userStore) { loadFlow() @@ -100,6 +91,8 @@ requestBody: { enabled } }) loadSchedule() + + sendUserToast(`Schedule ${enabled ? 'enabled' : 'disabled'}`) } catch (err) { sendUserToast(`Cannot ` + (enabled ? 'disable' : 'enable') + ` schedule: ${err}`, true) loadSchedule() @@ -135,35 +128,95 @@ } let scheduleEditor: ScheduleEditor - let viewWebhookCommand = false - let args = undefined - function curlCommand(async: boolean) { - return `curl -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" -X POST -d '${JSON.stringify( - args - )}' ${$page.url.protocol}//${$page.url.hostname}/api/w/${$workspaceStore}/jobs/run${ - async ? '' : '_wait_result' - }/f/${flow?.path}` - } - - let webhook: HTMLHeadElement let moveDrawer: MoveDrawer let deploymentDrawer: DeployWorkspaceDrawer + let runForm: RunForm + + function getMainButtons(flow: Flow | undefined) { + if (!flow || $userStore?.operator) return [] + + const buttons: any = [] + if (!$userStore?.operator) { + buttons.push({ + label: 'Fork', + buttonProps: { + href: `/flows/add?template=${flow.path}`, + variant: 'border', + color: 'light', + size: 'xs', + disabled: !can_write, + startIcon: faCodeFork + } + }) + + buttons.push({ + label: 'Edit', + buttonProps: { + href: `/flows/edit/${path}?nodraft=true&args=${encodeState(args)}`, + variant: 'contained', + size: 'sm', + color: 'dark', + disabled: !can_write, + startIcon: faEdit + } + }) + } + return buttons + } + + function getMenuItems(flow: Flow | undefined) { + if (!flow || $userStore?.operator) return [] + + const menuItems: any = [] + + menuItems.push({ + label: 'Share', + onclick: () => shareModal.openDrawer(flow?.path ?? '', 'flow'), + Icon: Share, + disabled: !can_write + }) + + menuItems.push({ + label: 'Move/Rename', + onclick: () => moveDrawer.openDrawer(flow?.path ?? '', flow?.summary, 'flow'), + Icon: FolderOpen + }) + + menuItems.push({ + label: 'Deploy to staging/prod', + onclick: () => deploymentDrawer.openDrawer(flow?.path ?? '', 'flow'), + Icon: Server + }) + + if (can_write) { + menuItems.push({ + label: flow.archived ? 'Unarchive' : 'Archive', + onclick: () => flow?.path && archiveFlow(), + Icon: Archive, + color: 'red' + }) + menuItems.push({ + label: 'Delete', + onclick: () => flow?.path && deleteFlow(), + Icon: Trash, + color: 'red' + }) + } + return menuItems + } - loadSchedule()} bind:this={scheduleEditor} /> - - - + loadSchedule()} bind:this={scheduleEditor} /> - + { @@ -173,261 +226,117 @@ }} /> - - {#if flow} -
-
-
- - {#if !$userStore?.operator} - - - {/if} - -
-

- {defaultIfEmptyString(flow.summary, flow.path)} -

-
- {#if !emptyString(flow.summary)} - {flow.path} - {/if} -
- {/if} - +{#if flow} + + + + + + + + +
+
+ {#if !emptyString(flow.summary)} + {flow.path} + {/if} + + Edited {displayDaysAgo(flow.edited_at ?? '')} by {flow.edited_by} + -
- - {#if flow} -
- - Edited {displayDaysAgo(flow.edited_at ?? '')} by {flow.edited_by} + {#if flow.archived} +
+ This flow was archived + {/if} - {#if schedule} - - Primary schedule - {/if} - - {#if flow.archived} -
- This flow was archived - {/if} - -
- - - - - - -
-
-
-
- -
- {#if !emptyString(flow.description)} -
- -
- {/if} -
-
- - -

Webhooks - Pass the input as a json payload, the token as a Bearer token or as query arg - `?token=XXX` and pass as header: 'Content-Type: application/json'. The webhook also - support 'x-www-form-urlencoded' encoded payloads See docs

-
- - -
- -
-
-
- -
- {#if viewWebhookCommand} -
- - UUID/Async - Result/Sync - - -
{curlCommand(true)}  copyToClipboard(curlCommand(true))}
-													class="cursor-pointer ml-2">

//^ returns an UUID. Fetch result until completed == true
curl -H "Authorization: Bearer $TOKEN" {$page.url.protocol}//{$page.url - .hostname}/api/w/{$workspaceStore}/jobs_u/completed/get_result_maybe/$UUID
{curlCommand(false)} copyToClipboard(curlCommand(false))} - class="cursor-pointer ml-2">
-
-
+ {#if !emptyString(flow.description)} +
+ +
+ {/if}
- {/if} -
-
- {#if schedule} -
-

Primary Schedule
- {schedule.schedule} + +

+ + + + + + + + + { + runForm?.setArgs(JSON.parse(JSON.stringify(e.detail))) + }} + /> + + +
+ +
+
+ + + + +
+ +
+ {#if schedule} +
+
+
+ + Primary schedule +
+
{ @@ -437,51 +346,41 @@ sendUserToast('not enough permission', true) } }} + options={{ + right: 'On' + }} + size="xs" /> - +
+ + Runs +
+ + +
+
+ {#if Object.keys(schedule?.args ?? {}).length > 0} +
-
- -
-
- {/if} + {:else} +
This flow takes no argument
+ {/if} +
+ {/if} + + +
+ +
-
- {#if can_write} -

Danger zone

-
- - -
- {/if} -
- {/if} -
- + + +{/if} diff --git a/frontend/src/routes/(root)/(logged)/scripts/get/[...hash]/+page.svelte b/frontend/src/routes/(root)/(logged)/scripts/get/[...hash]/+page.svelte index 136e86d408..884b7100e8 100644 --- a/frontend/src/routes/(root)/(logged)/scripts/get/[...hash]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/scripts/get/[...hash]/+page.svelte @@ -2,71 +2,70 @@ import { page } from '$app/stores' import { JobService, ScriptService, type Script } from '$lib/gen' import { - truncateHash, - displayDaysAgo, defaultIfEmptyString, - copyToClipboard, emptyString, encodeState, - canWrite + canWrite, + displayDaysAgo, + truncateHash } from '$lib/utils' - import { - faPlay, - faEdit, - faArchive, - faList, - faTrash, - faCalendar, - faShare, - faGlobe, - faCodeFork, - faClipboard, - faArrowLeft, - faChevronUp, - faChevronDown, - faFileExport - } from '@fortawesome/free-solid-svg-icons' + import { faEdit, faCalendar, faCodeFork, faHistory } from '@fortawesome/free-solid-svg-icons' import Tooltip from '$lib/components/Tooltip.svelte' import ShareModal from '$lib/components/ShareModal.svelte' - import { superadmin, userStore, workspaceStore } from '$lib/stores' - import SharedBadge from '$lib/components/SharedBadge.svelte' + import { userStore, workspaceStore } from '$lib/stores' import SchemaViewer from '$lib/components/SchemaViewer.svelte' - import CenteredPage from '$lib/components/CenteredPage.svelte' import { onDestroy } from 'svelte' import HighlightCode from '$lib/components/HighlightCode.svelte' - import { Badge, Tabs, Tab, TabContent, Button, Alert } from '$lib/components/common' + import { + Tabs, + Tab, + TabContent, + Button, + Badge, + Alert, + DrawerContent, + Drawer + } from '$lib/components/common' import Skeleton from '$lib/components/common/skeleton/Skeleton.svelte' - import UserSettings from '$lib/components/UserSettings.svelte' - import Icon from 'svelte-awesome' import RunForm from '$lib/components/RunForm.svelte' import { goto } from '$app/navigation' - import Popover from '$lib/components/Popover.svelte' import ScheduleEditor from '$lib/components/ScheduleEditor.svelte' - import { Loader2 } from 'lucide-svelte' - import { slide } from 'svelte/transition' import MoveDrawer from '$lib/components/MoveDrawer.svelte' - import { - DEFAULT_WEBHOOK_TYPE, - SCRIPT_VIEW_SHOW_PUBLISH_TO_HUB, - SCRIPT_VIEW_SHOW_SCHEDULE, - SCRIPT_VIEW_SHOW_EXAMPLE_CURL, - SCRIPT_VIEW_SHOW_CREATE_TOKEN_BUTTON, - SCRIPT_VIEW_WEBHOOK_INFO_LINK, - SCRIPT_VIEW_WEBHOOK_INFO_TIP - } from '$lib/consts' + import { sendUserToast } from '$lib/toast' - import { scriptToHubUrl } from '$lib/hub' import Urlize from '$lib/components/Urlize.svelte' import DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte' - let userSettings: UserSettings + import SavedInputs from '$lib/components/SavedInputs.svelte' + import WebhooksPanel from '$lib/components/details/WebhooksPanel.svelte' + import DetailPageLayout from '$lib/components/details/DetailPageLayout.svelte' + import DetailPageHeader from '$lib/components/details/DetailPageHeader.svelte' + import InlineCodeCopy from '$lib/components/InlineCodeCopy.svelte' + import CliHelpBox from '$lib/components/CliHelpBox.svelte' + import { + Archive, + ArchiveRestore, + FolderOpen, + Globe2, + Loader2, + Server, + Share, + Trash + } from 'lucide-svelte' + import { SCRIPT_VIEW_SHOW_PUBLISH_TO_HUB } from '$lib/consts' + import { scriptToHubUrl } from '$lib/hub' + import SharedBadge from '$lib/components/SharedBadge.svelte' + import ScriptVersionHistory from '$lib/components/ScriptVersionHistory.svelte' + let script: Script | undefined let topHash: string | undefined let can_write = false let deploymentInProgress = false let intervalId: NodeJS.Timer - let shareModal: ShareModal + let runForm: RunForm + + $: cliCommand = `wmill script run ${script?.path} -d '${JSON.stringify(args)}'` $: loading = !script $: if ($workspaceStore) { @@ -186,20 +185,147 @@ } } let scheduleEditor: ScheduleEditor - let webhookElem: HTMLHeadingElement - - let viewWebhookCommand = false let args = undefined - function curlCommand(async: boolean) { - return `curl -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" -X POST -d '${JSON.stringify( - args - )}' ${$page.url.protocol}//${$page.url.hostname}/api/w/${$workspaceStore}/jobs/run${ - async ? '' : '_wait_result' - }/p/${script?.path}` - } let moveDrawer: MoveDrawer let deploymentDrawer: DeployWorkspaceDrawer + + function getMainButtons(script: Script | undefined) { + if (!script || $userStore?.operator) return [] + + const buttons: any = [] + + if (Array.isArray(script.parent_hashes) && script.parent_hashes.length > 0) { + buttons.push({ + label: `History`, + buttonProps: { + onClick: () => { + versionsDrawerOpen = !versionsDrawerOpen + }, + + size: 'xs', + color: 'light', + startIcon: faHistory + } + }) + } + + if (!$userStore?.operator) { + if (!topHash) { + buttons.push({ + label: 'Fork', + buttonProps: { + href: `/scripts/add?template=${script.path}`, + + size: 'xs', + color: 'light', + startIcon: faCodeFork + } + }) + } + + buttons.push({ + label: 'Edit', + buttonProps: { + href: `/scripts/edit/${script.path}?args=${encodeState(args)}${ + topHash ? `&hash=${script.hash}&topHash=` + topHash : '' + }`, + disabled: !can_write, + size: 'xs', + startIcon: faEdit, + color: 'dark', + variant: 'contained' + } + }) + } + + return buttons + } + + function getMenuItems(script: Script | undefined) { + if (!script || $userStore?.operator) return [] + + const menuItems: any = [] + + menuItems.push({ + label: 'Move/Rename', + Icon: FolderOpen, + onclick: () => { + moveDrawer.openDrawer(script?.path ?? '', script?.summary, 'script') + } + }) + + menuItems.push({ + label: 'Share', + Icon: Share, + onclick: () => { + shareModal.openDrawer(script?.path ?? '', 'script') + } + }) + + menuItems.push({ + label: 'Deploy to staging/prod', + Icon: Server, + onclick: () => { + deploymentDrawer.openDrawer(script?.path ?? '', 'script') + } + }) + + if (SCRIPT_VIEW_SHOW_PUBLISH_TO_HUB) { + menuItems.push({ + label: 'Publish to Hub', + Icon: Globe2, + onclick: () => { + if (!script) return + + goto( + scriptToHubUrl( + script.content, + script.summary, + script.description ?? '', + script.kind, + script.language, + script.schema, + script.language == 'deno' ? '' : script.lock + ).toString() + ) + } + }) + } + + if (script.archived) { + menuItems.push({ + label: 'Unarchive', + Icon: ArchiveRestore, + onclick: async () => { + unarchiveScript(script.hash) + }, + color: 'red' + }) + } else { + menuItems.push({ + label: 'Archive', + Icon: Archive, + onclick: async () => { + archiveScript(script.hash) + }, + color: 'red' + }) + } + + menuItems.push({ + label: 'Delete', + Icon: Trash, + onclick: async () => { + deleteScript(script.path) + }, + color: 'red' + }) + + return menuItems + } + + let versionsDrawerOpen = false - + + {#if script} - - + + (versionsDrawerOpen = false)}> + { + if (script) { + goto(`/scripts/get/${e.detail.version}?workspace=${$workspaceStore}`) + } + versionsDrawerOpen = false + }} + /> + + + + + + + +
+
+ {#if script.lock_error_logs || topHash || script.archived || script.deleted} +
+ {#if script.lock_error_logs} + + {/if} + {#if topHash} +
+ + This hash is not HEAD (latest non-archived version at this path) : + Go to the HEAD of this path + + {/if} + {#if script.archived && !topHash} + This path was archived + {/if} + {#if script.deleted} + + {/if} +
+ {/if} -
-
-
- - {#if !$userStore?.operator} - - {#if !topHash} - + {#if !emptyString(script.summary)} + {script.path} + {/if} + +
+ + Edited {displayDaysAgo(script.created_at || '')} by {script.created_by || 'unknown'} + + + {truncateHash(script?.hash ?? '')} + + {#if script?.is_template} + Template {/if} - {/if} - -
-
-

{defaultIfEmptyString(script.summary, script.path)}

-
-
- - {#if !emptyString(script.summary)} - {script.path} - {/if} - -
- - Edited {displayDaysAgo(script.created_at || '')} by {script.created_by || 'unknown'} - - - {truncateHash(script?.hash ?? '')} - - {#if script?.is_template} - Template - {/if} - {#if script && script.kind !== 'script'} - - {script?.kind} - - {/if} - {#if deploymentInProgress} - - - Deployment in progress - - {/if} - -
- -
- {#if SCRIPT_VIEW_SHOW_PUBLISH_TO_HUB} - - {/if} - - {#if SCRIPT_VIEW_SHOW_SCHEDULE} - - {/if} - - - - {#if Array.isArray(script.parent_hashes) && script.parent_hashes.length > 0} - - {/if} -
- - {#if script.lock_error_logs || topHash || script.archived || script.deleted} -
- {#if script.lock_error_logs} - - {/if} - {#if topHash} -
- - This hash is not HEAD (latest non-archived version at this path) : - Go to the HEAD of this path - - {/if} - {#if script.archived && !topHash} - This path was archived - {/if} - {#if script.deleted} - - {/if} -
- {/if} - -
-
- -
- {#if !emptyString(script.description)} -
- + {#if script && script.kind !== 'script'} + + {script?.kind} + + {/if} + {#if deploymentInProgress} + + + Deployment in progress + + {/if} +
- {/if} -
-
+ {#if !emptyString(script.description)} +
+ +
+ {/if} +
+ + +
+ + + {#if args} + { + runForm?.setArgs(JSON.parse(JSON.stringify(e.detail))) + }} + /> + {/if} + + + + + +
+ +
+
+ +
- Code - Dependencies lock file - - Arguments JSON Schema + Code + Lock file + + + Inputs The jsonschema defines the constraints that the payload must respect to be compatible with the input parameters of this script. The UI form is generated @@ -452,21 +499,25 @@ -
- +
+
-
+
{#if script?.lock} -
{script.lock}
+
{script.lock}
{:else} -

There is no lock file for this script

+

There is no lock file for this script

{/if}
-
+
@@ -482,155 +533,12 @@ {/each} {/if} - -
-

- Webhooks - - {SCRIPT_VIEW_WEBHOOK_INFO_TIP} - See docs - -

- - - UUID/Async - Result/Sync - - {#each Object.keys(webhooks) as key} - - - {#if SCRIPT_VIEW_SHOW_CREATE_TOKEN_BUTTON} -
- -
- {/if} - {#if SCRIPT_VIEW_SHOW_EXAMPLE_CURL} -
- -
- {/if} - {#if viewWebhookCommand} - {@const command = curlCommand(key == 'async')} -
- -
{command}  copyToClipboard(command)}
-												class="cursor-pointer ml-2">{#if key == 'async'}

//^ returns an UUID. Fetch until completed == true
curl -H "Authorization: Bearer $TOKEN" {$page.url.protocol}//{$page.url - .hostname}/api/w/{$workspaceStore}/jobs_u/completed/get_result_maybe/$UUID{/if}
-
- {/if} -
- {/each} -
-
+ + +
+ +
-
- {#if can_write} -

Danger zone

-
- - - require to be admin - - {#if script.archived} - - {:else} - - {/if} -
- {/if} -
-
- + + {/if} - - - -