mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-18 16:02:10 +00:00
feat(frontend): migrate toggle to melt (4/4) (#5329)
* use melt menu in sidebar * stop keyboard navigation for disabled items * use melt menu for FavoriteMenu and WorkspaceMenu * fix popover placement for menuButton * use melt menu for operator menu * fix notification * fix operator menu * Use melt menu in FlowJobsMenu * use melt menu for AppMenu * clean code * clean code * add use clickOutside option to Menu * use pointerdown_outside * use pointerdown_outside # Conflicts: # frontend/src/lib/components/meltComponents/Menu.svelte * use pointerdown in menus * add max-h to app dropdown menu * keep more open in operator menu * add a MenuItem component * clean * nit * nit * clean code * put conditionalMelt as utility function * remove unused Portal * Add debounce effect in operator menu * fix component jumping due to z-index * format pages * migrate dropdown to melt * migrate toggle to melt * migrate popup to melt popover * fix missing toggle item * feat: remove `pip` fallback option for python and ansible (#5186) * refactor!: Remove `pip` fallback option for python and ansible BREAKING CHANGE: pip was deprecated since 1.425.0 (2024-11-15) * fix errors in main.rs * fix tests * remove nsjail for pip * fix imports * fix compilation error * reinforce melt types * fix racing condition issue in closing operator menu * nit * fix id conflix with melt element * nit * clean code * use melt dropdown instead of menubar * prevent modal from closing on click outside button in menu * Apply automatic changes * fix nit * nit * close dropdown when opening a new one * replace MenuV2 with melt Menu (1/4) (#5214) * use melt menu in sidebar * stop keyboard navigation for disabled items * use melt menu for FavoriteMenu and WorkspaceMenu * fix popover placement for menuButton * use melt menu for operator menu * fix notification * fix operator menu * Use melt menu in FlowJobsMenu * use melt menu for AppMenu * clean code * clean code * add use clickOutside option to Menu * use pointerdown_outside * use pointerdown_outside # Conflicts: # frontend/src/lib/components/meltComponents/Menu.svelte * use pointerdown in menus * add max-h to app dropdown menu * keep more open in operator menu * add a MenuItem component * clean * nit * nit * clean code * put conditionalMelt as utility function * remove unused Portal * Add debounce effect in operator menu * fix component jumping due to z-index * feat: remove `pip` fallback option for python and ansible (#5186) * refactor!: Remove `pip` fallback option for python and ansible BREAKING CHANGE: pip was deprecated since 1.425.0 (2024-11-15) * fix errors in main.rs * fix tests * remove nsjail for pip * fix imports * fix compilation error * reinforce melt types * fix racing condition issue in closing operator menu * nit * fix id conflix with melt element * nit * prevent modal from closing on click outside button in menu --------- Co-authored-by: pyranota <92104930+pyranota@users.noreply.github.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> # Conflicts: # frontend/src/lib/components/meltComponents/MenuItem.svelte # frontend/src/lib/utils.ts * clean * fix z index and render * fix initialize of dropdownmenu after melt migration * feat: add support for | None and Optional in python (#5361) * feat: add support for | None and Optional in python * update python parser package * add local rooting for MenuItem * fix z index * clean * nit * nit * clean code * nit * nit * clean code * reinforce melt types * wip * reiforce instance select types for toggleButton * nit * fix double event * fix selectedTable toggle * fix sqs toggleButton * fix potential issue with binding in toggleGroup * Update frontend/src/routes/(root)/(logged)/runs/[...path]/+page.svelte Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> --------- Co-authored-by: pyranota <92104930+pyranota@users.noreply.github.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> Co-authored-by: HugoCasa <hugo@casademont.ch> Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
Vendored
+5
-5
@@ -1,7 +1,7 @@
|
||||
declare namespace svelte.JSX {
|
||||
interface DOMAttributes<T> {
|
||||
onclick_outside?: CompositionEventHandler<T>
|
||||
onpointerdown_outside?: (event: CustomEvent) => void
|
||||
onpointerdown_connecting?: (event: CustomEvent) => void
|
||||
declare namespace svelteHTML {
|
||||
interface HTMLAttributes<T> {
|
||||
'on:click_outside'?: (event: CustomEvent) => void
|
||||
'on:pointerdown_outside'?: (event: CustomEvent) => void
|
||||
'on:pointerdown_connecting'?: (event: CustomEvent) => void
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,26 +92,24 @@
|
||||
{/if}
|
||||
|
||||
<span class="text-xs mb-1 pt-2 leading-6">Role</span>
|
||||
<ToggleButtonGroup bind:selected class="mb-4">
|
||||
<ToggleButtonGroup bind:selected class="mb-4" let:item>
|
||||
<ToggleButton
|
||||
value="operator"
|
||||
size="sm"
|
||||
label="Operator"
|
||||
tooltip="An operator can only execute and view scripts/flows/apps from your workspace, and only those that he has visibility on."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
position="center"
|
||||
value="developer"
|
||||
size="sm"
|
||||
label="Developer"
|
||||
tooltip="A Developer can execute and view scripts/flows/apps, but they can also create new ones and edit those they are allowed to by their path (either u/ or Writer or Admin of their folder found at /f)."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
position="right"
|
||||
value="admin"
|
||||
size="sm"
|
||||
label="Admin"
|
||||
tooltip="An admin has full control over a specific Windmill workspace, including the ability to manage users, edit entities, and control permissions within the workspace."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
<Button
|
||||
|
||||
@@ -756,14 +756,16 @@
|
||||
<div class="flex flex-col gap-2 w-full">
|
||||
{#if oneOf && oneOf.length >= 2}
|
||||
<ToggleButtonGroup
|
||||
bind:selected={oneOfSelected}
|
||||
on:selected={() => {
|
||||
value = { label: oneOfSelected }
|
||||
selected={oneOfSelected}
|
||||
on:selected={({ detail }) => {
|
||||
oneOfSelected = detail
|
||||
value = { label: detail }
|
||||
redraw += 1
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
{#each oneOf as obj}
|
||||
<ToggleButton value={obj.title} label={obj.title} />
|
||||
<ToggleButton value={obj.title ?? ''} label={obj.title} {item} />
|
||||
{/each}
|
||||
</ToggleButtonGroup>
|
||||
{#if oneOfSelected}
|
||||
|
||||
@@ -52,9 +52,15 @@
|
||||
<label class="block pb-2">
|
||||
<div class="flex gap-2 items-end">
|
||||
<div>
|
||||
<ToggleButtonGroup bind:selected={value['custom']}>
|
||||
<ToggleButton value={false} label={'Org'} />
|
||||
<ToggleButton value={true} label="Custom" />
|
||||
<ToggleButtonGroup
|
||||
selected={value['custom'] ? 'custom' : 'org'}
|
||||
on:selected={({ detail }) => {
|
||||
value['custom'] = detail === 'custom'
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="org" label={'Org'} {item} />
|
||||
<ToggleButton value="custom" label="Custom" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<div class="grow">
|
||||
|
||||
@@ -264,28 +264,23 @@
|
||||
on:selected={(e) => dispatch('dirty')}
|
||||
bind:selected={config.integration.type}
|
||||
class="mb-4 mt-2"
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
value="dryrun"
|
||||
size="sm"
|
||||
label="Dry run"
|
||||
tooltip="See autoscaling events but not actual scaling actions will be performed"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="script"
|
||||
size="sm"
|
||||
label="Custom script"
|
||||
tooltip="Run a custom script to scale your worker group"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton position="center" disabled value="ecs" size="sm" label="ECS (soon)" />
|
||||
<ToggleButton position="right" disabled value="nomad" size="sm" label="Nomad (soon)" />
|
||||
<ToggleButton
|
||||
position="right"
|
||||
disabled
|
||||
value="kubernetes"
|
||||
size="sm"
|
||||
label="Kubernetes (soon)"
|
||||
/>
|
||||
<ToggleButton disabled value="ecs" label="ECS (soon)" {item} />
|
||||
<ToggleButton disabled value="nomad" label="Nomad (soon)" {item} />
|
||||
<ToggleButton disabled value="kubernetes" label="Kubernetes (soon)" {item} />
|
||||
</ToggleButtonGroup>
|
||||
|
||||
{#if config.integration.type === 'script'}
|
||||
@@ -347,12 +342,12 @@
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<ToggleButtonGroup selected={'script'} disabled class="mb-4 mt-2">
|
||||
<ToggleButton value="dryrun" size="sm" label="Dry run" />
|
||||
<ToggleButton value="script" size="sm" label="Custom script" />
|
||||
<ToggleButton position="center" value="ecs" size="sm" label="ECS (soon)" />
|
||||
<ToggleButton position="right" value="nomad" size="sm" label="Nomad (soon)" />
|
||||
<ToggleButton position="right" value="kubernetes" size="sm" label="Kubernetes (soon)" />
|
||||
<ToggleButtonGroup selected={'script'} disabled class="mb-4 mt-2" let:item>
|
||||
<ToggleButton value="dryrun" label="Dry run" {item} />
|
||||
<ToggleButton value="script" label="Custom script" {item} />
|
||||
<ToggleButton value="ecs" label="ECS (soon)" {item} />
|
||||
<ToggleButton value="nomad" label="Nomad (soon)" {item} />
|
||||
<ToggleButton value="kubernetes" label="Kubernetes (soon)" {item} />
|
||||
</ToggleButtonGroup>
|
||||
|
||||
<label>
|
||||
|
||||
@@ -157,15 +157,23 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2 flex-wrap sticky top-0 left-0 right-0 bg-surface">
|
||||
<div class="p-2">
|
||||
<ToggleButtonGroup bind:selected={searchKind} class="h-10 ">
|
||||
<ToggleButton small light value="all" label={'All' + counts.all} />
|
||||
<ToggleButton small light value="scripts" icon={Code2} label={'Scripts' + counts.scripts} />
|
||||
<ToggleButtonGroup bind:selected={searchKind} class="h-10 " let:item>
|
||||
<ToggleButton small light value="all" label={'All' + counts.all} {item} />
|
||||
<ToggleButton
|
||||
small
|
||||
light
|
||||
value="scripts"
|
||||
icon={Code2}
|
||||
label={'Scripts' + counts.scripts}
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
small
|
||||
light
|
||||
value="resources"
|
||||
icon={Boxes}
|
||||
label={'Resources' + counts.resources}
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
small
|
||||
@@ -174,6 +182,7 @@
|
||||
label={'Flows' + counts.flows}
|
||||
icon={FlowIcon}
|
||||
selectedColor="#14b8a6"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
small
|
||||
@@ -182,6 +191,7 @@
|
||||
label={'Apps' + counts.apps}
|
||||
icon={LayoutDashboard}
|
||||
selectedColor="#fb923c"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -53,6 +53,12 @@
|
||||
$: dbSchema = resourcePath && resourcePath in $dbSchemas ? $dbSchemas[resourcePath] : undefined
|
||||
|
||||
$: shouldDisplayError = resourcePath && resourcePath in $dbSchemas && !$dbSchemas[resourcePath]
|
||||
|
||||
function handleSelected({ detail }: CustomEvent<string>) {
|
||||
if (dbSchema && dbSchema.lang !== 'graphql') {
|
||||
dbSchema.publicOnly = detail === 'dbo'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if loading}
|
||||
@@ -86,9 +92,14 @@
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
{#if dbSchema.lang !== 'graphql' && (dbSchema.schema?.public || dbSchema.schema?.PUBLIC || dbSchema.schema?.dbo)}
|
||||
<ToggleButtonGroup class="mb-4" bind:selected={dbSchema.publicOnly}>
|
||||
<ToggleButton value={true} label={dbSchema.schema.dbo ? 'Dbo' : 'Public'} />
|
||||
<ToggleButton value={false} label="All" />
|
||||
<ToggleButtonGroup
|
||||
class="mb-4"
|
||||
selected={dbSchema.publicOnly ? 'dbo' : 'all'}
|
||||
on:selected={handleSelected}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="dbo" label={dbSchema.schema.dbo ? 'Dbo' : 'Public'} {item} />
|
||||
<ToggleButton value="all" label="All" {item} />
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
{#if dbSchema.lang === 'graphql'}
|
||||
|
||||
@@ -146,9 +146,9 @@
|
||||
</Button>
|
||||
{/if}
|
||||
<!-- <div>
|
||||
<ToggleButtonGroup bind:selected={format}>
|
||||
<ToggleButton light small value={'local'} label="local" />
|
||||
<ToggleButton light small value={'utc'} label="utc" />
|
||||
<ToggleButtonGroup bind:selected={format} let:item>
|
||||
<ToggleButton light small value={'local'} label="local" {item} />
|
||||
<ToggleButton light small value={'utc'} label="utc" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
@@ -402,10 +402,11 @@
|
||||
on:selected={(ev) => {
|
||||
globalForceJson = ev.detail === 'json'
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton class="px-1.5" value="pretty" label="Pretty" icon={Highlighter} />
|
||||
<ToggleButton class="px-1.5" value="pretty" label="Pretty" icon={Highlighter} {item} />
|
||||
|
||||
<ToggleButton class="px-1.5" value="json" label="JSON" icon={Braces} />
|
||||
<ToggleButton class="px-1.5" value="json" label="JSON" icon={Braces} {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -438,16 +439,23 @@
|
||||
{#if !hideAsJson && !['json', 's3object'].includes(resultKind ?? '') && typeof result === 'object'}<ToggleButtonGroup
|
||||
class="h-6"
|
||||
selected={forceJson ? 'json' : resultKind?.startsWith('table-') ? 'table' : 'pretty'}
|
||||
let:item
|
||||
on:selected={(ev) => {
|
||||
forceJson = ev.detail === 'json'
|
||||
}}
|
||||
>
|
||||
{#if ['table-col', 'table-row', 'table-row-object'].includes(resultKind ?? '')}
|
||||
<ToggleButton class="px-1.5" value="table" label="Table" icon={Table2} />
|
||||
<ToggleButton class="px-1.5" value="table" label="Table" icon={Table2} {item} />
|
||||
{:else}
|
||||
<ToggleButton class="px-1.5" value="pretty" label="Pretty" icon={Highlighter} />
|
||||
<ToggleButton
|
||||
class="px-1.5"
|
||||
value="pretty"
|
||||
label="Pretty"
|
||||
icon={Highlighter}
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
<ToggleButton class="px-1.5" value="json" label="JSON" icon={Braces} />
|
||||
<ToggleButton class="px-1.5" value="json" label="JSON" icon={Braces} {item} />
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -93,7 +93,13 @@
|
||||
{#if $$slots.buttonReplacement}
|
||||
<slot name="buttonReplacement" />
|
||||
{:else}
|
||||
<Button nonCaptureEvent size="xs" color="light" startIcon={{ icon: MoreVertical }} />
|
||||
<Button
|
||||
nonCaptureEvent
|
||||
size="xs"
|
||||
color="light"
|
||||
startIcon={{ icon: MoreVertical }}
|
||||
btnClasses="bg-transparent"
|
||||
/>
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
|
||||
@@ -465,6 +465,7 @@
|
||||
<ToggleButtonGroup
|
||||
tabListClass="flex-wrap"
|
||||
class="h-auto"
|
||||
let:item
|
||||
bind:selected
|
||||
on:selected={(e) => {
|
||||
const isS3 = e.detail == 'S3'
|
||||
@@ -545,7 +546,7 @@
|
||||
}}
|
||||
>
|
||||
{#each [['String', 'string'], ['Number', 'number'], ['Integer', 'integer'], ['Object', 'object'], ['OneOf', 'oneOf'], ['Array', 'array'], ['Boolean', 'boolean'], ['S3 Object', 'S3']] as x}
|
||||
<ToggleButton value={x[1]} label={x[0]} />
|
||||
<ToggleButton value={x[1]} label={x[0]} {item} />
|
||||
{/each}
|
||||
</ToggleButtonGroup>
|
||||
</Label>
|
||||
|
||||
@@ -184,9 +184,13 @@
|
||||
</Alert>
|
||||
<div class="flex items-center gap-1">
|
||||
<div>
|
||||
<ToggleButtonGroup bind:selected={ownerKind} on:selected={() => (ownerItem = '')}>
|
||||
<ToggleButton value="user" size="xs" label="User" />
|
||||
<ToggleButton value="group" size="xs" label="Group" />
|
||||
<ToggleButtonGroup
|
||||
bind:selected={ownerKind}
|
||||
on:selected={() => (ownerItem = '')}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="user" label="User" {item} />
|
||||
<ToggleButton value="group" label="Group" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -194,7 +198,9 @@
|
||||
<AutoComplete
|
||||
required
|
||||
noInputStyles
|
||||
items={ownerKind === 'user' ? usernames.filter((x) => !perms?.map((y) => y.owner_name).includes('u/'+x)) : groups.filter((x) => !perms?.map((y) => y.owner_name).includes('g/'+x))}
|
||||
items={ownerKind === 'user'
|
||||
? usernames.filter((x) => !perms?.map((y) => y.owner_name).includes('u/' + x))
|
||||
: groups.filter((x) => !perms?.map((y) => y.owner_name).includes('g/' + x))}
|
||||
bind:selectedItem={ownerItem}
|
||||
/>
|
||||
{#if ownerKind == 'group'}
|
||||
@@ -271,6 +277,7 @@
|
||||
<div>
|
||||
<ToggleButtonGroup
|
||||
selected={role}
|
||||
let:item
|
||||
on:selected={async (e) => {
|
||||
const role = e.detail
|
||||
// const wasInFolder = (folder?.owners ?? []).includes(folder)
|
||||
@@ -309,25 +316,25 @@
|
||||
>
|
||||
<ToggleButton
|
||||
value="viewer"
|
||||
size="xs"
|
||||
label="Viewer"
|
||||
tooltip="A viewer of a folder has read-only access to all the elements (scripts/flows/apps/schedules/resources/variables) inside the folder"
|
||||
{item}
|
||||
/>
|
||||
|
||||
<ToggleButton
|
||||
position="center"
|
||||
value="writer"
|
||||
size="xs"
|
||||
label="Writer"
|
||||
tooltip="A writer of a folder has read AND write access to all the elements (scripts/flows/apps/schedules/resources/variables) inside the folder"
|
||||
{item}
|
||||
/>
|
||||
|
||||
<ToggleButton
|
||||
position="right"
|
||||
value="admin"
|
||||
size="xs"
|
||||
label="Admin"
|
||||
tooltip="An admin of a folder has read AND write access to all the elements inside the folders and can manage the permissions as well as add new admins"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -150,6 +150,7 @@
|
||||
<div>
|
||||
<ToggleButtonGroup
|
||||
selected={role}
|
||||
let:item
|
||||
on:selected={async (e) => {
|
||||
const role = e.detail
|
||||
// const wasInGroup = (group?.members ?? []).includes(group)
|
||||
@@ -215,6 +216,7 @@
|
||||
size="xs"
|
||||
label="Member"
|
||||
tooltip="A Member of a group can see everything the group can see, write to everything the group can write, and generally act on behalf of the group"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
position="right"
|
||||
@@ -222,6 +224,7 @@
|
||||
size="xs"
|
||||
label="Admin"
|
||||
tooltip="An admin of a group is a member of a group that can also add and remove members to the group, or make them admin."
|
||||
{item}
|
||||
/>
|
||||
{#if role === 'manager'}
|
||||
<ToggleButton
|
||||
@@ -230,6 +233,7 @@
|
||||
label="Manager"
|
||||
tooltip="A manager of a group can manage the group, adding and removing users and
|
||||
change their roles. Being a manager does not make you a member"
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
</ToggleButtonGroup>
|
||||
|
||||
@@ -358,6 +358,7 @@
|
||||
<div>
|
||||
<ToggleButtonGroup
|
||||
selected={propertyType}
|
||||
let:item
|
||||
on:selected={(e) => {
|
||||
if (e.detail == propertyType) return
|
||||
const staticTemplate = isStaticTemplate(inputCat)
|
||||
@@ -417,9 +418,10 @@
|
||||
value="static"
|
||||
size="xs2"
|
||||
label={'${}'}
|
||||
{item}
|
||||
/>
|
||||
{:else}
|
||||
<ToggleButton small label="Static" value="static" />
|
||||
<ToggleButton small label="Static" value="static" {item} />
|
||||
{/if}
|
||||
|
||||
{#if codeInjectionDetected && propertyType == 'static'}
|
||||
@@ -441,6 +443,7 @@
|
||||
tooltip="JavaScript expression ('flow_input' or 'results')."
|
||||
value="javascript"
|
||||
icon={FunctionSquare}
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
</ToggleButtonGroup>
|
||||
|
||||
@@ -185,12 +185,13 @@
|
||||
</span>
|
||||
{/if}
|
||||
</label>
|
||||
<ToggleButtonGroup bind:selected={$values[setting.key]}>
|
||||
<ToggleButtonGroup bind:selected={$values[setting.key]} let:item={toggleButton}>
|
||||
{#each setting.select_items ?? [] as item}
|
||||
<ToggleButton
|
||||
value={item.value ?? item.label}
|
||||
label={item.label}
|
||||
tooltip={item.tooltip}
|
||||
item={toggleButton}
|
||||
/>
|
||||
{/each}
|
||||
</ToggleButtonGroup>
|
||||
|
||||
@@ -80,28 +80,26 @@
|
||||
bind:value={email}
|
||||
class="mr-4"
|
||||
/>
|
||||
<ToggleButtonGroup bind:selected>
|
||||
<ToggleButtonGroup bind:selected let:item>
|
||||
<ToggleButton
|
||||
value="operator"
|
||||
size="sm"
|
||||
label="Operator"
|
||||
tooltip="An operator can only execute and view scripts/flows/apps from your workspace, and only those that he has visibility on."
|
||||
{item}
|
||||
/>
|
||||
|
||||
<ToggleButton
|
||||
position="center"
|
||||
value="developer"
|
||||
size="sm"
|
||||
label="Developer"
|
||||
tooltip="A Developer can execute and view scripts/flows/apps, but they can also create new ones and edit those they are allowed to by their path (either u/ or Writer or Admin of their folder found at /f)."
|
||||
{item}
|
||||
/>
|
||||
|
||||
<ToggleButton
|
||||
position="right"
|
||||
value="admin"
|
||||
size="sm"
|
||||
label="Admin"
|
||||
tooltip="An admin has full control over a specific Windmill workspace, including the ability to manage users, edit entities, and control permissions within the workspace."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
<Button
|
||||
|
||||
@@ -52,9 +52,15 @@
|
||||
<label class="block pb-2">
|
||||
<div class="flex gap-2 items-end">
|
||||
<div>
|
||||
<ToggleButtonGroup bind:selected={value['custom']}>
|
||||
<ToggleButton value={false} label={'Org'} />
|
||||
<ToggleButton value={true} label="Custom" />
|
||||
<ToggleButtonGroup
|
||||
selected={value['custom'] ? 'custom' : 'org'}
|
||||
on:selected={({ detail }) => {
|
||||
value['custom'] = detail === 'custom'
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="org" label={'Org'} {item} />
|
||||
<ToggleButton value="custom" label="Custom" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<div class="grow">
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
}
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
icon={User}
|
||||
@@ -383,6 +384,7 @@
|
||||
value="user"
|
||||
position="left"
|
||||
label="User"
|
||||
{item}
|
||||
/>
|
||||
<!-- <ToggleButton light size="xs" value="group" position="center">Group</ToggleButton> -->
|
||||
<ToggleButton
|
||||
@@ -393,6 +395,7 @@
|
||||
value="folder"
|
||||
position="right"
|
||||
label="Folder"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
import TimeAgo from './TimeAgo.svelte'
|
||||
import Popover from './meltComponents/Popover.svelte'
|
||||
import { autoPlacement } from '@floating-ui/core'
|
||||
import { Calendar, CornerDownLeft } from 'lucide-svelte'
|
||||
import RunFormAdvancedPopup from './RunFormAdvancedPopup.svelte'
|
||||
import { page } from '$app/stores'
|
||||
@@ -205,24 +204,7 @@
|
||||
{scheduledForStr ? 'Schedule to run later' : buttonText}
|
||||
</Button>
|
||||
<div>
|
||||
<Popover
|
||||
floatingConfig={{
|
||||
middleware: [
|
||||
autoPlacement({
|
||||
allowedPlacements: [
|
||||
'bottom-start',
|
||||
'bottom-end',
|
||||
'top-start',
|
||||
'top-end',
|
||||
'top',
|
||||
'bottom'
|
||||
]
|
||||
})
|
||||
]
|
||||
}}
|
||||
closeButton
|
||||
usePointerDownOutside
|
||||
>
|
||||
<Popover placement="bottom" closeButton usePointerDownOutside>
|
||||
<svelte:fragment slot="trigger">
|
||||
<Button nonCaptureEvent startIcon={{ icon: Calendar }} size="xs" color="light">
|
||||
Advanced
|
||||
|
||||
@@ -335,27 +335,30 @@
|
||||
{#if linkedSecretCandidates?.includes(argName)}
|
||||
<div>
|
||||
<ToggleButtonGroup
|
||||
selected={linkedSecret == argName}
|
||||
selected={linkedSecret == argName ? 'secret' : 'inlined'}
|
||||
on:selected={(e) => {
|
||||
if (e.detail) {
|
||||
if (e.detail === 'secret') {
|
||||
linkedSecret = argName
|
||||
} else if (linkedSecret == argName) {
|
||||
linkedSecret = undefined
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
value={false}
|
||||
value="inlined"
|
||||
size="sm"
|
||||
label="Inlined"
|
||||
tooltip="The value is inlined in the resource and thus has no special treatment."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
position="right"
|
||||
value={true}
|
||||
value="secret"
|
||||
size="sm"
|
||||
label="Secret"
|
||||
tooltip="The value will be stored in a newly created linked secret variable at the same path. That variable can be permissioned differently, will be treated as a secret the UI, operators will not be able to load it and every access will generate a corresponding audit log."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>{/if}</svelte:fragment
|
||||
|
||||
@@ -910,6 +910,7 @@
|
||||
script.kind = detail
|
||||
initContent(script.language, detail, template)
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
{#each scriptKindOptions as { value, title, desc, documentationLink, Icon }}
|
||||
<ToggleButton
|
||||
@@ -919,6 +920,7 @@
|
||||
{documentationLink}
|
||||
icon={Icon}
|
||||
showTooltipIcon={Boolean(desc)}
|
||||
{item}
|
||||
/>
|
||||
{/each}
|
||||
</ToggleButtonGroup>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
items = (
|
||||
await ScriptService.listScripts({
|
||||
workspace: $workspaceStore!,
|
||||
kinds: kinds.join(','),
|
||||
kinds: kinds.join(',')
|
||||
})
|
||||
).map((script) => ({
|
||||
value: script.path,
|
||||
@@ -85,9 +85,9 @@
|
||||
<div class="flex flex-row items-center gap-4 w-full mt-2">
|
||||
{#if options.length > 1}
|
||||
<div>
|
||||
<ToggleButtonGroup bind:selected={itemKind}>
|
||||
<ToggleButtonGroup bind:selected={itemKind} let:item>
|
||||
{#each options as [label, value, icon, selectedColor]}
|
||||
<ToggleButton {icon} {disabled} {value} {label} {selectedColor} />
|
||||
<ToggleButton {icon} {disabled} {value} {label} {selectedColor} {item} />
|
||||
{/each}
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -190,9 +190,15 @@
|
||||
{#if selectedVersionIndex !== undefined && versions?.slice(selectedVersionIndex + 1).length}
|
||||
<div class="p-2 flex flex-row items-center gap-2 h-8">
|
||||
<div class="w-min">
|
||||
<ToggleButtonGroup bind:selected={showDiff}>
|
||||
<ToggleButton light small value={false} label="Code" icon={Code} />
|
||||
<ToggleButton light small value={true} label="Diff" icon={Diff} />
|
||||
<ToggleButtonGroup
|
||||
selected={showDiff ? 'diff' : 'code'}
|
||||
let:item
|
||||
on:selected={({ detail }) => {
|
||||
showDiff = detail === 'diff'
|
||||
}}
|
||||
>
|
||||
<ToggleButton light small value="code" label="Code" icon={Code} {item} />
|
||||
<ToggleButton light small value="diff" label="Diff" icon={Diff} {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -123,9 +123,13 @@
|
||||
{#if own}
|
||||
<div class="flex flex-row flex-wrap gap-2 items-center">
|
||||
<div>
|
||||
<ToggleButtonGroup bind:selected={ownerKind} on:selected={() => (owner = '')}>
|
||||
<ToggleButton value="user" size="xs" label="User" />
|
||||
<ToggleButton value="group" size="xs" label="Group" />
|
||||
<ToggleButtonGroup
|
||||
bind:selected={ownerKind}
|
||||
on:selected={() => (owner = '')}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="user" size="xs" label="User" {item} />
|
||||
<ToggleButton value="group" size="xs" label="Group" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
{#key ownerKind}
|
||||
@@ -163,9 +167,10 @@
|
||||
}
|
||||
loadAcls()
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="viewer" size="xs" label="Viewer" />
|
||||
<ToggleButton value="writer" size="xs" label="Writer" />
|
||||
<ToggleButton value="viewer" size="xs" label="Viewer" {item} />
|
||||
<ToggleButton value="writer" size="xs" label="Writer" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
{:else}{write}{/if}</td
|
||||
|
||||
@@ -133,9 +133,16 @@
|
||||
disableVariablePicker = undefined
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
{#each FIELD_SETTINGS as x}
|
||||
<ToggleButton value={x[1]} label={x[0]} tooltip={x[2]} showTooltipIcon={Boolean(x[2])} />
|
||||
<ToggleButton
|
||||
value={x[1]}
|
||||
label={x[0]}
|
||||
tooltip={x[2]}
|
||||
showTooltipIcon={Boolean(x[2])}
|
||||
{item}
|
||||
/>
|
||||
{/each}
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
|
||||
@@ -292,15 +292,22 @@
|
||||
sendUserToast('User updated')
|
||||
listUsers(activeOnly)
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value={'user'} size="xs" label="User" />
|
||||
<ToggleButton value={'user'} size="xs" label="User" {item} />
|
||||
<ToggleButton
|
||||
value={'devops'}
|
||||
size="xs"
|
||||
label="Devops"
|
||||
tooltip="Devops is a role that grants visibilty similar to that of a super admin, but without giving all rights. For example devops users can see service logs and crtical alerts. You can think of it as a 'readonly' super admin"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value={'super_admin'}
|
||||
size="xs"
|
||||
label="Superadmin"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton value={'super_admin'} size="xs" label="Superadmin" />
|
||||
</ToggleButtonGroup>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</script>
|
||||
|
||||
<div class="max-w-min">
|
||||
<ToggleButtonGroup bind:selected>
|
||||
<ToggleButton value="hub" icon={WindmillIcon} label="Hub" />
|
||||
<ToggleButton value="workspace" icon={Building} label="Workspace" />
|
||||
<ToggleButtonGroup bind:selected let:item>
|
||||
<ToggleButton value="hub" icon={WindmillIcon} label="Hub" {item} />
|
||||
<ToggleButton value="workspace" icon={Building} label="Workspace" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
</script>
|
||||
|
||||
<div class="max-w-min">
|
||||
<ToggleButtonGroup id="flow-editor-flow-providers" bind:selected>
|
||||
<ToggleButton value="all" label="All" light small />
|
||||
<ToggleButton value="hub" icon={WindmillIcon2} label="Hub" light small />
|
||||
<ToggleButton value="workspace" icon={Building} label="Workspace" light small />
|
||||
<ToggleButtonGroup id="flow-editor-flow-providers" bind:selected let:item>
|
||||
<ToggleButton value="all" label="All" light small {item} />
|
||||
<ToggleButton value="hub" icon={WindmillIcon2} label="Hub" light small {item} />
|
||||
<ToggleButton value="workspace" icon={Building} label="Workspace" light small {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -183,10 +183,10 @@
|
||||
>{/if}{/if}
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<ToggleButtonGroup bind:selected={editorKind}>
|
||||
<ToggleButton value="plain" label="Plain" />
|
||||
<ToggleButton value="json" label="Json" />
|
||||
<ToggleButton value="yaml" label="YAML" />
|
||||
<ToggleButtonGroup bind:selected={editorKind} let:item>
|
||||
<ToggleButton value="plain" label="Plain" {item} />
|
||||
<ToggleButton value="json" label="Json" {item} />
|
||||
<ToggleButton value="yaml" label="YAML" {item} />
|
||||
</ToggleButtonGroup>
|
||||
{#if editorKind == 'plain'}
|
||||
<textarea
|
||||
|
||||
@@ -263,13 +263,21 @@
|
||||
}
|
||||
}}
|
||||
class="mb-4"
|
||||
let:item
|
||||
>
|
||||
<ToggleButton position="left" value="normal" size="sm" label="Any jobs within worker tags" />
|
||||
<ToggleButton
|
||||
position="left"
|
||||
value="normal"
|
||||
size="sm"
|
||||
label="Any jobs within worker tags"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
position="dedicated"
|
||||
value="dedicated"
|
||||
size="sm"
|
||||
label="Dedicated to a script/flow"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
{#if selected == 'normal'}
|
||||
@@ -682,9 +690,10 @@
|
||||
envvar.value = undefined
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton position="left" value="dynamic" label="Dynamic" />
|
||||
<ToggleButton position="right" value="static" label="Static" />
|
||||
<ToggleButton value="dynamic" label="Dynamic" {item} />
|
||||
<ToggleButton value="static" label="Static" {item} />
|
||||
</ToggleButtonGroup>
|
||||
<input
|
||||
type="text"
|
||||
|
||||
@@ -1553,18 +1553,21 @@
|
||||
on:selected={({ detail }) => {
|
||||
$app.fullscreen = detail === 'true'
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
icon={AlignHorizontalSpaceAround}
|
||||
value={'false'}
|
||||
tooltip="The max width is 1168px and the content stay centered instead of taking the full page width"
|
||||
iconProps={{ size: 16 }}
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
tooltip="The width is of the app if the full width of its container"
|
||||
icon={Expand}
|
||||
value={'true'}
|
||||
iconProps={{ size: 16 }}
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
@@ -1578,40 +1581,46 @@
|
||||
setTheme(theme)
|
||||
}}
|
||||
selected={$app.darkMode === undefined ? 'auto' : $app.darkMode ? 'dark' : 'sun'}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
icon={SunMoon}
|
||||
value={'auto'}
|
||||
tooltip="The app mode between dark/light is automatic"
|
||||
iconProps={{ size: 16 }}
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
icon={Sun}
|
||||
value={'sun'}
|
||||
tooltip="Force light mode"
|
||||
iconProps={{ size: 16 }}
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
tooltip="Force dark mode"
|
||||
icon={Moon}
|
||||
value={'dark'}
|
||||
iconProps={{ size: 16 }}
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
<div class="flex flex-row gap-2">
|
||||
<ToggleButtonGroup class="h-[30px]" bind:selected={$breakpoint}>
|
||||
<ToggleButtonGroup class="h-[30px]" bind:selected={$breakpoint} let:item>
|
||||
<ToggleButton
|
||||
tooltip="Computer View"
|
||||
icon={Laptop2}
|
||||
value={'lg'}
|
||||
iconProps={{ size: 16 }}
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
tooltip="Mobile View"
|
||||
icon={Smartphone}
|
||||
value={'sm'}
|
||||
iconProps={{ size: 16 }}
|
||||
{item}
|
||||
/>
|
||||
{#if $breakpoint === 'sm'}
|
||||
<Toggle
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
jobsById.set({})
|
||||
jobs.set([])
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
label="Editor"
|
||||
@@ -26,6 +27,7 @@
|
||||
disabled={loading}
|
||||
iconProps={{ size: 16 }}
|
||||
class="gap-2"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
label="Preview"
|
||||
@@ -36,5 +38,6 @@
|
||||
id="app-editor-preview-toggle"
|
||||
iconProps={{ size: 16 }}
|
||||
class="gap-2"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
|
||||
@@ -124,27 +124,31 @@
|
||||
{/if}
|
||||
{#if quickStyleProperties?.length}
|
||||
<ToggleButtonGroup
|
||||
bind:selected={richEditorOpen}
|
||||
on:selected={() => {
|
||||
selected={richEditorOpen ? 'true' : 'false'}
|
||||
on:selected={({ detail }) => {
|
||||
richEditorOpen = detail === 'true'
|
||||
if (richEditorOpen !== isQuickMenuOpen) {
|
||||
toggleQuickMenu()
|
||||
richEditorOpen = isQuickMenuOpen
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
small
|
||||
light
|
||||
value={false}
|
||||
value={'false'}
|
||||
icon={Code}
|
||||
tooltip="Edit the CSS directly"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
small
|
||||
light
|
||||
value={true}
|
||||
value={'true'}
|
||||
icon={Paintbrush2}
|
||||
tooltip="Open the rich editor to style the component with a visual interface"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
|
||||
@@ -26,10 +26,11 @@
|
||||
noWFull
|
||||
on:selected={() => ($app = $app)}
|
||||
bind:selected={component.horizontalAlignment}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="left" icon={AlignStartVertical} />
|
||||
<ToggleButton value="center" icon={AlignCenterVertical} />
|
||||
<ToggleButton value="right" icon={AlignEndVertical} />
|
||||
<ToggleButton value="left" icon={AlignStartVertical} {item} />
|
||||
<ToggleButton value="center" icon={AlignCenterVertical} {item} />
|
||||
<ToggleButton value="right" icon={AlignEndVertical} {item} />
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
{#if component.type !== 'formcomponent' && component.verticalAlignment}
|
||||
@@ -37,10 +38,11 @@
|
||||
noWFull
|
||||
on:selected={() => ($app = $app)}
|
||||
bind:selected={component.verticalAlignment}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="top" icon={AlignStartHorizontal} />
|
||||
<ToggleButton value="center" icon={AlignCenterHorizontal} />
|
||||
<ToggleButton value="bottom" icon={AlignEndHorizontal} />
|
||||
<ToggleButton value="top" icon={AlignStartHorizontal} {item} />
|
||||
<ToggleButton value="center" icon={AlignCenterHorizontal} {item} />
|
||||
<ToggleButton value="bottom" icon={AlignEndHorizontal} {item} />
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
}}
|
||||
noWFull
|
||||
bind:selected={componentInput.type}
|
||||
let:item
|
||||
>
|
||||
{#if componentInput.fieldType === 'template'}
|
||||
{#if componentInput.type == 'template'}
|
||||
@@ -65,6 +66,7 @@
|
||||
disabled={disableStatic}
|
||||
icon={CurlyBraces}
|
||||
label="Template"
|
||||
{item}
|
||||
/>
|
||||
{:else}
|
||||
<ToggleButton
|
||||
@@ -73,6 +75,7 @@
|
||||
disabled={disableStatic}
|
||||
icon={CurlyBraces}
|
||||
label="Template"
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
{:else if componentInput.noStatic !== true}
|
||||
@@ -82,6 +85,7 @@
|
||||
disabled={disableStatic}
|
||||
iconOnly={clientWidth < iconOnlyThreshold}
|
||||
icon={Pen}
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
{#if componentInput.type == 'connected'}
|
||||
@@ -90,6 +94,7 @@
|
||||
icon={Plug2}
|
||||
iconOnly={clientWidth < iconOnlyThreshold}
|
||||
label="Connect"
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
<ToggleButton
|
||||
@@ -97,6 +102,7 @@
|
||||
icon={FunctionSquare}
|
||||
iconOnly={clientWidth < iconOnlyThreshold}
|
||||
label="Eval"
|
||||
{item}
|
||||
/>
|
||||
|
||||
<ToggleButton
|
||||
@@ -104,6 +110,7 @@
|
||||
icon={Code}
|
||||
iconOnly={clientWidth < iconOnlyThreshold}
|
||||
label="Compute"
|
||||
{item}
|
||||
id="data-source-compute"
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
|
||||
+5
-2
@@ -394,19 +394,22 @@
|
||||
<div class="p-2">
|
||||
<ToggleButtonGroup
|
||||
bind:selected
|
||||
on:selected={() => {
|
||||
handleSelected(selected)
|
||||
on:selected={({ detail }) => {
|
||||
handleSelected(detail)
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
value="ui-editor"
|
||||
label="UI Editor"
|
||||
tooltip="Use the UI editor to quickly create a plotly chart."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="json"
|
||||
label="JSON"
|
||||
tooltip="Switch to JSON mode for complete customization of Plotly settings."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -141,21 +141,28 @@
|
||||
componentInput['expr'] = JSON.stringify(JSON.parse(componentInput['expr']), null, 4)
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="static" icon={Pen} iconOnly tooltip="Static" />
|
||||
<ToggleButton value="static" icon={Pen} iconOnly tooltip="Static" {item} />
|
||||
{#if userInputEnabled}
|
||||
<ToggleButton value="user" icon={User} iconOnly tooltip="User Input" />
|
||||
<ToggleButton value="user" icon={User} iconOnly tooltip="User Input" {item} />
|
||||
{/if}
|
||||
{#if fileUpload}
|
||||
<ToggleButton value="upload" icon={Upload} iconOnly tooltip="Upload" />
|
||||
<ToggleButton value="upload" icon={Upload} iconOnly tooltip="Upload" {item} />
|
||||
{/if}
|
||||
{#if componentInput?.type === 'connected'}
|
||||
<ToggleButton value="connected" icon={Plug2} iconOnly tooltip="Connect" />
|
||||
<ToggleButton value="connected" icon={Plug2} iconOnly tooltip="Connect" {item} />
|
||||
{/if}
|
||||
{#if componentInput?.type === 'eval'}
|
||||
<ToggleButton value="eval" icon={FunctionSquare} iconOnly tooltip="Eval Legacy" />
|
||||
<ToggleButton
|
||||
value="eval"
|
||||
icon={FunctionSquare}
|
||||
iconOnly
|
||||
tooltip="Eval Legacy"
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
<ToggleButton value="evalv2" icon={FunctionSquare} iconOnly tooltip="Eval" />
|
||||
<ToggleButton value="evalv2" icon={FunctionSquare} iconOnly tooltip="Eval" {item} />
|
||||
</ToggleButtonGroup>
|
||||
<ConnectionButton {closeConnection} {openConnection} isOpen={!!$connectingInput.opened} />
|
||||
{/if}
|
||||
|
||||
@@ -289,21 +289,30 @@
|
||||
{#if $workspaceStore == 'admins'}
|
||||
<div class="flex gap-1 relative w-full">
|
||||
<span class="text-xs absolute -top-4">Scope</span>
|
||||
<ToggleButtonGroup bind:selected={scope}>
|
||||
<ToggleButtonGroup
|
||||
selected={scope ?? 'admins'}
|
||||
on:selected={({ detail }) => {
|
||||
scope = detail === 'admins' ? undefined : detail
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
value={undefined}
|
||||
value={'admins'}
|
||||
label="Admins"
|
||||
tooltip="Displays events from the admins workspace only."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="all_workspaces"
|
||||
label="All"
|
||||
tooltip="Displays events from all workspaces."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="instance"
|
||||
label="Instance"
|
||||
tooltip="Displays instance-scope events, such as user logins and registrations, instance user and group management, and worker configuration changes."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { Tab } from '@rgossiaux/svelte-headlessui'
|
||||
import type { ToggleButtonContext } from './ToggleButtonGroup.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
|
||||
import Tooltip from '$lib/components/meltComponents/Tooltip.svelte'
|
||||
import { type ToggleGroupElements, type ToggleGroupItemProps, melt } from '@melt-ui/svelte'
|
||||
import { Info } from 'lucide-svelte'
|
||||
|
||||
export let value: any
|
||||
export let label: string | undefined = undefined
|
||||
export let iconOnly: boolean = false
|
||||
export let tooltip: string | undefined = undefined
|
||||
@@ -20,48 +16,51 @@
|
||||
export let showTooltipIcon: boolean = false
|
||||
export let documentationLink: string | undefined = undefined
|
||||
export let id: string | undefined = undefined
|
||||
|
||||
const { select, selected } = getContext<ToggleButtonContext>('ToggleButtonGroup')
|
||||
export let item: ToggleGroupElements['item']
|
||||
export let value: ToggleGroupItemProps
|
||||
</script>
|
||||
|
||||
<Popover
|
||||
notClickable
|
||||
<Tooltip
|
||||
class={twMerge('flex', disabled ? 'cursor-not-allowed' : 'cursor-pointer')}
|
||||
disablePopup={tooltip === undefined}
|
||||
disappearTimeout={0}
|
||||
{documentationLink}
|
||||
>
|
||||
<div {id} class="flex">
|
||||
<Tab
|
||||
{disabled}
|
||||
class={twMerge(
|
||||
' rounded-md transition-all text-xs flex gap-1 flex-row items-center',
|
||||
small ? 'px-1.5 py-0.5 text-2xs' : 'px-2 py-1',
|
||||
light ? 'font-medium' : '',
|
||||
$selected === value
|
||||
? 'bg-surface shadow-md'
|
||||
: 'bg-surface-secondary hover:bg-surface-hover',
|
||||
$$props.class
|
||||
)}
|
||||
on:click={() => select(value)}
|
||||
>
|
||||
{#if icon}
|
||||
<svelte:component
|
||||
this={icon}
|
||||
size={small ? 12 : 14}
|
||||
color={$selected === value ? selectedColor : '#9CA3AF'}
|
||||
{...iconProps}
|
||||
/>
|
||||
{/if}
|
||||
{#if label && !iconOnly}
|
||||
{label}
|
||||
{/if}
|
||||
{#if showTooltipIcon}
|
||||
<Info size={14} class="text-gray-400" />
|
||||
{/if}
|
||||
</Tab>
|
||||
</div>
|
||||
<button
|
||||
{id}
|
||||
{disabled}
|
||||
class={twMerge(
|
||||
'group rounded-md transition-all text-xs flex gap-1 flex-row items-center',
|
||||
small ? 'px-1.5 py-0.5 text-2xs' : 'px-2 py-1',
|
||||
light ? 'font-medium' : '',
|
||||
'data-[state=on]:bg-surface data-[state=on]:shadow-md',
|
||||
'bg-surface-secondary hover:bg-surface-hover',
|
||||
$$props.class
|
||||
)}
|
||||
use:melt={$item(value)}
|
||||
style={`--selected-color: ${selectedColor}`}
|
||||
>
|
||||
{#if icon}
|
||||
<svelte:component
|
||||
this={icon}
|
||||
size={small ? 12 : 14}
|
||||
{...iconProps}
|
||||
class={twMerge(
|
||||
'text-gray-400',
|
||||
'group-data-[state=on]:text-[var(--selected-color)]',
|
||||
iconProps.class
|
||||
)}
|
||||
/>
|
||||
{/if}
|
||||
{#if label && !iconOnly}
|
||||
{label}
|
||||
{/if}
|
||||
{#if showTooltipIcon}
|
||||
<Info size={14} class="text-gray-400" />
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<svelte:fragment slot="text">
|
||||
{tooltip}
|
||||
</svelte:fragment>
|
||||
</Popover>
|
||||
</Tooltip>
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
<script context="module" lang="ts">
|
||||
export type ToggleButtonContext = {
|
||||
selected: Writable<any>
|
||||
select: (value: any) => void
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, setContext } from 'svelte'
|
||||
import { writable, type Writable } from 'svelte/store'
|
||||
import { TabGroup, TabList } from '@rgossiaux/svelte-headlessui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { createSync } from '@melt-ui/svelte'
|
||||
|
||||
export let id: string | null | undefined = undefined
|
||||
export let selected: any
|
||||
export let selected: string | string[] | undefined = undefined
|
||||
export let noWFull: boolean = false
|
||||
export let disabled: boolean = false
|
||||
export let tabListClass: string = ''
|
||||
export let allowEmpty: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const selectedContent = writable(selected)
|
||||
|
||||
function setSelected(selected: any) {
|
||||
if ($selectedContent != selected) {
|
||||
selectedContent.set(selected)
|
||||
}
|
||||
}
|
||||
import { createToggleGroup, melt } from '@melt-ui/svelte'
|
||||
|
||||
$: setSelected(selected)
|
||||
|
||||
setContext<ToggleButtonContext>('ToggleButtonGroup', {
|
||||
selected: selectedContent,
|
||||
select: (value: any) => {
|
||||
selectedContent.set(value)
|
||||
selected = value
|
||||
dispatch('selected', value)
|
||||
const {
|
||||
elements: { root, item },
|
||||
options: { disabled: disabledOption },
|
||||
states
|
||||
} = createToggleGroup({
|
||||
type: 'single',
|
||||
onValueChange: ({ curr, next }) => {
|
||||
if (next === undefined && !allowEmpty) {
|
||||
return curr
|
||||
}
|
||||
if (curr !== next) {
|
||||
dispatch('selected', next)
|
||||
}
|
||||
return next
|
||||
}
|
||||
})
|
||||
|
||||
$: $disabledOption = disabled
|
||||
|
||||
const sync = createSync(states)
|
||||
$: sync.value(selected, (v) => (selected = v))
|
||||
</script>
|
||||
|
||||
<TabGroup
|
||||
{id}
|
||||
<div
|
||||
use:melt={$root}
|
||||
class={twMerge(
|
||||
`h-8 flex ${noWFull ? '' : 'w-full'} ${disabled ? 'disabled' : ''}`,
|
||||
$$props.class
|
||||
$$props.class,
|
||||
'flex items-center data-[orientation="vertical"]:flex-col'
|
||||
)}
|
||||
aria-label="Toggle button group"
|
||||
{id}
|
||||
>
|
||||
<TabList
|
||||
class={twMerge('flex bg-surface-secondary rounded-md p-0.5 gap-1 h-full ', tabListClass)}
|
||||
>
|
||||
<slot />
|
||||
</TabList>
|
||||
</TabGroup>
|
||||
<div class={twMerge('flex bg-surface-secondary rounded-md p-0.5 gap-1 h-full ', tabListClass)}>
|
||||
<slot {item} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { Tab } from '@rgossiaux/svelte-headlessui'
|
||||
import type { ToggleButtonContext } from './ToggleButtonGroup.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
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
|
||||
@@ -18,11 +17,14 @@
|
||||
|
||||
export let togglableItems: TogglableItem[]
|
||||
|
||||
const { select, selected } = getContext<ToggleButtonContext>('ToggleButtonGroup')
|
||||
function select(v: string) {
|
||||
console.log('dbg select', v)
|
||||
selected = v
|
||||
}
|
||||
|
||||
let items = togglableItems.map((i) => ({ displayName: i.label, action: () => select(i.value) }))
|
||||
|
||||
function isAnOptionSelected(selected: string) {
|
||||
function isAnOptionSelected(selected: string | undefined) {
|
||||
return togglableItems.some((i) => i.value === selected)
|
||||
}
|
||||
</script>
|
||||
@@ -34,21 +36,16 @@
|
||||
disappearTimeout={0}
|
||||
>
|
||||
<div {id} class="flex">
|
||||
{#if isAnOptionSelected($selected)}
|
||||
<Tab
|
||||
{#if isAnOptionSelected(selected)}
|
||||
<ToggleButton
|
||||
{disabled}
|
||||
class={twMerge(
|
||||
' rounded-md transition-all text-xs flex gap-1 flex-row items-center',
|
||||
small ? 'px-1.5 py-0.5 text-2xs' : 'px-2 py-1',
|
||||
light ? 'font-medium' : '',
|
||||
isAnOptionSelected($selected)
|
||||
? 'bg-surface shadow-md'
|
||||
: 'bg-surface-secondary hover:bg-surface-hover',
|
||||
$$props.class
|
||||
)}
|
||||
>
|
||||
{togglableItems.find((i) => i.value === $selected)?.label}
|
||||
</Tab>
|
||||
value={selected ?? ''}
|
||||
{item}
|
||||
{small}
|
||||
{light}
|
||||
{id}
|
||||
label={togglableItems.find((i) => i.value === selected)?.label}
|
||||
/>
|
||||
{/if}
|
||||
<div class="flex items-center">
|
||||
<DropdownV2 {items} />
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { Tab } from '@rgossiaux/svelte-headlessui'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
|
||||
export let label: string | undefined = undefined
|
||||
export let tooltip: string | undefined = undefined
|
||||
export let disabled: boolean = false
|
||||
export let small = false
|
||||
export let light = false
|
||||
export let checked: boolean = false
|
||||
export let id: string | undefined = undefined
|
||||
</script>
|
||||
|
||||
<div {id} class="flex">
|
||||
<Tab
|
||||
{disabled}
|
||||
class={twMerge(
|
||||
' rounded-md transition-all text-xs flex gap-1 flex-row items-center',
|
||||
small ? 'px-1.5 py-0.5 text-2xs' : 'px-2 py-1',
|
||||
light ? 'font-medium' : '',
|
||||
'bg-surface-secondary ',
|
||||
$$props.class
|
||||
)}
|
||||
>
|
||||
<Toggle
|
||||
size="xs"
|
||||
options={{
|
||||
right: label,
|
||||
rightTooltip: tooltip
|
||||
}}
|
||||
textClass="text-2xs whitespace-nowrap white !w-full"
|
||||
bind:checked
|
||||
/>
|
||||
</Tab>
|
||||
</div>
|
||||
@@ -40,9 +40,10 @@
|
||||
$currentStepStore = numberToChars(0)
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="sequence" label="Sequence" />
|
||||
<ToggleButton value="trigger" label="Trigger" />
|
||||
<ToggleButton value="sequence" label="Sequence" {item} />
|
||||
<ToggleButton value="trigger" label="Trigger" {item} />
|
||||
</ToggleButtonGroup>
|
||||
{#if flowCopilotMode === 'trigger'}
|
||||
<Alert title="Trigger flow builder">
|
||||
|
||||
@@ -406,9 +406,15 @@
|
||||
{:else if $copilotInfo.exists_ai_resource}
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-row justify-between items-center w-96 gap-2">
|
||||
<ToggleButtonGroup class="w-auto shrink-0 h-auto" bind:selected={mode}>
|
||||
<ToggleButton value={'gen'} label="Generate from scratch" light class="px-2" />
|
||||
<ToggleButton value={'edit'} label="Edit existing code" light class="px-2" />
|
||||
<ToggleButtonGroup class="w-auto shrink-0 h-auto" bind:selected={mode} let:item>
|
||||
<ToggleButton
|
||||
value={'gen'}
|
||||
label="Generate from scratch"
|
||||
light
|
||||
class="px-2"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton value={'edit'} label="Edit existing code" light class="px-2" {item} />
|
||||
</ToggleButtonGroup>
|
||||
|
||||
<div class="min-w-0">
|
||||
@@ -520,14 +526,16 @@
|
||||
class="w-auto shrink-0"
|
||||
selected={dbSchema?.publicOnly ? 'true' : 'false'}
|
||||
on:selected={handlePublicOnlySelected}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
value={'true'}
|
||||
label={(dbSchema.schema?.dbo ? 'Dbo' : 'Public') + ' schema'}
|
||||
small
|
||||
light
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton value={'false'} label="All schemas" small light />
|
||||
<ToggleButton value={'false'} label="All schemas" small light {item} />
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -111,10 +111,10 @@
|
||||
<slot name="postgres" />
|
||||
{:else if triggerSelected === 'kafka' || triggerSelected === 'nats' || triggerSelected === 'sqs'}
|
||||
<div class="m-1.5">
|
||||
<ToggleButtonGroup bind:selected={eventStreamType}>
|
||||
<ToggleButton value="kafka" label="Kafka" icon={KafkaIcon} />
|
||||
<ToggleButton value="nats" label="NATS" icon={NatsIcon} />
|
||||
<ToggleButton value="sqs" label="SQS" icon={AwsIcon} />
|
||||
<ToggleButtonGroup bind:selected={eventStreamType} let:item>
|
||||
<ToggleButton value="kafka" label="Kafka" icon={KafkaIcon} {item} />
|
||||
<ToggleButton value="nats" label="NATS" icon={NatsIcon} {item} />
|
||||
<ToggleButton value="sqs" label="SQS" icon={AwsIcon} {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
{#if eventStreamType === 'kafka'}
|
||||
|
||||
@@ -110,9 +110,9 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-row justify-between">
|
||||
<div class="text-xs font-semibold flex flex-row items-center">Call method</div>
|
||||
<ToggleButtonGroup class="h-[30px] w-auto" bind:selected={requestType}>
|
||||
<ToggleButton label="By path" value="path" />
|
||||
<ToggleButton label="By hash" value="hash" />
|
||||
<ToggleButtonGroup class="h-[30px] w-auto" bind:selected={requestType} let:item>
|
||||
<ToggleButton label="By path" value="path" {item} />
|
||||
<ToggleButton label="By hash" value="hash" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -68,12 +68,13 @@
|
||||
{:else}{#if !failureModule && !preprocessorModule}
|
||||
<div class="center-center">
|
||||
<div class="max-w-min">
|
||||
<ToggleButtonGroup bind:selected={kind}>
|
||||
<ToggleButtonGroup bind:selected={kind} let:item>
|
||||
<ToggleButton
|
||||
value="script"
|
||||
icon={Code}
|
||||
label="Action"
|
||||
tooltip="An action script is simply a script that is neither a trigger nor an approval script. Those are the majority of the scripts."
|
||||
{item}
|
||||
/>
|
||||
{#if !shouldDisableTriggerScripts}
|
||||
<ToggleButton
|
||||
@@ -81,6 +82,7 @@
|
||||
icon={Zap}
|
||||
label="Trigger"
|
||||
tooltip="Used as a first step most commonly with a state and a schedule to watch for changes on an external system, compute the diff since last time and set the new state. The diffs are then treated one by one with a for-loop."
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
<ToggleButton
|
||||
@@ -88,6 +90,7 @@
|
||||
icon={Check}
|
||||
label="Approval"
|
||||
tooltip="An approval step will suspend the execution of a flow until it has been approved through the resume endpoints or the approval page by and solely by the recipients of those secret urls."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -629,13 +629,18 @@
|
||||
</div>
|
||||
<div class="flex gap-2 justify-between mb-4 items-center">
|
||||
<div class="flex gap-2">
|
||||
<ToggleButtonGroup bind:selected={s3Kind} class="w-auto">
|
||||
<ToggleButtonGroup bind:selected={s3Kind} class="w-auto" let:item>
|
||||
{#if flowModule.value['language'] === 'deno'}
|
||||
<ToggleButton value="s3_client" size="sm" label="S3 lite client" />
|
||||
<ToggleButton
|
||||
value="s3_client"
|
||||
size="sm"
|
||||
label="S3 lite client"
|
||||
{item}
|
||||
/>
|
||||
{:else}
|
||||
<ToggleButton value="s3_client" size="sm" label="Boto3" />
|
||||
<ToggleButton value="polars" size="sm" label="Polars" />
|
||||
<ToggleButton value="duckdb" size="sm" label="DuckDB" />
|
||||
<ToggleButton value="s3_client" size="sm" label="Boto3" {item} />
|
||||
<ToggleButton value="polars" size="sm" label="Polars" {item} />
|
||||
<ToggleButton value="duckdb" size="sm" label="DuckDB" {item} />
|
||||
{/if}
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -68,10 +68,11 @@
|
||||
setExponentialRetries()
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton light value="disabled" label="Disabled" />
|
||||
<ToggleButton light value="constant" label="Constant" />
|
||||
<ToggleButton light value="exponential" label="Exponential" />
|
||||
<ToggleButton light value="disabled" label="Disabled" {item} />
|
||||
<ToggleButton light value="constant" label="Constant" {item} />
|
||||
<ToggleButton light value="exponential" label="Exponential" {item} />
|
||||
</ToggleButtonGroup>
|
||||
<div class="flex h-[calc(100%-22px)]">
|
||||
<div class="w-1/2 h-full overflow-auto pr-2">
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<script lang="ts">
|
||||
import BarsStaggered from '$lib/components/icons/BarsStaggered.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export let color: string = 'black'
|
||||
</script>
|
||||
|
||||
<BarsStaggered size={14} style={`color: ${color};`} />
|
||||
<div class={twMerge(`text-${color}`, $$props.class)}>
|
||||
<BarsStaggered size={14} />
|
||||
</div>
|
||||
|
||||
@@ -346,9 +346,16 @@
|
||||
setQuery($page.url, 'kind', itemKind)
|
||||
}}
|
||||
class="h-10"
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="all" label="All" class="text-sm px-4 py-2" />
|
||||
<ToggleButton value="script" icon={Code2} label="Scripts" class="text-sm px-4 py-2" />
|
||||
<ToggleButton value="all" label="All" class="text-sm px-4 py-2" {item} />
|
||||
<ToggleButton
|
||||
value="script"
|
||||
icon={Code2}
|
||||
label="Scripts"
|
||||
class="text-sm px-4 py-2"
|
||||
{item}
|
||||
/>
|
||||
{#if HOME_SEARCH_SHOW_FLOW}
|
||||
<ToggleButton
|
||||
value="flow"
|
||||
@@ -356,6 +363,7 @@
|
||||
icon={FlowIcon}
|
||||
class="text-sm px-4 py-2"
|
||||
selectedColor="#14b8a6"
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
<ToggleButton
|
||||
@@ -364,6 +372,7 @@
|
||||
icon={LayoutDashboard}
|
||||
class="text-sm px-4 py-2"
|
||||
selectedColor="#fb923c"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -11,25 +11,25 @@ export interface Setting {
|
||||
label: string
|
||||
tooltip?: string
|
||||
// If not specified, label will be used
|
||||
value?: any
|
||||
value?: string
|
||||
}[]
|
||||
fieldType:
|
||||
| 'text'
|
||||
| 'number'
|
||||
| 'boolean'
|
||||
| 'password'
|
||||
| 'select'
|
||||
| 'textarea'
|
||||
| 'codearea'
|
||||
| 'seconds'
|
||||
| 'email'
|
||||
| 'license_key'
|
||||
| 'object_store_config'
|
||||
| 'critical_error_channels'
|
||||
| 'slack_connect'
|
||||
| 'smtp_connect'
|
||||
| 'indexer_rates'
|
||||
| 'otel'
|
||||
| 'text'
|
||||
| 'number'
|
||||
| 'boolean'
|
||||
| 'password'
|
||||
| 'select'
|
||||
| 'textarea'
|
||||
| 'codearea'
|
||||
| 'seconds'
|
||||
| 'email'
|
||||
| 'license_key'
|
||||
| 'object_store_config'
|
||||
| 'critical_error_channels'
|
||||
| 'slack_connect'
|
||||
| 'smtp_connect'
|
||||
| 'indexer_rates'
|
||||
| 'otel'
|
||||
storage: SettingStorage
|
||||
advancedToggle?: {
|
||||
label: string
|
||||
@@ -81,9 +81,9 @@ export const settings: Record<string, Setting[]> = {
|
||||
isValid: (value: string | undefined) =>
|
||||
value
|
||||
? value?.startsWith('http') &&
|
||||
value.includes('://') &&
|
||||
!value?.endsWith('/') &&
|
||||
!value?.endsWith(' ')
|
||||
value.includes('://') &&
|
||||
!value?.endsWith('/') &&
|
||||
!value?.endsWith(' ')
|
||||
: false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
})
|
||||
|
||||
let isOpen = false
|
||||
export let isOpen = false
|
||||
const sync = createSync(states)
|
||||
$: sync.open(isOpen, (v) => (isOpen = v))
|
||||
|
||||
|
||||
@@ -103,6 +103,8 @@
|
||||
let labelTimeout: NodeJS.Timeout | undefined = undefined
|
||||
let concurrencyKeyTimeout: NodeJS.Timeout | undefined = undefined
|
||||
let tagTimeout: NodeJS.Timeout | undefined = undefined
|
||||
|
||||
let allWorkspacesValue = allWorkspaces ? 'all' : 'admins'
|
||||
</script>
|
||||
|
||||
<div class="flex gap-4">
|
||||
@@ -111,9 +113,13 @@
|
||||
{#if $workspaceStore == 'admins'}
|
||||
<div class="relative">
|
||||
<span class="text-xs absolute -top-4">Workspaces</span>
|
||||
<ToggleButtonGroup bind:selected={allWorkspaces}>
|
||||
<ToggleButton value={false} label="Admins" />
|
||||
<ToggleButton value={true} label="All" />
|
||||
<ToggleButtonGroup
|
||||
bind:selected={allWorkspacesValue}
|
||||
on:selected={({ detail }) => (allWorkspaces = detail === 'all')}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value={'admins'} label="Admins" {item} />
|
||||
<ToggleButton value={'all'} label="All" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -135,10 +141,11 @@
|
||||
autoSet = false
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="path" label="Path" />
|
||||
<ToggleButton value="user" label="User" />
|
||||
<ToggleButton value="folder" label="Folder" />
|
||||
<ToggleButton value="path" label="Path" {item} />
|
||||
<ToggleButton value="user" label="User" {item} />
|
||||
<ToggleButton value="folder" label="Folder" {item} />
|
||||
<ToggleButtonMore
|
||||
togglableItems={[
|
||||
{ label: 'Schedule path', value: 'schedulePath' },
|
||||
@@ -146,6 +153,8 @@
|
||||
{ label: 'Label', value: 'label' },
|
||||
{ label: 'Tag', value: 'tag' }
|
||||
]}
|
||||
{item}
|
||||
bind:selected={filterBy}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
@@ -410,48 +419,56 @@
|
||||
</div>
|
||||
<div class="relative">
|
||||
<span class="text-xs absolute -top-4">Kind</span>
|
||||
<ToggleButtonGroup bind:selected={jobKindsCat}>
|
||||
<ToggleButton value="all" label="All" />
|
||||
<ToggleButtonGroup bind:selected={jobKindsCat} let:item>
|
||||
<ToggleButton value="all" label="All" {item} />
|
||||
<ToggleButton
|
||||
value="runs"
|
||||
label="Runs"
|
||||
showTooltipIcon
|
||||
tooltip="Runs are jobs that have no parent jobs (flows are jobs that are parent of the jobs they start), they have been triggered through the UI, a schedule or webhook"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="previews"
|
||||
label="Previews"
|
||||
showTooltipIcon
|
||||
tooltip="Previews are jobs that have been started in the editor as 'Tests'"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="dependencies"
|
||||
label="Deps"
|
||||
showTooltipIcon
|
||||
tooltip="Deploying a script, flow or an app launch a dependency job that create and then attach the lockfile to the deployed item. This mechanism ensure that logic is always executed with the exact same direct and indirect dependencies."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="deploymentcallbacks"
|
||||
label="Sync"
|
||||
showTooltipIcon
|
||||
tooltip="Sync jobs that are triggered on every script deployment to sync the workspace with the Git repository configured in the the workspace settings"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<span class="text-xs absolute -top-4">Status</span>
|
||||
<ToggleButtonGroup
|
||||
allowEmpty
|
||||
bind:selected={success}
|
||||
on:selected={() => dispatch('successChange', success)}
|
||||
selected={success ?? 'all'}
|
||||
on:selected={({ detail }) => {
|
||||
success = detail === 'all' ? undefined : detail
|
||||
dispatch('successChange', success)
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value={undefined} label="All" />
|
||||
<ToggleButton value={'all'} label="All" {item} />
|
||||
<ToggleButton
|
||||
value={'running'}
|
||||
tooltip="Running"
|
||||
class="whitespace-nowrap"
|
||||
icon={PlayCircle}
|
||||
iconProps={{ color: success === 'running' ? 'blue' : 'gray' }}
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value={'success'}
|
||||
@@ -459,6 +476,7 @@
|
||||
class="whitespace-nowrap"
|
||||
icon={CheckCircle2}
|
||||
iconProps={{ color: success === 'success' ? 'green' : 'gray' }}
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value={'failure'}
|
||||
@@ -466,6 +484,7 @@
|
||||
class="whitespace-nowrap"
|
||||
icon={AlertCircle}
|
||||
iconProps={{ color: success === 'failure' ? 'red' : 'gray' }}
|
||||
{item}
|
||||
/>
|
||||
{#if success == 'waiting'}
|
||||
<ToggleButton
|
||||
@@ -474,6 +493,7 @@
|
||||
class="whitespace-nowrap"
|
||||
icon={Hourglass}
|
||||
iconProps={{ color: 'blue' }}
|
||||
{item}
|
||||
/>
|
||||
{:else if success == 'suspended'}
|
||||
<ToggleButton
|
||||
@@ -482,6 +502,7 @@
|
||||
class="whitespace-nowrap"
|
||||
icon={Hourglass}
|
||||
iconProps={{ color: 'blue' }}
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
</ToggleButtonGroup>
|
||||
@@ -505,6 +526,7 @@
|
||||
{#if mobile || true}
|
||||
<Label label="Filter by">
|
||||
<ToggleButtonGroup
|
||||
let:item
|
||||
bind:selected={filterBy}
|
||||
on:selected={() => {
|
||||
if (!autoSet) {
|
||||
@@ -520,13 +542,13 @@
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ToggleButton value="path" label="Path" />
|
||||
<ToggleButton value="user" label="User" />
|
||||
<ToggleButton value="folder" label="Folder" />
|
||||
<ToggleButton value="schedulePath" label="Schedule" />
|
||||
<ToggleButton value="concurrencyKey" label="Concurrency" />
|
||||
<ToggleButton value="tag" label="Tag" />
|
||||
<ToggleButton value="label" label="Label" />
|
||||
<ToggleButton value="path" label="Path" {item} />
|
||||
<ToggleButton value="user" label="User" {item} />
|
||||
<ToggleButton value="folder" label="Folder" {item} />
|
||||
<ToggleButton value="schedulePath" label="Schedule" {item} />
|
||||
<ToggleButton value="concurrencyKey" label="Concurrency" {item} />
|
||||
<ToggleButton value="tag" label="Tag" {item} />
|
||||
<ToggleButton value="label" label="Label" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</Label>
|
||||
|
||||
@@ -726,41 +748,49 @@
|
||||
{/if}
|
||||
|
||||
<Label label="Kind">
|
||||
<ToggleButtonGroup bind:selected={jobKindsCat}>
|
||||
<ToggleButton value="all" label="All" />
|
||||
<ToggleButtonGroup bind:selected={jobKindsCat} let:item>
|
||||
<ToggleButton value="all" label="All" {item} />
|
||||
<ToggleButton
|
||||
value="runs"
|
||||
label="Runs"
|
||||
showTooltipIcon
|
||||
tooltip="Runs are jobs that have no parent jobs (flows are jobs that are parent of the jobs they start), they have been triggered through the UI, a schedule or webhook"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="previews"
|
||||
label="Previews"
|
||||
showTooltipIcon
|
||||
tooltip="Previews are jobs that have been started in the editor as 'Tests'"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="dependencies"
|
||||
label="Deps"
|
||||
showTooltipIcon
|
||||
tooltip="Deploying a script, flow or an app launch a dependency job that create and then attach the lockfile to the deployed item. This mechanism ensure that logic is always executed with the exact same direct and indirect dependencies."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="deploymentcallbacks"
|
||||
label="Sync"
|
||||
showTooltipIcon
|
||||
tooltip="Sync jobs that are triggered on every script deployment to sync the workspace with the Git repository configured in the the workspace settings"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</Label>
|
||||
|
||||
<Label label="Status">
|
||||
<ToggleButtonGroup bind:selected={success}>
|
||||
<ToggleButton value={undefined} label="All" />
|
||||
<ToggleButton value={'running'} label="Running" class="whitespace-nowrap" />
|
||||
<ToggleButton value={'success'} label="Success" class="whitespace-nowrap" />
|
||||
<ToggleButton value={'failure'} label="Failure" class="whitespace-nowrap" />
|
||||
<ToggleButtonGroup
|
||||
selected={success ?? 'all'}
|
||||
on:selected={({ detail }) => (success = detail === 'all' ? undefined : detail)}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value={'all'} label="All" {item} />
|
||||
<ToggleButton value={'running'} label="Running" class="whitespace-nowrap" {item} />
|
||||
<ToggleButton value={'success'} label="Success" class="whitespace-nowrap" {item} />
|
||||
<ToggleButton value={'failure'} label="Failure" class="whitespace-nowrap" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</Label>
|
||||
{/if}
|
||||
|
||||
@@ -181,9 +181,14 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
{#if type === 'object' && schema.oneOf && schema.oneOf.length >= 2}
|
||||
<div class="flex flex-row gap-1 items-center justify-start">
|
||||
<ToggleButtonGroup bind:selected={oneOfSelected} class="w-auto" tabListClass="flex-wrap">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={oneOfSelected}
|
||||
class="h-auto w-auto"
|
||||
tabListClass="flex-wrap"
|
||||
let:item
|
||||
>
|
||||
{#each schema.oneOf as obj}
|
||||
<ToggleButton value={obj.title} label={obj.title} />
|
||||
<ToggleButton value={obj.title ?? ''} label={obj.title} {item} />
|
||||
{/each}
|
||||
</ToggleButtonGroup>
|
||||
|
||||
|
||||
@@ -193,9 +193,9 @@
|
||||
bind:currencyLocale={extra['currencyLocale']}
|
||||
/>
|
||||
{:else if type == 'object' && oneOf && oneOf.length >= 2 && !isFlowInput && !isAppInput}
|
||||
<ToggleButtonGroup bind:selected={oneOfSelected} class="mb-2">
|
||||
<ToggleButtonGroup bind:selected={oneOfSelected} class="mb-2" let:item>
|
||||
{#each oneOf as obj}
|
||||
<ToggleButton value={obj.title} label={obj.title} />
|
||||
<ToggleButton value={obj.title ?? ''} label={obj.title} {item} />
|
||||
{/each}
|
||||
</ToggleButtonGroup>
|
||||
{#if oneOfSelected && oneOfSchemas}
|
||||
|
||||
@@ -71,9 +71,9 @@
|
||||
|
||||
$: enableAllState = (() => {
|
||||
const values = Object.values(operatorWorkspaceSettings)
|
||||
if (values.every((v) => v === true)) return true
|
||||
if (values.every((v) => v === false)) return false
|
||||
return null
|
||||
if (values.every((v) => v === true)) return 'true'
|
||||
if (values.every((v) => v === false)) return 'false'
|
||||
return undefined
|
||||
})()
|
||||
|
||||
function toggleAllSettings(event) {
|
||||
@@ -111,9 +111,25 @@
|
||||
<Cell head first>Section</Cell>
|
||||
<Cell head>Description</Cell>
|
||||
<Cell head last>
|
||||
<ToggleButtonGroup bind:selected={enableAllState} on:selected={toggleAllSettings}>
|
||||
<ToggleButton icon={EyeIcon} small={true} value={true} label="Enable All" />
|
||||
<ToggleButton icon={EyeOffIcon} small={true} value={false} label="Disable All" />
|
||||
<ToggleButtonGroup
|
||||
bind:selected={enableAllState}
|
||||
on:selected={toggleAllSettings}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
icon={EyeIcon}
|
||||
small={true}
|
||||
value={'true'}
|
||||
label="Enable All"
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
icon={EyeOffIcon}
|
||||
small={true}
|
||||
value={'false'}
|
||||
label="Disable All"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</Cell>
|
||||
</tr>
|
||||
@@ -124,9 +140,13 @@
|
||||
<Cell first>{title}</Cell>
|
||||
<Cell>{description}</Cell>
|
||||
<Cell last class="pl-8">
|
||||
<ToggleButtonGroup bind:selected={operatorWorkspaceSettings[key]}>
|
||||
<ToggleButton icon={EyeIcon} small={true} value={true} label="On" />
|
||||
<ToggleButton icon={EyeOffIcon} small={true} value={false} label="Off" />
|
||||
<ToggleButtonGroup
|
||||
selected={operatorWorkspaceSettings[key] ? 'on' : 'off'}
|
||||
on:selected={({ detail }) => (operatorWorkspaceSettings[key] = detail === 'on')}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton icon={EyeIcon} small={true} value={'on'} label="On" {item} />
|
||||
<ToggleButton icon={EyeOffIcon} small={true} value={'off'} label="Off" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</Cell>
|
||||
</tr>
|
||||
|
||||
@@ -205,9 +205,10 @@
|
||||
autoAdd = e.detail === 'add'
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="invite" size="xs" label="Auto-invite" />
|
||||
<ToggleButton value="add" size="xs" label="Auto-add" />
|
||||
<ToggleButton value="invite" size="xs" label="Auto-invite" {item} />
|
||||
<ToggleButton value="add" size="xs" label="Auto-add" {item} />
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
|
||||
@@ -235,18 +236,19 @@
|
||||
operatorOnly = e.detail === 'operator'
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
value="operator"
|
||||
size="xs"
|
||||
label="Operator"
|
||||
tooltip="An operator can only execute and view scripts/flows/apps from your workspace, and only those that he has visibility on."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="developer"
|
||||
size="xs"
|
||||
label="Developer"
|
||||
tooltip="A Developer can execute and view scripts/flows/apps, but they can also create new ones and edit those they are allowed to by their path (either u/ or Writer or Admin of their folder found at /f)."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
<div class="pt-2">
|
||||
@@ -365,26 +367,27 @@
|
||||
})
|
||||
listUsers()
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
value="operator"
|
||||
size="xs"
|
||||
label="Operator"
|
||||
tooltip="An operator can only execute and view scripts/flows/apps from your workspace, and only those that he has visibility on."
|
||||
{item}
|
||||
/>
|
||||
|
||||
<ToggleButton
|
||||
value="developer"
|
||||
size="xs"
|
||||
label="Developer"
|
||||
tooltip="A Developer can execute and view scripts/flows/apps, but they can also create new ones and edit those they are allowed to by their path (either u/ or Writer or Admin of their folder found at /f)."
|
||||
{item}
|
||||
/>
|
||||
|
||||
<ToggleButton
|
||||
value="admin"
|
||||
size="xs"
|
||||
label="Admin"
|
||||
tooltip="An admin has full control over a specific Windmill workspace, including the ability to manage users, edit entities, and control permissions within the workspace."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
@@ -494,26 +497,27 @@
|
||||
})
|
||||
listUsers()
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
value="operator"
|
||||
size="xs"
|
||||
label="Operator"
|
||||
tooltip="An operator can only execute and view scripts/flows/apps from your workspace, and only those that he has visibility on."
|
||||
{item}
|
||||
/>
|
||||
|
||||
<ToggleButton
|
||||
value="developer"
|
||||
size="xs"
|
||||
label="Developer"
|
||||
tooltip="A Developer can execute and view scripts/flows/apps, but they can also create new ones and edit those they are allowed to by their path (either u/ or Writer or Admin of their folder found at /f)."
|
||||
{item}
|
||||
/>
|
||||
|
||||
<ToggleButton
|
||||
value="admin"
|
||||
size="xs"
|
||||
label="Admin"
|
||||
tooltip="An admin has full control over a specific Windmill workspace, including the ability to manage users, edit entities, and control permissions within the workspace."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import Popover from '$lib/components/meltComponents/Popover.svelte'
|
||||
import { Button } from '$lib/components/common'
|
||||
import { Webhook, Route, Unplug, Mail, Plus, Database } from 'lucide-svelte'
|
||||
import KafkaIcon from '$lib/components/icons/KafkaIcon.svelte'
|
||||
@@ -10,11 +9,10 @@
|
||||
import CaptureIcon from './CaptureIcon.svelte'
|
||||
import NatsIcon from '../icons/NatsIcon.svelte'
|
||||
import AwsIcon from '../icons/AwsIcon.svelte'
|
||||
import DropdownV2 from '$lib/components/DropdownV2.svelte'
|
||||
|
||||
export let small = false
|
||||
|
||||
let isOpen = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
function handleClick(kind: CaptureTriggerKind) {
|
||||
@@ -22,12 +20,56 @@
|
||||
kind: captureTriggerKindToTriggerKind(kind),
|
||||
config: {}
|
||||
})
|
||||
isOpen = false
|
||||
}
|
||||
|
||||
$: items = [
|
||||
{
|
||||
icon: Webhook,
|
||||
displayName: 'Webhook',
|
||||
action: () => handleClick('webhook')
|
||||
},
|
||||
{
|
||||
icon: Route,
|
||||
displayName: 'HTTP',
|
||||
action: () => handleClick('http')
|
||||
},
|
||||
{
|
||||
icon: Unplug,
|
||||
displayName: 'Websocket',
|
||||
action: () => handleClick('websocket')
|
||||
},
|
||||
{
|
||||
icon: AwsIcon,
|
||||
displayName: 'SQS',
|
||||
action: () => handleClick('sqs')
|
||||
},
|
||||
{
|
||||
icon: Database,
|
||||
displayName: 'Postgres',
|
||||
action: () => handleClick('postgres')
|
||||
},
|
||||
{
|
||||
icon: Mail,
|
||||
displayName: 'Email',
|
||||
action: () => handleClick('email')
|
||||
},
|
||||
{
|
||||
icon: KafkaIcon,
|
||||
displayName: 'Kafka',
|
||||
action: () => handleClick('kafka'),
|
||||
disabled: !$enterpriseLicense
|
||||
},
|
||||
{
|
||||
icon: NatsIcon,
|
||||
displayName: 'Nats',
|
||||
action: () => handleClick('nats'),
|
||||
disabled: !$enterpriseLicense
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
||||
<Popover closeButton={false} bind:isOpen>
|
||||
<svelte:fragment slot="trigger">
|
||||
<DropdownV2 {items} placement="bottom-start">
|
||||
<svelte:fragment slot="buttonReplacement">
|
||||
{#if small}
|
||||
<Button
|
||||
color="light"
|
||||
@@ -54,82 +96,4 @@
|
||||
</Button>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="content">
|
||||
<div class="flex flex-col bg-surface">
|
||||
<button
|
||||
class="hover:bg-surface-hover p-2 transition-colors duration-150"
|
||||
on:click={() => handleClick('webhook')}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<Webhook size={16} />
|
||||
<p class="text-xs text-secondary">Webhook</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="hover:bg-surface-hover p-2 transition-colors duration-150"
|
||||
on:click={() => handleClick('http')}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<Route size={16} />
|
||||
<p class="text-xs text-secondary">HTTP</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="hover:bg-surface-hover p-2 transition-colors duration-150"
|
||||
on:click={() => handleClick('websocket')}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<Unplug size={16} />
|
||||
<p class="text-xs text-secondary">Websocket</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="hover:bg-surface-hover p-2 transition-colors duration-150"
|
||||
on:click={() => handleClick('sqs')}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<AwsIcon size={16} />
|
||||
<p class="text-xs text-secondary">SQS</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="hover:bg-surface-hover p-2 transition-colors duration-150"
|
||||
on:click={() => handleClick('postgres')}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<Database size={16} />
|
||||
<p class="text-xs text-secondary">Postgres</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="hover:bg-surface-hover p-2 transition-colors duration-150"
|
||||
on:click={() => handleClick('email')}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<Mail size={16} />
|
||||
<p class="text-xs text-secondary">Email</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
disabled={!$enterpriseLicense}
|
||||
class="hover:bg-surface-hover p-2 transition-colors duration-150"
|
||||
on:click={() => handleClick('kafka')}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<KafkaIcon size={16} />
|
||||
<p class="text-xs text-secondary">Kafka</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
disabled={!$enterpriseLicense}
|
||||
class="hover:bg-surface-hover p-2 transition-colors duration-150"
|
||||
on:click={() => handleClick('nats')}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<NatsIcon size={16} />
|
||||
<p class="text-xs text-secondary">Nats</p>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
</Popover>
|
||||
</DropdownV2>
|
||||
|
||||
@@ -208,13 +208,15 @@
|
||||
on:selected={(e) => {
|
||||
initLoadCaptures(e.detail)
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="main" label={isFlow ? 'Flow' : 'Main'} small />
|
||||
<ToggleButton value="main" label={isFlow ? 'Flow' : 'Main'} small {item} />
|
||||
<ToggleButton
|
||||
value="preprocessor"
|
||||
label="Preprocessor"
|
||||
small
|
||||
tooltip="When the runnable has a preprocessor, it receives additional information about the request"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
@@ -155,10 +155,10 @@
|
||||
</div>
|
||||
{:else if $selectedTrigger === 'kafka' || $selectedTrigger === 'nats' || $selectedTrigger === 'sqs'}
|
||||
<div class="p-4 flex flex-col gap-2">
|
||||
<ToggleButtonGroup bind:selected={eventStreamType}>
|
||||
<ToggleButton value="kafka" label="Kafka" icon={KafkaIcon} />
|
||||
<ToggleButton value="nats" label="NATS" icon={NatsIcon} />
|
||||
<ToggleButton value="sqs" label="SQS" icon={AwsIcon} />
|
||||
<ToggleButtonGroup bind:selected={eventStreamType} let:item>
|
||||
<ToggleButton value="kafka" label="Kafka" icon={KafkaIcon} {item} />
|
||||
<ToggleButton value="nats" label="NATS" icon={NatsIcon} {item} />
|
||||
<ToggleButton value="sqs" label="SQS" icon={AwsIcon} {item} />
|
||||
</ToggleButtonGroup>
|
||||
{#if eventStreamType === 'kafka'}
|
||||
<KafkaTriggersPanel
|
||||
|
||||
@@ -150,12 +150,13 @@
|
||||
disabled={!($userStore?.is_admin || $userStore?.is_super_admin) ||
|
||||
!can_write ||
|
||||
!!static_asset_config}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton label="GET" value="get" />
|
||||
<ToggleButton label="POST" value="post" />
|
||||
<ToggleButton label="PUT" value="put" />
|
||||
<ToggleButton label="PATCH" value="patch" />
|
||||
<ToggleButton label="DELETE" value="delete" />
|
||||
<ToggleButton label="GET" value="get" {item} />
|
||||
<ToggleButton label="POST" value="post" {item} />
|
||||
<ToggleButton label="PUT" value="put" {item} />
|
||||
<ToggleButton label="PATCH" value="patch" {item} />
|
||||
<ToggleButton label="DELETE" value="delete" {item} />
|
||||
</ToggleButtonGroup>
|
||||
<div class="flex flex-col w-full mt-2">
|
||||
<div class="flex justify-start w-full">
|
||||
|
||||
@@ -252,10 +252,11 @@
|
||||
static_asset_config = undefined
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton label="Runnable" value="runnable" />
|
||||
<ToggleButton label="Static asset" value="static_asset" />
|
||||
<ToggleButton label="Static website" value="static_website" />
|
||||
<ToggleButton label="Runnable" value="runnable" {item} />
|
||||
<ToggleButton label="Static asset" value="static_asset" {item} />
|
||||
<ToggleButton label="Static website" value="static_website" {item} />
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
|
||||
@@ -385,18 +386,24 @@
|
||||
<svelte:fragment slot="action">
|
||||
<ToggleButtonGroup
|
||||
class="w-auto h-full"
|
||||
bind:selected={is_async}
|
||||
selected={is_async ? 'async' : 'sync'}
|
||||
on:selected={({ detail }) => {
|
||||
is_async = detail === 'async'
|
||||
}}
|
||||
disabled={!can_write || !!static_asset_config}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton
|
||||
label="Async"
|
||||
value={true}
|
||||
value="async"
|
||||
tooltip="The returning value is the uuid of the job assigned to execute the job."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
label="Sync"
|
||||
value={false}
|
||||
value="sync"
|
||||
tooltip="Triggers the execution, wait for the job to complete and return it as a response."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</svelte:fragment>
|
||||
@@ -407,14 +414,19 @@
|
||||
<svelte:fragment slot="action">
|
||||
<ToggleButtonGroup
|
||||
class="w-auto h-full"
|
||||
bind:selected={requires_auth}
|
||||
selected={requires_auth ? 'required' : 'none'}
|
||||
on:selected={({ detail }) => {
|
||||
requires_auth = detail === 'required'
|
||||
}}
|
||||
disabled={!can_write}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton label="None" value={false} />
|
||||
<ToggleButton label="None" value="none" {item} />
|
||||
<ToggleButton
|
||||
label="Required"
|
||||
value={true}
|
||||
value="required"
|
||||
tooltip="Requires authentication with read access on the route"
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -200,9 +200,10 @@
|
||||
delete args.security
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="static" label="Static" small={true} />
|
||||
<ToggleButton value="resource" label="Resource" icon={Boxes} small={true} />
|
||||
<ToggleButton value="static" label="Static" small={true} {item} />
|
||||
<ToggleButton value="resource" label="Resource" icon={Boxes} small={true} {item} />
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -251,9 +251,10 @@
|
||||
delete args.require_tls
|
||||
}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="static" label="Static" small={true} />
|
||||
<ToggleButton value="resource" label="Resource" icon={Boxes} small={true} />
|
||||
<ToggleButton value="static" label="Static" small={true} {item} />
|
||||
<ToggleButton value="resource" label="Resource" icon={Boxes} small={true} {item} />
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -490,9 +490,10 @@
|
||||
replication_slot_name = ''
|
||||
}}
|
||||
disabled={!can_write}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="create" label="Create Slot" />
|
||||
<ToggleButton value="get" label="Get Slot" />
|
||||
<ToggleButton value="create" label="Create Slot" {item} />
|
||||
<ToggleButton value="get" label="Get Slot" {item} />
|
||||
</ToggleButtonGroup>
|
||||
{#if selectedSlotAction === 'create'}
|
||||
<div class="flex gap-3">
|
||||
@@ -527,9 +528,10 @@
|
||||
>
|
||||
<div class="flex flex-col gap-3">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={selectedPublicationAction}
|
||||
selected={selectedPublicationAction}
|
||||
disabled={!can_write}
|
||||
on:selected={() => {
|
||||
on:selected={({ detail }) => {
|
||||
selectedPublicationAction = detail
|
||||
if (selectedPublicationAction === 'create') {
|
||||
selectedTable = 'specific'
|
||||
publication_name = `windmill_publication_${random_adj()}`
|
||||
@@ -541,9 +543,10 @@
|
||||
relations = []
|
||||
transaction_to_track = []
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="create" label="Create Publication" />
|
||||
<ToggleButton value="get" label="Get Publication" />
|
||||
<ToggleButton value="create" label="Create Publication" {item} />
|
||||
<ToggleButton value="get" label="Get Publication" {item} />
|
||||
</ToggleButtonGroup>
|
||||
{#if selectedPublicationAction === 'create'}
|
||||
<div class="flex gap-3">
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
|
||||
let cached: Relations[] = relations
|
||||
|
||||
const defaultRelations: Relations[] = [
|
||||
{
|
||||
schema_name: 'public',
|
||||
table_to_track: []
|
||||
}
|
||||
]
|
||||
|
||||
function addTable(name: string, index: number) {
|
||||
if (relations == undefined || !Array.isArray(relations)) {
|
||||
relations = []
|
||||
@@ -36,18 +43,24 @@
|
||||
<div class="grow-0 flex flex-row gap-2 w-full items-center">
|
||||
<div class="grow-0">
|
||||
<ToggleButtonGroup
|
||||
on:selected={() => {
|
||||
if (selectedTable === 'all') {
|
||||
on:selected={({ detail }) => {
|
||||
if (detail === 'all') {
|
||||
cached = relations
|
||||
relations = []
|
||||
} else {
|
||||
relations = cached
|
||||
if (cached.length === 0) {
|
||||
relations = defaultRelations
|
||||
} else {
|
||||
relations = cached
|
||||
}
|
||||
}
|
||||
selectedTable = detail
|
||||
}}
|
||||
bind:selected={selectedTable}
|
||||
selected={selectedTable}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="all" label="All Tables" />
|
||||
<ToggleButton value="specific" label="Specific Tables" />
|
||||
<ToggleButton value="all" label="All Tables" light {item} />
|
||||
<ToggleButton value="specific" label="Specific Tables" light {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -110,18 +110,20 @@
|
||||
>
|
||||
<div class="mt-2">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={tab}
|
||||
on:selected={() => {
|
||||
if (tab === 'all') {
|
||||
selected={tab}
|
||||
on:selected={({ detail }) => {
|
||||
if (detail === 'all') {
|
||||
cached = message_attributes
|
||||
message_attributes = ['All']
|
||||
} else {
|
||||
message_attributes = cached
|
||||
}
|
||||
tab = detail
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="all" label="All attributes" />
|
||||
<ToggleButton value="specific" label="Specific attributes" />
|
||||
<ToggleButton value="all" label="All attributes" {item} />
|
||||
<ToggleButton value="specific" label="Specific attributes" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<div class="flex flex-col mt-3 gap-1">
|
||||
|
||||
@@ -308,26 +308,29 @@ done`
|
||||
<div class="flex flex-row justify-between">
|
||||
<div class="text-sm font-normal text-secondary flex flex-row items-center">Request type</div
|
||||
>
|
||||
<ToggleButtonGroup class="h-[30px] w-auto" bind:selected={webhookType}>
|
||||
<ToggleButtonGroup class="h-[30px] w-auto" bind:selected={webhookType} let:item>
|
||||
<ToggleButton
|
||||
label="Async"
|
||||
value="async"
|
||||
tooltip="The returning value is the uuid of the job assigned to execute the job."
|
||||
{item}
|
||||
/>
|
||||
<ToggleButton
|
||||
label="Sync"
|
||||
value="sync"
|
||||
tooltip="Triggers the execution, wait for the job to complete and return it as a response."
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<div class="flex flex-row justify-between">
|
||||
<div class="text-sm font-normal text-secondary flex flex-row items-center">Call method</div>
|
||||
<ToggleButtonGroup class="h-[30px] w-auto" bind:selected={requestType}>
|
||||
<ToggleButtonGroup class="h-[30px] w-auto" bind:selected={requestType} let:item>
|
||||
<ToggleButton
|
||||
label="POST by path"
|
||||
value="path"
|
||||
icon={ArrowUpRight}
|
||||
{item}
|
||||
selectedColor="#fb923c"
|
||||
/>
|
||||
{#if !isFlow}
|
||||
@@ -337,6 +340,7 @@ done`
|
||||
icon={ArrowUpRight}
|
||||
selectedColor="#fb923c"
|
||||
disabled={!hash}
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -345,6 +349,7 @@ done`
|
||||
value="get_path"
|
||||
icon={ArrowDownRight}
|
||||
disabled={webhookType !== 'sync'}
|
||||
{item}
|
||||
selectedColor="#14b8a6"
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
@@ -353,9 +358,9 @@ done`
|
||||
<div class="text-sm font-normal text-secondary flex flex-row items-center"
|
||||
>Token configuration</div
|
||||
>
|
||||
<ToggleButtonGroup class="h-[30px] w-auto" bind:selected={tokenType}>
|
||||
<ToggleButton label="Token in Headers" value="headers" />
|
||||
<ToggleButton label="Token in Query" value="query" />
|
||||
<ToggleButtonGroup class="h-[30px] w-auto" bind:selected={tokenType} let:item>
|
||||
<ToggleButton label="Token in Headers" value="headers" {item} />
|
||||
<ToggleButton label="Token in Query" value="query" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -102,9 +102,10 @@
|
||||
url = ev.detail === 'runnable' ? '$script:' : ''
|
||||
url_runnable_args = {}
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="static" label="Static URL" />
|
||||
<ToggleButton value="runnable" label="Runnable result as URL" />
|
||||
<ToggleButton value="static" label="Static URL" {item} />
|
||||
<ToggleButton value="runnable" label="Runnable result as URL" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
{#if url?.startsWith('$')}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="content">
|
||||
{#if value}
|
||||
<div class="flex flex-col w-96 gap-4 p-4 max-h-[50vh] overflow-y-auto">
|
||||
<div class="flex flex-col w-96 gap-4 p-4 max-h-[70vh] overflow-y-auto">
|
||||
<Label label="Name">
|
||||
<input type="text" bind:value={value.name} />
|
||||
</Label>
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="content">
|
||||
{#if value}
|
||||
<div class="flex flex-col w-96 p-4 gap-4 max-h-[50vh] overflow-y-auto">
|
||||
<div class="flex flex-col w-96 p-4 gap-4 max-h-[70vh] overflow-y-auto">
|
||||
<span class="text-sm mb-2 leading-6 font-semibold">
|
||||
Column definitions
|
||||
<Tooltip
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="content">
|
||||
{#if value}
|
||||
<div class="flex flex-col w-96 p-4 gap-4 max-h-[50vh] overflow-y-auto">
|
||||
<div class="flex flex-col w-96 p-4 gap-4 max-h-[70vh] overflow-y-auto">
|
||||
<Label label="Name">
|
||||
<input type="text" bind:value={value.name} />
|
||||
</Label>
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
placement: 'left-start',
|
||||
middleware: [offset(8), flip(), shift()]
|
||||
}}
|
||||
contentClasses="max-h-[50vh] overflow-y-auto p-4 flex flex-col gap-4 w-96"
|
||||
contentClasses="max-h-[70vh] overflow-y-auto p-4 flex flex-col gap-4 w-96"
|
||||
closeOnOtherPopoverOpen
|
||||
>
|
||||
<svelte:fragment slot="trigger">
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="content">
|
||||
{#if value}
|
||||
<div class="flex flex-col w-96 p-4 gap-4 max-h-[50vh] overflow-y-auto">
|
||||
<div class="flex flex-col w-96 p-4 gap-4 max-h-[70vh] overflow-y-auto">
|
||||
<Label label="Name">
|
||||
<input type="text" bind:value={value.name} />
|
||||
</Label>
|
||||
|
||||
@@ -244,9 +244,9 @@
|
||||
/>
|
||||
<div class="flex flex-row items-center gap-2 mt-6">
|
||||
<div class="text-sm shrink-0"> Filter by path of </div>
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind}>
|
||||
<ToggleButton small value="trigger" label="Kafka trigger" icon={KafkaIcon} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} />
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind} let:item>
|
||||
<ToggleButton small value="trigger" label="Kafka trigger" icon={KafkaIcon} {item} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<ListFilters syncQuery bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
|
||||
@@ -208,223 +208,230 @@
|
||||
f={(x) => (x.summary ?? '') + ' ' + x.path + ' (' + x.script_path + ')'}
|
||||
/>
|
||||
|
||||
{#if $userStore?.operator && $workspaceStore && !$userWorkspaces.find(_ => _.id === $workspaceStore)?.operator_settings?.triggers}
|
||||
<div class="bg-red-100 border-l-4 border-red-600 text-orange-700 p-4 m-4 mt-12" role="alert">
|
||||
<p class="font-bold">Unauthorized</p>
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{#if $userStore?.operator && $workspaceStore && !$userWorkspaces.find((_) => _.id === $workspaceStore)?.operator_settings?.triggers}
|
||||
<div class="bg-red-100 border-l-4 border-red-600 text-orange-700 p-4 m-4 mt-12" role="alert">
|
||||
<p class="font-bold">Unauthorized</p>
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{:else}
|
||||
<CenteredPage>
|
||||
<PageHeader
|
||||
title="NATS triggers"
|
||||
tooltip="Windmill can consume NATS events and trigger scripts or flows based on them."
|
||||
>
|
||||
<Button size="md" startIcon={{ icon: Plus }} on:click={() => natsTriggerEditor.openNew(false)}>
|
||||
New NATS trigger
|
||||
</Button>
|
||||
</PageHeader>
|
||||
<CenteredPage>
|
||||
<PageHeader
|
||||
title="NATS triggers"
|
||||
tooltip="Windmill can consume NATS events and trigger scripts or flows based on them."
|
||||
>
|
||||
<Button
|
||||
size="md"
|
||||
startIcon={{ icon: Plus }}
|
||||
on:click={() => natsTriggerEditor.openNew(false)}
|
||||
>
|
||||
New NATS trigger
|
||||
</Button>
|
||||
</PageHeader>
|
||||
|
||||
{#if isCloudHosted()}
|
||||
<Alert title="Not compatible with multi-tenant cloud" type="warning">
|
||||
NATS triggers are disabled in the multi-tenant cloud.
|
||||
</Alert>
|
||||
<div class="py-4" />
|
||||
{/if}
|
||||
<div class="w-full h-full flex flex-col">
|
||||
<div class="w-full pb-4 pt-6">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search NATS triggers"
|
||||
bind:value={filter}
|
||||
class="search-item"
|
||||
/>
|
||||
<div class="flex flex-row items-center gap-2 mt-6">
|
||||
<div class="text-sm shrink-0"> Filter by path of </div>
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind}>
|
||||
<ToggleButton small value="trigger" label="NATS trigger" icon={NatsIcon} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} />
|
||||
</ToggleButtonGroup>
|
||||
{#if isCloudHosted()}
|
||||
<Alert title="Not compatible with multi-tenant cloud" type="warning">
|
||||
NATS triggers are disabled in the multi-tenant cloud.
|
||||
</Alert>
|
||||
<div class="py-4" />
|
||||
{/if}
|
||||
<div class="w-full h-full flex flex-col">
|
||||
<div class="w-full pb-4 pt-6">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search NATS triggers"
|
||||
bind:value={filter}
|
||||
class="search-item"
|
||||
/>
|
||||
<div class="flex flex-row items-center gap-2 mt-6">
|
||||
<div class="text-sm shrink-0"> Filter by path of </div>
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind} let:item>
|
||||
<ToggleButton small value="trigger" label="NATS trigger" icon={NatsIcon} {item} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<ListFilters syncQuery bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
|
||||
<div class="flex flex-row items-center justify-end gap-4">
|
||||
{#if $userStore?.is_super_admin && $userStore.username.includes('@')}
|
||||
<Toggle size="xs" bind:checked={filterUserFolders} options={{ right: 'Only f/*' }} />
|
||||
{:else if $userStore?.is_admin || $userStore?.is_super_admin}
|
||||
<Toggle
|
||||
size="xs"
|
||||
bind:checked={filterUserFolders}
|
||||
options={{ right: `Only u/${$userStore.username} and f/*` }}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<ListFilters syncQuery bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
{#if loading}
|
||||
{#each new Array(6) as _}
|
||||
<Skeleton layout={[[6], 0.4]} />
|
||||
{/each}
|
||||
{:else if !triggers?.length}
|
||||
<div class="text-center text-sm text-tertiary mt-2"> No NATS triggers </div>
|
||||
{:else if items?.length}
|
||||
<div class="border rounded-md divide-y">
|
||||
{#each items.slice(0, nbDisplayed) as { path, edited_by, edited_at, script_path, is_flow, nats_resource_path, subjects, extra_perms, canWrite, marked, server_id, error, last_server_ping, enabled } (path)}
|
||||
{@const href = `${is_flow ? '/flows/get' : '/scripts/get'}/${script_path}`}
|
||||
{@const ping = last_server_ping ? new Date(last_server_ping) : undefined}
|
||||
{@const pinging = ping && ping.getTime() > new Date().getTime() - 15 * 1000}
|
||||
|
||||
<div class="flex flex-row items-center justify-end gap-4">
|
||||
{#if $userStore?.is_super_admin && $userStore.username.includes('@')}
|
||||
<Toggle size="xs" bind:checked={filterUserFolders} options={{ right: 'Only f/*' }} />
|
||||
{:else if $userStore?.is_admin || $userStore?.is_super_admin}
|
||||
<Toggle
|
||||
size="xs"
|
||||
bind:checked={filterUserFolders}
|
||||
options={{ right: `Only u/${$userStore.username} and f/*` }}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if loading}
|
||||
{#each new Array(6) as _}
|
||||
<Skeleton layout={[[6], 0.4]} />
|
||||
{/each}
|
||||
{:else if !triggers?.length}
|
||||
<div class="text-center text-sm text-tertiary mt-2"> No NATS triggers </div>
|
||||
{:else if items?.length}
|
||||
<div class="border rounded-md divide-y">
|
||||
{#each items.slice(0, nbDisplayed) as { path, edited_by, edited_at, script_path, is_flow, nats_resource_path, subjects, extra_perms, canWrite, marked, server_id, error, last_server_ping, enabled } (path)}
|
||||
{@const href = `${is_flow ? '/flows/get' : '/scripts/get'}/${script_path}`}
|
||||
{@const ping = last_server_ping ? new Date(last_server_ping) : undefined}
|
||||
{@const pinging = ping && ping.getTime() > new Date().getTime() - 15 * 1000}
|
||||
|
||||
<div
|
||||
class="hover:bg-surface-hover w-full items-center px-4 py-2 gap-4 first-of-type:!border-t-0
|
||||
<div
|
||||
class="hover:bg-surface-hover w-full items-center px-4 py-2 gap-4 first-of-type:!border-t-0
|
||||
first-of-type:rounded-t-md last-of-type:rounded-b-md flex flex-col"
|
||||
>
|
||||
<div class="w-full flex gap-5 items-center">
|
||||
<RowIcon kind={is_flow ? 'flow' : 'script'} />
|
||||
>
|
||||
<div class="w-full flex gap-5 items-center">
|
||||
<RowIcon kind={is_flow ? 'flow' : 'script'} />
|
||||
|
||||
<a
|
||||
href="#{path}"
|
||||
on:click={() => natsTriggerEditor?.openEdit(path, is_flow)}
|
||||
class="min-w-0 grow hover:underline decoration-gray-400"
|
||||
>
|
||||
<div class="text-primary flex-wrap text-left text-md font-semibold mb-1 truncate">
|
||||
{#if marked}
|
||||
<span class="text-xs">
|
||||
{@html marked}
|
||||
</span>
|
||||
{:else}
|
||||
{nats_resource_path} - {subjects.join(', ')}
|
||||
<a
|
||||
href="#{path}"
|
||||
on:click={() => natsTriggerEditor?.openEdit(path, is_flow)}
|
||||
class="min-w-0 grow hover:underline decoration-gray-400"
|
||||
>
|
||||
<div class="text-primary flex-wrap text-left text-md font-semibold mb-1 truncate">
|
||||
{#if marked}
|
||||
<span class="text-xs">
|
||||
{@html marked}
|
||||
</span>
|
||||
{:else}
|
||||
{nats_resource_path} - {subjects.join(', ')}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-secondary text-xs truncate text-left font-light">
|
||||
{path}
|
||||
</div>
|
||||
<div class="text-secondary text-xs truncate text-left font-light">
|
||||
runnable: {script_path}
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="hidden lg:flex flex-row gap-1 items-center">
|
||||
<SharedBadge {canWrite} extraPerms={extra_perms} />
|
||||
</div>
|
||||
|
||||
<div class="w-10">
|
||||
{#if (enabled && (!pinging || error)) || (!enabled && error) || (enabled && !server_id)}
|
||||
<Popover notClickable>
|
||||
<span class="flex h-4 w-4">
|
||||
<Circle
|
||||
class="text-red-600 animate-ping absolute inline-flex fill-current"
|
||||
size={12}
|
||||
/>
|
||||
<Circle class="text-red-600 relative inline-flex fill-current" size={12} />
|
||||
</span>
|
||||
<div slot="text">
|
||||
{#if enabled}
|
||||
{#if !server_id}
|
||||
Consumer is starting...
|
||||
{:else}
|
||||
Consumer is not connected{error ? ': ' + error : ''}
|
||||
{/if}
|
||||
{:else}
|
||||
Consumer was disabled because of an error: {error}
|
||||
{/if}
|
||||
</div>
|
||||
</Popover>
|
||||
{:else if enabled}
|
||||
<Popover notClickable>
|
||||
<span class="flex h-4 w-4">
|
||||
<Circle
|
||||
class="text-green-600 relative inline-flex fill-current"
|
||||
size={12}
|
||||
/>
|
||||
</span>
|
||||
<div slot="text"> Consumer is connected </div>
|
||||
</Popover>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-secondary text-xs truncate text-left font-light">
|
||||
{path}
|
||||
</div>
|
||||
<div class="text-secondary text-xs truncate text-left font-light">
|
||||
runnable: {script_path}
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="hidden lg:flex flex-row gap-1 items-center">
|
||||
<SharedBadge {canWrite} extraPerms={extra_perms} />
|
||||
</div>
|
||||
|
||||
<div class="w-10">
|
||||
{#if (enabled && (!pinging || error)) || (!enabled && error) || (enabled && !server_id)}
|
||||
<Popover notClickable>
|
||||
<span class="flex h-4 w-4">
|
||||
<Circle
|
||||
class="text-red-600 animate-ping absolute inline-flex fill-current"
|
||||
size={12}
|
||||
/>
|
||||
<Circle class="text-red-600 relative inline-flex fill-current" size={12} />
|
||||
</span>
|
||||
<div slot="text">
|
||||
{#if enabled}
|
||||
{#if !server_id}
|
||||
Consumer is starting...
|
||||
{:else}
|
||||
Consumer is not connected{error ? ': ' + error : ''}
|
||||
{/if}
|
||||
{:else}
|
||||
Consumer was disabled because of an error: {error}
|
||||
{/if}
|
||||
</div>
|
||||
</Popover>
|
||||
{:else if enabled}
|
||||
<Popover notClickable>
|
||||
<span class="flex h-4 w-4">
|
||||
<Circle class="text-green-600 relative inline-flex fill-current" size={12} />
|
||||
</span>
|
||||
<div slot="text"> Consumer is connected </div>
|
||||
</Popover>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<Toggle
|
||||
checked={enabled}
|
||||
disabled={!canWrite}
|
||||
on:change={(e) => {
|
||||
setTriggerEnabled(path, e.detail)
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class="flex gap-2 items-center justify-end">
|
||||
<Button
|
||||
on:click={() => natsTriggerEditor?.openEdit(path, is_flow)}
|
||||
size="xs"
|
||||
startIcon={canWrite
|
||||
? { icon: Pen }
|
||||
: {
|
||||
icon: Eye
|
||||
}}
|
||||
color="dark"
|
||||
>
|
||||
{canWrite ? 'Edit' : 'View'}
|
||||
</Button>
|
||||
<Dropdown
|
||||
items={[
|
||||
{
|
||||
displayName: `View ${is_flow ? 'Flow' : 'Script'}`,
|
||||
icon: Eye,
|
||||
action: () => {
|
||||
goto(href)
|
||||
}
|
||||
},
|
||||
{
|
||||
displayName: 'Delete',
|
||||
type: 'delete',
|
||||
icon: Trash,
|
||||
disabled: !canWrite,
|
||||
action: async () => {
|
||||
await NatsTriggerService.deleteNatsTrigger({
|
||||
workspace: $workspaceStore ?? '',
|
||||
path
|
||||
})
|
||||
loadTriggers()
|
||||
}
|
||||
},
|
||||
{
|
||||
displayName: canWrite ? 'Edit' : 'View',
|
||||
icon: canWrite ? Pen : Eye,
|
||||
action: () => {
|
||||
natsTriggerEditor?.openEdit(path, is_flow)
|
||||
}
|
||||
},
|
||||
{
|
||||
displayName: 'Audit logs',
|
||||
icon: Eye,
|
||||
href: `${base}/audit_logs?resource=${path}`
|
||||
},
|
||||
{
|
||||
displayName: canWrite ? 'Share' : 'See Permissions',
|
||||
icon: Share,
|
||||
action: () => {
|
||||
shareModal.openDrawer(path, 'nats_trigger')
|
||||
}
|
||||
}
|
||||
]}
|
||||
<Toggle
|
||||
checked={enabled}
|
||||
disabled={!canWrite}
|
||||
on:change={(e) => {
|
||||
setTriggerEnabled(path, e.detail)
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class="flex gap-2 items-center justify-end">
|
||||
<Button
|
||||
on:click={() => natsTriggerEditor?.openEdit(path, is_flow)}
|
||||
size="xs"
|
||||
startIcon={canWrite
|
||||
? { icon: Pen }
|
||||
: {
|
||||
icon: Eye
|
||||
}}
|
||||
color="dark"
|
||||
>
|
||||
{canWrite ? 'Edit' : 'View'}
|
||||
</Button>
|
||||
<Dropdown
|
||||
items={[
|
||||
{
|
||||
displayName: `View ${is_flow ? 'Flow' : 'Script'}`,
|
||||
icon: Eye,
|
||||
action: () => {
|
||||
goto(href)
|
||||
}
|
||||
},
|
||||
{
|
||||
displayName: 'Delete',
|
||||
type: 'delete',
|
||||
icon: Trash,
|
||||
disabled: !canWrite,
|
||||
action: async () => {
|
||||
await NatsTriggerService.deleteNatsTrigger({
|
||||
workspace: $workspaceStore ?? '',
|
||||
path
|
||||
})
|
||||
loadTriggers()
|
||||
}
|
||||
},
|
||||
{
|
||||
displayName: canWrite ? 'Edit' : 'View',
|
||||
icon: canWrite ? Pen : Eye,
|
||||
action: () => {
|
||||
natsTriggerEditor?.openEdit(path, is_flow)
|
||||
}
|
||||
},
|
||||
{
|
||||
displayName: 'Audit logs',
|
||||
icon: Eye,
|
||||
href: `${base}/audit_logs?resource=${path}`
|
||||
},
|
||||
{
|
||||
displayName: canWrite ? 'Share' : 'See Permissions',
|
||||
icon: Share,
|
||||
action: () => {
|
||||
shareModal.openDrawer(path, 'nats_trigger')
|
||||
}
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full flex justify-between items-baseline">
|
||||
<div
|
||||
class="flex flex-wrap text-[0.7em] text-tertiary gap-1 items-center justify-end truncate pr-2"
|
||||
><div class="truncate">edited by {edited_by}</div><div class="truncate"
|
||||
>the {displayDate(edited_at)}</div
|
||||
<div class="w-full flex justify-between items-baseline">
|
||||
<div
|
||||
class="flex flex-wrap text-[0.7em] text-tertiary gap-1 items-center justify-end truncate pr-2"
|
||||
><div class="truncate">edited by {edited_by}</div><div class="truncate"
|
||||
>the {displayDate(edited_at)}</div
|
||||
></div
|
||||
></div
|
||||
></div
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<NoItemFound />
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<NoItemFound />
|
||||
{/if}
|
||||
</div>
|
||||
{#if items && items?.length > 15 && nbDisplayed < items.length}
|
||||
<span class="text-xs"
|
||||
>{nbDisplayed} items out of {items.length}
|
||||
<button class="ml-4" on:click={() => (nbDisplayed += 30)}>load 30 more</button></span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{#if items && items?.length > 15 && nbDisplayed < items.length}
|
||||
<span class="text-xs"
|
||||
>{nbDisplayed} items out of {items.length}
|
||||
<button class="ml-4" on:click={() => (nbDisplayed += 30)}>load 30 more</button></span
|
||||
>
|
||||
{/if}
|
||||
</CenteredPage>
|
||||
</CenteredPage>
|
||||
{/if}
|
||||
|
||||
<ShareModal
|
||||
|
||||
@@ -237,9 +237,9 @@
|
||||
/>
|
||||
<div class="flex flex-row items-center gap-2 mt-6">
|
||||
<div class="text-sm shrink-0"> Filter by path of </div>
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind}>
|
||||
<ToggleButton small value="trigger" label="Postgres trigger" icon={Database} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} />
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind} let:item>
|
||||
<ToggleButton small value="trigger" label="Postgres trigger" icon={Database} {item} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<ListFilters syncQuery bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
|
||||
@@ -183,9 +183,9 @@
|
||||
<input type="text" placeholder="Search routes" bind:value={filter} class="search-item" />
|
||||
<div class="flex flex-row items-center gap-2 mt-6">
|
||||
<div class="text-sm shrink-0"> Filter by path of </div>
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind}>
|
||||
<ToggleButton small value="trigger" label="Route" icon={Route} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} />
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind} let:item>
|
||||
<ToggleButton small value="trigger" label="Route" icon={Route} {item} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<ListFilters syncQuery bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
|
||||
@@ -710,13 +710,16 @@
|
||||
<div class="absolute right-0 -mt-6">
|
||||
<div class="flex flex-row justify-between items-center">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={graph}
|
||||
on:selected={() => {
|
||||
selected={graph}
|
||||
on:selected={({ detail }) => {
|
||||
graph = detail
|
||||
graphIsRunsChart = graph === 'RunChart'
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="RunChart" label="Duration" />
|
||||
<ToggleButton value="RunChart" label="Duration" {item} />
|
||||
<ToggleButton
|
||||
{item}
|
||||
value="ConcurrencyChart"
|
||||
label="Concurrency"
|
||||
icon={warnJobLimit ? AlertTriangle : undefined}
|
||||
@@ -1090,13 +1093,15 @@
|
||||
<div class="relative z-10">
|
||||
<div class="absolute right-2">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={graph}
|
||||
on:selected={() => {
|
||||
selected={graph}
|
||||
on:selected={({ detail }) => {
|
||||
graph = detail
|
||||
graphIsRunsChart = graph == 'RunChart'
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="RunChart" label="Duration" />
|
||||
<ToggleButton value="ConcurrencyChart" label="Concurrency" />
|
||||
<ToggleButton value="RunChart" label="Duration" {item} />
|
||||
<ToggleButton value="ConcurrencyChart" label="Concurrency" {item} />
|
||||
</ToggleButtonGroup>
|
||||
{#if !graphIsRunsChart}
|
||||
<DropdownV2
|
||||
|
||||
@@ -273,18 +273,18 @@
|
||||
<input type="text" placeholder="Search schedule" bind:value={filter} class="search-item" />
|
||||
<div class="flex flex-row items-center gap-2 mt-6">
|
||||
<div class="text-sm shrink-0"> Filter by path of </div>
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind}>
|
||||
<ToggleButton small value="schedule" label="Schedule" icon={Calendar} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} />
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind} let:item>
|
||||
<ToggleButton small value="schedule" label="Schedule" icon={Calendar} {item} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<ListFilters syncQuery bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
|
||||
<div class="flex flex-row items-center justify-end gap-4">
|
||||
<ToggleButtonGroup class="h-6 w-auto" bind:selected={filterEnabledDisabled}>
|
||||
<ToggleButton small value="all" label="All" />
|
||||
<ToggleButton small value="enabled" label="Enabled" />
|
||||
<ToggleButton small value="disabled" label="Disabled" />
|
||||
<ToggleButtonGroup class="h-6 w-auto" bind:selected={filterEnabledDisabled} let:item>
|
||||
<ToggleButton small value="all" label="All" {item} />
|
||||
<ToggleButton small value="enabled" label="Enabled" {item} />
|
||||
<ToggleButton small value="disabled" label="Disabled" {item} />
|
||||
</ToggleButtonGroup>
|
||||
{#if $userStore?.is_super_admin && $userStore.username.includes('@')}
|
||||
<Toggle size="xs" bind:checked={filterUserFolders} options={{ right: 'Only f/*' }} />
|
||||
|
||||
@@ -140,15 +140,15 @@
|
||||
(x) =>
|
||||
x.path.startsWith(ownerFilter + '/') &&
|
||||
filterItemsPathsBaseOnUserFilters(x, selectedFilterKind, filterUserFolders)
|
||||
)
|
||||
)
|
||||
: triggers?.filter(
|
||||
(x) =>
|
||||
x.script_path.startsWith(ownerFilter + '/') &&
|
||||
filterItemsPathsBaseOnUserFilters(x, selectedFilterKind, filterUserFolders)
|
||||
)
|
||||
)
|
||||
: triggers?.filter((x) =>
|
||||
filterItemsPathsBaseOnUserFilters(x, selectedFilterKind, filterUserFolders)
|
||||
)
|
||||
)
|
||||
|
||||
$: if ($workspaceStore) {
|
||||
ownerFilter = undefined
|
||||
@@ -158,10 +158,10 @@
|
||||
selectedFilterKind === 'trigger'
|
||||
? Array.from(
|
||||
new Set(filteredItems?.map((x) => x.path.split('/').slice(0, 2).join('/')) ?? [])
|
||||
).sort()
|
||||
).sort()
|
||||
: Array.from(
|
||||
new Set(filteredItems?.map((x) => x.script_path.split('/').slice(0, 2).join('/')) ?? [])
|
||||
).sort()
|
||||
).sort()
|
||||
|
||||
$: items = filter !== '' ? filteredItems : preFilteredItems
|
||||
|
||||
@@ -230,9 +230,9 @@
|
||||
/>
|
||||
<div class="flex flex-row items-center gap-2 mt-6">
|
||||
<div class="text-sm shrink-0"> Filter by path of </div>
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind}>
|
||||
<ToggleButton small value="trigger" label="SQS trigger" icon={Database} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} />
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind} let:item>
|
||||
<ToggleButton small value="trigger" label="SQS trigger" icon={Database} {item} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<ListFilters syncQuery bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
@@ -337,7 +337,7 @@
|
||||
? { icon: Pen }
|
||||
: {
|
||||
icon: Eye
|
||||
}}
|
||||
}}
|
||||
color="dark"
|
||||
>
|
||||
{canWrite ? 'Edit' : 'View'}
|
||||
|
||||
@@ -233,8 +233,8 @@
|
||||
{/if}
|
||||
</label>
|
||||
{/if}
|
||||
<label class="block pb-4">
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="block pb-4">
|
||||
<label for="ai-key" class="flex flex-col gap-1">
|
||||
<span class="text-secondary text-sm">
|
||||
AI key for Windmill AI
|
||||
<Tooltip>
|
||||
@@ -246,19 +246,22 @@
|
||||
</Tooltip>
|
||||
<span class="text-2xs text-tertiary ml-2">(optional but recommended)</span>
|
||||
</span>
|
||||
|
||||
<div class="pb-2">
|
||||
<ToggleButtonGroup bind:selected>
|
||||
<ToggleButton value="openai" label="OpenAI" />
|
||||
<ToggleButton value="anthropic" label="Anthropic" />
|
||||
<ToggleButton value="mistral" label="Mistral" />
|
||||
<ToggleButton value="deepseek" label="DeepSeek" />
|
||||
<ToggleButton value="groq" label="Groq" />
|
||||
<ToggleButton value="openrouter" label="OpenRouter" />
|
||||
<ToggleButtonGroup bind:selected let:item>
|
||||
<ToggleButton value="openai" label="OpenAI" {item} />
|
||||
<ToggleButton value="anthropic" label="Anthropic" {item} />
|
||||
<ToggleButton value="mistral" label="Mistral" {item} />
|
||||
<ToggleButton value="deepseek" label="DeepSeek" {item} />
|
||||
<ToggleButton value="groq" label="Groq" {item} />
|
||||
<ToggleButton value="openrouter" label="OpenRouter" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div class="flex flex-row gap-1 pb-4">
|
||||
<input
|
||||
id="ai-key"
|
||||
type="password"
|
||||
autocomplete="new-password"
|
||||
bind:value={aiKey}
|
||||
@@ -278,7 +281,7 @@
|
||||
options={{ right: 'Enable code completion' }}
|
||||
/>
|
||||
{/if}
|
||||
</label>
|
||||
</div>
|
||||
<Toggle
|
||||
disabled={isCloudHosted() && !isDomainAllowed}
|
||||
bind:checked={auto_invite}
|
||||
@@ -304,9 +307,10 @@
|
||||
on:selected={(e) => {
|
||||
operatorOnly = e.detail == 'operator'
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="operator" size="xs" label="Operator" />
|
||||
<ToggleButton value="developer" size="xs" label="Developer" />
|
||||
<ToggleButton value="operator" size="xs" label="Operator" {item} />
|
||||
<ToggleButton value="developer" size="xs" label="Developer" {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<div class="flex flex-wrap flex-row justify-between pt-10 gap-1">
|
||||
|
||||
@@ -232,9 +232,9 @@
|
||||
<input type="text" placeholder="Search WS triggers" bind:value={filter} class="search-item" />
|
||||
<div class="flex flex-row items-center gap-2 mt-6">
|
||||
<div class="text-sm shrink-0"> Filter by path of </div>
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind}>
|
||||
<ToggleButton small value="trigger" label="WS trigger" icon={Unplug} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} />
|
||||
<ToggleButtonGroup bind:selected={selectedFilterKind} let:item>
|
||||
<ToggleButton small value="trigger" label="WS trigger" icon={Unplug} {item} />
|
||||
<ToggleButton small value="script_flow" label="Script/Flow" icon={Code} {item} />
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<ListFilters syncQuery bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
|
||||
@@ -1069,20 +1069,22 @@
|
||||
aiModels = []
|
||||
codeCompletionModel = undefined
|
||||
}}
|
||||
let:item
|
||||
>
|
||||
<ToggleButton value="openai" label="OpenAI" />
|
||||
<ToggleButton value="anthropic" label="Anthropic" />
|
||||
<ToggleButton value="mistral" label="Mistral" />
|
||||
<ToggleButton value="deepseek" label="DeepSeek" />
|
||||
<ToggleButton value="googleai" label="Google AI" />
|
||||
<ToggleButton value="groq" label="Groq" />
|
||||
<ToggleButton value="openrouter" label="OpenRouter" />
|
||||
<ToggleButton value="openai" label="OpenAI" {item} />
|
||||
<ToggleButton value="anthropic" label="Anthropic" {item} />
|
||||
<ToggleButton value="mistral" label="Mistral" {item} />
|
||||
<ToggleButton value="deepseek" label="DeepSeek" {item} />
|
||||
<ToggleButton value="googleai" label="Google AI" {item} />
|
||||
<ToggleButton value="groq" label="Groq" {item} />
|
||||
<ToggleButton value="openrouter" label="OpenRouter" {item} />
|
||||
<ToggleButton
|
||||
value="customai"
|
||||
label={'Custom AI' + ($enterpriseLicense ? '' : ' (EE)')}
|
||||
disabled={!$enterpriseLicense}
|
||||
tooltip="Configure a custom AI provider that is OpenAI API compatible"
|
||||
showTooltipIcon
|
||||
{item}
|
||||
/>
|
||||
</ToggleButtonGroup>
|
||||
<div class="flex gap-1">
|
||||
|
||||
Reference in New Issue
Block a user