mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-05 16:03:47 +00:00
* migrate postgresEditorInner to svelte 5 syntaxe
* Add postgress
* add postgres capture section
* migrate kafka trigger config to svelte 5
* use snippets in kafka config
* feat: Update KafkaTriggerEditorInner with editMode, hideTarget and other props from WebsocketTriggerEditorInner
* feat: Create KafkaTriggerPanelV2 following WebsocketTriggersPanelV2 model
* feat: Integrate KafkaTriggerPanelV2 into TriggersEditorV2
* feat: add kafka capture panel
* use svelte 5 syntaxe for nats config
* use snippet in nats config
* feat: add editMode for nats trigger config
* fix import
* create NatsTriggerPanelV2.svelte for NATS trigger
* integrate NatsTriggerPanelV2 into TriggersEditorV2.svelte
* Create NatsCapture.svelte and update CaptureWrapperV2.svelte to use it
* migrate MqttTriggerEditorInner to svelte 5
* add mqtt trigger to new trigger panel
* migrate SqsTriggerEditorInner to svelte 5 syntaxe
* feat: add sqs triggers panel
* Add badge to MQTT config section
* remove unnecessary binding
* add gcp to the trigger list
* add prop size to GCP icon
* add gcp trigger utils
* migrate GcpTriggerEditorInner to svelte5 syntaxe
* add gcp trigger panel
* Revert "add gcp trigger utils"
This reverts commit 58f0df9985.
* fix type error
* add gcp to trigger bar
* add capture gcp panel
* add schedule poll panel
* feat: add trigger table horizontal bar
* add http trigger label
* make triggerbar vertical
* nit
* add trigger delete button for drafts
* enable edit from table for all triggers
* fix automatic edit mode for draft trigger
* fix proxy dispatching issue
* fix primary star positionning
* fix apply args to preprocessor
* automatically load bigpayloads
* clean capture wrapper code
* nit
* fix capture config not passed
* use Url component
* remove unused prop captureTable
* use new schedule panel for scheduled poll
* update triggersWrapperV2
* improve webhook capture panel
* remove debug log
* save draft with flow draft
* add path in draft label when available
* remove flowcard title
* use trigger label for trigger badge dropdown
* break from table to sidebar at 1000px
* remove triggers badge allways show sidebar behavior
* fix multiple primary addition
* improve primary schedule deploy logic
* remove debug logs
* gather imports
* add path for draft primary schedule
* handle redirection
* Add confirmation modal to deploy triggers
* remove debug log
* Save draft route trigger on deploy
* Allow draft for deployed triggers
* add component trigger editor toolbar
* improve update trigger utility function
* Add reset button for deployed draft triggers
* allow draft trigger for kafka triggers
* allow draft trigger for websocket triggers
* allow draft trigger for postgres triggers
* Add toggle to trigger toolbar
* allow draft for nats triggers
* allow draft for mqtt triggers
* allow draft sqs triggers
* allow draft for gcp triggers
* revert changes on the schedule editor
* update all triggers to use the same toolbar
* remove debug logs
* remove PrimarySchedule Panel and merge primary schedule logic with all triggers
* load schema from draft when editing a draft schedule
* prevent overflow in trigger table
* fix path saving for draft schedule
* fix trigger badge dropdown display
* get draft status from trigger
* remove unused event
* nit
* Add deploy badge to trigger
* replace checkbox with toggle for the modal
* fix selection of triggers with draft
* fix nit
* fix nit
* add missing config for loading schedule
* save schedule from config
* save http route from cfg
* save websocket trigger from cfg
* save postgres trigger from cfg
* save kafka trigger from cfg
* save sqs trigger from cfg
* save nats trigger from cfg
* save mqtt triggers from cfg
* save gcp trigger from config
* nit
* fix path update when editing a trigger
* remove unused saveCb
* fix trigger node navigation
* remove debug log
* add min size for trigger editor capture panel
* Integrate new triggers Editor to script builder
* remove previous triggersEdior page
* Remove former triggers Editor
* Migrate detail page to new triggers editor UI
* Remove unused dev TriggersBadge
* migrate triggers to V2
* Migrate capture components to V2
* improve triggers badge UI
* fix trigger panel with scheduled poll
* fix auto select all draft on deploy
* simplify permission check
* Add custom label to every trigger editor
* fix draft not deleting when saving triggers and add option to deploy now
* remove unused utility function
* fix triggers loading from draft
* make advanced route section collapsible
* handle subflow triggers display
* center triggers badge
* fix panel redirection when adding a new triggers from node
* Remove unnecessary alerts
* Fix proxy issue in schedule editor inner
* Remove unused schedule pages
* nit
* nit cli panel
* Migrate selectedTrigger store to V2
* handle extra header button for trigger editor panel
* prevent reload on toggle schedule enable
* remove unused utility function
* remove primaryScheduleStore
* handle triggerCount with drafts
* fix editing in Schedule Poll Mode
* Remove triggers default value context store
* fix triggers label max width
* Remove dbg logs
* improve no trigger selected message
* nit
* Do not show enable toggle for http triggers
* Adapt ui to dark mode
* nit
* remove captureOn context value
* improve dark mode
* fix nit
* fix merge issue
* nit
* nit
* fix schedule permission initialisation
* nit
* Disable deploy now if needed
* Improve utilitu function for handling with triggers
* improve trigger badge look
* fix kafka
* nit
* fix schedule display
* fix toggling edit mode
* fix edit/cancel edit
* nit
* prevent capture config update in editor
* migrate webhook panel to svelte 5
* fix postgres trigger creation
* fix bind issue in nats triggers
* fix modal triggers message flow/script
* fix apply args for script
* fix gcp triggers update when creating
* fix gcp capture
* nits
* add loading state for deploying all triggers
* remove default mqtt
* update base_endpoint for gcp
* nit
* fix
* fix
* remove base endpoint
* add catch in case of error while creating a trigger
* Add animation is capture panels
* show preprocessor extra when there is a preprocessor
* Add loading state for captures
* add missing fields for capture
* migrate URL to svelte 5
* show icon by default in confirmation modal
* do not show draft triggers in detail badge list
* migrate to new captures
* revert unwanted change
* migrate to preprocesor v2
* nit
* fix email capture
* nits and fix
* nits
* update repo ref
* Feat: auto save draft instad of save button
* use triggerIndex as selection
* Add modified tag to triggers
* Update trigger modal
* fix trigger node select
* fix schedule page
* migrate TriggersEditor to svelte 5
* remove unused props
* fix schedule editor init
* fix store reactivity issue
* use class instead of store for triggers context
* nit
* nit
* fix schedule init
* Add postgres error message
* nit
* fix deploy new script
* load schema in shedule editor
* improve transitions
* Improve capture indication
* revert unwanted changes
* improve update
* nit
* migrate captures section to svelte 5
* only show trash on hover triggers row
* Add token count
* improve trigger display
* Add relevent naming for triggers
* Use wrapper div insted of width binding in flow card
* add trigger sorting
* nit
* handle reload from URL for draft triggers
* dirty script and flow draft with draft triggers
* handle cloud hosted triggers
* nit
* nit
* fix nats reactivity
* remove debug log
* handle deployed draft triggers in the flow editor
* Add warning for event stream capture
---------
Co-authored-by: dieriba <dieriba.pro@gmail.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
305 lines
8.2 KiB
Svelte
305 lines
8.2 KiB
Svelte
<script lang="ts">
|
|
import { createEventDispatcher } from 'svelte'
|
|
import { ButtonType } from './model'
|
|
import { twMerge } from 'tailwind-merge'
|
|
import Dropdown from '$lib/components/DropdownV2.svelte'
|
|
import { getModifierKey, type Item } from '$lib/utils'
|
|
import { Loader2, ChevronDown } from 'lucide-svelte'
|
|
import { createTooltip } from '@melt-ui/svelte'
|
|
import type { Placement } from '@floating-ui/core'
|
|
import { conditionalMelt } from '$lib/utils'
|
|
import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted'
|
|
|
|
export let size: ButtonType.Size = 'md'
|
|
export let spacingSize: ButtonType.Size = size
|
|
export let color: ButtonType.Color | string = 'blue'
|
|
export let variant: ButtonType.Variant = 'contained'
|
|
export let btnClasses: string = ''
|
|
export let wrapperClasses: string = ''
|
|
export let wrapperStyle: string = ''
|
|
export let disabled: boolean = false
|
|
export let href: string | undefined = undefined
|
|
export let target: '_self' | '_blank' | undefined = undefined
|
|
export let iconOnly: boolean = false
|
|
export let loadUntilNav: boolean = false
|
|
|
|
export let clickableWhileLoading = false
|
|
|
|
export let element: ButtonType.Element | undefined = undefined
|
|
export let id: string = ''
|
|
export let nonCaptureEvent: boolean = false
|
|
export let propagateEvent: boolean = false
|
|
export let loading = false
|
|
export let title: string | undefined = undefined
|
|
export let style: string = ''
|
|
export let download: string | undefined = undefined
|
|
export let startIcon: ButtonType.Icon | undefined = undefined
|
|
export let endIcon: ButtonType.Icon | undefined = undefined
|
|
export let shortCut:
|
|
| { key?: string; hide?: boolean; Icon?: any; withoutModifier?: boolean }
|
|
| undefined = undefined
|
|
export let tooltipPopover:
|
|
| {
|
|
placement?: Placement
|
|
openDelay?: number
|
|
closeDelay?: number
|
|
portal?: string
|
|
}
|
|
| undefined = undefined
|
|
|
|
type MenuItem = {
|
|
label: string
|
|
onClick?: (e?: Event) => void
|
|
href?: string
|
|
icon?: any
|
|
disabled?: boolean
|
|
}
|
|
export let dropdownItems: MenuItem[] | (() => MenuItem[]) | undefined = undefined
|
|
export let hideDropdown: boolean = false
|
|
|
|
function computeDropdowns(menuItems: MenuItem[] | (() => MenuItem[])): Item[] {
|
|
const items = typeof menuItems === 'function' ? menuItems() : menuItems
|
|
return items.map((item) => ({
|
|
displayName: item.label,
|
|
action: item.onClick ? (e) => item.onClick?.(e) : undefined,
|
|
icon: item.icon,
|
|
disabled: item.disabled ?? false,
|
|
href: item.href
|
|
}))
|
|
}
|
|
|
|
export function focus() {
|
|
element?.focus({})
|
|
}
|
|
|
|
const dispatch = createEventDispatcher()
|
|
const dispatchIfMounted = createDispatcherIfMounted(dispatch)
|
|
// Order of classes: border, border modifier, bg, bg modifier, text, text modifier, everything else
|
|
|
|
async function onClick(event: MouseEvent) {
|
|
if (!nonCaptureEvent) {
|
|
event.preventDefault()
|
|
if (!propagateEvent) {
|
|
// by default events are not propagated, added this prop so that we can
|
|
event.stopPropagation()
|
|
}
|
|
dispatch('click', event)
|
|
}
|
|
}
|
|
|
|
function getColorClass(color, variant) {
|
|
if (color in ButtonType.ColorVariants) {
|
|
return ButtonType.ColorVariants[color][variant]
|
|
} else {
|
|
return color
|
|
}
|
|
}
|
|
|
|
$: buttonClass = twMerge(
|
|
'w-full',
|
|
getColorClass(color, variant),
|
|
variant === 'border' ? 'border' : '',
|
|
ButtonType.FontSizeClasses[size],
|
|
ButtonType.SpacingClasses[spacingSize][variant],
|
|
'focus-visible:ring-2 font-semibold',
|
|
dropdownItems && dropdownItems.length > 0 ? 'rounded-l-md h-full' : 'rounded-md',
|
|
'justify-center items-center text-center whitespace-nowrap inline-flex gap-2',
|
|
btnClasses,
|
|
'active:opacity-80 transition-all',
|
|
disabled ? '!bg-surface-disabled !text-tertiary cursor-not-allowed' : '',
|
|
loading ? 'cursor-wait' : ''
|
|
)
|
|
|
|
const iconMap = {
|
|
xs3: 12,
|
|
xs2: 14,
|
|
xs: 14,
|
|
sm: 16,
|
|
md: 16,
|
|
lg: 18,
|
|
xl: 18
|
|
}
|
|
|
|
const iconOnlyPadding = {
|
|
xs3: 'm-[0.5px] qhd:m-[1px]',
|
|
xs2: 'm-[1px] qhd:m-[1.125px]',
|
|
xs: 'm-[1px] qhd:m-[1.125px]',
|
|
sm: 'm-[2px] qhd:m-[2.25px]',
|
|
md: 'm-[2px] qhd:m-[2.25px]',
|
|
lg: 'm-[5px] qhd:m-[5.625px]',
|
|
xl: 'm-[5px] qhd:m-[5.625px]'
|
|
}
|
|
|
|
$: lucideIconSize = (iconMap[size] ?? 12) * 1
|
|
|
|
const {
|
|
elements: { trigger, content },
|
|
states: { open },
|
|
options: { openDelay }
|
|
} = tooltipPopover
|
|
? createTooltip({
|
|
positioning: {
|
|
placement: tooltipPopover?.placement
|
|
},
|
|
closeDelay: tooltipPopover?.closeDelay,
|
|
group: true,
|
|
portal: tooltipPopover?.portal
|
|
})
|
|
: {
|
|
elements: { trigger: undefined, content: undefined },
|
|
states: { open: undefined },
|
|
options: { openDelay: undefined }
|
|
}
|
|
$: tooltipPopover && openDelay !== undefined && ($openDelay = tooltipPopover?.openDelay) //This option is reactive
|
|
|
|
$: $open !== undefined && dispatchIfMounted('tooltipOpen', $open)
|
|
</script>
|
|
|
|
<div
|
|
class={twMerge(
|
|
dropdownItems && dropdownItems.length > 0 && variant === 'contained'
|
|
? ButtonType.ColorVariants[color].divider
|
|
: '',
|
|
wrapperClasses,
|
|
'flex flex-row',
|
|
disabled ? 'divide-text-disabled' : ''
|
|
)}
|
|
style={wrapperStyle}
|
|
data-interactive
|
|
>
|
|
{#if href && !disabled}
|
|
<a
|
|
bind:this={element}
|
|
on:pointerdown
|
|
on:focus
|
|
on:blur
|
|
on:mouseenter
|
|
on:mouseleave
|
|
on:click={() => {
|
|
loading = true
|
|
dispatch('click', event)
|
|
if (!loadUntilNav) {
|
|
loading = false
|
|
}
|
|
}}
|
|
{href}
|
|
{download}
|
|
class={buttonClass}
|
|
{id}
|
|
{target}
|
|
tabindex={disabled ? -1 : 0}
|
|
{...$$restProps}
|
|
{style}
|
|
>
|
|
{#if loading}
|
|
<Loader2 class={twMerge('animate-spin', iconOnlyPadding[size])} size={lucideIconSize} />
|
|
{:else if startIcon?.icon}
|
|
<svelte:component
|
|
this={startIcon.icon}
|
|
class={twMerge(startIcon?.classes, iconOnlyPadding[size])}
|
|
size={lucideIconSize}
|
|
{...startIcon.props}
|
|
/>
|
|
{/if}
|
|
|
|
{#if !iconOnly}
|
|
<slot />
|
|
{/if}
|
|
{#if endIcon?.icon}
|
|
<svelte:component
|
|
this={endIcon.icon}
|
|
class={twMerge(endIcon?.classes, iconOnlyPadding[size])}
|
|
size={lucideIconSize}
|
|
/>
|
|
{/if}
|
|
{#if shortCut && !shortCut.hide}
|
|
<div class="flex flex-row items-center !text-md opacity-60 gap-0 font-normal">
|
|
{#if shortCut.withoutModifier !== true}{getModifierKey()}{/if}{#if shortCut.Icon}<shortCut.Icon
|
|
class="w-4 h-4"
|
|
size={lucideIconSize}
|
|
/>{:else}{shortCut.key}{/if}
|
|
</div>
|
|
{/if}
|
|
</a>
|
|
{:else}
|
|
<button
|
|
bind:this={element}
|
|
on:pointerdown
|
|
on:click={onClick}
|
|
on:focus
|
|
on:blur
|
|
on:mouseenter
|
|
on:mouseleave
|
|
class={buttonClass}
|
|
{id}
|
|
tabindex={disabled ? -1 : 0}
|
|
{title}
|
|
{...$$restProps}
|
|
disabled={disabled || (loading && !clickableWhileLoading)}
|
|
{style}
|
|
use:conditionalMelt={trigger}
|
|
{...$trigger}
|
|
>
|
|
{#if loading}
|
|
<Loader2 class={twMerge('animate-spin', iconOnlyPadding[size])} size={lucideIconSize} />
|
|
{:else if startIcon?.icon}
|
|
<svelte:component
|
|
this={startIcon.icon}
|
|
class={twMerge(startIcon?.classes, iconOnlyPadding[size])}
|
|
size={lucideIconSize}
|
|
{...startIcon.props}
|
|
/>
|
|
{/if}
|
|
|
|
{#if !iconOnly}
|
|
<slot />
|
|
{/if}
|
|
{#if endIcon?.icon}
|
|
<svelte:component
|
|
this={endIcon.icon}
|
|
class={twMerge(endIcon?.classes, iconOnlyPadding[size])}
|
|
size={lucideIconSize}
|
|
/>
|
|
{/if}
|
|
{#if shortCut && !shortCut.hide}
|
|
{@const Icon = shortCut.Icon}
|
|
<div class="flex flex-row items-center !text-md opacity-60 gap-0 font-normal">
|
|
{#if shortCut.withoutModifier !== true}{getModifierKey()}{/if}{#if shortCut.Icon}<Icon
|
|
size={lucideIconSize}
|
|
/>{:else}{shortCut.key}{/if}
|
|
</div>
|
|
{/if}
|
|
</button>
|
|
{#if tooltipPopover && $open}
|
|
<div use:conditionalMelt={content} {...$content} class="z-[20000]">
|
|
<slot name="tooltip" />
|
|
</div>
|
|
{/if}
|
|
{/if}
|
|
|
|
{#if dropdownItems && dropdownItems.length > 0}
|
|
<Dropdown
|
|
items={computeDropdowns(dropdownItems)}
|
|
class="h-auto w-fit"
|
|
hidePopup={hideDropdown}
|
|
usePointerDownOutside
|
|
on:open={() => dispatch('dropdownOpen', true)}
|
|
on:close={() => dispatch('dropdownOpen', false)}
|
|
>
|
|
<svelte:fragment slot="buttonReplacement">
|
|
<div
|
|
class={twMerge(
|
|
buttonClass,
|
|
'rounded-md m-0 p-0 center-center h-full',
|
|
variant === 'border' ? 'border-0 border-r border-y ' : 'border-0',
|
|
'rounded-r-md !rounded-l-none',
|
|
size === 'xs2' ? '!w-8' : '!w-10'
|
|
)}
|
|
>
|
|
<ChevronDown size={lucideIconSize} />
|
|
</div>
|
|
</svelte:fragment>
|
|
</Dropdown>
|
|
{/if}
|
|
</div>
|