mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-09 00:04:10 +00:00
nits svelte 5 migration
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<script context="module" lang="ts">
|
||||
<script module lang="ts">
|
||||
import { writable } from 'svelte/store'
|
||||
const activeDropdown = writable<{ id: string | null; close: (() => void) | null }>({
|
||||
id: null,
|
||||
@@ -17,24 +17,49 @@
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { _ } from 'ag-grid-community'
|
||||
import { untrack } from 'svelte'
|
||||
|
||||
export let aiId: string | undefined = undefined
|
||||
export let aiDescription: string | undefined = undefined
|
||||
export let items: Item[] | (() => Item[]) | (() => Promise<Item[]>) = []
|
||||
export let disabled = false
|
||||
export let placement: Placement = 'bottom-end'
|
||||
export let usePointerDownOutside = false
|
||||
export let closeOnOtherDropdownOpen = true
|
||||
export let fixedHeight = true
|
||||
export let hidePopup = false
|
||||
export let open = false
|
||||
export let customWidth: number | undefined = undefined
|
||||
export let customMenu = false
|
||||
interface Props {
|
||||
aiId?: string | undefined
|
||||
aiDescription?: string | undefined
|
||||
items?: Item[] | (() => Item[]) | (() => Promise<Item[]>)
|
||||
disabled?: boolean
|
||||
placement?: Placement
|
||||
usePointerDownOutside?: boolean
|
||||
closeOnOtherDropdownOpen?: boolean
|
||||
fixedHeight?: boolean
|
||||
hidePopup?: boolean
|
||||
open?: boolean
|
||||
customWidth?: number | undefined
|
||||
customMenu?: boolean
|
||||
class?: string | undefined
|
||||
buttonReplacement?: import('svelte').Snippet
|
||||
menu?: import('svelte').Snippet
|
||||
}
|
||||
|
||||
let buttonEl: HTMLButtonElement | undefined = undefined
|
||||
let {
|
||||
aiId = undefined,
|
||||
aiDescription = undefined,
|
||||
items = [],
|
||||
disabled = false,
|
||||
placement = 'bottom-end',
|
||||
usePointerDownOutside = false,
|
||||
closeOnOtherDropdownOpen = true,
|
||||
fixedHeight = true,
|
||||
hidePopup = false,
|
||||
open = $bindable(false),
|
||||
customWidth = undefined,
|
||||
customMenu = false,
|
||||
class: classNames = undefined,
|
||||
buttonReplacement,
|
||||
menu
|
||||
}: Props = $props()
|
||||
|
||||
let buttonEl: HTMLButtonElement | undefined = $state(undefined)
|
||||
|
||||
const {
|
||||
elements: { menu, item, trigger },
|
||||
elements: { menu: menuEl, item, trigger },
|
||||
states,
|
||||
ids: { menu: dropdownId }
|
||||
} = createDropdownMenu({
|
||||
@@ -60,7 +85,12 @@
|
||||
})
|
||||
|
||||
const sync = createSync(states)
|
||||
$: sync.open(open, (v) => (open = Boolean(v)))
|
||||
$effect(() => {
|
||||
open
|
||||
untrack(() => {
|
||||
sync.open(open, (v) => (open = Boolean(v)))
|
||||
})
|
||||
})
|
||||
|
||||
export function close() {
|
||||
open = false
|
||||
@@ -88,25 +118,25 @@
|
||||
description: aiDescription,
|
||||
callback: () => buttonEl?.click()
|
||||
}}
|
||||
class={twMerge('w-full flex items-center justify-end', fixedHeight && 'h-8', $$props.class)}
|
||||
class={twMerge('w-full flex items-center justify-end', fixedHeight && 'h-8', classNames)}
|
||||
use:melt={$trigger}
|
||||
{disabled}
|
||||
on:click={(e) => e.stopPropagation()}
|
||||
onclick={(e) => e.stopPropagation()}
|
||||
use:pointerDownOutside={{
|
||||
capture: true,
|
||||
stopPropagation: false,
|
||||
exclude: getMenuElements,
|
||||
customEventName: 'pointerdown_menu'
|
||||
}}
|
||||
on:pointerdown_outside={() => {
|
||||
if (usePointerDownOutside) {
|
||||
close()
|
||||
customEventName: 'pointerdown_menu',
|
||||
onClickOutside: () => {
|
||||
if (usePointerDownOutside) {
|
||||
close()
|
||||
}
|
||||
}
|
||||
}}
|
||||
data-menu
|
||||
>
|
||||
{#if $$slots.buttonReplacement}
|
||||
<slot name="buttonReplacement" />
|
||||
{#if buttonReplacement}
|
||||
{@render buttonReplacement?.()}
|
||||
{:else}
|
||||
<Button
|
||||
nonCaptureEvent
|
||||
@@ -119,9 +149,9 @@
|
||||
</button>
|
||||
|
||||
{#if open && !hidePopup}
|
||||
<div use:melt={$menu} data-menu class="z-[6000] transition-all duration-100">
|
||||
<div use:melt={$menuEl} data-menu class="z-[6000] transition-all duration-100">
|
||||
{#if customMenu}
|
||||
<slot name="menu" />
|
||||
{@render menu?.()}
|
||||
{:else}
|
||||
<div
|
||||
class="bg-surface border w-56 origin-top-right rounded-md shadow-md focus:outline-none overflow-y-auto py-1 max-h-[50vh]"
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
<div class="flex flex-col">
|
||||
{#each computedItems ?? [] as item}
|
||||
<MenuItem
|
||||
on:click={(e) => item?.action?.(e)}
|
||||
onClick={(e) => item?.action?.(e)}
|
||||
href={item?.href}
|
||||
target={item?.hrefTarget}
|
||||
disabled={item?.disabled}
|
||||
class={twMerge(
|
||||
'px-4 py-2 text-primary font-semibold hover:bg-surface-hover cursor-pointer text-xs transition-all w-full',
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
import FlowTutorials from './FlowTutorials.svelte'
|
||||
import { tutorialsToDo } from '$lib/stores'
|
||||
|
||||
let targetTutorial: string | undefined = undefined
|
||||
let flowTutorials: FlowTutorials | undefined = undefined
|
||||
let targetTutorial: string | undefined = $state(undefined)
|
||||
let flowTutorials: FlowTutorials | undefined = $state(undefined)
|
||||
|
||||
async function getTutorialItems() {
|
||||
const tutorials = [
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
{#key $tutorialsToDo}
|
||||
<Dropdown items={getTutorialItems} class="w-fit">
|
||||
<svelte:fragment slot="buttonReplacement">
|
||||
{#snippet buttonReplacement()}
|
||||
<Button
|
||||
nonCaptureEvent
|
||||
size="xs"
|
||||
@@ -51,7 +51,7 @@
|
||||
id="tutorials-button"
|
||||
startIcon={{ icon: BookOpen }}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</Dropdown>
|
||||
{/key}
|
||||
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
import FlowBuilderTutorialForLoop from './tutorials/FlowBuilderTutorialForLoop.svelte'
|
||||
import FlowBuilderTutorialErrorHandler from './tutorials/FlowBuilderTutorialErrorHandler.svelte'
|
||||
|
||||
let flowBuilderTutorialSimpleFlow: FlowBuilderTutorialSimpleFlow | undefined = undefined
|
||||
let flowBuilderTutorialForLoop: FlowBuilderTutorialForLoop | undefined = undefined
|
||||
let flowBuilderTutorialBranchOne: FlowBuilderTutorialBranchOne | undefined = undefined
|
||||
let flowBuilderTutorialBranchAll: FlowBuilderTutorialBranchAll | undefined = undefined
|
||||
let flowBuilderTutorialErrorHandler: FlowBuilderTutorialErrorHandler | undefined = undefined
|
||||
let flowBuilderTutorialSimpleFlow: FlowBuilderTutorialSimpleFlow | undefined = $state(undefined)
|
||||
let flowBuilderTutorialForLoop: FlowBuilderTutorialForLoop | undefined = $state(undefined)
|
||||
let flowBuilderTutorialBranchOne: FlowBuilderTutorialBranchOne | undefined = $state(undefined)
|
||||
let flowBuilderTutorialBranchAll: FlowBuilderTutorialBranchAll | undefined = $state(undefined)
|
||||
let flowBuilderTutorialErrorHandler: FlowBuilderTutorialErrorHandler | undefined =
|
||||
$state(undefined)
|
||||
|
||||
export function runTutorialById(id: string, indexToInsertAt?: number | undefined) {
|
||||
if (id === 'forloop') {
|
||||
|
||||
@@ -4,12 +4,15 @@
|
||||
import DataTable from './table/DataTable.svelte'
|
||||
import Head from './table/Head.svelte'
|
||||
|
||||
export let headers: string[] | undefined
|
||||
export let data: any[] | undefined // Object containing the data
|
||||
export let keys: string[]
|
||||
export let size: 'sm' | 'md' | 'lg' = 'md'
|
||||
interface Props {
|
||||
headers: string[] | undefined
|
||||
data: any[] | undefined // Object containing the data
|
||||
keys: string[]
|
||||
size?: 'sm' | 'md' | 'lg'
|
||||
getRowActions?: ((row: any) => any[]) | undefined
|
||||
}
|
||||
|
||||
export let getRowActions: ((row: any) => any[]) | undefined = undefined
|
||||
let { headers, data, keys, size = 'md', getRowActions = undefined }: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="mt-2 w-full">
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
|
||||
function onTemplateChange(previousValueKey: string) {
|
||||
return (newValue) => {
|
||||
console.log('onTemplateChange', previousValueKey, newValue, id)
|
||||
// console.log('onTemplateChange', previousValueKey, newValue, id)
|
||||
previousConnectedValues[previousValueKey] = newValue
|
||||
debounceTemplate()
|
||||
}
|
||||
|
||||
@@ -801,7 +801,8 @@
|
||||
displayName: 'Public URL',
|
||||
icon: Globe,
|
||||
disabled: !secretUrlHref,
|
||||
href: secretUrlHref
|
||||
href: secretUrlHref,
|
||||
hrefTarget: '_blank'
|
||||
},
|
||||
// {
|
||||
// displayName: 'Publish to Hub',
|
||||
@@ -876,7 +877,7 @@
|
||||
appExport?.open(toStatic($app, $staticExporter, $summary).app)
|
||||
}
|
||||
}
|
||||
])
|
||||
]) as Item[]
|
||||
|
||||
let appEditorTutorial: AppEditorTutorial | undefined = $state(undefined)
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
import ConfirmationModal from '$lib/components/common/confirmationModal/ConfirmationModal.svelte'
|
||||
import { isAppTainted } from '$lib/components/tutorials/utils'
|
||||
|
||||
let appTutorials: AppTutorials | undefined = undefined
|
||||
let targetTutorial: string | undefined = undefined
|
||||
let appTutorials: AppTutorials | undefined = $state(undefined)
|
||||
let targetTutorial: string | undefined = $state(undefined)
|
||||
|
||||
const { app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
{#key $tutorialsToDo}
|
||||
<Dropdown items={getTutorialItems}>
|
||||
<svelte:fragment slot="buttonReplacement">
|
||||
{#snippet buttonReplacement()}
|
||||
<Button
|
||||
nonCaptureEvent
|
||||
size="xs"
|
||||
@@ -92,7 +92,7 @@
|
||||
icon: BookOpen
|
||||
}}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</Dropdown>
|
||||
{/key}
|
||||
|
||||
|
||||
@@ -6,11 +6,21 @@
|
||||
import Badge from '$lib/components/common/badge/Badge.svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let componentNumber: number = 0
|
||||
export let interval: number | undefined = undefined
|
||||
export let refreshing: string[] = []
|
||||
export let progress: number = 100
|
||||
export let loading: boolean | undefined = false
|
||||
interface Props {
|
||||
componentNumber?: number
|
||||
interval?: number | undefined
|
||||
refreshing?: string[]
|
||||
progress?: number
|
||||
loading?: boolean | undefined
|
||||
}
|
||||
|
||||
let {
|
||||
componentNumber = 0,
|
||||
interval = undefined,
|
||||
refreshing = [],
|
||||
progress = 100,
|
||||
loading = false
|
||||
}: Props = $props()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -53,7 +63,7 @@
|
||||
</Button>
|
||||
|
||||
<Dropdown {items} class="w-fit h-auto">
|
||||
<svelte:fragment slot="buttonReplacement">
|
||||
{#snippet buttonReplacement()}
|
||||
<div
|
||||
class="flex flex-row gap-2 text-xs bg-surface hover:bg-surface-hover px-2 items-center h-7"
|
||||
>
|
||||
@@ -66,7 +76,7 @@
|
||||
<TimerReset size={14} />
|
||||
</div>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</Dropdown>
|
||||
</div>
|
||||
{#if interval}
|
||||
|
||||
@@ -1,21 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { createBubbler, stopPropagation } from 'svelte/legacy'
|
||||
|
||||
const bubble = createBubbler()
|
||||
import Dropdown from '$lib/components/DropdownV2.svelte'
|
||||
import { classNames } from '$lib/utils'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import type { AppViewerContext } from '../types'
|
||||
import { Bug } from 'lucide-svelte'
|
||||
|
||||
export let tabs: any[] = []
|
||||
export let id: string
|
||||
|
||||
export let isConditionalDebugMode: boolean = false
|
||||
export let isSmall = false
|
||||
|
||||
const { componentControl } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
export let isManuallySelected: boolean = false
|
||||
let selected: number | null = null
|
||||
interface Props {
|
||||
tabs?: any[]
|
||||
id: string
|
||||
isConditionalDebugMode?: boolean
|
||||
isSmall?: boolean
|
||||
isManuallySelected?: boolean
|
||||
}
|
||||
|
||||
let {
|
||||
tabs = [],
|
||||
id,
|
||||
isConditionalDebugMode = false,
|
||||
isSmall = false,
|
||||
isManuallySelected = $bindable(false)
|
||||
}: Props = $props()
|
||||
let selected: number | null = $state(null)
|
||||
|
||||
async function getItems() {
|
||||
return [
|
||||
@@ -48,7 +59,7 @@
|
||||
|
||||
{#key tabs}
|
||||
<Dropdown items={getItems} class="w-fit h-auto" usePointerDownOutside>
|
||||
<svelte:fragment slot="buttonReplacement">
|
||||
{#snippet buttonReplacement()}
|
||||
<button
|
||||
title={isConditionalDebugMode ? 'Debug conditions' : 'Debug tabs'}
|
||||
class={classNames(
|
||||
@@ -57,8 +68,8 @@
|
||||
? 'hover:bg-red-200 hover:text-red-800'
|
||||
: 'text-blue-600 hover:bg-blue-300 hover:text-blue-800'
|
||||
)}
|
||||
on:click={() => dispatch('triggerInlineEditor')}
|
||||
on:pointerdown|stopPropagation
|
||||
onclick={() => dispatch('triggerInlineEditor')}
|
||||
onpointerdown={stopPropagation(bubble('pointerdown'))}
|
||||
>
|
||||
{#if isManuallySelected}
|
||||
<div class="whitespace-nowrap">
|
||||
@@ -79,6 +90,6 @@
|
||||
{isConditionalDebugMode ? `Debug conditions` : `Debug tabs`}
|
||||
{/if}
|
||||
</button>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</Dropdown>
|
||||
{/key}
|
||||
|
||||
@@ -9,11 +9,15 @@
|
||||
import Dropdown from '$lib/components/DropdownV2.svelte'
|
||||
import { ResourceService } from '$lib/gen'
|
||||
|
||||
export let row: {
|
||||
name: string
|
||||
path: string
|
||||
interface Props {
|
||||
row: {
|
||||
name: string
|
||||
path: string
|
||||
}
|
||||
}
|
||||
|
||||
let { row }: Props = $props()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
async function toggleDelete() {
|
||||
|
||||
@@ -8,11 +8,15 @@
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import GroupNameEditor from './NameEditor.svelte'
|
||||
|
||||
export let row: {
|
||||
name: string
|
||||
path: string
|
||||
interface Props {
|
||||
row: {
|
||||
name: string
|
||||
path: string
|
||||
}
|
||||
}
|
||||
|
||||
let { row }: Props = $props()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
async function toggleDelete() {
|
||||
|
||||
@@ -16,17 +16,20 @@
|
||||
import ThemeDrawer from './ThemeDrawer.svelte'
|
||||
import Dropdown from '$lib/components/DropdownV2.svelte'
|
||||
|
||||
export let previewThemePath: string | undefined = undefined
|
||||
|
||||
export let row: {
|
||||
name: string
|
||||
path: string
|
||||
interface Props {
|
||||
previewThemePath?: string | undefined
|
||||
row: {
|
||||
name: string
|
||||
path: string
|
||||
}
|
||||
}
|
||||
|
||||
let { previewThemePath = $bindable(undefined), row }: Props = $props()
|
||||
|
||||
const { previewTheme, app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let cssString: string | undefined = $app?.theme?.type === 'inlined' ? $app.theme.css : undefined
|
||||
$: type = $app?.theme?.type
|
||||
let type = $derived($app?.theme?.type)
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -162,7 +165,7 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
let themeDrawer: ThemeDrawer
|
||||
let themeDrawer: ThemeDrawer | undefined = $state()
|
||||
</script>
|
||||
|
||||
<tr class={twMerge(previewThemePath === row.path ? 'bg-blue-200' : '', 'transition-all')}>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { run, createBubbler } from 'svelte/legacy'
|
||||
|
||||
const bubble = createBubbler()
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { ButtonType } from './model'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
@@ -11,46 +14,6 @@
|
||||
import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
|
||||
export let id: string = ''
|
||||
export let aiId: string | undefined = undefined
|
||||
export let aiDescription: string | undefined = undefined
|
||||
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 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
|
||||
export let dropdownBtnClasses: string = ''
|
||||
|
||||
type MenuItem = {
|
||||
label: string
|
||||
onClick?: (e?: Event) => void
|
||||
@@ -58,8 +21,84 @@
|
||||
icon?: any
|
||||
disabled?: boolean
|
||||
}
|
||||
export let dropdownItems: MenuItem[] | (() => MenuItem[]) | undefined = undefined
|
||||
export let hideDropdown: boolean = false
|
||||
interface Props {
|
||||
id?: string
|
||||
aiId?: string | undefined
|
||||
aiDescription?: string | undefined
|
||||
size?: ButtonType.Size
|
||||
spacingSize?: ButtonType.Size
|
||||
color?: ButtonType.Color | string
|
||||
variant?: ButtonType.Variant
|
||||
btnClasses?: string
|
||||
wrapperClasses?: string
|
||||
wrapperStyle?: string
|
||||
disabled?: boolean
|
||||
href?: string | undefined
|
||||
target?: '_self' | '_blank' | undefined
|
||||
iconOnly?: boolean
|
||||
loadUntilNav?: boolean
|
||||
clickableWhileLoading?: boolean
|
||||
element?: ButtonType.Element | undefined
|
||||
nonCaptureEvent?: boolean
|
||||
propagateEvent?: boolean
|
||||
loading?: boolean
|
||||
title?: string | undefined
|
||||
style?: string
|
||||
download?: string | undefined
|
||||
startIcon?: ButtonType.Icon | undefined
|
||||
endIcon?: ButtonType.Icon | undefined
|
||||
shortCut?: { key?: string; hide?: boolean; Icon?: any; withoutModifier?: boolean } | undefined
|
||||
tooltipPopover?:
|
||||
| {
|
||||
placement?: Placement
|
||||
openDelay?: number
|
||||
closeDelay?: number
|
||||
portal?: string
|
||||
}
|
||||
| undefined
|
||||
dropdownBtnClasses?: string
|
||||
dropdownItems?: MenuItem[] | (() => MenuItem[]) | undefined
|
||||
hideDropdown?: boolean
|
||||
children?: import('svelte').Snippet
|
||||
tooltip?: import('svelte').Snippet
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
let {
|
||||
id = '',
|
||||
aiId = undefined,
|
||||
aiDescription = undefined,
|
||||
size = 'md',
|
||||
spacingSize = size,
|
||||
color = 'blue',
|
||||
variant = 'contained',
|
||||
btnClasses = '',
|
||||
wrapperClasses = '',
|
||||
wrapperStyle = '',
|
||||
disabled = false,
|
||||
href = undefined,
|
||||
target = undefined,
|
||||
iconOnly = false,
|
||||
loadUntilNav = false,
|
||||
clickableWhileLoading = false,
|
||||
element = $bindable(undefined),
|
||||
nonCaptureEvent = false,
|
||||
propagateEvent = false,
|
||||
loading = $bindable(false),
|
||||
title = undefined,
|
||||
style = '',
|
||||
download = undefined,
|
||||
startIcon = undefined,
|
||||
endIcon = undefined,
|
||||
shortCut = undefined,
|
||||
tooltipPopover = undefined,
|
||||
dropdownBtnClasses = '',
|
||||
dropdownItems = undefined,
|
||||
hideDropdown = false,
|
||||
children,
|
||||
tooltip,
|
||||
...rest
|
||||
}: Props = $props()
|
||||
|
||||
function computeDropdowns(menuItems: MenuItem[] | (() => MenuItem[])): Item[] {
|
||||
const items = typeof menuItems === 'function' ? menuItems() : menuItems
|
||||
@@ -103,19 +142,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: 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' : ''
|
||||
let buttonClass = $derived(
|
||||
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 = {
|
||||
@@ -138,7 +179,7 @@
|
||||
xl: 'm-[5px] qhd:m-[5.625px]'
|
||||
}
|
||||
|
||||
$: lucideIconSize = (iconMap[size] ?? 12) * 1
|
||||
let lucideIconSize = $derived((iconMap[size] ?? 12) * 1)
|
||||
|
||||
const {
|
||||
elements: { trigger, content },
|
||||
@@ -158,9 +199,13 @@
|
||||
states: { open: undefined },
|
||||
options: { openDelay: undefined }
|
||||
}
|
||||
$: tooltipPopover && openDelay !== undefined && ($openDelay = tooltipPopover?.openDelay) //This option is reactive
|
||||
run(() => {
|
||||
tooltipPopover && openDelay !== undefined && ($openDelay = tooltipPopover?.openDelay)
|
||||
}) //This option is reactive
|
||||
|
||||
$: $open !== undefined && dispatchIfMounted('tooltipOpen', $open)
|
||||
run(() => {
|
||||
$open !== undefined && dispatchIfMounted('tooltipOpen', $open)
|
||||
})
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -182,141 +227,137 @@
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#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 href && !disabled}
|
||||
<a
|
||||
bind:this={element}
|
||||
onpointerdown={bubble('pointerdown')}
|
||||
onfocus={bubble('focus')}
|
||||
onblur={bubble('blur')}
|
||||
onmouseenter={bubble('mouseenter')}
|
||||
onmouseleave={bubble('mouseleave')}
|
||||
onclick={() => {
|
||||
loading = true
|
||||
dispatch('click', event)
|
||||
if (!loadUntilNav) {
|
||||
loading = false
|
||||
}
|
||||
}}
|
||||
{href}
|
||||
{download}
|
||||
class={buttonClass}
|
||||
{id}
|
||||
{target}
|
||||
tabindex={disabled ? -1 : 0}
|
||||
{...rest}
|
||||
{style}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class={twMerge('animate-spin', iconOnlyPadding[size])} size={lucideIconSize} />
|
||||
{:else if startIcon?.icon}
|
||||
<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" />
|
||||
{#if !iconOnly}
|
||||
{@render children?.()}
|
||||
{/if}
|
||||
{#if endIcon?.icon}
|
||||
<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}
|
||||
{/if}
|
||||
</a>
|
||||
{:else}
|
||||
<button
|
||||
bind:this={element}
|
||||
onpointerdown={bubble('pointerdown')}
|
||||
onclick={onClick}
|
||||
onfocus={bubble('focus')}
|
||||
onblur={bubble('blur')}
|
||||
onmouseenter={bubble('mouseenter')}
|
||||
onmouseleave={bubble('mouseleave')}
|
||||
class={buttonClass}
|
||||
{id}
|
||||
tabindex={disabled ? -1 : 0}
|
||||
{title}
|
||||
{...rest}
|
||||
disabled={disabled || (loading && !clickableWhileLoading)}
|
||||
{style}
|
||||
use:conditionalMelt={trigger}
|
||||
{...$trigger}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class={twMerge('animate-spin', iconOnlyPadding[size])} size={lucideIconSize} />
|
||||
{:else if startIcon?.icon}
|
||||
<startIcon.icon
|
||||
class={twMerge(startIcon?.classes, iconOnlyPadding[size])}
|
||||
size={lucideIconSize}
|
||||
{...startIcon.props}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if dropdownItems && dropdownItems.length > 0}
|
||||
<Dropdown
|
||||
aiId={aiId ? `${aiId}-dropdown` : undefined}
|
||||
aiDescription={aiDescription ? `${aiDescription} dropdown` : undefined}
|
||||
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' || size === 'xs' ? '!w-8' : '!w-10',
|
||||
dropdownBtnClasses
|
||||
)}
|
||||
>
|
||||
<ChevronDown size={lucideIconSize} />
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
</Dropdown>
|
||||
{#if !iconOnly}
|
||||
{@render children?.()}
|
||||
{/if}
|
||||
{#if endIcon?.icon}
|
||||
<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]">
|
||||
{@render tooltip?.()}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if dropdownItems && dropdownItems.length > 0}
|
||||
<Dropdown
|
||||
aiId={aiId ? `${aiId}-dropdown` : undefined}
|
||||
aiDescription={aiDescription ? `${aiDescription} dropdown` : undefined}
|
||||
items={computeDropdowns(dropdownItems)}
|
||||
class="h-auto w-fit"
|
||||
hidePopup={hideDropdown}
|
||||
usePointerDownOutside
|
||||
on:open={() => dispatch('dropdownOpen', true)}
|
||||
on:close={() => dispatch('dropdownOpen', false)}
|
||||
>
|
||||
{#snippet 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' || size === 'xs' ? '!w-8' : '!w-10',
|
||||
dropdownBtnClasses
|
||||
)}
|
||||
>
|
||||
<ChevronDown size={lucideIconSize} />
|
||||
</div>
|
||||
{/snippet}
|
||||
</Dropdown>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -33,20 +33,34 @@
|
||||
import { isDeployable } from '$lib/utils_deployable'
|
||||
import { getDeployUiSettings } from '$lib/components/home/deploy_ui'
|
||||
|
||||
export let app: ListableApp & { has_draft?: boolean; draft_only?: boolean; canWrite: boolean }
|
||||
export let marked: string | undefined
|
||||
export let starred: boolean
|
||||
export let shareModal: ShareModal
|
||||
export let moveDrawer: MoveDrawer
|
||||
export let deploymentDrawer: DeployWorkspaceDrawer
|
||||
export let deleteConfirmedCallback: (() => void) | undefined
|
||||
export let depth: number = 0
|
||||
export let menuOpen: boolean = false
|
||||
interface Props {
|
||||
app: ListableApp & { has_draft?: boolean; draft_only?: boolean; canWrite: boolean }
|
||||
marked: string | undefined
|
||||
starred: boolean
|
||||
shareModal: ShareModal
|
||||
moveDrawer: MoveDrawer
|
||||
deploymentDrawer: DeployWorkspaceDrawer
|
||||
deleteConfirmedCallback: (() => void) | undefined
|
||||
depth?: number
|
||||
menuOpen?: boolean
|
||||
}
|
||||
|
||||
let {
|
||||
app,
|
||||
marked,
|
||||
starred,
|
||||
shareModal,
|
||||
moveDrawer,
|
||||
deploymentDrawer,
|
||||
deleteConfirmedCallback = $bindable(),
|
||||
depth = 0,
|
||||
menuOpen = $bindable(false)
|
||||
}: Props = $props()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let appExport: { open: (path: string) => void } | undefined = undefined
|
||||
let appDeploymentHistory: AppDeploymentHistory | undefined = undefined
|
||||
let appExport: { open: (path: string) => void } | undefined = $state(undefined)
|
||||
let appDeploymentHistory: AppDeploymentHistory | undefined = $state(undefined)
|
||||
|
||||
async function loadAppJson() {
|
||||
appExport?.open(app.path)
|
||||
@@ -72,7 +86,7 @@
|
||||
canFavorite={!app.draft_only}
|
||||
{depth}
|
||||
>
|
||||
<svelte:fragment slot="badges">
|
||||
{#snippet badges()}
|
||||
{#if app.execution_mode == 'anonymous'}
|
||||
<Badge small>
|
||||
<div class="flex gap-1 items-center">
|
||||
@@ -92,8 +106,8 @@
|
||||
<SharedBadge canWrite={app.canWrite} extraPerms={app.extra_perms} />
|
||||
<DraftBadge has_draft={app.has_draft} draft_only={app.draft_only} />
|
||||
<div class="w-8 center-center"></div>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
{/snippet}
|
||||
{#snippet actions()}
|
||||
<span class="hidden md:inline-flex gap-x-1">
|
||||
{#if !$userStore?.operator}
|
||||
{#if app.canWrite}
|
||||
@@ -284,5 +298,5 @@
|
||||
menuOpen = true
|
||||
}}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</Row>
|
||||
|
||||
@@ -35,16 +35,31 @@
|
||||
import FlowHistory from '$lib/components/flows/FlowHistory.svelte'
|
||||
import { getDeployUiSettings } from '$lib/components/home/deploy_ui'
|
||||
|
||||
export let flow: Flow & { has_draft?: boolean; draft_only?: boolean; canWrite: boolean }
|
||||
export let marked: string | undefined
|
||||
export let starred: boolean
|
||||
export let shareModal: ShareModal
|
||||
export let moveDrawer: MoveDrawer
|
||||
export let deleteConfirmedCallback: (() => void) | undefined
|
||||
export let deploymentDrawer: DeployWorkspaceDrawer
|
||||
export let errorHandlerMuted: boolean
|
||||
export let depth: number = 0
|
||||
export let menuOpen: boolean = false
|
||||
interface Props {
|
||||
flow: Flow & { has_draft?: boolean; draft_only?: boolean; canWrite: boolean }
|
||||
marked: string | undefined
|
||||
starred: boolean
|
||||
shareModal: ShareModal
|
||||
moveDrawer: MoveDrawer
|
||||
deleteConfirmedCallback: (() => void) | undefined
|
||||
deploymentDrawer: DeployWorkspaceDrawer
|
||||
errorHandlerMuted: boolean
|
||||
depth?: number
|
||||
menuOpen?: boolean
|
||||
}
|
||||
|
||||
let {
|
||||
flow,
|
||||
marked,
|
||||
starred,
|
||||
shareModal,
|
||||
moveDrawer,
|
||||
deleteConfirmedCallback = $bindable(),
|
||||
deploymentDrawer,
|
||||
errorHandlerMuted,
|
||||
depth = 0,
|
||||
menuOpen = $bindable(false)
|
||||
}: Props = $props()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -71,8 +86,8 @@
|
||||
sendUserToast(`Could not delete this flow ${err.body}`, true)
|
||||
}
|
||||
}
|
||||
let scheduleEditor: ScheduleEditor
|
||||
let flowHistory: FlowHistory
|
||||
let scheduleEditor: ScheduleEditor | undefined = $state(undefined)
|
||||
let flowHistory: FlowHistory | undefined = $state(undefined)
|
||||
</script>
|
||||
|
||||
{#if menuOpen}
|
||||
@@ -97,15 +112,15 @@
|
||||
canFavorite={!flow.draft_only}
|
||||
{depth}
|
||||
>
|
||||
<svelte:fragment slot="badges">
|
||||
{#snippet badges()}
|
||||
{#if flow.archived}
|
||||
<Badge color="red" baseClass="border">archived</Badge>
|
||||
{/if}
|
||||
<SharedBadge canWrite={flow.canWrite} extraPerms={flow.extra_perms} />
|
||||
<DraftBadge has_draft={flow.has_draft} draft_only={flow.draft_only} />
|
||||
<div class="w-8 center-center"></div>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
{/snippet}
|
||||
{#snippet actions()}
|
||||
<span class="hidden md:inline-flex gap-x-1">
|
||||
{#if !$userStore?.operator}
|
||||
{#if flow.canWrite && !flow.archived}
|
||||
@@ -218,7 +233,7 @@
|
||||
displayName: 'Deployments',
|
||||
icon: HistoryIcon,
|
||||
action: () => {
|
||||
flowHistory.open()
|
||||
flowHistory?.open()
|
||||
},
|
||||
hide: $userStore?.operator
|
||||
},
|
||||
@@ -291,5 +306,5 @@
|
||||
menuOpen = true
|
||||
}}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</Row>
|
||||
|
||||
@@ -18,17 +18,31 @@
|
||||
import { isDeployable } from '$lib/utils_deployable'
|
||||
import { getDeployUiSettings } from '$lib/components/home/deploy_ui'
|
||||
|
||||
export let app: ListableRawApp & { canWrite: boolean }
|
||||
export let marked: string | undefined
|
||||
export let starred: boolean
|
||||
export let shareModal: ShareModal
|
||||
export let moveDrawer: MoveDrawer
|
||||
export let deleteConfirmedCallback: (() => void) | undefined
|
||||
export let deploymentDrawer: DeployWorkspaceDrawer
|
||||
export let depth: number = 0
|
||||
export let menuOpen: boolean = false
|
||||
interface Props {
|
||||
app: ListableRawApp & { canWrite: boolean }
|
||||
marked: string | undefined
|
||||
starred: boolean
|
||||
shareModal: ShareModal
|
||||
moveDrawer: MoveDrawer
|
||||
deleteConfirmedCallback: (() => void) | undefined
|
||||
deploymentDrawer: DeployWorkspaceDrawer
|
||||
depth?: number
|
||||
menuOpen?: boolean
|
||||
}
|
||||
|
||||
let updateAppDrawer: Drawer
|
||||
let {
|
||||
app,
|
||||
marked,
|
||||
starred,
|
||||
shareModal,
|
||||
moveDrawer,
|
||||
deleteConfirmedCallback = $bindable(),
|
||||
deploymentDrawer,
|
||||
depth = 0,
|
||||
menuOpen = $bindable(false)
|
||||
}: Props = $props()
|
||||
|
||||
let updateAppDrawer: Drawer | undefined = $state(undefined)
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
@@ -66,10 +80,10 @@
|
||||
canFavorite={true}
|
||||
{depth}
|
||||
>
|
||||
<svelte:fragment slot="badges">
|
||||
{#snippet badges()}
|
||||
<SharedBadge canWrite={app.canWrite} extraPerms={app.extra_perms} />
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
{/snippet}
|
||||
{#snippet actions()}
|
||||
<span class="hidden md:inline-flex gap-x-1">
|
||||
{#if !$userStore?.operator}
|
||||
{#if app.canWrite}
|
||||
@@ -143,5 +157,5 @@
|
||||
menuOpen = true
|
||||
}}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</Row>
|
||||
|
||||
@@ -7,26 +7,55 @@
|
||||
import { goto } from '$lib/navigation'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
|
||||
export let marked: string | undefined
|
||||
export let starred: boolean
|
||||
export let canFavorite: boolean = true
|
||||
export let errorHandlerMuted: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
export let aiId: string | undefined = undefined
|
||||
export let aiDescription: string | undefined = undefined
|
||||
export let kind: 'script' | 'flow' | 'app' | 'raw_app' = 'script'
|
||||
export let summary: string | undefined = undefined
|
||||
export let path: string
|
||||
export let href: string
|
||||
export let workspaceId: string
|
||||
export let depth: number = 0
|
||||
interface Props {
|
||||
marked: string | undefined
|
||||
starred: boolean
|
||||
canFavorite?: boolean
|
||||
errorHandlerMuted?: boolean
|
||||
aiId?: string | undefined
|
||||
aiDescription?: string | undefined
|
||||
kind?: 'script' | 'flow' | 'app' | 'raw_app'
|
||||
summary?: string | undefined
|
||||
path: string
|
||||
href: string
|
||||
workspaceId: string
|
||||
depth?: number
|
||||
badges?: import('svelte').Snippet
|
||||
actions?: import('svelte').Snippet
|
||||
}
|
||||
|
||||
let {
|
||||
marked,
|
||||
starred,
|
||||
canFavorite = true,
|
||||
errorHandlerMuted = false,
|
||||
aiId = undefined,
|
||||
aiDescription = undefined,
|
||||
kind = 'script',
|
||||
summary = undefined,
|
||||
path,
|
||||
href,
|
||||
workspaceId,
|
||||
depth = 0,
|
||||
badges,
|
||||
actions
|
||||
}: Props = $props()
|
||||
|
||||
let displayPath: string = (depth === 0 ? path : path?.split('/')?.slice(-1)?.[0]) ?? ''
|
||||
</script>
|
||||
|
||||
<div style="display: none" use:triggerableByAI={{id: aiId, description: aiDescription, callback: () => { goto(href) }}}></div>
|
||||
<div
|
||||
style="display: none"
|
||||
use:triggerableByAI={{
|
||||
id: aiId,
|
||||
description: aiDescription,
|
||||
callback: () => {
|
||||
goto(href)
|
||||
}
|
||||
}}
|
||||
></div>
|
||||
<div
|
||||
class={twMerge(
|
||||
'hover:bg-surface-hover w-full inline-flex items-center gap-4 first-of-type:!border-t-0 first-of-type:rounded-t-md last-of-type:rounded-b-md [*:not(:last-child)]:border-b px-4 py-2.5 border-b last:border-b-0',
|
||||
@@ -56,9 +85,9 @@
|
||||
<BellOff class="w-8 opacity-60" size={12} fill="currentcolor" />
|
||||
{/if}
|
||||
|
||||
{#if $$slots.badges}
|
||||
{#if badges}
|
||||
<div class="hidden lg:flex flex-row gap-4 items-center">
|
||||
<slot name="badges" />
|
||||
{@render badges?.()}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -79,6 +108,6 @@
|
||||
{/if}
|
||||
|
||||
<div class="flex gap-1 items-center justify-end pr-2">
|
||||
<slot name="actions" />
|
||||
{@render actions?.()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -42,17 +42,33 @@
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import { getDeployUiSettings } from '$lib/components/home/deploy_ui'
|
||||
|
||||
export let script: Script & { canWrite: boolean; use_codebase: boolean }
|
||||
export let marked: string | undefined
|
||||
export let starred: boolean
|
||||
export let shareModal: ShareModal
|
||||
export let moveDrawer: MoveDrawer
|
||||
export let deploymentDrawer: DeployWorkspaceDrawer
|
||||
export let deleteConfirmedCallback: (() => void) | undefined
|
||||
export let errorHandlerMuted: boolean
|
||||
export let showCode: (path: string, summary: string) => void
|
||||
export let depth: number = 0
|
||||
export let menuOpen: boolean = false
|
||||
interface Props {
|
||||
script: Script & { canWrite: boolean; use_codebase: boolean }
|
||||
marked: string | undefined
|
||||
starred: boolean
|
||||
shareModal: ShareModal
|
||||
moveDrawer: MoveDrawer
|
||||
deploymentDrawer: DeployWorkspaceDrawer
|
||||
deleteConfirmedCallback: (() => void) | undefined
|
||||
errorHandlerMuted: boolean
|
||||
showCode: (path: string, summary: string) => void
|
||||
depth?: number
|
||||
menuOpen?: boolean
|
||||
}
|
||||
|
||||
let {
|
||||
script,
|
||||
marked,
|
||||
starred,
|
||||
shareModal,
|
||||
moveDrawer,
|
||||
deploymentDrawer,
|
||||
deleteConfirmedCallback = $bindable(),
|
||||
errorHandlerMuted,
|
||||
showCode,
|
||||
depth = 0,
|
||||
menuOpen = $bindable(false)
|
||||
}: Props = $props()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -81,10 +97,10 @@
|
||||
dispatch('change')
|
||||
sendUserToast(`Deleted script ${path}`)
|
||||
}
|
||||
let scheduleEditor: ScheduleEditor
|
||||
let scheduleEditor: ScheduleEditor | undefined = $state(undefined)
|
||||
|
||||
const dlt: 'delete' = 'delete'
|
||||
let versionsDrawerOpen: boolean = false
|
||||
let versionsDrawerOpen: boolean = $state(false)
|
||||
</script>
|
||||
|
||||
{#if menuOpen}
|
||||
@@ -108,7 +124,7 @@
|
||||
canFavorite={!script.draft_only}
|
||||
{depth}
|
||||
>
|
||||
<svelte:fragment slot="badges">
|
||||
{#snippet badges()}
|
||||
{#if script.lock_error_logs}
|
||||
<Badge color="red" baseClass="border border-red-200">Deployment failed</Badge>
|
||||
{/if}
|
||||
@@ -128,9 +144,9 @@
|
||||
<div class="w-8 center-center">
|
||||
<LanguageIcon lang={script.language} width={12} height={12} />
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
{#snippet actions()}
|
||||
<span class="hidden md:inline-flex gap-x-1">
|
||||
{#if !$userStore?.operator}
|
||||
{#if script.use_codebase}
|
||||
@@ -261,7 +277,7 @@
|
||||
displayName: 'Schedule',
|
||||
icon: Calendar,
|
||||
action: () => {
|
||||
scheduleEditor.openNew(false, script.path)
|
||||
scheduleEditor?.openNew(false, script.path)
|
||||
},
|
||||
disabled: script.archived,
|
||||
hide: $userStore?.operator
|
||||
@@ -340,7 +356,7 @@
|
||||
menuOpen = true
|
||||
}}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</Row>
|
||||
|
||||
{#if script}
|
||||
|
||||
@@ -4,18 +4,30 @@
|
||||
import DropdownV2 from '$lib/components/DropdownV2.svelte'
|
||||
import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte'
|
||||
|
||||
export let disabled: boolean = false
|
||||
export let small = false
|
||||
export let light = false
|
||||
export let id: string | undefined = undefined
|
||||
export let item: any | undefined = undefined
|
||||
export let selected: string | undefined = undefined
|
||||
type TogglableItem = {
|
||||
label: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export let togglableItems: TogglableItem[]
|
||||
interface Props {
|
||||
disabled?: boolean
|
||||
small?: boolean
|
||||
light?: boolean
|
||||
id?: string | undefined
|
||||
item?: any | undefined
|
||||
selected?: string | undefined
|
||||
togglableItems: TogglableItem[]
|
||||
}
|
||||
|
||||
let {
|
||||
disabled = false,
|
||||
small = false,
|
||||
light = false,
|
||||
id = undefined,
|
||||
item = undefined,
|
||||
selected = $bindable(undefined),
|
||||
togglableItems
|
||||
}: Props = $props()
|
||||
|
||||
function select(v: string) {
|
||||
selected = v
|
||||
|
||||
@@ -23,16 +23,31 @@
|
||||
color?: 'red'
|
||||
}
|
||||
|
||||
const { triggersCount, triggersState } = getContext<TriggerContext>('TriggerContext')
|
||||
const { triggersCount, triggersState } = $state(getContext<TriggerContext>('TriggerContext'))
|
||||
|
||||
export let mainButtons: MainButton[] = []
|
||||
export let menuItems: MenuItemButton[] = []
|
||||
export let title: string
|
||||
export let tag: string | undefined
|
||||
interface Props {
|
||||
mainButtons?: MainButton[]
|
||||
menuItems?: MenuItemButton[]
|
||||
title: string
|
||||
tag: string | undefined
|
||||
errorHandlerKind: 'flow' | 'script'
|
||||
scriptOrFlowPath: string
|
||||
errorHandlerMuted: boolean | undefined
|
||||
children?: import('svelte').Snippet
|
||||
trigger_badges?: import('svelte').Snippet
|
||||
}
|
||||
|
||||
export let errorHandlerKind: 'flow' | 'script'
|
||||
export let scriptOrFlowPath: string
|
||||
export let errorHandlerMuted: boolean | undefined
|
||||
let {
|
||||
mainButtons = [],
|
||||
menuItems = [],
|
||||
title,
|
||||
tag,
|
||||
errorHandlerKind,
|
||||
scriptOrFlowPath,
|
||||
errorHandlerMuted = $bindable(),
|
||||
children,
|
||||
trigger_badges
|
||||
}: Props = $props()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
@@ -51,7 +66,7 @@
|
||||
</div>{#if tag}
|
||||
<Badge>tag: {tag}</Badge>
|
||||
{/if}
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
{#if triggersState?.triggers?.some((t) => t.isPrimary && !t.isDraft)}
|
||||
{@const primarySchedule = triggersState.triggers.findIndex(
|
||||
(t) => t.isPrimary && !t.isDraft
|
||||
@@ -71,7 +86,7 @@
|
||||
{$triggersCount?.primary_schedule?.schedule ?? ''}
|
||||
</Button>
|
||||
{/if}
|
||||
<slot name="trigger-badges" />
|
||||
{@render trigger_badges?.()}
|
||||
</div>
|
||||
<div class="flex gap-1 md:gap-2 items-center">
|
||||
{#if menuItems.length > 0}
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
import { Loader2, Plus } from 'lucide-svelte'
|
||||
import YAML from 'yaml'
|
||||
|
||||
let drawer: Drawer | undefined = undefined
|
||||
let pendingRaw: string
|
||||
let importType: 'yaml' | 'json' = 'yaml'
|
||||
let drawer: Drawer | undefined = $state(undefined)
|
||||
let pendingRaw: string | undefined = $state(undefined)
|
||||
let importType: 'yaml' | 'json' = $state('yaml')
|
||||
|
||||
async function importRaw() {
|
||||
$importFlowStore = importType === 'yaml' ? YAML.parse(pendingRaw) : JSON.parse(pendingRaw)
|
||||
$importFlowStore =
|
||||
importType === 'yaml' ? YAML.parse(pendingRaw ?? '') : JSON.parse(pendingRaw ?? '')
|
||||
await goto('/flows/add')
|
||||
drawer?.closeDrawer?.()
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
items[idx].success == false ? 'text-red-400' : '',
|
||||
'data-[highlighted]:bg-surface-hover'
|
||||
)}
|
||||
on:click={() => {
|
||||
onClick={() => {
|
||||
onSelectedIteration({
|
||||
moduleId: moduleId,
|
||||
index: items[idx].index,
|
||||
|
||||
@@ -295,7 +295,7 @@
|
||||
<MenuItem
|
||||
{item}
|
||||
class={itemClass}
|
||||
on:click={() => {
|
||||
onClick={() => {
|
||||
onSelect?.(triggerIndex)
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -3,15 +3,36 @@
|
||||
import type { MenubarMenuElements } from '@melt-ui/svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
|
||||
export let aiId: string | undefined = undefined
|
||||
export let aiDescription: string | undefined = undefined
|
||||
export let href: string | undefined = undefined
|
||||
export let disabled: boolean = false
|
||||
export let target: string | undefined = undefined
|
||||
export let item: MenubarMenuElements['item']
|
||||
interface Props {
|
||||
aiId?: string | undefined
|
||||
aiDescription?: string | undefined
|
||||
href?: string | undefined
|
||||
disabled?: boolean
|
||||
target?: string | undefined
|
||||
item: MenubarMenuElements['item']
|
||||
class?: string | undefined
|
||||
onClick?: (event: MouseEvent) => void
|
||||
children?: import('svelte').Snippet
|
||||
onFocusIn?: (event: FocusEvent) => void
|
||||
onFocusOut?: (event: FocusEvent) => void
|
||||
}
|
||||
|
||||
let aRef: HTMLAnchorElement | undefined = undefined
|
||||
let buttonRef: HTMLButtonElement | undefined = undefined
|
||||
let {
|
||||
aiId = undefined,
|
||||
aiDescription = undefined,
|
||||
href = undefined,
|
||||
disabled = false,
|
||||
target = undefined,
|
||||
item,
|
||||
class: classNames = undefined,
|
||||
children,
|
||||
onClick,
|
||||
onFocusIn,
|
||||
onFocusOut
|
||||
}: Props = $props()
|
||||
|
||||
let aRef: HTMLAnchorElement | undefined = $state(undefined)
|
||||
let buttonRef: HTMLButtonElement | undefined = $state(undefined)
|
||||
</script>
|
||||
|
||||
{#if href}
|
||||
@@ -26,20 +47,20 @@
|
||||
}
|
||||
}}
|
||||
{href}
|
||||
class={$$props.class}
|
||||
class={classNames}
|
||||
role="menuitem"
|
||||
aria-disabled={disabled}
|
||||
tabindex={disabled ? -1 : undefined}
|
||||
{target}
|
||||
on:m-focusin
|
||||
on:m-focusout
|
||||
onfocusin={onFocusIn}
|
||||
onfocusout={onFocusOut}
|
||||
>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</a>
|
||||
{:else}
|
||||
<button
|
||||
bind:this={buttonRef}
|
||||
on:click
|
||||
onclick={onClick}
|
||||
use:melt={$item}
|
||||
use:triggerableByAI={{
|
||||
id: aiId,
|
||||
@@ -49,11 +70,11 @@
|
||||
}
|
||||
}}
|
||||
{disabled}
|
||||
class={$$props.class}
|
||||
class={classNames}
|
||||
role="menuitem"
|
||||
on:m-focusin
|
||||
on:m-focusout
|
||||
onfocusin={onFocusIn}
|
||||
onfocusout={onFocusOut}
|
||||
>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
|
||||
<div role="none">
|
||||
<MenuItem
|
||||
on:click={() => {
|
||||
onClick={() => {
|
||||
if (!document.documentElement.classList.contains('dark')) {
|
||||
document.documentElement.classList.add('dark')
|
||||
window.localStorage.setItem('dark-mode', 'dark')
|
||||
@@ -244,7 +244,7 @@
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
href="{base}/user/workspaces"
|
||||
on:click={() => {
|
||||
onClick={() => {
|
||||
localStorage.removeItem('workspace')
|
||||
}}
|
||||
class={twMerge(
|
||||
@@ -274,7 +274,7 @@
|
||||
{/if}
|
||||
|
||||
<MenuItem
|
||||
on:click={() => logout()}
|
||||
onClick={() => logout()}
|
||||
class={twMerge(
|
||||
'flex flex-row gap-3.5 items-center px-2 py-2 w-full',
|
||||
'text-secondary text-xs',
|
||||
@@ -293,8 +293,8 @@
|
||||
role="none"
|
||||
>
|
||||
<MenuItem
|
||||
on:m-focusin={() => debouncedSetMoreOpen(true)}
|
||||
on:m-focusout={() => debouncedSetMoreOpen(false)}
|
||||
onFocusIn={() => debouncedSetMoreOpen(true)}
|
||||
onFocusOut={() => debouncedSetMoreOpen(false)}
|
||||
{item}
|
||||
>
|
||||
{#if !moreOpen || secondMenuLinks.length === 0}
|
||||
@@ -311,8 +311,8 @@
|
||||
'data-[highlighted]:bg-surface-hover data-[highlighted]:text-primary'
|
||||
)}
|
||||
{item}
|
||||
on:m-focusin={() => debouncedSetMoreOpen(true)}
|
||||
on:m-focusout={() => debouncedSetMoreOpen(false)}
|
||||
onFocusIn={() => debouncedSetMoreOpen(true)}
|
||||
onFocusOut={() => debouncedSetMoreOpen(false)}
|
||||
>
|
||||
{menuLink.label}
|
||||
</MenuItem>
|
||||
|
||||
@@ -510,7 +510,7 @@
|
||||
class={itemClass}
|
||||
href={subItem.href}
|
||||
{item}
|
||||
on:click={() => {
|
||||
onClick={() => {
|
||||
subItem?.['action']?.()
|
||||
}}
|
||||
aiId={subItem.aiId}
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
on:click={() => {
|
||||
onClick={() => {
|
||||
if (!document.documentElement.classList.contains('dark')) {
|
||||
document.documentElement.classList.add('dark')
|
||||
window.localStorage.setItem('dark-mode', 'dark')
|
||||
@@ -87,7 +87,7 @@
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
on:click={() => logout()}
|
||||
onClick={() => logout()}
|
||||
class={twMerge(itemClass, 'text-primary font-semibold')}
|
||||
{item}
|
||||
>
|
||||
@@ -124,7 +124,7 @@
|
||||
{#if $userStore?.is_admin}
|
||||
<MenuItem
|
||||
class={twMerge(itemClass, 'py-2')}
|
||||
on:click={() => {
|
||||
onClick={() => {
|
||||
goto('/workspace_settings?tab=premium')
|
||||
}}
|
||||
{item}
|
||||
@@ -135,7 +135,7 @@
|
||||
{:else}
|
||||
<MenuItem
|
||||
class={twMerge(itemClass, 'py-2')}
|
||||
on:click={() => {
|
||||
onClick={() => {
|
||||
goto('/workspace_settings?tab=premium')
|
||||
}}
|
||||
{item}
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
? 'cursor-default bg-surface-selected'
|
||||
: 'cursor-pointer hover:bg-surface-hover data-[highlighted]:bg-surface-hover'
|
||||
)}
|
||||
on:click={async () => {
|
||||
onClick={async () => {
|
||||
await toggleSwitchWorkspace(workspace.id)
|
||||
}}
|
||||
{item}
|
||||
@@ -123,7 +123,7 @@
|
||||
<div class="py-1" role="none">
|
||||
<MenuItem
|
||||
href="{base}/user/workspaces"
|
||||
on:click={() => {
|
||||
onClick={() => {
|
||||
localStorage.removeItem('workspace')
|
||||
}}
|
||||
class={twMerge(
|
||||
@@ -169,7 +169,7 @@
|
||||
'text-secondary block font-normal w-full text-left px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900',
|
||||
'data-[highlighted]:bg-gray-100 data-[highlighted]:text-gray-900'
|
||||
)}
|
||||
on:click={() => {
|
||||
onClick={() => {
|
||||
goto('/workspace_settings?tab=premium')
|
||||
}}
|
||||
{item}
|
||||
|
||||
@@ -975,7 +975,6 @@
|
||||
{/snippet}
|
||||
{#snippet action()}
|
||||
<div class="flex flex-row items-center gap-1 text-2xs text-tertiary">
|
||||
defaults
|
||||
<Dropdown
|
||||
disabled={!can_write}
|
||||
items={[
|
||||
@@ -990,7 +989,7 @@
|
||||
}
|
||||
]}
|
||||
>
|
||||
{#snippet children()}
|
||||
{#snippet buttonReplacement()}
|
||||
<Save size={12} class="mr-1" />
|
||||
Set as default
|
||||
{/snippet}
|
||||
@@ -1091,7 +1090,7 @@
|
||||
}
|
||||
]}
|
||||
>
|
||||
{#snippet children()}
|
||||
{#snippet buttonReplacement()}
|
||||
<Save size={12} class="mr-1" />
|
||||
Set as default
|
||||
{/snippet}
|
||||
@@ -1182,7 +1181,7 @@
|
||||
}
|
||||
]}
|
||||
>
|
||||
{#snippet children()}
|
||||
{#snippet buttonReplacement()}
|
||||
<Save size={12} class="mr-1" />
|
||||
Set as default
|
||||
{/snippet}
|
||||
|
||||
@@ -1250,6 +1250,7 @@ export type Item = {
|
||||
icon?: any
|
||||
iconColor?: string
|
||||
href?: string
|
||||
hrefTarget?: '_blank' | '_self' | '_parent' | '_top'
|
||||
disabled?: boolean
|
||||
type?: 'action' | 'delete'
|
||||
hide?: boolean | undefined
|
||||
|
||||
@@ -446,7 +446,7 @@
|
||||
tag={flow.tag}
|
||||
>
|
||||
<!-- @migration-task: migrate this slot by hand, `trigger-badges` is an invalid identifier -->
|
||||
<svelte:fragment slot="trigger-badges">
|
||||
{#snippet trigger_badges()}
|
||||
<TriggersBadge
|
||||
showOnlyWithCount={true}
|
||||
showDraft={false}
|
||||
@@ -461,7 +461,7 @@
|
||||
}}
|
||||
small={false}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
{#if $workspaceStore}
|
||||
<Star
|
||||
kind="flow"
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
import Head from '$lib/components/table/Head.svelte'
|
||||
import Cell from '$lib/components/table/Cell.svelte'
|
||||
import Row from '$lib/components/table/Row.svelte'
|
||||
import { untrack } from 'svelte'
|
||||
|
||||
type GroupW = Group & { canWrite: boolean }
|
||||
|
||||
let newGroupName: string = ''
|
||||
let groups: GroupW[] | undefined = undefined
|
||||
let instanceGroups: InstanceGroup[] | undefined = undefined
|
||||
let groupDrawer: Drawer
|
||||
let newGroupName: string = $state('')
|
||||
let groups: GroupW[] | undefined = $state(undefined)
|
||||
let instanceGroups: InstanceGroup[] | undefined = $state(undefined)
|
||||
let groupDrawer: Drawer | undefined = $state()
|
||||
|
||||
async function loadGroups(): Promise<void> {
|
||||
groups = (await GroupService.listGroups({ workspace: $workspaceStore! })).map((x) => {
|
||||
@@ -56,17 +57,17 @@
|
||||
})
|
||||
loadGroups()
|
||||
editGroupName = newGroupName
|
||||
groupDrawer.openDrawer()
|
||||
groupDrawer?.openDrawer()
|
||||
}
|
||||
|
||||
$: {
|
||||
loadInstanceGroups()
|
||||
$effect(() => {
|
||||
untrack(() => loadInstanceGroups())
|
||||
if ($workspaceStore && $userStore) {
|
||||
loadGroups()
|
||||
untrack(() => loadGroups())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let editGroupName: string = ''
|
||||
let editGroupName: string = $state('')
|
||||
</script>
|
||||
|
||||
<Drawer bind:this={groupDrawer}>
|
||||
@@ -93,14 +94,14 @@
|
||||
floatingConfig={{ strategy: 'absolute', placement: 'bottom-end' }}
|
||||
containerClasses="border rounded-lg shadow-lg p-4 bg-surface"
|
||||
>
|
||||
<svelte:fragment slot="trigger">
|
||||
{#snippet trigger()}
|
||||
<Button size="md" startIcon={{ icon: Plus }} nonCaptureEvent>New group</Button>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="content" let:close>
|
||||
{/snippet}
|
||||
{#snippet content({ close })}
|
||||
<div class="flex-col flex gap-2 p-4">
|
||||
<input
|
||||
class="mr-2"
|
||||
on:keyup={(e) => handleKeyUp(e, close)}
|
||||
onkeyup={(e) => handleKeyUp(e, close)}
|
||||
placeholder="New group name"
|
||||
bind:value={newGroupName}
|
||||
/>
|
||||
@@ -116,7 +117,7 @@
|
||||
Create
|
||||
</Button>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
@@ -146,7 +147,7 @@
|
||||
hoverable
|
||||
on:click={() => {
|
||||
editGroupName = name
|
||||
groupDrawer.openDrawer()
|
||||
groupDrawer?.openDrawer()
|
||||
}}
|
||||
>
|
||||
<Cell first>
|
||||
@@ -174,7 +175,7 @@
|
||||
action: (e) => {
|
||||
e?.stopPropagation()
|
||||
editGroupName = name
|
||||
groupDrawer.openDrawer()
|
||||
groupDrawer?.openDrawer()
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -206,27 +207,30 @@
|
||||
/>
|
||||
<div class="relative mb-20 pt-8">
|
||||
<TableCustom>
|
||||
<!-- @migration-task: migrate this slot by hand, `header-row` is an invalid identifier -->
|
||||
<tr slot="header-row">
|
||||
<th>Name</th>
|
||||
<th>Members</th>
|
||||
</tr>
|
||||
<tbody slot="body">
|
||||
{#each instanceGroups as { name, emails }}
|
||||
<tr>
|
||||
<td>
|
||||
<a
|
||||
href="#{name}"
|
||||
on:click={() => {
|
||||
editGroupName = name
|
||||
groupDrawer.openDrawer()
|
||||
}}
|
||||
>{name}
|
||||
</a>
|
||||
</td>
|
||||
<td>{emails?.length ?? 0} members</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
{#snippet body()}
|
||||
<tbody>
|
||||
{#each instanceGroups ?? [] as { name, emails }}
|
||||
<tr>
|
||||
<td>
|
||||
<a
|
||||
href="#{name}"
|
||||
onclick={() => {
|
||||
editGroupName = name
|
||||
groupDrawer?.openDrawer()
|
||||
}}
|
||||
>{name}
|
||||
</a>
|
||||
</td>
|
||||
<td>{emails?.length ?? 0} members</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
{/snippet}
|
||||
</TableCustom>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -564,12 +564,11 @@
|
||||
rightPaneSelected = 'triggers'
|
||||
}}
|
||||
>
|
||||
<!-- @migration-task: migrate this slot by hand, `trigger-badges` is an invalid identifier -->
|
||||
<svelte:fragment slot="trigger-badges">
|
||||
{#snippet trigger_badges()}
|
||||
<TriggersBadge
|
||||
showOnlyWithCount={true}
|
||||
showDraft={false}
|
||||
path={script.path}
|
||||
path={script?.path ?? ''}
|
||||
newItem={false}
|
||||
isFlow={false}
|
||||
selected={rightPaneSelected === 'triggers'}
|
||||
@@ -581,7 +580,7 @@
|
||||
triggersState.selectedTriggerIndex = triggerIndex
|
||||
}}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
{/snippet}
|
||||
{#if $workspaceStore}
|
||||
<Star
|
||||
kind="script"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import DarkModeToggle from '$lib/components/sidebar/DarkModeToggle.svelte'
|
||||
import { Globe } from 'lucide-svelte'
|
||||
|
||||
let tab = 'button'
|
||||
let tab = $state('button')
|
||||
let dropdownItems = [
|
||||
{
|
||||
label: 'Lorem ipsum',
|
||||
|
||||
Reference in New Issue
Block a user