-
- {#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}
+
+
Error deploying this script
+
+ This script has not been deployed successfully because of the following errors:
+
+
{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}
+
+
Deleted
+
The content of this script was deleted (by an admin, no less)
+
+ {/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}
-
-
Error deploying this script
-
This script has not been deployed successfully because of the following errors:
-
{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}
-
-
Deleted
-
The content of this script was deleted (by an admin, no less)
-
- {/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}
-
-
-
-