From a235dfbe1f0d846b86173b04ab4b59ea4c67ea14 Mon Sep 17 00:00:00 2001 From: Faton Ramadani Date: Fri, 21 Apr 2023 15:09:18 +0200 Subject: [PATCH] App templates (#1448) * feat(backend): workers are instantly ready and sync with global cache in background * feat(frontend): add templates * feat(frontend): fix * feat(frontend): add psql template * feat(frontend): Move braces --------- Co-authored-by: Ruben Fiszel --- .../EmptyInlineScript.svelte | 124 ++++++++++-------- .../components/common/button/Button.svelte | 2 +- .../common/button/ButtonDropdown.svelte | 4 +- .../common/languageIcons/FetchIcon.svelte | 1 + .../common/languageIcons/LanguageIcon.svelte | 9 +- .../flows/pickers/FlowScriptPicker.svelte | 3 +- frontend/src/lib/script_helpers.ts | 55 +++++++- 7 files changed, 135 insertions(+), 63 deletions(-) create mode 100644 frontend/src/lib/components/common/languageIcons/FetchIcon.svelte diff --git a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte index d182e4ccfb..3504611784 100644 --- a/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte +++ b/frontend/src/lib/components/apps/editor/inlineScriptsPanel/EmptyInlineScript.svelte @@ -44,7 +44,7 @@ async function createInlineScriptByLanguage( language: Preview.language, path: string, - subkind: 'pgsql' | 'mysql' | undefined = undefined + subkind: 'pgsql' | 'mysql' | 'fetch' | undefined = undefined ) { const content = defaultCode(componentType ?? '', subkind || language) ?? @@ -139,7 +139,7 @@ -
+
Choose a language:
@@ -163,61 +163,77 @@
-
- {#each langs as lang} - { - createInlineScriptByLanguage(lang, name) - }} - /> - {/each} - { - createInlineScriptByLanguage(Script.language.DENO, name, 'pgsql') - }} - /> +
+
+
Backend
- -
-
-
- Script executed in the client's browser directly:  - - Frontend scripts are executed in the browser and can manipulate the app context directly - +
+ {#each langs as lang} + { + createInlineScriptByLanguage(lang, name) + }} + /> + {/each} +
+ +
Typescript templates
+ +
+ { + createInlineScriptByLanguage(Script.language.DENO, name, 'pgsql') + }} + /> + + { + createInlineScriptByLanguage(Script.language.DENO, name, 'fetch') + }} + /> +
- { - const newInlineScript = { - content: `// read outputs and ctx -console.log(ctx.email) +
+
+ Frontend + + Frontend scripts are executed in the browser and can manipulate the app context directly + +
-// access a global state store -if (!state.foo) { state.foo = 0 } -state.foo += 1 - -// you can also navigate (goto), recompute a script (recompute), or set a tab (setTab) - -return state.foo`, - language: 'frontend', - path: 'frontend script', - schema: undefined - } - dispatch('new', newInlineScript) - }} - /> +
+ { + const newInlineScript = { + content: `// read outputs and ctx + console.log(ctx.email) + + // access a global state store + if (!state.foo) { state.foo = 0 } + state.foo += 1 + + // you can also navigate (goto), recompute a script (recompute), or set a tab (setTab) + + return state.foo`, + language: 'frontend', + path: 'frontend script', + schema: undefined + } + dispatch('new', newInlineScript) + }} + /> +
+
diff --git a/frontend/src/lib/components/common/button/Button.svelte b/frontend/src/lib/components/common/button/Button.svelte index d97bb317cf..4e0f58cc57 100644 --- a/frontend/src/lib/components/common/button/Button.svelte +++ b/frontend/src/lib/components/common/button/Button.svelte @@ -176,7 +176,7 @@
{#if item.icon} diff --git a/frontend/src/lib/components/common/button/ButtonDropdown.svelte b/frontend/src/lib/components/common/button/ButtonDropdown.svelte index 6de9c5afa4..7e3b21509f 100644 --- a/frontend/src/lib/components/common/button/ButtonDropdown.svelte +++ b/frontend/src/lib/components/common/button/ButtonDropdown.svelte @@ -9,10 +9,10 @@ diff --git a/frontend/src/lib/components/common/languageIcons/FetchIcon.svelte b/frontend/src/lib/components/common/languageIcons/FetchIcon.svelte new file mode 100644 index 0000000000..28e3dda3d8 --- /dev/null +++ b/frontend/src/lib/components/common/languageIcons/FetchIcon.svelte @@ -0,0 +1 @@ +HTTP diff --git a/frontend/src/lib/components/common/languageIcons/LanguageIcon.svelte b/frontend/src/lib/components/common/languageIcons/LanguageIcon.svelte index 10f5ed149b..23e7456a21 100644 --- a/frontend/src/lib/components/common/languageIcons/LanguageIcon.svelte +++ b/frontend/src/lib/components/common/languageIcons/LanguageIcon.svelte @@ -5,13 +5,15 @@ import type { SvelteComponent } from 'svelte' import { BashIcon, GoIcon, PythonIcon, TypeScriptIcon } from './' import JavaScript from './JavaScript.svelte' + import FetchIcon from './FetchIcon.svelte' - export let lang: SupportedLanguage | 'pgsql' | 'mysql' | 'javascript' + export let lang: SupportedLanguage | 'pgsql' | 'mysql' | 'javascript' | 'fetch' export let width = 30 export let height = 30 export let scale = 1 + const langToComponent: Record< - SupportedLanguage | 'pgsql' | 'mysql' | 'javascript', + SupportedLanguage | 'pgsql' | 'mysql' | 'javascript' | 'fetch', typeof SvelteComponent > = { go: GoIcon, @@ -20,7 +22,8 @@ bash: BashIcon, pgsql: PostgresIcon, mysql: MySQLIcon, - javascript: JavaScript + javascript: JavaScript, + fetch: FetchIcon } diff --git a/frontend/src/lib/components/flows/pickers/FlowScriptPicker.svelte b/frontend/src/lib/components/flows/pickers/FlowScriptPicker.svelte index ff4f33e45e..6277c03947 100644 --- a/frontend/src/lib/components/flows/pickers/FlowScriptPicker.svelte +++ b/frontend/src/lib/components/flows/pickers/FlowScriptPicker.svelte @@ -6,7 +6,8 @@ export let disabled: boolean = false export let label: string - export let lang: SupportedLanguage | 'pgsql' | 'mysql' | 'javascript' | undefined = undefined + export let lang: SupportedLanguage | 'pgsql' | 'mysql' | 'javascript' | 'fetch' | undefined = + undefined export let icon: IconDefinition | undefined = undefined export let iconColor: string | undefined = undefined diff --git a/frontend/src/lib/script_helpers.ts b/frontend/src/lib/script_helpers.ts index 2d3f852d40..8aef2fe686 100644 --- a/frontend/src/lib/script_helpers.ts +++ b/frontend/src/lib/script_helpers.ts @@ -100,7 +100,25 @@ export async function main( db, )\`INSERT INTO demo VALUES (\${key}, \${value}) RETURNING *\`; return query.rows; -}` + +} + /** + // The following code accepts raw queries. The code above is recommended because it uses SQL prepared statement. + import { pgClient, type Resource, type Sql } from "https://deno.land/x/windmill@v1.88.1/mod.ts"; + + export async function main( + db: Resource<"postgresql">, + query: Sql = "SELECT * FROM demo;", + ) { + if(!query) { + throw Error('Query must not be empty.') + } + const { rows } = await pgClient(db).queryObject(query); + return rows; + } + */ + +` export const MYSQL_INIT_CODE = `import { mySql, @@ -119,6 +137,37 @@ export async function main( return query.rows; }` +export const FETCH_INIT_CODE = `export async function main( + url: string | undefined, + method: string = 'GET', + body: Object = {}, + headers: Record = {} +): Promise { + if (!url) { + console.error('Error: URL is undefined') + return null + } + + const requestOptions: RequestInit = { + method: method || 'GET', + headers: headers || {} + } + + if (requestOptions.method !== 'GET' && requestOptions.method !== 'HEAD' && body !== undefined) { + requestOptions.body = JSON.stringify(body) + requestOptions.headers = { + 'Content-Type': 'application/json', + ...requestOptions.headers + } + } + + return await fetch(url, requestOptions) + .then((res) => res.json()) + .catch(() => { + throw new Error('An error occured') + }) +}` + export const BASH_INIT_CODE = `# arguments of the form X="$I" are parsed as parameters X of type string msg="$1" dflt="\${2:-default value}" @@ -202,7 +251,7 @@ export function isInitialCode(content: string): boolean { export function initialCode( language: 'deno' | 'python3' | 'go' | 'bash', kind: Script.kind, - subkind: 'pgsql' | 'mysql' | 'flow' | 'script' | undefined + subkind: 'pgsql' | 'mysql' | 'flow' | 'script' | 'fetch' | undefined ): string { if (language === 'deno') { if (kind === 'trigger') { @@ -214,6 +263,8 @@ export function initialCode( return POSTGRES_INIT_CODE } else if (subkind === 'mysql') { return MYSQL_INIT_CODE + } else if (subkind === 'fetch') { + return FETCH_INIT_CODE } else { return DENO_INIT_CODE }