feat: is_trigger is just a type tag, soon to include failure and command (#523)

* script kind

* all

* init code flow

* kind: trigger

* kind: trigger
This commit is contained in:
Ruben Fiszel
2022-09-05 09:55:04 +02:00
committed by GitHub
parent 778ed223b1
commit 66df58af47
23 changed files with 243 additions and 164 deletions

View File

@@ -0,0 +1 @@
-- Add down migration script here

View File

@@ -0,0 +1,5 @@
-- Add up migration script here
CREATE TYPE SCRIPT_KIND AS ENUM ('script', 'trigger', 'failure', 'command');
ALTER TABLE script ADD COLUMN kind SCRIPT_KIND NOT NULL DEFAULT 'script';
ALTER TABLE script DROP COLUMN is_trigger;

View File

@@ -1532,8 +1532,9 @@ paths:
type: string
approved:
type: boolean
is_trigger:
type: boolean
kind:
type: string
enum: [script, failure, trigger, command]
votes:
type: number
views:
@@ -1544,7 +1545,7 @@ paths:
- summary
- app
- approved
- is_trigger
- kind
- views
- votes
@@ -1688,15 +1689,13 @@ paths:
in: query
schema:
type: boolean
- name: is_trigger
- name: kind
description: |
(default regardless)
if true show only the trigger scripts
if false show only the non trigger scripts
if not defined, show all regardless of if the script is a trigger script
script kind
in: query
schema:
type: boolean
type: string
responses:
"200":
description: All available scripts
@@ -1744,8 +1743,9 @@ paths:
language:
type: string
enum: [python3, deno]
is_trigger:
type: boolean
kind:
type: string
enum: [script, failure, trigger, command]
required:
- path
- summary
@@ -3241,8 +3241,9 @@ components:
language:
type: string
enum: [python3, deno]
is_trigger:
type: boolean
kind:
type: string
enum: [script, failure, trigger, command]
required:
- hash
- path
@@ -3255,7 +3256,7 @@ components:
- is_template
- extra_perms
- language
- is_trigger
- kind
ScriptArgs:
type: object

View File

@@ -1215,6 +1215,52 @@
"nullable": []
}
},
"5fee34ce48f01bb55707227548ea4d1e77ba75abfae412a902b1d8d6a1963725": {
"query": "INSERT INTO script (workspace_id, hash, path, parent_hashes, summary, description, content, created_by, schema, is_template, extra_perms, lock, language, kind) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::text::json, $10, $11, $12, $13, $14)",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Int8",
"Varchar",
"Int8Array",
"Text",
"Text",
"Text",
"Varchar",
"Text",
"Bool",
"Jsonb",
"Text",
{
"Custom": {
"name": "script_lang",
"kind": {
"Enum": [
"python3",
"deno"
]
}
}
},
{
"Custom": {
"name": "script_kind",
"kind": {
"Enum": [
"script",
"trigger",
"failure"
]
}
}
}
]
},
"nullable": []
}
},
"6199e8be5cb13db71108e555ea20f0b76dc38476670f9fc0667b057d2766d42e": {
"query": "SELECT set_config('session.groups', $1, true)",
"describe": {
@@ -2368,41 +2414,6 @@
]
}
},
"b49868120aa48f9163ffb0262804c0528723c858d20d7e556750fe712e3d5123": {
"query": "INSERT INTO script (workspace_id, hash, path, parent_hashes, summary, description, content, created_by, schema, is_template, extra_perms, lock, language, is_trigger) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::text::json, $10, $11, $12, $13, $14)",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Int8",
"Varchar",
"Int8Array",
"Text",
"Text",
"Text",
"Varchar",
"Text",
"Bool",
"Jsonb",
"Text",
{
"Custom": {
"name": "script_lang",
"kind": {
"Enum": [
"python3",
"deno"
]
}
}
},
"Bool"
]
},
"nullable": []
}
},
"b7dd791cd69748ef51b7520f505c0c8bb1b4014a273476eddfecf1ab658a18b4": {
"query": "select hash from script where path = $1 AND (workspace_id = $2 OR workspace_id = 'starter') AND\n created_at = (SELECT max(created_at) FROM script WHERE path = $1 AND (workspace_id = $2 OR workspace_id = 'starter')) AND\n deleted = false",
"describe": {

View File

@@ -124,6 +124,15 @@ impl Serialize for ScriptHashes {
}
}
#[derive(sqlx::Type, Serialize, Deserialize, Debug, Hash)]
#[sqlx(type_name = "SCRIPT_KIND", rename_all = "lowercase")]
#[serde(rename_all = "lowercase")]
pub enum ScriptKind {
Trigger,
Failure,
Script,
}
#[derive(FromRow, Serialize)]
pub struct Script {
pub workspace_id: String,
@@ -143,7 +152,7 @@ pub struct Script {
pub lock: Option<String>,
pub lock_error_logs: Option<String>,
pub language: ScriptLang,
pub is_trigger: bool,
pub kind: ScriptKind,
}
#[derive(Serialize, Deserialize, sqlx::Type, Debug)]
@@ -170,7 +179,7 @@ pub struct NewScript {
pub is_template: Option<bool>,
pub lock: Option<Vec<String>>,
pub language: ScriptLang,
pub is_trigger: Option<bool>,
pub kind: Option<ScriptKind>,
}
#[derive(Deserialize)]
@@ -185,7 +194,7 @@ pub struct ListScriptQuery {
pub order_by: Option<String>,
pub order_desc: Option<bool>,
pub is_template: Option<bool>,
pub is_trigger: Option<bool>,
pub kind: Option<String>,
}
async fn list_scripts(
@@ -216,7 +225,7 @@ async fn list_scripts(
"null as lock",
"CASE WHEN lock_error_logs IS NOT NULL THEN 'error' ELSE null END as lock_error_logs",
"language",
"is_trigger",
"kind",
])
.order_by("created_at", lq.order_desc.unwrap_or(true))
.and_where("workspace_id = ? OR workspace_id = 'starter'".bind(&w_id))
@@ -254,8 +263,8 @@ async fn list_scripts(
if let Some(it) = &lq.is_template {
sqlb.and_where_eq("is_template", it);
}
if let Some(it) = &lq.is_trigger {
sqlb.and_where_eq("is_trigger", it);
if let Some(k) = &lq.kind {
sqlb.and_where_eq("kind", "?".bind(&k.to_lowercase()));
}
let sql = sqlb.sql().map_err(|e| Error::InternalErr(e.to_string()))?;
@@ -407,7 +416,7 @@ async fn create_script(
//::text::json is to ensure we use serde_json with preserve order
sqlx::query!(
"INSERT INTO script (workspace_id, hash, path, parent_hashes, summary, description, \
content, created_by, schema, is_template, extra_perms, lock, language, is_trigger) \
content, created_by, schema, is_template, extra_perms, lock, language, kind) \
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::text::json, $10, $11, $12, $13, $14)",
&w_id,
&hash.0,
@@ -422,7 +431,7 @@ async fn create_script(
extra_perms,
lock,
ns.language: ScriptLang,
ns.is_trigger.unwrap_or(false),
ns.kind.unwrap_or(ScriptKind::Script): ScriptKind,
)
.execute(&mut tx)
.await?;

View File

@@ -36,7 +36,7 @@
</script>
<Modal bind:this={modal} z="z-30">
<div slot="title">search a {itemName}</div>
<div slot="title">Search a {itemName}</div>
<div slot="content">
<div class="w-12/12 pb-4">
<input placeholder="Search {itemName}" bind:value={itemsFilter} class="search-item" />
@@ -57,7 +57,7 @@
<IconedResourceType silent={true} name={obj['app']} />
<span class="mr-2" />
{/if}
<span class="mr-2">{obj[extraField]}</span><span class="font-normal whitespace-nowrap"
<span class="mr-2">{obj[extraField]}</span><span class="font-normal break-all"
>{obj['path'] ?? ''}</span
>
</p>

View File

@@ -93,7 +93,8 @@
on:new={(e) =>
apply(createInlineScriptModule, {
language: e.detail.language,
type: e.detail.type
kind: e.detail.kind,
subkind: e.detail.subkind
})}
on:loop={() => applyCreateLoop()}
/>

View File

@@ -1,15 +1,10 @@
<script lang="ts">
import { ScriptService, type Script } from '$lib/gen'
import { Script, ScriptService } from '$lib/gen'
import { goto } from '$app/navigation'
import { page } from '$app/stores'
import { inferArgs } from '$lib/infer'
import {
DENO_INIT_CODE,
DENO_INIT_CODE_TRIGGER,
initialCode,
POSTGRES_INIT_CODE
} from '$lib/script_helpers'
import { initialCode, isInitialCode } from '$lib/script_helpers'
import { workspaceStore } from '$lib/stores'
import { emptySchema, encodeState, sendUserToast, setQueryWithoutLoad } from '$lib/utils'
import { Breadcrumb, BreadcrumbItem } from 'flowbite-svelte'
@@ -21,33 +16,30 @@
import ScriptEditor from './ScriptEditor.svelte'
import ScriptSchema from './ScriptSchema.svelte'
import CenteredPage from './CenteredPage.svelte'
import Tooltip from './Tooltip.svelte'
let editor: ScriptEditor
let scriptSchema: ScriptSchema
export let script: Script
export let initialPath: string = ''
export let template: 'pgsql' | undefined = undefined
export let template: 'pgsql' | 'script' = 'script'
let pathError = ''
$: setQueryWithoutLoad($page.url, 'state', encodeState(script))
$: step = Number($page.url.searchParams.get('step')) || 1
$: {
if (script.language == 'python3') {
script.is_trigger = false
}
}
if (script.content == '') {
initContent(script.language, template)
initContent(script.language, script.kind, template)
}
function initContent(language: 'deno' | 'python3', template: 'pgsql' | undefined) {
script.content = initialCode(
language,
template == 'pgsql' ? 'pgsql' : script.is_trigger ? 'trigger' : undefined
)
function initContent(
language: 'deno' | 'python3',
kind: Script.kind,
template: 'pgsql' | 'script'
) {
script.content = initialCode(language, kind, template)
}
async function editScript(): Promise<void> {
@@ -63,7 +55,7 @@
schema: script.schema,
is_template: script.is_template,
language: script.language,
is_trigger: script.is_trigger
kind: script.kind
}
})
sendUserToast(`Success! New script version created with hash ${newHash}`)
@@ -200,28 +192,77 @@
['Typescript (Deno)', 'deno'],
['Python 3.10', 'python3']
]}
on:change={(e) => initContent(e.detail, template)}
on:change={(e) => initContent(e.detail, script.kind, template)}
bind:value={script.language}
/>
</div>
<h4 class="text-gray-700 border-b">
Script Kind <Tooltip
>In most cases, you will want the General Script. <br />
Trigger are meant to be used as the first module of flows to trigger them based on watching
new events externally. <br />
Failure scripts are used to handle unrecoverable errors of flows and for handling errors
at the workspace level. <br />
Command scripts are used when the workspace is associated with a slack workspace to be triggered
on command.</Tooltip
>
</h4>
{#if script.language == 'deno'}
<h4 class="text-gray-700 border-b">Template</h4>
<div class="max-w-lg">
<RadioButton
label="Script Type"
options={[
['General Script', Script.kind.SCRIPT],
['Trigger Script', Script.kind.TRIGGER]
// ['Failure Handler', Script.kind.FAILURE],
// ['Command Handler', Script.kind.COMMAND]
]}
on:change={(e) => {
if (isInitialCode(script.content)) {
template = 'script'
initContent(script.language, e.detail, template)
}
}}
bind:value={script.kind}
/>
</div>
{:else}
<div class="max-w-lg">
<RadioButton
label="Script Type"
options={[['General Script', Script.kind.SCRIPT]]}
on:change={(e) => {
if (isInitialCode(script.content)) {
template = 'script'
initContent(script.language, e.detail, template)
}
}}
bind:value={script.kind}
/>
</div>
{/if}
{#if script.language == 'deno' && script.kind == Script.kind.SCRIPT}
<h4 class="text-gray-700 border-b">
Script Template <Tooltip
>A template is a pre-filled script corresponding to a more specialized use-case</Tooltip
>
</h4>
<div class="max-w-md">
<RadioButton
label="Template"
options={[
['None', undefined],
['PostgreSQL', 'pgsql']
['Standard', 'script'],
['PostgreSQL Prepared Statement', 'pgsql']
]}
on:change={(e) => initContent(script.language, e.detail)}
on:change={(e) => initContent(script.language, script.kind, e.detail)}
bind:value={template}
/>
</div>
{/if}
<h3 class="text-gray-700 pb-1 border-b">Metadata</h3>
<label class="block ">
<span class="text-gray-700">Summary <Required required={false} /></span>
<textarea
@@ -261,28 +302,14 @@
</label>
<label class="block">
<span class="text-gray-700 mr-2">Save as template</span>
<span class="text-gray-700 mr-2"
>Save as workspace template <Tooltip
>Enable your teammates to use this script as a template to write new scripts.</Tooltip
>
</span>
<input type="checkbox" bind:checked={script.is_template} />
</label>
<label class="block">
<span class="text-gray-700 mr-2">Save as trigger script</span>
<input
disabled={script.language == 'python3'}
type="checkbox"
bind:checked={script.is_trigger}
on:change={() => {
if (
script.content == DENO_INIT_CODE ||
script.content == DENO_INIT_CODE_TRIGGER ||
script.content == POSTGRES_INIT_CODE
) {
initContent(script.language, template)
}
}}
/>
</label>
<div>
<h3 class="text-gray-700 ">Description rendered</h3>
<div

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { ScriptService, FlowService } from '$lib/gen'
import { ScriptService, FlowService, Script } from '$lib/gen'
import Icon from 'svelte-awesome'
import { faSearch } from '@fortawesome/free-solid-svg-icons'
@@ -18,7 +18,7 @@
export let allowFlow = false
export let allowHub = false
export let itemKind: 'hub' | 'script' | 'flow' = allowHub ? 'hub' : 'script'
export let isTrigger: boolean | undefined = undefined
export let kind: Script.kind = Script.kind.SCRIPT
let items: { summary: String; path: String; version?: String }[] = []
let itemPicker: ItemPicker
@@ -35,7 +35,7 @@
if (itemKind == 'flow') {
items = await FlowService.listFlows({ workspace: $workspaceStore! })
} else if (itemKind == 'script') {
items = await ScriptService.listScripts({ workspace: $workspaceStore!, isTrigger })
items = await ScriptService.listScripts({ workspace: $workspaceStore!, kind })
} else {
items = $hubScripts ?? []
}

View File

@@ -53,7 +53,6 @@
class="w-96 text-left"
>
<slot />
<div id="arrow" data-popper-arrow />
</div>
{/if}

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { RawScript } from '$lib/gen'
import { RawScript, Script } from '$lib/gen'
import { faCode, faRepeat } from '@fortawesome/free-solid-svg-icons'
import { createEventDispatcher } from 'svelte'
@@ -18,8 +18,8 @@
{/if}
<div class="grid sm:grid-col-2 lg:grid-cols-3 gap-4">
<PickScript on:pick />
<PickHubScript on:pick />
<PickScript kind={Script.kind.SCRIPT} on:pick />
<PickHubScript kind={Script.kind.SCRIPT} on:pick />
<FlowScriptPicker
label={`Create a for-loop here`}
@@ -33,21 +33,24 @@
label={`New PostgreSQL query`}
icon={faCode}
iconColor="text-blue-800"
on:click={() => dispatch('new', { language: RawScript.language.DENO, type: 'pgsql' })}
on:click={() =>
dispatch('new', { language: RawScript.language.DENO, kind: 'script', subkind: 'pgsql' })}
/>
<FlowScriptPicker
label="New Python script (3.10)"
icon={faCode}
iconColor="text-green-500"
on:click={() => dispatch('new', { language: RawScript.language.PYTHON3, type: 'flow' })}
on:click={() =>
dispatch('new', { language: RawScript.language.PYTHON3, kind: 'script', subkind: 'flow' })}
/>
<FlowScriptPicker
label="New Typescript script (Deno)"
icon={faCode}
iconColor="text-blue-800"
on:click={() => dispatch('new', { language: RawScript.language.DENO, type: 'flow' })}
on:click={() =>
dispatch('new', { language: RawScript.language.DENO, kind: 'script', subkind: 'flow' })}
/>
</div>
@@ -55,13 +58,13 @@
<div class="text-sm font-bold">Trigger scripts</div>
<div class="grid sm:grid-col-1 md:grid-col-2 lg:grid-cols-3 gap-4">
<PickScript isTrigger={true} on:pick />
<PickHubScript isTrigger={true} on:pick />
<PickScript kind={Script.kind.TRIGGER} on:pick />
<PickHubScript kind={Script.kind.TRIGGER} on:pick />
<FlowScriptPicker
label="New Typescript script (Deno)"
icon={faCode}
iconColor="text-blue-800"
on:click={() => dispatch('new', { language: RawScript.language.DENO, type: 'trigger' })}
on:click={() => dispatch('new', { language: RawScript.language.DENO, kind: 'trigger' })}
/>
</div>
{/if}

View File

@@ -2,6 +2,7 @@ import type { Schema } from '$lib/common'
import {
CompletedJob,
Job,
Script,
ScriptService,
type Flow,
type FlowModule,
@@ -52,12 +53,14 @@ export async function pickScript(path: string): Promise<FlowModuleSchema> {
export async function createInlineScriptModule({
language,
type
kind,
subkind
}: {
language: RawScript.language
type: 'trigger' | 'flow' | 'pgsql'
kind: Script.kind,
subkind: 'pgsql' | 'flow'
}): Promise<FlowModuleSchema> {
const code = initialCode(language, type)
const code = initialCode(language, kind, subkind)
const flowModule: FlowModule = {
value: { type: 'rawscript', content: code, language },

View File

@@ -5,13 +5,14 @@
import ItemPicker from '$lib/components/ItemPicker.svelte'
import { hubScripts } from '$lib/stores'
import { createEventDispatcher } from 'svelte'
import { Script } from '$lib/gen'
export let isTrigger: boolean = false
export let kind: Script.kind
type Item = { summary: String; path: String; version?: String }
let items: Item[]
$: items = $hubScripts?.filter((x) => x.is_trigger == isTrigger) ?? []
$: items = $hubScripts?.filter((x) => x.kind == kind) ?? []
let itemPicker: ItemPicker
const dispatch = createEventDispatcher()
@@ -30,7 +31,7 @@
/>
<FlowScriptPicker
label={`Pick a ${isTrigger ? 'trigger ' : ''} script from the Hub`}
label={`Pick a ${kind == Script.kind.SCRIPT ? '' : kind} script from the Hub`}
icon={faUserGroup}
iconColor="text-blue-500"
on:click={() => itemPicker.openModal()}

View File

@@ -7,23 +7,16 @@
import { createEventDispatcher } from 'svelte'
import FlowScriptPicker from './FlowScriptPicker.svelte'
export let isTrigger: boolean = false
export let kind: string
type Item = { summary: String; path: String; version?: String }
let items: Item[] = []
let itemPicker: ItemPicker
const dispatch = createEventDispatcher()
async function loadItems(): Promise<void> {
items = await ScriptService.listScripts({ workspace: $workspaceStore!, isTrigger })
}
$: {
if ($workspaceStore) {
loadItems()
}
async function loadItems(): Promise<Item[]> {
return await ScriptService.listScripts({ workspace: $workspaceStore!, kind })
}
</script>
@@ -34,13 +27,11 @@
}}
itemName={'Script'}
extraField="summary"
loadItems={async () => {
return items
}}
{loadItems}
/>
<FlowScriptPicker
label={`Pick a ${isTrigger ? 'trigger ' : ''}script from your workspace`}
label={`Pick a ${kind == 'script' ? '' : kind} script from your workspace`}
icon={faUserGroup}
iconColor="text-blue-500"
on:click={() => itemPicker.openModal()}

View File

@@ -24,9 +24,9 @@
<span class="bg-blue-100 text-blue-800 text-xs font-semibold px-2.5 py-0.5 rounded ">
{String(script.language).toUpperCase()}
</span>
{#if script.is_trigger}
{#if script.kind != 'script'}
<span class="bg-red-100 text-red-800 text-xs font-semibold px-2.5 py-0.5 rounded">
TRIGGER
{script.kind}
</span>
{/if}
</div>

View File

@@ -1,3 +1,5 @@
import type { Script } from "./gen"
export const PYTHON_INIT_CODE = `import os
import wmill
from datetime import datetime
@@ -98,19 +100,34 @@ export async function main() {
}
`
export function initialCode(language: 'deno' | 'python3', type: 'trigger' | 'flow' | 'pgsql' | undefined): string {
const ALL_INITIAL_CODE = [PYTHON_INIT_CODE, DENO_INIT_CODE, POSTGRES_INIT_CODE, DENO_INIT_CODE_TRIGGER, DENO_INIT_CODE_CLEAR, PYTHON_INIT_CODE_CLEAR]
export function isInitialCode(content: string): boolean {
for (const code of ALL_INITIAL_CODE) {
if (content === code) {
return true
}
}
return false
}
export function initialCode(language: 'deno' | 'python3', kind: Script.kind, subkind: 'pgsql' | 'flow' | 'script' | undefined): string {
if (language === 'deno') {
if (type === 'trigger') {
if (kind === 'trigger') {
return DENO_INIT_CODE_TRIGGER
} else if (type === 'flow') {
return DENO_INIT_CODE_CLEAR
} else if (type === 'pgsql') {
return POSTGRES_INIT_CODE
} else if (kind === 'script') {
if (subkind === 'flow') {
return DENO_INIT_CODE_CLEAR
} else if (subkind === 'pgsql') {
return POSTGRES_INIT_CODE
} else {
return DENO_INIT_CODE
}
} else {
return DENO_INIT_CODE
}
} else {
if (type === 'flow') {
if (subkind === 'flow') {
return PYTHON_INIT_CODE_CLEAR
} else {
return PYTHON_INIT_CODE

View File

@@ -27,7 +27,7 @@ export const hubScripts = writable<
path: string
summary: string
approved: boolean
is_trigger: boolean
kind: string
app: string
}>
| undefined

View File

@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { goto } from '$app/navigation'
import { FlowService, ScriptService, type Flow, type FlowModule, type User } from '$lib/gen'
import { FlowService, Script, ScriptService, type Flow, type FlowModule, type User } from '$lib/gen'
import { toast } from '@zerodevx/svelte-toast'
import { get } from 'svelte/store'
import type { Schema } from './common'
@@ -502,7 +502,7 @@ export async function loadHubScripts() {
path: `hub/${x.id}/${x.app}/${x.summary.toLowerCase().replaceAll(/\s+/g, '_')}`,
summary: `${x.summary} (${x.app}) ${x.views} uses`,
approved: x.approved,
is_trigger: x.is_trigger,
kind: x.kind,
app: x.app,
views: x.views,
votes: x.votes,
@@ -545,14 +545,14 @@ export function scriptToHubUrl(
content: string,
summary: string,
description: string,
trigger: boolean
kind: Script.kind
): URL {
const url = new URL('https://hub.windmill.dev/scripts/add')
url.searchParams.append('content', content)
url.searchParams.append('summary', summary)
url.searchParams.append('description', description)
url.searchParams.append('trigger', trigger.toString())
url.searchParams.append('kind', kind)
return url
}

View File

@@ -9,7 +9,7 @@
<script lang="ts">
import { page } from '$app/stores'
import { sendUserToast, formatCron } from '$lib/utils'
import { ScriptService, type Script, ScheduleService, type Flow, FlowService } from '$lib/gen'
import { ScriptService, Script, ScheduleService, type Flow, FlowService } from '$lib/gen'
import PageHeader from '$lib/components/PageHeader.svelte'
import Path from '$lib/components/Path.svelte'
@@ -139,7 +139,12 @@
<p class="text-xs mb-1 text-gray-600">
Pick a script or flow to be triggered by the schedule<Required required={true} />
</p>
<ScriptPicker isTrigger={false} allowFlow={true} bind:itemKind bind:scriptPath={script_path} />
<ScriptPicker
kind={Script.kind.SCRIPT}
allowFlow={true}
bind:itemKind
bind:scriptPath={script_path}
/>
<div class="max-w-5xl {edit ? '' : 'mt-2 md:mt-6'}">
<h2>Arguments</h2>
{#if runnable}

View File

@@ -305,7 +305,7 @@
<p class="text-xs text-gray-600 italic">No scripts yet</p>
{:else}
<div class="grid md:grid-cols-2 gap-4 sm:grid-cols-1 xl:grid-cols-3">
{#each scripts as { summary, path, hash, language, extra_perms, canWrite, lock_error_logs, is_trigger }}
{#each scripts as { summary, path, hash, language, extra_perms, canWrite, lock_error_logs, kind }}
<div
class="flex flex-col justify-between script max-w-lg overflow-visible shadow-sm shadow-blue-100 border border-gray-200 bg-gray-50 py-2"
>
@@ -325,8 +325,8 @@
<div class="mr-3 w-full">
<SharedBadge {canWrite} extraPerms={extra_perms} />
<Badge twBgColor="bg-blue-200">{language}</Badge>
{#if is_trigger}
<Badge twBgColor="bg-blue-300">{is_trigger}</Badge>
{#if kind != 'script'}
<Badge twBgColor="bg-blue-300">{kind}</Badge>
{/if}
{#if lock_error_logs}<Badge
twBgColor="bg-red-200"

View File

@@ -14,7 +14,6 @@
import ScriptBuilder from '$lib/components/ScriptBuilder.svelte'
import type { Schema } from '$lib/common'
import { decodeState, emptySchema, getScriptByPath, sendUserToast } from '$lib/utils'
import CenteredPage from '$lib/components/CenteredPage.svelte'
// Default
let schema: Schema = emptySchema()
@@ -40,7 +39,7 @@
is_template: false,
extra_perms: {},
language: 'deno',
is_trigger: false
kind: Script.kind.SCRIPT
}
async function loadTemplate(): Promise<void> {

View File

@@ -134,9 +134,9 @@
>Template</span
>
{/if}
{#if script?.is_trigger}
{#if script && script.kind != 'script'}
<span class="mx-2 bg-blue-500 rounded-md bg-opacity-25 text-sm font-normal px-1 py-px"
>Trigger</span
>{script.kind}</span
>
{/if}
<SharedBadge canWrite={can_write} extraPerms={script?.extra_perms ?? {}} />
@@ -197,7 +197,7 @@
script.content,
script.summary,
script.description ?? '',
script.is_trigger
script.kind
).toString()}
>
<div class="inline-flex items-center justify-center">

View File

@@ -8,7 +8,13 @@
<script lang="ts">
import Fuse from 'fuse.js'
import { UserService, type WorkspaceInvite, WorkspaceService, OauthService } from '$lib/gen'
import {
UserService,
type WorkspaceInvite,
WorkspaceService,
OauthService,
Script
} from '$lib/gen'
import type { User } from '$lib/gen'
import { sendUserToast, msToSec } from '$lib/utils'
import PageHeader from '$lib/components/PageHeader.svelte'
@@ -216,7 +222,7 @@
</button>
{/if}
<h3 class="mt-5 text-gray-700">Select a script to run on /windmill command:</h3>
<ScriptPicker isTrigger={false} bind:scriptPath on:select={editSlackCommand} />
<ScriptPicker kind={Script.kind.SCRIPT} bind:scriptPath on:select={editSlackCommand} />
<p class="text-sm text-gray-700 italic mt-3">
A script run from slack /windmill command is run as group 'slack' and hence every variables or