mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 16:02:14 +00:00
UX improvements
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
import { Tab, Tabs, TabContent, Button } from './common'
|
||||
import SchemaViewer from './SchemaViewer.svelte'
|
||||
import FieldHeader from './FieldHeader.svelte'
|
||||
import SvelteMarkdown from 'svelte-markdown'
|
||||
import { copyToClipboard } from '../utils'
|
||||
import FlowGraphViewer from './FlowGraphViewer.svelte'
|
||||
|
||||
@@ -49,7 +48,7 @@
|
||||
<div class="flow-root w-full pb-4">
|
||||
{#if !noSummary}
|
||||
<h2 class="my-4">{flow.summary}</h2>
|
||||
<SvelteMarkdown source={flow.description ?? ''} />
|
||||
<div>{flow.description ?? ''}</div>
|
||||
{/if}
|
||||
|
||||
<p class="font-black text-lg w-full my-4">
|
||||
|
||||
@@ -309,11 +309,7 @@
|
||||
/>
|
||||
{:else if step === 3}
|
||||
<CenteredPage>
|
||||
<ScriptSchema
|
||||
bind:summary={script.summary}
|
||||
bind:description={script.description}
|
||||
bind:schema={script.schema}
|
||||
/>
|
||||
<ScriptSchema bind:description={script.description} bind:schema={script.schema} />
|
||||
</CenteredPage>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -8,11 +8,10 @@
|
||||
|
||||
import Highlight from 'svelte-highlight'
|
||||
import json from 'svelte-highlight/languages/json'
|
||||
import SvelteMarkdown from 'svelte-markdown'
|
||||
import { Alert } from './common'
|
||||
import autosize from 'svelte-autosize'
|
||||
|
||||
export let schema: Schema
|
||||
export let summary: string
|
||||
export let description: string | undefined
|
||||
|
||||
export function setSchema(newSchema: Schema) {
|
||||
@@ -24,37 +23,19 @@
|
||||
<h1 class="my-4">Advanced</h1>
|
||||
|
||||
<Tabs selected="ui">
|
||||
<Tab value="ui">UI</Tab>
|
||||
<Tab value="ui">Description & Arguments refinement</Tab>
|
||||
<Tab value="jsonschema">JSON Schema</Tab>
|
||||
<svelte:fragment slot="content">
|
||||
<TabContent value="ui">
|
||||
<h2 class="border-b pb-1 mt-6">Display</h2>
|
||||
<div class="grid grid-cols-3 gap-2 mt-4">
|
||||
<label>
|
||||
<div class="text-gray-700 text-sm">Summary</div>
|
||||
<textarea bind:value={summary} placeholder="Edit summary" class="text-sm" />
|
||||
</label>
|
||||
<label class="col-span-2">
|
||||
<div class="text-gray-700 text-sm">Description</div>
|
||||
<textarea
|
||||
bind:value={description}
|
||||
placeholder="Edit description. Markdown accepted."
|
||||
class="text-sm"
|
||||
/>
|
||||
<div class="mt-1 px-2">
|
||||
{#if description}
|
||||
<div
|
||||
class="prose !max-w-full !max-h-48 text-xs shadow-inner shadow-blue overflow-auto mt-1"
|
||||
>
|
||||
<SvelteMarkdown source={description} />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-xs text-gray-500"> Enter a description to see the preview </div>
|
||||
{/if}
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<h2 class="border-b pb-1 my-4">Arguments</h2>
|
||||
<h2 class="border-b pb-1 mt-6 mb-4">Description</h2>
|
||||
<textarea
|
||||
use:autosize
|
||||
bind:value={description}
|
||||
placeholder="Edit description"
|
||||
class="text-sm"
|
||||
/>
|
||||
|
||||
<h2 class="border-b pb-1 mb-4 mt-8">Arguments</h2>
|
||||
<Alert type="info" title="Synchronized with main signature">
|
||||
Argument names, being required or not, and default values are derived from the main
|
||||
signature of step 2 and cannot be edited directly. Change the main signature to edit them.
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import Required from '$lib/components/Required.svelte'
|
||||
import FlowCard from '../common/FlowCard.svelte'
|
||||
import FlowSchedules from './FlowSchedules.svelte'
|
||||
import SvelteMarkdown from 'svelte-markdown'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { Alert } from '$lib/components/common'
|
||||
import { FlowGraph } from '$lib/components/graph'
|
||||
@@ -66,7 +65,7 @@
|
||||
<div class="font-bold pb-1 mt-4">Description preview</div>
|
||||
{#if $flowStore.description}
|
||||
<div class="prose max-h-48 mt-5 text-xs shadow-inner shadow-blue p-4 overflow-auto">
|
||||
<SvelteMarkdown source={$flowStore.description} />
|
||||
{$flowStore.description}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-sm text-gray-500"> Enter a description to see the preview </div>
|
||||
|
||||
@@ -42,10 +42,8 @@ def main(no_default: str,
|
||||
# the return value is then parsed and can be retrieved by other scripts conveniently
|
||||
return {"splitted": name.split(), "user": user, "state": new_state}
|
||||
`
|
||||
export const DENO_INIT_CODE = `// reload the smart assistant on the top right if it dies to get autocompletion and syntax highlighting
|
||||
// (Ctrl+space to cache dependencies on imports hover, Ctrl+S to autoformat and parse parameters).
|
||||
export const DENO_INIT_CODE = `// Ctrl+space to cache dependencies on imports hover, Ctrl+S to format.
|
||||
|
||||
// you can use npm imports directly
|
||||
// import { toWords } from "npm:number-to-words@1"
|
||||
// import * as wmill from "https://deno.land/x/windmill@v${__pkg__.version}/mod.ts"
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores'
|
||||
import { FlowService, ScheduleService, type Flow, type Schedule } from '$lib/gen'
|
||||
import { FlowService, JobService, ScheduleService, type Flow, type Schedule } from '$lib/gen'
|
||||
import {
|
||||
displayDaysAgo,
|
||||
canWrite,
|
||||
@@ -42,6 +42,8 @@
|
||||
import JobArgs from '$lib/components/JobArgs.svelte'
|
||||
import CronInput from '$lib/components/CronInput.svelte'
|
||||
import Icon from 'svelte-awesome'
|
||||
import RunForm from '$lib/components/RunForm.svelte'
|
||||
import { goto } from '$app/navigation'
|
||||
|
||||
let userSettings: UserSettings
|
||||
|
||||
@@ -95,6 +97,20 @@
|
||||
}
|
||||
|
||||
$: url = `${$page.url.hostname}/api/w/${$workspaceStore}/jobs/run/f/${flow?.path}`
|
||||
|
||||
let runForm: RunForm | undefined
|
||||
let isValid = true
|
||||
|
||||
async function runFlow(scheduledForStr: string | undefined, args: Record<string, any>) {
|
||||
const scheduledFor = scheduledForStr ? new Date(scheduledForStr).toISOString() : undefined
|
||||
let run = await JobService.runFlowByPath({
|
||||
workspace: $workspaceStore!,
|
||||
path,
|
||||
requestBody: args,
|
||||
scheduledFor
|
||||
})
|
||||
await goto('/run/' + run + '?workspace=' + $workspaceStore)
|
||||
}
|
||||
</script>
|
||||
|
||||
<UserSettings bind:this={userSettings} />
|
||||
@@ -212,11 +228,24 @@
|
||||
{#if flow.archived}
|
||||
<div class="bg-red-100 border-l-4 border-red-500 text-orange-700 p-4" role="alert">
|
||||
<p class="font-bold">Archived</p>
|
||||
<p>This version was archived</p>
|
||||
<p>This flow was archived</p>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="prose text-sm box max-w-6xl w-full mt-4">
|
||||
<SvelteMarkdown source={defaultIfEmptyString(flow?.description, 'No description')} />
|
||||
|
||||
<div class="mt-6 grid grid-cols-1 sm:grid-cols-3 gap-6">
|
||||
<div class="col-span-2">
|
||||
<RunForm
|
||||
autofocus
|
||||
detailed={false}
|
||||
bind:isValid
|
||||
bind:this={runForm}
|
||||
runnable={flow}
|
||||
runAction={runFlow}
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
{defaultIfEmptyString(flow.description, 'No description')}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<FlowViewer {flow} noSummary={true} />
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
import { Button, Kbd, Skeleton } from '$lib/components/common'
|
||||
import { faPlay, faScroll } from '@fortawesome/free-solid-svg-icons'
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import SvelteMarkdown from 'svelte-markdown'
|
||||
|
||||
const path = $page.params.path
|
||||
let flow: Flow | undefined
|
||||
@@ -54,7 +53,6 @@
|
||||
requestBody: args,
|
||||
scheduledFor
|
||||
})
|
||||
sendUserToast(`Job <a href='/run/${run}?workspace=${$workspaceStore}'>${run}</a> started`)
|
||||
goto('/run/' + run + '?workspace=' + $workspaceStore)
|
||||
}
|
||||
|
||||
@@ -128,7 +126,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="prose text-sm box max-w-6xl w-full mt-8">
|
||||
<SvelteMarkdown source={defaultIfEmptyString(flow.description, 'No description')} />
|
||||
{defaultIfEmptyString(flow.description, 'No description')}
|
||||
</div>
|
||||
</div>
|
||||
<RunForm
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
import IconedResourceType from '$lib/components/IconedResourceType.svelte'
|
||||
import ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import SvelteMarkdown from 'svelte-markdown'
|
||||
import { userStore, workspaceStore, oauthStore, superadmin } from '$lib/stores'
|
||||
import SchemaEditor from '$lib/components/SchemaEditor.svelte'
|
||||
import SchemaViewer from '$lib/components/SchemaViewer.svelte'
|
||||
@@ -213,7 +212,7 @@
|
||||
<div>
|
||||
<h1 class="mb-8 mt-4"><IconedResourceType name={resourceTypeViewerObj.rt} /></h1>
|
||||
<div class="py-2 box prose mb-8">
|
||||
<SvelteMarkdown source={resourceTypeViewerObj.description} />
|
||||
{resourceTypeViewerObj.description ?? ''}
|
||||
</div>
|
||||
<SchemaViewer schema={resourceTypeViewerObj.schema} />
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores'
|
||||
import { ScriptService, type Script } from '$lib/gen'
|
||||
import { JobService, ScriptService, type Script } from '$lib/gen'
|
||||
import {
|
||||
truncateHash,
|
||||
sendUserToast,
|
||||
@@ -54,6 +54,8 @@
|
||||
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'
|
||||
|
||||
let userSettings: UserSettings
|
||||
let script: Script | undefined
|
||||
@@ -138,6 +140,23 @@
|
||||
onDestroy(() => {
|
||||
intervalId && clearInterval(intervalId)
|
||||
})
|
||||
|
||||
let isValid = true
|
||||
let runForm: RunForm | undefined
|
||||
async function runScript(scheduledForStr: string | undefined, args: Record<string, any>) {
|
||||
try {
|
||||
const scheduledFor = scheduledForStr ? new Date(scheduledForStr).toISOString() : undefined
|
||||
let run = await JobService.runScriptByHash({
|
||||
workspace: $workspaceStore!,
|
||||
hash: script?.hash ?? '',
|
||||
requestBody: args,
|
||||
scheduledFor
|
||||
})
|
||||
await goto('/run/' + run + '?workspace=' + $workspaceStore)
|
||||
} catch (err) {
|
||||
sendUserToast(`Could not create job: ${err.body}`, true)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if script}
|
||||
@@ -178,6 +197,15 @@
|
||||
</Button>
|
||||
{/if}
|
||||
{/if}
|
||||
<Button
|
||||
href={`/runs/${script.path}`}
|
||||
size="md"
|
||||
startIcon={{ icon: faList }}
|
||||
color="light"
|
||||
variant="border"
|
||||
>
|
||||
View Runs
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -253,15 +281,6 @@
|
||||
>
|
||||
Schedule
|
||||
</Button>
|
||||
<Button
|
||||
href={`/runs/${script.path}`}
|
||||
size="xs"
|
||||
startIcon={{ icon: faList }}
|
||||
color="light"
|
||||
variant="border"
|
||||
>
|
||||
View runs
|
||||
</Button>
|
||||
{#if Array.isArray(script.parent_hashes) && script.parent_hashes.length > 0}
|
||||
<ButtonPopup
|
||||
color="dark"
|
||||
@@ -310,33 +329,39 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="max-w-2xl box mt-6">
|
||||
<SvelteMarkdown source={defaultIfEmptyString(script.description, 'No description')} />
|
||||
<div class="mt-6 grid grid-cols-1 sm:grid-cols-3 gap-6">
|
||||
<div class="col-span-2">
|
||||
<RunForm
|
||||
autofocus
|
||||
detailed={false}
|
||||
bind:isValid
|
||||
bind:this={runForm}
|
||||
runnable={script}
|
||||
runAction={runScript}
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
{defaultIfEmptyString(script.description, 'No description')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-2xl">
|
||||
<h3>
|
||||
Arguments JSON schema
|
||||
|
||||
<Tooltip>
|
||||
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 automatically from
|
||||
the script jsonschema. See
|
||||
<a href="https://json-schema.org/" class="text-blue-500"> jsonschema documentation </a>
|
||||
</Tooltip>
|
||||
</h3>
|
||||
<Skeleton {loading} layout={[[15]]} />
|
||||
<SchemaViewer schema={script.schema} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Code</h3>
|
||||
|
||||
<div class="mt-8">
|
||||
<Skeleton {loading} layout={[[20]]} />
|
||||
|
||||
<Tabs selected="code">
|
||||
<Tab value="code">Code</Tab>
|
||||
<Tab value="dependencies">Dependencies lock file</Tab>
|
||||
<Tab value="arguments"
|
||||
>Arguments JSON Schema
|
||||
<Tooltip>
|
||||
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 automatically from
|
||||
the script jsonschema. See
|
||||
<a href="https://json-schema.org/" class="text-blue-500">
|
||||
jsonschema documentation
|
||||
</a>
|
||||
</Tooltip></Tab
|
||||
>
|
||||
<svelte:fragment slot="content">
|
||||
<TabContent value="code">
|
||||
<div class="border rounded-sm mt-2">
|
||||
@@ -352,6 +377,11 @@
|
||||
{/if}
|
||||
</div>
|
||||
</TabContent>
|
||||
<TabContent value="arguments">
|
||||
<div class="max-w-2xl">
|
||||
<SchemaViewer schema={script.schema} />
|
||||
</div>
|
||||
</TabContent>
|
||||
</svelte:fragment>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
import RunForm from '$lib/components/RunForm.svelte'
|
||||
import { Alert, Badge, Button, Kbd, Skeleton } from '$lib/components/common'
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import SvelteMarkdown from 'svelte-markdown'
|
||||
import { faPlay, faScroll } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
$: hash = $page.params.hash
|
||||
@@ -163,7 +162,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="prose text-sm box max-w-6xl w-full mb-4 mt-8">
|
||||
<SvelteMarkdown source={defaultIfEmptyString(script.description, 'No description')} />
|
||||
{defaultIfEmptyString(script.description, 'No description')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user