From bb58eba2b521aef67b91cfc23f3ddcc8a001e18f Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Sat, 23 Jul 2022 21:11:31 +0200 Subject: [PATCH] feat(frontend): deeper integration with the hub --- frontend/src/app.css | 4 + frontend/src/lib/components/EditorBar.svelte | 26 ++-- .../src/lib/components/FlowBuilder.svelte | 14 +- .../src/lib/components/ScriptPicker.svelte | 19 +-- .../components/flows/FlowModuleHeader.svelte | 5 +- frontend/src/lib/components/flows/utils.ts | 26 +--- frontend/src/lib/stores.ts | 3 +- frontend/src/lib/utils.ts | 42 +++++- frontend/src/routes/__layout-root@none.svelte | 3 +- frontend/src/routes/flows/add.svelte | 2 +- frontend/src/routes/scripts.svelte | 124 ++++++++++++++---- frontend/src/routes/scripts/add.svelte | 16 ++- 12 files changed, 190 insertions(+), 94 deletions(-) diff --git a/frontend/src/app.css b/frontend/src/app.css index 40ba59c39c..72af153fe1 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -17,6 +17,10 @@ a { @apply text-blue-500; } + + .flex pre code.hljs { + @apply text-sm; + } #table-custom th { @apply py-3.5 text-left text-sm font-semibold text-gray-900 capitalize; diff --git a/frontend/src/lib/components/EditorBar.svelte b/frontend/src/lib/components/EditorBar.svelte index d619947ac7..6cade9d6db 100644 --- a/frontend/src/lib/components/EditorBar.svelte +++ b/frontend/src/lib/components/EditorBar.svelte @@ -1,11 +1,11 @@ @@ -55,12 +62,9 @@ { - codeContent = ( - await ScriptService.getScriptByPath({ - workspace: $workspaceStore ?? '', - path - }) - ).content + const { language, content } = await getScriptByPath(path ?? '') + codeContent = content + codeLang = language codeViewer.openModal() }} closeOnClick={false} @@ -72,9 +76,9 @@
Code
- {#if lang == 'python3'} + {#if codeLang == 'python3'} - {:else if lang == 'deno'} + {:else if codeLang == 'deno'} {/if}
({ - path: `hub/${x.id}/${x.summary.toLowerCase().replaceAll(/\s+/g, '_')}`, - summary: `${x.summary} (${x.app})`, - approved: x.approved, - is_trigger: x.is_trigger - })) - } - async function saveFlow(): Promise { const newFlow = flowToMode($flowStore, mode) @@ -70,7 +60,7 @@ }) onMount(() => { - loadSearchData() + loadHubScripts() clearPreviewResults() }) diff --git a/frontend/src/lib/components/ScriptPicker.svelte b/frontend/src/lib/components/ScriptPicker.svelte index 76b41290c9..a90ecab5b2 100644 --- a/frontend/src/lib/components/ScriptPicker.svelte +++ b/frontend/src/lib/components/ScriptPicker.svelte @@ -12,6 +12,7 @@ import { python, typescript } from 'svelte-highlight/languages' import github from 'svelte-highlight/styles/github' + import { getScript, getScriptByPath } from '$lib/utils' export let scriptPath: string | undefined = undefined export let allowFlow = false @@ -30,20 +31,6 @@ allowFlow && options.push(['Flow', 'flow']) const dispatch = createEventDispatcher() - async function getScript() { - if (itemKind == 'hub') { - code = await ScriptService.getHubScriptContentByPath({ path: scriptPath! }) - lang = Script.language.DENO - } else { - const script = await ScriptService.getScriptByPath({ - workspace: $workspaceStore!, - path: scriptPath! - }) - code = script.content - lang = script.language - } - } - async function loadItems(): Promise { if (itemKind == 'flow') { items = await FlowService.listFlows({ workspace: $workspaceStore! }) @@ -92,7 +79,9 @@ diff --git a/frontend/src/lib/components/flows/FlowModuleHeader.svelte b/frontend/src/lib/components/flows/FlowModuleHeader.svelte index c04638350f..a3c1862648 100644 --- a/frontend/src/lib/components/flows/FlowModuleHeader.svelte +++ b/frontend/src/lib/components/flows/FlowModuleHeader.svelte @@ -1,5 +1,6 @@ + + {@html github} + + + +
{codeViewerPath}
+
+ +
+ - + {#if tab != 'hub'} + + {/if}
- {#each tab == 'all' ? ['personal', 'groups', 'shared', 'community'] : [tab] as sectionTab} + {#each tab == 'all' ? ['personal', 'groups', 'shared', 'examples', 'hub'] : [tab] as sectionTab}
{#if sectionTab == 'personal'}

@@ -168,32 +207,71 @@

All scripts owned by you (and visible only to you if you do not explicitely share them) - will be displayed below

{:else if sectionTab == 'groups'}

Groups that I am member of

- All scripts being owned by groups that you are member of will be displayed below + All scripts being owned by groups that you are member of

{:else if sectionTab == 'shared'}

Shared with me

- All scripts visible to you because they have been shared to you will be displayed below + All scripts visible to you because they have been shared to you

- {:else if sectionTab == 'community'} -

Community templates & examples

+ {:else if sectionTab == 'examples'} +

Shared across all workspaces of this instance

- All scripts by the community that went through a review process and merged to the - official github repo will be displayed - below. Contributions welcome as Github PR. + Template and examples shared across all workspaces of this instance. They are managed + from a special workspace called 'starter' that only superadmin can change.

+ {:else if sectionTab == 'hub'} +

Approved scripts from the WindmillHub

+

+ All approved Deno scripts from the WindmillHub. + Approved scripts have been reviewed by the Windmill team and are safe to use in + production. The hub only offers Deno scripts because Hub scripts are meant to be solely + used as building blocks of flows and are much more efficient to execute than their + Python counterparts. +

+ +
+ + + App + Summary + + + + {#each filteredHub ?? [] as { path, summary, app }} + + {app} + + + | + hub's page + | fork + + + {/each} + + +
{/if} - {#each sectionTab == 'community' ? communityScripts : groupedScripts.filter((x) => tabFromPath(x[0]) == sectionTab) as [section, scripts]} - {#if sectionTab != 'personal' && sectionTab != 'community'} + {#each sectionTab == 'examples' ? communityScripts : groupedScripts.filter((x) => tabFromPath(x[0]) == sectionTab) as [section, scripts]} + {#if sectionTab != 'personal' && sectionTab != 'examples'}

owner: {section} {#if section == 'g/all'} - 'g/all' is the namespace for the group all. Every user is a member of all. Everything in this namespace is visible by all users. At the opposite, 'u/myuser' are private user namespaces. - import { ScriptService, type Script } from '$lib/gen' + import { Script, ScriptService } from '$lib/gen' import { page } from '$app/stores' import { workspaceStore } from '$lib/stores' import ScriptBuilder from '$lib/components/ScriptBuilder.svelte' import type { Schema } from '$lib/common' - import { emptySchema, sendUserToast } from '$lib/utils' + import { emptySchema, getScriptByPath, sendUserToast } from '$lib/utils' // Default let schema: Schema = emptySchema() $: templatePath = $page.url.searchParams.get('template') + $: hubPath = $page.url.searchParams.get('hub') const initialState = $page.url.searchParams.get('state') @@ -47,9 +48,20 @@ } } + async function loadHub(): Promise { + if (hubPath) { + const template = await getScriptByPath(hubPath) + script.summary = `Fork of ${hubPath}` + script.content = template.content + script.language = Script.language.DENO + sendUserToast(`Code has been loaded from hub script ${hubPath}.`) + } + } + $: { if ($workspaceStore) { loadTemplate() + loadHub() } }