mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-25 08:00:59 +00:00
all
This commit is contained in:
@@ -9,15 +9,12 @@
|
||||
import { importFlowStore } from '$lib/components/flows/flowStore.svelte'
|
||||
import { importScriptStore } from '$lib/components/scripts/scriptStore.svelte'
|
||||
import Modal from '$lib/components/common/modal/Modal.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import Tabs from '$lib/components/common/tabs/Tabs.svelte'
|
||||
import Tab from '$lib/components/common/tabs/Tab.svelte'
|
||||
import { PythonIcon, TypeScriptIcon } from '$lib/components/common/languageIcons'
|
||||
import { Code2, Loader2, Plus } from 'lucide-svelte'
|
||||
import { Code2, Loader2, NetworkIcon, Plus } from 'lucide-svelte'
|
||||
import YAML from 'yaml'
|
||||
|
||||
const SKIP_FLOW_MODAL_KEY = 'windmill_skip_flow_modal'
|
||||
|
||||
let drawer: Drawer | undefined = $state(undefined)
|
||||
let wacDrawer: Drawer | undefined = $state(undefined)
|
||||
let pendingRaw: string | undefined = $state(undefined)
|
||||
@@ -26,9 +23,6 @@
|
||||
let wacImportType: 'yaml' | 'json' = $state('yaml')
|
||||
let flowModalOpen = $state(false)
|
||||
let wacHovered = $state(false)
|
||||
let skipModal = $state(
|
||||
typeof localStorage !== 'undefined' && localStorage.getItem(SKIP_FLOW_MODAL_KEY) === 'true'
|
||||
)
|
||||
|
||||
async function importRaw() {
|
||||
$importFlowStore =
|
||||
@@ -46,11 +40,7 @@
|
||||
}
|
||||
|
||||
function handleFlowClick() {
|
||||
if (skipModal) {
|
||||
goto(`${base}/flows/add?nodraft=true`)
|
||||
} else {
|
||||
flowModalOpen = true
|
||||
}
|
||||
flowModalOpen = true
|
||||
}
|
||||
|
||||
function selectFlowEditor() {
|
||||
@@ -68,9 +58,9 @@
|
||||
goto(`${base}/scripts/add?nodraft=true&wac=typescript`)
|
||||
}
|
||||
|
||||
function toggleSkipModal() {
|
||||
skipModal = !skipModal
|
||||
localStorage.setItem(SKIP_FLOW_MODAL_KEY, String(skipModal))
|
||||
function selectPipeline() {
|
||||
flowModalOpen = false
|
||||
goto(`${base}/pipeline`)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -113,9 +103,13 @@
|
||||
</div>
|
||||
|
||||
<!-- Flow Type Selection Modal -->
|
||||
<Modal bind:open={flowModalOpen} title="Create a new flow">
|
||||
<!-- max-w-4xl widens the modal to fit three tiles comfortably; default
|
||||
`max-w-lg` (~512px) was sized for two tiles and squeezed the grid.
|
||||
kind="X" replaces the bottom Cancel button with a top-right close (X)
|
||||
so the action area is purely the three tile buttons. -->
|
||||
<Modal bind:open={flowModalOpen} title="Create a new flow" class="sm:max-w-4xl" kind="X">
|
||||
<div class="flex flex-col gap-4 pr-4">
|
||||
<div class="grid grid-cols-2 gap-8">
|
||||
<div class="grid grid-cols-3 gap-6">
|
||||
<!-- Flow Editor option -->
|
||||
<button
|
||||
class="flex flex-col items-center gap-3 p-6 rounded-lg border-2 border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 transition-all cursor-pointer group"
|
||||
@@ -142,13 +136,6 @@
|
||||
onmouseenter={() => (wacHovered = true)}
|
||||
onmouseleave={() => (wacHovered = false)}
|
||||
>
|
||||
<!-- Alpha badge -->
|
||||
<div
|
||||
class="absolute top-2 right-2 z-10 px-2 py-0.5 rounded-full bg-purple-500 text-white text-2xs font-bold uppercase tracking-wide"
|
||||
>
|
||||
Alpha
|
||||
</div>
|
||||
|
||||
<!-- Default state -->
|
||||
<div
|
||||
class="flex flex-col items-center gap-3 p-6 absolute inset-0 transition-all duration-300"
|
||||
@@ -196,11 +183,31 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2 px-1">
|
||||
<Toggle size="xs" checked={skipModal} on:change={toggleSkipModal} />
|
||||
<span class="text-2xs text-tertiary">Always use the Flow editor (skip this modal)</span>
|
||||
<!-- Pipeline option -->
|
||||
<button
|
||||
class="relative flex flex-col items-center gap-3 p-6 rounded-lg border-2 border-gray-200 dark:border-gray-700 hover:border-emerald-500 dark:hover:border-emerald-400 hover:bg-emerald-50 dark:hover:bg-emerald-900/20 transition-all cursor-pointer group"
|
||||
onclick={selectPipeline}
|
||||
>
|
||||
<!-- Alpha badge — pipeline is the newest of the three; same
|
||||
positioning the WAC tile used so it reads consistently. -->
|
||||
<div
|
||||
class="absolute top-2 right-2 z-10 px-2 py-0.5 rounded-full bg-emerald-500 text-white text-2xs font-bold uppercase tracking-wide"
|
||||
>
|
||||
Alpha
|
||||
</div>
|
||||
<div
|
||||
class="w-32 h-32 rounded-xl bg-emerald-100 dark:bg-emerald-900/40 flex items-center justify-center group-hover:bg-emerald-200 dark:group-hover:bg-emerald-800/50 transition-colors"
|
||||
>
|
||||
<NetworkIcon size={32} class="text-emerald-600 dark:text-emerald-400" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<h3 class="font-semibold text-primary">Pipeline</h3>
|
||||
<p class="text-xs text-tertiary mt-1">
|
||||
Asset-driven DAG of scripts. Trigger on schedule, asset change, or external event.
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
import { getContext, untrack } from 'svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
import TextInput from '../text_input/TextInput.svelte'
|
||||
import { NetworkIcon } from 'lucide-svelte'
|
||||
import { base } from '$lib/base'
|
||||
interface Props {
|
||||
filter?: string
|
||||
subtab?: 'flow' | 'script' | 'app'
|
||||
@@ -594,6 +596,27 @@
|
||||
/>
|
||||
{:else}
|
||||
<div class="border rounded-md bg-surface-tertiary">
|
||||
<!-- One pipeline row per folder that has pipeline-member scripts.
|
||||
Mirrors the entry the tree view shows under each folder, so
|
||||
users in flat view get the same affordance — clicking opens
|
||||
the pipeline editor for that folder. Hidden when an
|
||||
active filter is set (filter operates on items, not on
|
||||
folder-level entries). -->
|
||||
{#if filter === ''}
|
||||
{#each [...pipelineFolders].sort() as folder (folder)}
|
||||
<!-- px-4/py-3 + gap-4 mirrors common/table/Row.svelte so the
|
||||
row is the same height as the script/flow/app items
|
||||
beneath it; without it the single-line pipeline row
|
||||
was visibly shorter than the surrounding rows. -->
|
||||
<a
|
||||
href="{base}/pipeline/{encodeURIComponent(folder)}"
|
||||
class="w-full inline-flex items-center gap-4 px-4 py-3 border-b last:border-b-0 hover:bg-surface-hover transition-colors text-sm first-of-type:rounded-t-md"
|
||||
>
|
||||
<NetworkIcon size={16} class="text-emerald-600 dark:text-emerald-400" />
|
||||
<span class="text-xs font-medium text-emphasis truncate">Pipeline · f/{folder}</span>
|
||||
</a>
|
||||
{/each}
|
||||
{/if}
|
||||
{#each (items ?? []).slice(0, nbDisplayed) as item (item.type + '/' + item.path + (item.hash ? '/' + item.hash : ''))}
|
||||
<Item
|
||||
{item}
|
||||
|
||||
@@ -82,16 +82,16 @@
|
||||
{#if opened || isSearching}
|
||||
<div>
|
||||
{#if hasPipeline && isFolder(item)}
|
||||
<!-- py-3 matches common/table/Row.svelte so this row sits at
|
||||
the same height as the script/flow/app rows that follow
|
||||
it under the same folder; py-2 was visibly shorter. -->
|
||||
<a
|
||||
href="{base}/pipeline/{encodeURIComponent(item.folderName)}"
|
||||
class="flex items-center gap-4 px-4 py-2 border-b text-sm hover:bg-surface-hover transition-colors"
|
||||
class="flex items-center gap-4 px-4 py-3 border-b text-sm hover:bg-surface-hover transition-colors"
|
||||
style="padding-left: {(depth + 1) * 16}px;"
|
||||
>
|
||||
<NetworkIcon size={16} class="text-emerald-600 dark:text-emerald-400" />
|
||||
<div class="flex flex-col">
|
||||
<span class="text-xs font-medium text-emphasis">Pipeline</span>
|
||||
<span class="text-2xs text-secondary">Open pipeline editor</span>
|
||||
</div>
|
||||
<span class="text-xs font-medium text-emphasis">Pipeline</span>
|
||||
</a>
|
||||
{/if}
|
||||
{#each item.items.slice(0, showMax) as subItem, index ((subItem['path'] ? subItem['type'] + '__' + subItem['path'] + '__' + index : undefined) ?? 'folder__' + subItem['folderName'] + '__' + index)}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
Loader2,
|
||||
Code,
|
||||
LayoutDashboard,
|
||||
NetworkIcon,
|
||||
PlugZap
|
||||
} from 'lucide-svelte'
|
||||
import { hubBaseUrlStore } from '$lib/stores'
|
||||
@@ -302,17 +301,6 @@
|
||||
{#if !$userStore?.operator && showCreateButtons}
|
||||
<CreateActionsScript aiId="create-script-button" aiDescription="Creates a new script" />
|
||||
{#if HOME_SHOW_CREATE_FLOW}<CreateActionsFlow />{/if}
|
||||
<Button
|
||||
id="pipeline-button"
|
||||
aiId="pipeline-button"
|
||||
aiDescription="Opens the pipeline editor"
|
||||
unifiedSize="lg"
|
||||
startIcon={{ icon: NetworkIcon }}
|
||||
href="{base}/pipeline"
|
||||
variant="accent"
|
||||
>
|
||||
Pipeline
|
||||
</Button>
|
||||
{#if HOME_SHOW_CREATE_APP}<CreateActionsApp />{/if}
|
||||
{/if}
|
||||
</PageHeader>
|
||||
|
||||
Reference in New Issue
Block a user