windmill-components 1.36.0 → 1.36.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/common/button/Button.svelte +42 -79
- package/components/common/button/Button.svelte.d.ts +13 -16
- package/components/common/button/ButtonPopup.svelte +67 -0
- package/components/common/button/ButtonPopup.svelte.d.ts +33 -0
- package/components/common/button/ButtonPopupItem.svelte +47 -0
- package/components/common/button/ButtonPopupItem.svelte.d.ts +27 -0
- package/components/common/button/model.d.ts +14 -1
- package/components/common/button/model.js +26 -1
- package/components/common/drawer/Drawer.svelte +1 -0
- package/components/common/drawer/Drawer.svelte.d.ts +2 -0
- package/components/common/drawer/DrawerContent.svelte +1 -1
- package/components/common/index.d.ts +4 -0
- package/components/common/index.js +4 -0
- package/components/common/kbd/Kbd.svelte +7 -0
- package/components/common/kbd/Kbd.svelte.d.ts +27 -0
- package/components/common/popup/Popup.svelte +147 -0
- package/components/common/popup/Popup.svelte.d.ts +46 -0
- package/components/flows/content/FlowLoop.svelte +11 -11
- package/components/flows/content/FlowModuleHeader.svelte +2 -2
- package/components/flows/content/FlowSettings.svelte +13 -0
- package/components/flows/pickers/PickHubScript.svelte +1 -1
- package/components/flows/pickers/model.d.ts +5 -0
- package/components/flows/pickers/model.js +1 -0
- package/components/scripts/CreateActions.svelte +114 -0
- package/components/scripts/CreateActions.svelte.d.ts +14 -0
- package/gen/models/FlowValue.d.ts +1 -0
- package/package.json +8 -1
- package/stateMachine.d.ts +30 -0
- package/stateMachine.js +41 -0
- package/utils.d.ts +3 -1
- package/utils.js +1 -2
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script>import { createEventDispatcher } from 'svelte';
|
|
2
|
+
import { goto } from '$app/navigation';
|
|
2
3
|
import { classNames } from '../../../utils';
|
|
3
4
|
import Icon from 'svelte-awesome';
|
|
5
|
+
import { ButtonType } from './model';
|
|
4
6
|
export let size = 'md';
|
|
5
7
|
export let spacingSize = size;
|
|
6
8
|
export let color = 'blue';
|
|
@@ -10,101 +12,62 @@ export let disabled = false;
|
|
|
10
12
|
export let href = undefined;
|
|
11
13
|
export let target = '_self';
|
|
12
14
|
export let iconOnly = false;
|
|
13
|
-
export let id = '';
|
|
14
15
|
export let startIcon = undefined;
|
|
15
16
|
export let endIcon = undefined;
|
|
17
|
+
export let element = undefined;
|
|
18
|
+
export let id = '';
|
|
19
|
+
const dispatch = createEventDispatcher();
|
|
16
20
|
// Order of classes: border, border modifier, bg, bg modifier, text, text modifier, everything else
|
|
17
21
|
const colorVariants = {
|
|
18
22
|
blue: {
|
|
19
|
-
border: 'border-blue-500 hover:border-blue-700 bg-white hover:bg-blue-100 text-blue-500 hover:text-blue-700 focus:ring-blue-300',
|
|
20
|
-
contained: 'bg-blue-500 hover:bg-blue-700 text-white focus:ring-blue-300'
|
|
23
|
+
border: 'border-blue-500 hover:border-blue-700 focus:border-blue-700 bg-white hover:bg-blue-100 focus:bg-blue-100 text-blue-500 hover:text-blue-700 focus:text-blue-700 focus:ring-blue-300',
|
|
24
|
+
contained: 'bg-blue-500 hover:bg-blue-700 focus:bg-blue-700 text-white focus:ring-blue-300'
|
|
21
25
|
},
|
|
22
26
|
red: {
|
|
23
27
|
border: 'border-red-600 hover:border-red-700 bg-white hover:bg-red-100 text-red-600 hover:text-red-700 focus:ring-red-300',
|
|
24
28
|
contained: 'bg-red-600 hover:bg-red-700 text-white focus:ring-red-300'
|
|
25
29
|
},
|
|
26
30
|
dark: {
|
|
27
|
-
border: 'border-gray-800 hover:border-gray-900 bg-white hover:bg-gray-200 text-gray-800 hover:text-gray-900 focus:ring-gray-300',
|
|
28
|
-
contained: 'bg-gray-700 hover:bg-gray-900 text-white focus:ring-gray-300'
|
|
31
|
+
border: 'border-gray-800 hover:border-gray-900 focus:border-gray-900 bg-white hover:bg-gray-200 focus:bg-gray-200 text-gray-800 hover:text-gray-900 focus:text-gray-900 focus:ring-gray-300',
|
|
32
|
+
contained: 'bg-gray-700 hover:bg-gray-900 focus:bg-gray-900 text-white focus:ring-gray-300'
|
|
29
33
|
},
|
|
30
34
|
light: {
|
|
31
|
-
border: 'border bg-white hover:bg-gray-100 text-gray-700 hover:text-gray-800 focus:ring-gray-300',
|
|
32
|
-
contained: 'bg-white hover:bg-gray-100 text-gray-700 focus:ring-gray-300'
|
|
35
|
+
border: 'border bg-white hover:bg-gray-100 focus:bg-gray-100 text-gray-700 hover:text-gray-800 focus:text-gray-800 focus:ring-gray-300',
|
|
36
|
+
contained: 'bg-white hover:bg-gray-100 focus:bg-gray-100 text-gray-700 focus:ring-gray-300'
|
|
33
37
|
}
|
|
34
38
|
};
|
|
35
|
-
const fontSizeClasses = {
|
|
36
|
-
xs: 'text-xs',
|
|
37
|
-
sm: 'text-sm',
|
|
38
|
-
md: 'text-md',
|
|
39
|
-
lg: 'text-lg',
|
|
40
|
-
xl: 'text-xl'
|
|
41
|
-
};
|
|
42
|
-
const spacingClasses = {
|
|
43
|
-
xs: 'px-3 py-1.5',
|
|
44
|
-
sm: 'px-3 py-1.5',
|
|
45
|
-
md: 'px-4 py-2',
|
|
46
|
-
lg: 'px-4 py-2',
|
|
47
|
-
xl: 'px-4 py-2'
|
|
48
|
-
};
|
|
49
|
-
const iconScale = {
|
|
50
|
-
xs: 0.6,
|
|
51
|
-
sm: 0.8,
|
|
52
|
-
md: 1,
|
|
53
|
-
lg: 1.1,
|
|
54
|
-
xl: 1.2
|
|
55
|
-
};
|
|
56
39
|
$: buttonProps = {
|
|
57
|
-
class: classNames(colorVariants[color][variant], variant === 'border' ? 'border' : '',
|
|
58
|
-
disabled
|
|
40
|
+
class: classNames(colorVariants[color][variant], variant === 'border' ? 'border' : '', ButtonType.FontSizeClasses[size], ButtonType.SpacingClasses[spacingSize], 'focus:ring-4 font-medium', 'rounded-md', 'flex justify-center items-center text-center whitespace-nowrap', btnClasses, disabled ? 'pointer-events-none cursor-default filter grayscale' : ''),
|
|
41
|
+
disabled,
|
|
42
|
+
href,
|
|
43
|
+
target,
|
|
44
|
+
tabindex: disabled ? -1 : 0
|
|
59
45
|
};
|
|
46
|
+
function onClick(event) {
|
|
47
|
+
dispatch('click', event);
|
|
48
|
+
if (href)
|
|
49
|
+
goto(href);
|
|
50
|
+
}
|
|
60
51
|
$: isSmall = size === 'xs' || size === 'sm';
|
|
52
|
+
$: startIconClass = classNames(iconOnly ? undefined : isSmall ? 'mr-1' : 'mr-2', startIcon?.classes);
|
|
53
|
+
$: endIconClass = classNames(iconOnly ? undefined : isSmall ? 'ml-1' : 'ml-2', endIcon?.classes);
|
|
61
54
|
</script>
|
|
62
55
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
{
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
{/if}
|
|
82
|
-
{#if endIcon}
|
|
83
|
-
<Icon
|
|
84
|
-
data={endIcon.icon}
|
|
85
|
-
class={classNames(iconOnly ? undefined : 'ml-2', endIcon.classes)}
|
|
86
|
-
scale={iconScale[size]}
|
|
87
|
-
/>
|
|
88
|
-
{/if}
|
|
89
|
-
</button>
|
|
90
|
-
{:else}
|
|
91
|
-
<button {id} type="button" on:click|stopPropagation {...buttonProps} {...$$restProps}>
|
|
92
|
-
{#if startIcon}
|
|
93
|
-
<Icon
|
|
94
|
-
data={startIcon.icon}
|
|
95
|
-
class={classNames(iconOnly ? undefined : 'mr-2', startIcon.classes)}
|
|
96
|
-
scale={iconScale[size]}
|
|
97
|
-
/>
|
|
98
|
-
{/if}
|
|
99
|
-
{#if !iconOnly}
|
|
100
|
-
<slot />
|
|
101
|
-
{/if}
|
|
102
|
-
{#if endIcon}
|
|
103
|
-
<Icon
|
|
104
|
-
data={endIcon.icon}
|
|
105
|
-
class={classNames(iconOnly ? undefined : 'ml-2', endIcon.classes)}
|
|
106
|
-
scale={iconScale[size]}
|
|
107
|
-
/>
|
|
108
|
-
{/if}
|
|
109
|
-
</button>
|
|
110
|
-
{/if}
|
|
56
|
+
<svelte:element
|
|
57
|
+
this={href ? 'a' : 'button'}
|
|
58
|
+
bind:this={element}
|
|
59
|
+
on:click|stopPropagation={onClick}
|
|
60
|
+
on:focus
|
|
61
|
+
on:blur
|
|
62
|
+
{...buttonProps}
|
|
63
|
+
>
|
|
64
|
+
{#if startIcon}
|
|
65
|
+
<Icon data={startIcon.icon} class={startIconClass} scale={ButtonType.IconScale[size]} />
|
|
66
|
+
{/if}
|
|
67
|
+
{#if !iconOnly}
|
|
68
|
+
<slot />
|
|
69
|
+
{/if}
|
|
70
|
+
{#if endIcon}
|
|
71
|
+
<Icon data={endIcon.icon} class={endIconClass} scale={ButtonType.IconScale[size]} />
|
|
72
|
+
{/if}
|
|
73
|
+
</svelte:element>
|
|
@@ -1,29 +1,26 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
import
|
|
2
|
+
import Icon from 'svelte-awesome';
|
|
3
|
+
import { ButtonType } from './model';
|
|
3
4
|
declare const __propDef: {
|
|
4
5
|
props: {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
variant?: Button.Variant | undefined;
|
|
6
|
+
size?: ButtonType.Size | undefined;
|
|
7
|
+
spacingSize?: ButtonType.Size | undefined;
|
|
8
|
+
color?: ButtonType.Color | undefined;
|
|
9
|
+
variant?: ButtonType.Variant | undefined;
|
|
10
10
|
btnClasses?: string | undefined;
|
|
11
11
|
disabled?: boolean | undefined;
|
|
12
12
|
href?: string | undefined;
|
|
13
|
-
target?:
|
|
13
|
+
target?: ButtonType.Target | undefined;
|
|
14
14
|
iconOnly?: boolean | undefined;
|
|
15
|
+
startIcon?: ButtonType.Icon | undefined;
|
|
16
|
+
endIcon?: ButtonType.Icon | undefined;
|
|
17
|
+
element?: ButtonType.Element | undefined;
|
|
15
18
|
id?: string | undefined;
|
|
16
|
-
startIcon?: {
|
|
17
|
-
icon: any;
|
|
18
|
-
classes?: string;
|
|
19
|
-
} | undefined;
|
|
20
|
-
endIcon?: {
|
|
21
|
-
icon: any;
|
|
22
|
-
classes?: string;
|
|
23
|
-
} | undefined;
|
|
24
19
|
};
|
|
25
20
|
events: {
|
|
26
|
-
|
|
21
|
+
focus: FocusEvent;
|
|
22
|
+
blur: FocusEvent;
|
|
23
|
+
click: CustomEvent<any>;
|
|
27
24
|
} & {
|
|
28
25
|
[evt: string]: CustomEvent<any>;
|
|
29
26
|
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script>import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
|
|
2
|
+
import { setContext } from 'svelte';
|
|
3
|
+
import Icon from 'svelte-awesome';
|
|
4
|
+
import { Button, ButtonType, Popup } from '..';
|
|
5
|
+
export let size = 'md';
|
|
6
|
+
export let color = 'blue';
|
|
7
|
+
export let variant = 'contained';
|
|
8
|
+
export let mainClasses = '';
|
|
9
|
+
export let toggleClasses = '';
|
|
10
|
+
export let disabled = false;
|
|
11
|
+
export let href = undefined;
|
|
12
|
+
export let target = '_self';
|
|
13
|
+
export let startIcon = undefined;
|
|
14
|
+
export let endIcon = undefined;
|
|
15
|
+
let ref;
|
|
16
|
+
setContext(ButtonType.ItemContextKey, { size, color });
|
|
17
|
+
$: separator = color === 'red' || color === 'blue' ? 'border-gray-200' : 'border-gray-400';
|
|
18
|
+
$: commonProps = {
|
|
19
|
+
size,
|
|
20
|
+
color,
|
|
21
|
+
variant,
|
|
22
|
+
disabled
|
|
23
|
+
};
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<div class="flex justy-start items-center">
|
|
27
|
+
{#if $$slots.main}
|
|
28
|
+
<Button
|
|
29
|
+
{...commonProps}
|
|
30
|
+
{href}
|
|
31
|
+
{target}
|
|
32
|
+
{startIcon}
|
|
33
|
+
{endIcon}
|
|
34
|
+
btnClasses="!rounded-r-none !border-r-0 {mainClasses}"
|
|
35
|
+
on:click
|
|
36
|
+
>
|
|
37
|
+
<slot name="main" />
|
|
38
|
+
</Button>
|
|
39
|
+
{/if}
|
|
40
|
+
<span class={$$slots.main && variant === 'contained' ? 'border-l ' + separator : ''}>
|
|
41
|
+
<Button
|
|
42
|
+
bind:element={ref}
|
|
43
|
+
{...commonProps}
|
|
44
|
+
btnClasses="{$$slots.main ? '!rounded-l-none' : ''} {toggleClasses}"
|
|
45
|
+
>
|
|
46
|
+
<slot name="toggle">
|
|
47
|
+
<!-- Invisible, but needed to match the height of the 'main' button -->
|
|
48
|
+
<span class="!opacity-0 !w-0">A</span>
|
|
49
|
+
<Icon data={faChevronDown} scale={ButtonType.IconScale[size]} />
|
|
50
|
+
</slot>
|
|
51
|
+
</Button>
|
|
52
|
+
</span>
|
|
53
|
+
</div>
|
|
54
|
+
{#if ref}
|
|
55
|
+
<Popup
|
|
56
|
+
{ref}
|
|
57
|
+
options={{
|
|
58
|
+
placement: $$slots.main ? 'bottom-end' : 'bottom',
|
|
59
|
+
strategy: 'absolute',
|
|
60
|
+
modifiers: [{ name: 'offset', options: { offset: [0, 0] } }]
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
<ul class="bg-white rounded-t border pt-1 pb-2 max-h-40 overflow-auto">
|
|
64
|
+
<slot />
|
|
65
|
+
</ul>
|
|
66
|
+
</Popup>
|
|
67
|
+
{/if}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import Icon from 'svelte-awesome';
|
|
3
|
+
import { ButtonType } from '..';
|
|
4
|
+
declare const __propDef: {
|
|
5
|
+
props: {
|
|
6
|
+
size?: ButtonType.Size | undefined;
|
|
7
|
+
color?: ButtonType.Color | undefined;
|
|
8
|
+
variant?: ButtonType.Variant | undefined;
|
|
9
|
+
mainClasses?: string | undefined;
|
|
10
|
+
toggleClasses?: string | undefined;
|
|
11
|
+
disabled?: boolean | undefined;
|
|
12
|
+
href?: string | undefined;
|
|
13
|
+
target?: ButtonType.Target | undefined;
|
|
14
|
+
startIcon?: ButtonType.Icon | undefined;
|
|
15
|
+
endIcon?: ButtonType.Icon | undefined;
|
|
16
|
+
};
|
|
17
|
+
events: {
|
|
18
|
+
click: CustomEvent<any>;
|
|
19
|
+
} & {
|
|
20
|
+
[evt: string]: CustomEvent<any>;
|
|
21
|
+
};
|
|
22
|
+
slots: {
|
|
23
|
+
main: {};
|
|
24
|
+
toggle: {};
|
|
25
|
+
default: {};
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export declare type ButtonPopupProps = typeof __propDef.props;
|
|
29
|
+
export declare type ButtonPopupEvents = typeof __propDef.events;
|
|
30
|
+
export declare type ButtonPopupSlots = typeof __propDef.slots;
|
|
31
|
+
export default class ButtonPopup extends SvelteComponentTyped<ButtonPopupProps, ButtonPopupEvents, ButtonPopupSlots> {
|
|
32
|
+
}
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
|
+
import { Button, ButtonType } from '..';
|
|
3
|
+
import { classNames } from '../../../utils';
|
|
4
|
+
export let btnClasses = '';
|
|
5
|
+
export let disabled = false;
|
|
6
|
+
export let href = undefined;
|
|
7
|
+
export let target = '_self';
|
|
8
|
+
export let iconOnly = false;
|
|
9
|
+
export let startIcon = undefined;
|
|
10
|
+
export let endIcon = undefined;
|
|
11
|
+
const props = getContext(ButtonType.ItemContextKey);
|
|
12
|
+
const iconWidthClass = {
|
|
13
|
+
xs: '!w-[12px]',
|
|
14
|
+
sm: '!w-[14px]',
|
|
15
|
+
md: '!w-[16px]',
|
|
16
|
+
lg: '!w-[18px]',
|
|
17
|
+
xl: '!w-[20px]'
|
|
18
|
+
};
|
|
19
|
+
const getWidthClass = () => (props?.size ? iconWidthClass[props.size] : undefined);
|
|
20
|
+
$: buttonProps = {
|
|
21
|
+
...props,
|
|
22
|
+
variant: 'border',
|
|
23
|
+
btnClasses: classNames(btnClasses, '!justify-start !border-0 !rounded-none !w-full'),
|
|
24
|
+
disabled,
|
|
25
|
+
href,
|
|
26
|
+
target,
|
|
27
|
+
iconOnly,
|
|
28
|
+
startIcon: startIcon
|
|
29
|
+
? {
|
|
30
|
+
icon: startIcon.icon,
|
|
31
|
+
classes: classNames(startIcon?.classes, getWidthClass())
|
|
32
|
+
}
|
|
33
|
+
: undefined,
|
|
34
|
+
endIcon: endIcon
|
|
35
|
+
? {
|
|
36
|
+
icon: endIcon.icon,
|
|
37
|
+
classes: classNames(endIcon?.classes, getWidthClass())
|
|
38
|
+
}
|
|
39
|
+
: undefined
|
|
40
|
+
};
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<li class="mt-1">
|
|
44
|
+
<Button {...buttonProps} on:click>
|
|
45
|
+
<slot />
|
|
46
|
+
</Button>
|
|
47
|
+
</li>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import { ButtonType } from '..';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
btnClasses?: string | undefined;
|
|
6
|
+
disabled?: boolean | undefined;
|
|
7
|
+
href?: string | undefined;
|
|
8
|
+
target?: ButtonType.Target | undefined;
|
|
9
|
+
iconOnly?: boolean | undefined;
|
|
10
|
+
startIcon?: ButtonType.Icon | undefined;
|
|
11
|
+
endIcon?: ButtonType.Icon | undefined;
|
|
12
|
+
};
|
|
13
|
+
events: {
|
|
14
|
+
click: CustomEvent<any>;
|
|
15
|
+
} & {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
};
|
|
18
|
+
slots: {
|
|
19
|
+
default: {};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export declare type ButtonPopupItemProps = typeof __propDef.props;
|
|
23
|
+
export declare type ButtonPopupItemEvents = typeof __propDef.events;
|
|
24
|
+
export declare type ButtonPopupItemSlots = typeof __propDef.slots;
|
|
25
|
+
export default class ButtonPopupItem extends SvelteComponentTyped<ButtonPopupItemProps, ButtonPopupItemEvents, ButtonPopupItemSlots> {
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
export declare namespace
|
|
1
|
+
export declare namespace ButtonType {
|
|
2
2
|
type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
3
3
|
type Color = 'blue' | 'red' | 'dark' | 'light';
|
|
4
4
|
type Variant = 'contained' | 'border';
|
|
5
5
|
type Target = '_self' | '_blank';
|
|
6
|
+
type Element = HTMLButtonElement | HTMLAnchorElement;
|
|
7
|
+
interface Icon {
|
|
8
|
+
icon: any;
|
|
9
|
+
classes?: string;
|
|
10
|
+
}
|
|
11
|
+
const FontSizeClasses: Record<ButtonType.Size, string>;
|
|
12
|
+
const SpacingClasses: Record<ButtonType.Size, string>;
|
|
13
|
+
const IconScale: Record<ButtonType.Size, number>;
|
|
14
|
+
const ItemContextKey: "popupItemProps";
|
|
15
|
+
interface ItemProps {
|
|
16
|
+
size: Size;
|
|
17
|
+
color: Color;
|
|
18
|
+
}
|
|
6
19
|
}
|
|
@@ -1 +1,26 @@
|
|
|
1
|
-
export
|
|
1
|
+
export var ButtonType;
|
|
2
|
+
(function (ButtonType) {
|
|
3
|
+
ButtonType.FontSizeClasses = {
|
|
4
|
+
xs: 'text-xs',
|
|
5
|
+
sm: 'text-sm',
|
|
6
|
+
md: 'text-md',
|
|
7
|
+
lg: 'text-lg',
|
|
8
|
+
xl: 'text-xl'
|
|
9
|
+
};
|
|
10
|
+
ButtonType.SpacingClasses = {
|
|
11
|
+
xs: 'px-3 py-1.5',
|
|
12
|
+
sm: 'px-3 py-1.5',
|
|
13
|
+
md: 'px-4 py-2',
|
|
14
|
+
lg: 'px-4 py-2',
|
|
15
|
+
xl: 'px-4 py-2'
|
|
16
|
+
};
|
|
17
|
+
ButtonType.IconScale = {
|
|
18
|
+
xs: 0.7,
|
|
19
|
+
sm: 0.8,
|
|
20
|
+
md: 1,
|
|
21
|
+
lg: 1.1,
|
|
22
|
+
xl: 1.2
|
|
23
|
+
};
|
|
24
|
+
// ButtonPopup types
|
|
25
|
+
ButtonType.ItemContextKey = 'popupItemProps';
|
|
26
|
+
})(ButtonType || (ButtonType = {}));
|
|
@@ -5,7 +5,7 @@ export let title = undefined;
|
|
|
5
5
|
const dispatch = createEventDispatcher();
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
|
-
<div class="divide-y h-screen">
|
|
8
|
+
<div class="flex flex-col divide-y h-screen">
|
|
9
9
|
<div class="flex justify-between items-center py-2 px-4">
|
|
10
10
|
<span class="text-sm font-bold">{title}</span>
|
|
11
11
|
<button on:click={() => dispatch('close')}>
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
export { default as ActionRow } from './actionRow/ActionRow.svelte';
|
|
2
2
|
export { default as Badge } from './badge/Badge.svelte';
|
|
3
3
|
export { default as Button } from './button/Button.svelte';
|
|
4
|
+
export { default as ButtonPopup } from './button/ButtonPopup.svelte';
|
|
5
|
+
export { default as ButtonPopupItem } from './button/ButtonPopupItem.svelte';
|
|
4
6
|
export { default as Drawer } from './drawer/Drawer.svelte';
|
|
5
7
|
export { default as DrawerContent } from './drawer/DrawerContent.svelte';
|
|
8
|
+
export { default as Kbd } from './kbd/Kbd.svelte';
|
|
6
9
|
export { default as Menu } from './menu/Menu.svelte';
|
|
7
10
|
export { default as MenuItem } from './menu/MenuItem.svelte';
|
|
11
|
+
export { default as Popup } from './popup/Popup.svelte';
|
|
8
12
|
export { default as Tab } from './tabs/Tab.svelte';
|
|
9
13
|
export { default as TabContent } from './tabs/TabContent.svelte';
|
|
10
14
|
export { default as Tabs } from './tabs/Tabs.svelte';
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
export { default as ActionRow } from './actionRow/ActionRow.svelte';
|
|
2
2
|
export { default as Badge } from './badge/Badge.svelte';
|
|
3
3
|
export { default as Button } from './button/Button.svelte';
|
|
4
|
+
export { default as ButtonPopup } from './button/ButtonPopup.svelte';
|
|
5
|
+
export { default as ButtonPopupItem } from './button/ButtonPopupItem.svelte';
|
|
4
6
|
export { default as Drawer } from './drawer/Drawer.svelte';
|
|
5
7
|
export { default as DrawerContent } from './drawer/DrawerContent.svelte';
|
|
8
|
+
export { default as Kbd } from './kbd/Kbd.svelte';
|
|
6
9
|
export { default as Menu } from './menu/Menu.svelte';
|
|
7
10
|
export { default as MenuItem } from './menu/MenuItem.svelte';
|
|
11
|
+
export { default as Popup } from './popup/Popup.svelte';
|
|
8
12
|
export { default as Tab } from './tabs/Tab.svelte';
|
|
9
13
|
export { default as TabContent } from './tabs/TabContent.svelte';
|
|
10
14
|
export { default as Tabs } from './tabs/Tabs.svelte';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} KbdProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} KbdEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} KbdSlots */
|
|
4
|
+
export default class Kbd extends SvelteComponentTyped<{
|
|
5
|
+
[x: string]: any;
|
|
6
|
+
}, {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
}, {
|
|
9
|
+
default: {};
|
|
10
|
+
}> {
|
|
11
|
+
}
|
|
12
|
+
export type KbdProps = typeof __propDef.props;
|
|
13
|
+
export type KbdEvents = typeof __propDef.events;
|
|
14
|
+
export type KbdSlots = typeof __propDef.slots;
|
|
15
|
+
import { SvelteComponentTyped } from "svelte";
|
|
16
|
+
declare const __propDef: {
|
|
17
|
+
props: {
|
|
18
|
+
[x: string]: any;
|
|
19
|
+
};
|
|
20
|
+
events: {
|
|
21
|
+
[evt: string]: CustomEvent<any>;
|
|
22
|
+
};
|
|
23
|
+
slots: {
|
|
24
|
+
default: {};
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
<svelte:options accessors />
|
|
2
|
+
|
|
3
|
+
<script>import { onMount, onDestroy } from 'svelte';
|
|
4
|
+
import { slide } from 'svelte/transition';
|
|
5
|
+
import { createPopperActions } from 'svelte-popperjs';
|
|
6
|
+
import { clickOutside } from '../../../utils';
|
|
7
|
+
import { Kbd } from '..';
|
|
8
|
+
import { createStateMachine } from '../../../stateMachine';
|
|
9
|
+
export let ref;
|
|
10
|
+
export let options = { placement: 'auto' };
|
|
11
|
+
/** Events on the reference element */
|
|
12
|
+
export let openOn = ['focus'];
|
|
13
|
+
/** Events on the reference element */
|
|
14
|
+
export let closeOn = ['blur'];
|
|
15
|
+
export let disableInstruction = false;
|
|
16
|
+
export let innerClasses = '';
|
|
17
|
+
export let outerClasses = '';
|
|
18
|
+
const states = ['closed', 'open-focus-in', 'open-focus-out'];
|
|
19
|
+
const stateMachine = createStateMachine(states, {
|
|
20
|
+
to: {
|
|
21
|
+
closed: ({ previousState, currentState }) => {
|
|
22
|
+
const activeElem = document.activeElement;
|
|
23
|
+
const revert = popup.contains(activeElem) || ref.contains(activeElem);
|
|
24
|
+
return revert ? previousState : currentState;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
const [popperRef, popperContent] = createPopperActions();
|
|
29
|
+
let popup;
|
|
30
|
+
let focusableElements;
|
|
31
|
+
function getFocusableElements() {
|
|
32
|
+
let elements = [];
|
|
33
|
+
popup
|
|
34
|
+
.querySelectorAll('a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])')
|
|
35
|
+
.forEach((elem) => elements.push(elem));
|
|
36
|
+
focusableElements = elements.filter((el) => !el.hasAttribute('disabled') && !el.getAttribute('aria-hidden'));
|
|
37
|
+
focusableElements.forEach((el) => {
|
|
38
|
+
el.tabIndex = -1;
|
|
39
|
+
el.addEventListener('click', openFocusIn);
|
|
40
|
+
el.addEventListener('blur', closed);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function closed() {
|
|
44
|
+
if ($stateMachine.currentState === 'open-focus-out') {
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
stateMachine.setState('closed');
|
|
47
|
+
}, 0);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
stateMachine.setState('closed');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function openFocusOut() {
|
|
54
|
+
stateMachine.setState('open-focus-out');
|
|
55
|
+
}
|
|
56
|
+
function openFocusIn() {
|
|
57
|
+
stateMachine.setState('open-focus-in');
|
|
58
|
+
}
|
|
59
|
+
function keyDown(event) {
|
|
60
|
+
const modifiers = ['Shift', 'Control', 'Command', 'Alt'];
|
|
61
|
+
// Prevent closing the popup when the only key pressed is a modifier key
|
|
62
|
+
if (modifiers.includes(event.key) || $stateMachine.currentState === 'closed')
|
|
63
|
+
return;
|
|
64
|
+
if (event.key === 'Escape') {
|
|
65
|
+
return document.activeElement?.blur();
|
|
66
|
+
}
|
|
67
|
+
if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown')
|
|
68
|
+
return;
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
if (popup.contains(document.activeElement)) {
|
|
71
|
+
const index = focusableElements.findIndex((elem) => elem === document.activeElement);
|
|
72
|
+
if (index === -1)
|
|
73
|
+
return;
|
|
74
|
+
let targetIndex = undefined;
|
|
75
|
+
if (event.key === 'ArrowUp') {
|
|
76
|
+
targetIndex = index === 0 ? focusableElements.length - 1 : index - 1;
|
|
77
|
+
}
|
|
78
|
+
else if (event.key === 'ArrowDown') {
|
|
79
|
+
targetIndex = index + 1 === focusableElements.length ? 0 : index + 1;
|
|
80
|
+
}
|
|
81
|
+
if (targetIndex !== undefined) {
|
|
82
|
+
focusableElements[targetIndex].focus();
|
|
83
|
+
stateMachine.setState('open-focus-in');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const elem = focusableElements[event.key === 'ArrowUp' ? focusableElements.length - 1 : 0];
|
|
88
|
+
if (elem) {
|
|
89
|
+
elem.focus();
|
|
90
|
+
stateMachine.setState('open-focus-in');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function addRefListeners() {
|
|
95
|
+
openOn.forEach((action) => ref.addEventListener(action, openFocusOut));
|
|
96
|
+
closeOn.forEach((action) => ref.addEventListener(action, closed));
|
|
97
|
+
}
|
|
98
|
+
function removeAllListeners() {
|
|
99
|
+
focusableElements?.forEach((el) => el.removeEventListener('click', openFocusIn));
|
|
100
|
+
focusableElements?.forEach((el) => el.removeEventListener('blur', closed));
|
|
101
|
+
openOn.forEach((action) => ref.removeEventListener(action, openFocusOut));
|
|
102
|
+
closeOn.forEach((action) => ref.removeEventListener(action, closed));
|
|
103
|
+
}
|
|
104
|
+
$: if ($stateMachine.currentState === 'closed') {
|
|
105
|
+
focusableElements?.forEach((el) => el.removeEventListener('click', openFocusIn));
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
setTimeout(() => {
|
|
109
|
+
getFocusableElements();
|
|
110
|
+
}, 0);
|
|
111
|
+
}
|
|
112
|
+
onMount(() => {
|
|
113
|
+
popperRef(ref);
|
|
114
|
+
addRefListeners();
|
|
115
|
+
});
|
|
116
|
+
onDestroy(removeAllListeners);
|
|
117
|
+
</script>
|
|
118
|
+
|
|
119
|
+
<svelte:window on:keydown={keyDown} />
|
|
120
|
+
|
|
121
|
+
<div
|
|
122
|
+
bind:this={popup}
|
|
123
|
+
use:popperContent={options}
|
|
124
|
+
use:clickOutside
|
|
125
|
+
on:click_outside={closed}
|
|
126
|
+
aria-haspopup="true"
|
|
127
|
+
aria-expanded={$stateMachine.currentState !== 'closed'}
|
|
128
|
+
>
|
|
129
|
+
{#if $stateMachine.currentState !== 'closed'}
|
|
130
|
+
<div transition:slide={{ duration: 200 }} class={outerClasses}>
|
|
131
|
+
<div class={innerClasses}>
|
|
132
|
+
<slot />
|
|
133
|
+
</div>
|
|
134
|
+
{#if !disableInstruction && focusableElements?.length}
|
|
135
|
+
<div
|
|
136
|
+
class="flex justify-center items-center font-semibold
|
|
137
|
+
text-xs text-gray-700 p-1 border-x border-b rounded-b bg-gray-100"
|
|
138
|
+
>
|
|
139
|
+
Use
|
|
140
|
+
<Kbd class="!bg-gray-200 !border-gray-300 !px-1 !py-0 !rounded-sm">↑</Kbd>
|
|
141
|
+
and
|
|
142
|
+
<Kbd class="!bg-gray-200 !border-gray-300 !px-1 !py-0 !rounded-sm">↓</Kbd>
|
|
143
|
+
</div>
|
|
144
|
+
{/if}
|
|
145
|
+
</div>
|
|
146
|
+
{/if}
|
|
147
|
+
</div>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import { type PopperOptions } from 'svelte-popperjs';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
ref: HTMLElement;
|
|
6
|
+
options?: PopperOptions<any>;
|
|
7
|
+
/** Events on the reference element */ openOn?: (keyof HTMLElementEventMap)[] | undefined;
|
|
8
|
+
/** Events on the reference element */ closeOn?: (keyof HTMLElementEventMap)[] | undefined;
|
|
9
|
+
disableInstruction?: boolean | undefined;
|
|
10
|
+
innerClasses?: string | undefined;
|
|
11
|
+
outerClasses?: string | undefined;
|
|
12
|
+
};
|
|
13
|
+
events: {
|
|
14
|
+
[evt: string]: CustomEvent<any>;
|
|
15
|
+
};
|
|
16
|
+
slots: {
|
|
17
|
+
default: {};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare type PopupProps = typeof __propDef.props;
|
|
21
|
+
export declare type PopupEvents = typeof __propDef.events;
|
|
22
|
+
export declare type PopupSlots = typeof __propDef.slots;
|
|
23
|
+
export default class Popup extends SvelteComponentTyped<PopupProps, PopupEvents, PopupSlots> {
|
|
24
|
+
get ref(): HTMLElement;
|
|
25
|
+
/**accessor*/
|
|
26
|
+
set ref(_: HTMLElement);
|
|
27
|
+
get options(): PopperOptions<any>;
|
|
28
|
+
/**accessor*/
|
|
29
|
+
set options(_: PopperOptions<any>);
|
|
30
|
+
get openOn(): (keyof HTMLElementEventMap)[] | undefined;
|
|
31
|
+
/**accessor*/
|
|
32
|
+
set openOn(_: (keyof HTMLElementEventMap)[] | undefined);
|
|
33
|
+
get closeOn(): (keyof HTMLElementEventMap)[] | undefined;
|
|
34
|
+
/**accessor*/
|
|
35
|
+
set closeOn(_: (keyof HTMLElementEventMap)[] | undefined);
|
|
36
|
+
get disableInstruction(): boolean | undefined;
|
|
37
|
+
/**accessor*/
|
|
38
|
+
set disableInstruction(_: boolean | undefined);
|
|
39
|
+
get innerClasses(): string | undefined;
|
|
40
|
+
/**accessor*/
|
|
41
|
+
set innerClasses(_: string | undefined);
|
|
42
|
+
get outerClasses(): string | undefined;
|
|
43
|
+
/**accessor*/
|
|
44
|
+
set outerClasses(_: string | undefined);
|
|
45
|
+
}
|
|
46
|
+
export {};
|
|
@@ -23,15 +23,15 @@ $: mod = $flowStore.value.modules[index];
|
|
|
23
23
|
$: pickableProperties = getStepPropPicker([Number(index)], $flowStore.schema, $flowStateStore, $previewArgs).pickableProperties;
|
|
24
24
|
</script>
|
|
25
25
|
|
|
26
|
-
<
|
|
27
|
-
<
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
<div class="h-full flex flex-col">
|
|
27
|
+
<FlowCard title="For loop">
|
|
28
|
+
<div slot="header" class="grow">
|
|
29
|
+
<input bind:value={mod.summary} placeholder={'Summary'} />
|
|
30
|
+
</div>
|
|
31
31
|
<div class="overflow-hidden flex-grow">
|
|
32
|
-
<VSplitPane topPanelSize="
|
|
33
|
-
<top slot="top">
|
|
34
|
-
<div class="p-6 flex flex-col">
|
|
32
|
+
<VSplitPane topPanelSize="60%" downPanelSize="40%" minTopPaneSize="20%" minDownPaneSize="20%">
|
|
33
|
+
<top slot="top" class="h-full">
|
|
34
|
+
<div class="p-6 flex flex-col h-full overflow-clip">
|
|
35
35
|
{#if mod.value.type === 'forloopflow'}
|
|
36
36
|
<span class="mb-2 text-sm font-bold"
|
|
37
37
|
>Iterator expression
|
|
@@ -163,6 +163,6 @@ $: pickableProperties = getStepPropPicker([Number(index)], $flowStore.schema, $f
|
|
|
163
163
|
</Tabs>
|
|
164
164
|
</down>
|
|
165
165
|
</VSplitPane>
|
|
166
|
-
</div
|
|
167
|
-
|
|
168
|
-
</
|
|
166
|
+
</div></FlowCard
|
|
167
|
+
>
|
|
168
|
+
</div>
|
|
@@ -67,8 +67,8 @@ $: moduleRetry = module.retry?.constant || module.retry?.exponential;
|
|
|
67
67
|
variant="border"
|
|
68
68
|
startIcon={{ icon: faTrashAlt }}
|
|
69
69
|
{iconOnly}
|
|
70
|
-
on:click={(
|
|
71
|
-
if (
|
|
70
|
+
on:click={({ detail }) => {
|
|
71
|
+
if (detail.shiftKey || shouldPick) {
|
|
72
72
|
dispatch('delete')
|
|
73
73
|
select('settings')
|
|
74
74
|
} else {
|
|
@@ -7,6 +7,7 @@ import Required from '../../Required.svelte';
|
|
|
7
7
|
import FlowCard from '../common/FlowCard.svelte';
|
|
8
8
|
import FlowSchedules from './FlowSchedules.svelte';
|
|
9
9
|
import SvelteMarkdown from 'svelte-markdown';
|
|
10
|
+
import { Toggle } from 'flowbite-svelte';
|
|
10
11
|
export let initialPath;
|
|
11
12
|
export let defaultTab = 'metadata';
|
|
12
13
|
</script>
|
|
@@ -15,6 +16,7 @@ export let defaultTab = 'metadata';
|
|
|
15
16
|
<Tabs selected={defaultTab}>
|
|
16
17
|
<Tab value="metadata">Metadata</Tab>
|
|
17
18
|
<Tab value="schedule">Schedule</Tab>
|
|
19
|
+
<Tab value="same-worker">Same Worker</Tab>
|
|
18
20
|
|
|
19
21
|
<svelte:fragment slot="content">
|
|
20
22
|
<TabContent value="metadata" class="p-4">
|
|
@@ -73,6 +75,17 @@ export let defaultTab = 'metadata';
|
|
|
73
75
|
<TabContent value="schedule" class="p-4">
|
|
74
76
|
<FlowSchedules />
|
|
75
77
|
</TabContent>
|
|
78
|
+
|
|
79
|
+
<TabContent value="same-worker" class="p-4">
|
|
80
|
+
<span class="my-2 text-sm font-bold">Same Worker</span>
|
|
81
|
+
|
|
82
|
+
<Toggle
|
|
83
|
+
bind:checked={$flowStore.value.same_worker}
|
|
84
|
+
options={{
|
|
85
|
+
right: 'Same Worker'
|
|
86
|
+
}}
|
|
87
|
+
/>
|
|
88
|
+
</TabContent>
|
|
76
89
|
</svelte:fragment>
|
|
77
90
|
</Tabs>
|
|
78
91
|
</FlowCard>
|
|
@@ -6,7 +6,7 @@ import { createEventDispatcher } from 'svelte';
|
|
|
6
6
|
import { Script } from '../../../gen';
|
|
7
7
|
export let kind;
|
|
8
8
|
let items;
|
|
9
|
-
$: items = $hubScripts?.filter((x) => x.kind == kind);
|
|
9
|
+
$: items = $hubScripts?.filter((x) => x.kind == kind) ?? [];
|
|
10
10
|
let itemPicker;
|
|
11
11
|
const dispatch = createEventDispatcher();
|
|
12
12
|
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<script>import { goto } from '$app/navigation';
|
|
2
|
+
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
|
3
|
+
import Fuse from 'fuse.js';
|
|
4
|
+
import { Script } from '../../gen';
|
|
5
|
+
import { ScriptService } from '../../gen';
|
|
6
|
+
import { workspaceStore, hubScripts } from '../../stores';
|
|
7
|
+
import { sendUserToast } from '../../utils';
|
|
8
|
+
import { Button, ButtonPopup, ButtonPopupItem } from '../common';
|
|
9
|
+
import ItemPicker from '../ItemPicker.svelte';
|
|
10
|
+
import Drawer from '../common/drawer/Drawer.svelte';
|
|
11
|
+
import DrawerContent from '../common/drawer/DrawerContent.svelte';
|
|
12
|
+
import SimpleEditor from '../SimpleEditor.svelte';
|
|
13
|
+
import { flowStore, initFlow } from '../flows/flowStore';
|
|
14
|
+
const drawers = {
|
|
15
|
+
hub: undefined,
|
|
16
|
+
template: undefined,
|
|
17
|
+
json: undefined
|
|
18
|
+
};
|
|
19
|
+
let hubItems;
|
|
20
|
+
let pendingJson;
|
|
21
|
+
let templateScripts = [];
|
|
22
|
+
let templateFilter = '';
|
|
23
|
+
let filteredTemplates;
|
|
24
|
+
const fuseOptions = {
|
|
25
|
+
includeScore: false,
|
|
26
|
+
keys: ['description', 'path', 'content', 'hash', 'summary']
|
|
27
|
+
};
|
|
28
|
+
const templateFuse = new Fuse(templateScripts, fuseOptions);
|
|
29
|
+
$: hubItems = $hubScripts?.filter((x) => x.kind == Script.kind.SCRIPT) || [];
|
|
30
|
+
$: filteredTemplates =
|
|
31
|
+
templateFilter.length > 0
|
|
32
|
+
? templateFuse.search(templateFilter).map((value) => value.item)
|
|
33
|
+
: templateScripts;
|
|
34
|
+
function importJson() {
|
|
35
|
+
Object.assign($flowStore, JSON.parse(pendingJson));
|
|
36
|
+
initFlow($flowStore);
|
|
37
|
+
sendUserToast('OpenFlow imported from JSON');
|
|
38
|
+
drawers.json?.toggleDrawer();
|
|
39
|
+
}
|
|
40
|
+
async function loadTemplateScripts() {
|
|
41
|
+
templateScripts = await ScriptService.listScripts({
|
|
42
|
+
workspace: $workspaceStore,
|
|
43
|
+
isTemplate: true
|
|
44
|
+
});
|
|
45
|
+
templateFuse.setCollection(templateScripts);
|
|
46
|
+
}
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<!-- Buttons -->
|
|
50
|
+
<div class="flex flex-row gap-2">
|
|
51
|
+
<ButtonPopup size="sm" startIcon={{ icon: faPlus }} href="/scripts/add">
|
|
52
|
+
<svelte:fragment slot="main">New script</svelte:fragment>
|
|
53
|
+
<ButtonPopupItem on:click={() => drawers.hub?.openModal()}>
|
|
54
|
+
Import script from WindmillHub
|
|
55
|
+
</ButtonPopupItem>
|
|
56
|
+
<ButtonPopupItem on:click={() => drawers.template?.toggleDrawer()}>
|
|
57
|
+
Import script from template
|
|
58
|
+
</ButtonPopupItem>
|
|
59
|
+
<ButtonPopupItem on:click={() => drawers.json?.toggleDrawer()}>
|
|
60
|
+
Import script from raw JSON
|
|
61
|
+
</ButtonPopupItem>
|
|
62
|
+
</ButtonPopup>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<!-- Initially hidden elements in a drawer -->
|
|
66
|
+
<!-- WindmillHub script list -->
|
|
67
|
+
<ItemPicker
|
|
68
|
+
bind:this={drawers.hub}
|
|
69
|
+
pickCallback={(path) => {
|
|
70
|
+
console.log('pick', { path })
|
|
71
|
+
goto('/scripts/add?hub=' + path)
|
|
72
|
+
}}
|
|
73
|
+
itemName={'Script'}
|
|
74
|
+
extraField="summary"
|
|
75
|
+
loadItems={async () => {
|
|
76
|
+
return hubItems
|
|
77
|
+
}}
|
|
78
|
+
/>
|
|
79
|
+
<!-- Template script list -->
|
|
80
|
+
<Drawer bind:this={drawers.template} size="800px" on:open={loadTemplateScripts}>
|
|
81
|
+
<DrawerContent title="Pick a template" on:close={() => drawers.template?.toggleDrawer()}>
|
|
82
|
+
<div class="pt-2 pb-4">
|
|
83
|
+
<input placeholder="Search templates" bind:value={templateFilter} class="search-bar" />
|
|
84
|
+
</div>
|
|
85
|
+
<div class="flex flex-col mb-2 md:mb-6">
|
|
86
|
+
{#if filteredTemplates && filteredTemplates.length > 0}
|
|
87
|
+
{#each filteredTemplates as { summary, path, hash }}
|
|
88
|
+
<a
|
|
89
|
+
class="p-1 flex flex-row items-baseline gap-2 selected text-gray-700"
|
|
90
|
+
href="/scripts/add?template={path}"
|
|
91
|
+
>
|
|
92
|
+
{#if summary}
|
|
93
|
+
<p class="text-sm font-semibold">{summary}</p>
|
|
94
|
+
{/if}
|
|
95
|
+
|
|
96
|
+
<p class="text-sm">{path}</p>
|
|
97
|
+
<p class="text-gray-400 text-xs text-right grow">
|
|
98
|
+
Last version: {hash}
|
|
99
|
+
</p>
|
|
100
|
+
</a>
|
|
101
|
+
{/each}
|
|
102
|
+
{:else}
|
|
103
|
+
<p class="text-sm text-gray-700">No templates</p>
|
|
104
|
+
{/if}
|
|
105
|
+
</div>
|
|
106
|
+
</DrawerContent>
|
|
107
|
+
</Drawer>
|
|
108
|
+
<!-- Raw JSON -->
|
|
109
|
+
<Drawer bind:this={drawers.json} size="800px">
|
|
110
|
+
<DrawerContent title="Import JSON" on:close={() => drawers.json?.toggleDrawer()}>
|
|
111
|
+
<div class="p-2"><Button size="sm" on:click={importJson}>Import</Button></div>
|
|
112
|
+
<SimpleEditor bind:code={pendingJson} lang="json" class="h-full" />
|
|
113
|
+
</DrawerContent>
|
|
114
|
+
</Drawer>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {};
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export declare type CreateActionsProps = typeof __propDef.props;
|
|
10
|
+
export declare type CreateActionsEvents = typeof __propDef.events;
|
|
11
|
+
export declare type CreateActionsSlots = typeof __propDef.slots;
|
|
12
|
+
export default class CreateActions extends SvelteComponentTyped<CreateActionsProps, CreateActionsEvents, CreateActionsSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "windmill-components",
|
|
3
|
-
"version": "1.36.
|
|
3
|
+
"version": "1.36.2",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"@playwright/test": "^1.26.1",
|
|
6
6
|
"@sveltejs/adapter-static": "^1.0.0-next.44",
|
|
@@ -132,6 +132,8 @@
|
|
|
132
132
|
"./components/common/badge/Badge.svelte": "./components/common/badge/Badge.svelte",
|
|
133
133
|
"./components/common/badge/model": "./components/common/badge/model.js",
|
|
134
134
|
"./components/common/button/Button.svelte": "./components/common/button/Button.svelte",
|
|
135
|
+
"./components/common/button/ButtonPopup.svelte": "./components/common/button/ButtonPopup.svelte",
|
|
136
|
+
"./components/common/button/ButtonPopupItem.svelte": "./components/common/button/ButtonPopupItem.svelte",
|
|
135
137
|
"./components/common/button/model": "./components/common/button/model.js",
|
|
136
138
|
"./components/common/confirmationModal/ConfirmationModal.svelte": "./components/common/confirmationModal/ConfirmationModal.svelte",
|
|
137
139
|
"./components/common/confirmationModal/UnsavedConfirmationModal.svelte": "./components/common/confirmationModal/UnsavedConfirmationModal.svelte",
|
|
@@ -139,8 +141,10 @@
|
|
|
139
141
|
"./components/common/drawer/Drawer.svelte": "./components/common/drawer/Drawer.svelte",
|
|
140
142
|
"./components/common/drawer/DrawerContent.svelte": "./components/common/drawer/DrawerContent.svelte",
|
|
141
143
|
"./components/common": "./components/common/index.js",
|
|
144
|
+
"./components/common/kbd/Kbd.svelte": "./components/common/kbd/Kbd.svelte",
|
|
142
145
|
"./components/common/menu/Menu.svelte": "./components/common/menu/Menu.svelte",
|
|
143
146
|
"./components/common/menu/MenuItem.svelte": "./components/common/menu/MenuItem.svelte",
|
|
147
|
+
"./components/common/popup/Popup.svelte": "./components/common/popup/Popup.svelte",
|
|
144
148
|
"./components/common/tabs/Tab.svelte": "./components/common/tabs/Tab.svelte",
|
|
145
149
|
"./components/common/tabs/TabContent.svelte": "./components/common/tabs/TabContent.svelte",
|
|
146
150
|
"./components/common/tabs/Tabs.svelte": "./components/common/tabs/Tabs.svelte",
|
|
@@ -178,6 +182,7 @@
|
|
|
178
182
|
"./components/flows/pickers/FlowScriptPicker.svelte": "./components/flows/pickers/FlowScriptPicker.svelte",
|
|
179
183
|
"./components/flows/pickers/PickHubScript.svelte": "./components/flows/pickers/PickHubScript.svelte",
|
|
180
184
|
"./components/flows/pickers/PickScript.svelte": "./components/flows/pickers/PickScript.svelte",
|
|
185
|
+
"./components/flows/pickers/model": "./components/flows/pickers/model.js",
|
|
181
186
|
"./components/flows/propPicker/PropPickerWrapper.svelte": "./components/flows/propPicker/PropPickerWrapper.svelte",
|
|
182
187
|
"./components/flows/scheduleUtils": "./components/flows/scheduleUtils.js",
|
|
183
188
|
"./components/flows/types": "./components/flows/types.js",
|
|
@@ -215,6 +220,7 @@
|
|
|
215
220
|
"./components/propertyPicker/WarningMessage.svelte": "./components/propertyPicker/WarningMessage.svelte",
|
|
216
221
|
"./components/propertyPicker/utils": "./components/propertyPicker/utils.js",
|
|
217
222
|
"./components/script_editor/LogPanel.svelte": "./components/script_editor/LogPanel.svelte",
|
|
223
|
+
"./components/scripts/CreateActions.svelte": "./components/scripts/CreateActions.svelte",
|
|
218
224
|
"./components/sidebar/MenuLink.svelte": "./components/sidebar/MenuLink.svelte",
|
|
219
225
|
"./components/sidebar/SidebarContent.svelte": "./components/sidebar/SidebarContent.svelte",
|
|
220
226
|
"./components/sidebar/UserMenu.svelte": "./components/sidebar/UserMenu.svelte",
|
|
@@ -340,6 +346,7 @@
|
|
|
340
346
|
"./script_helpers": "./script_helpers.js",
|
|
341
347
|
"./scripts": "./scripts.js",
|
|
342
348
|
"./sql": "./sql.js",
|
|
349
|
+
"./stateMachine": "./stateMachine.js",
|
|
343
350
|
"./stores": "./stores.js",
|
|
344
351
|
"./user": "./user.js",
|
|
345
352
|
"./utils": "./utils.js"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Readable } from 'svelte/store';
|
|
2
|
+
export interface StateMachine<T extends readonly string[]> {
|
|
3
|
+
states: T;
|
|
4
|
+
currentState: T[number];
|
|
5
|
+
}
|
|
6
|
+
export interface StateMachineTransition<T extends readonly string[]> {
|
|
7
|
+
from?: Partial<Record<T[number], TransitionFromFunction<T>>>;
|
|
8
|
+
to?: Partial<Record<T[number], TransitionToFunction<T>>>;
|
|
9
|
+
}
|
|
10
|
+
declare type StateMachineInfo<T extends readonly string[]> = {
|
|
11
|
+
states: StateMachine<T>['states'];
|
|
12
|
+
currentState: StateMachine<T>['currentState'];
|
|
13
|
+
};
|
|
14
|
+
/** The return value should be a `state` that is available on the current machine. */
|
|
15
|
+
export declare type TransitionFromFunction<T extends readonly string[]> = (info: StateMachineInfo<T> & {
|
|
16
|
+
desiredState: T[number];
|
|
17
|
+
}) => T[number];
|
|
18
|
+
/** Callback after the state has been changed. */
|
|
19
|
+
export declare type TransitionToFunction<T extends readonly string[]> = (info: StateMachineInfo<T> & {
|
|
20
|
+
previousState: T[number];
|
|
21
|
+
}) => T[number];
|
|
22
|
+
declare type StateStore<T extends readonly string[]> = Readable<StateMachine<T>> & {
|
|
23
|
+
setState: (state: T[number]) => StateMachineInfo<T>;
|
|
24
|
+
};
|
|
25
|
+
/** **IMPORTANT:** use the `as const` syntax on the states array to get type safety.
|
|
26
|
+
* *Example: `createStateMachine(['foo', 'bar'] as const)`*
|
|
27
|
+
*
|
|
28
|
+
* Returns a new state machine with the default state set to the first element of the `states` argument. */
|
|
29
|
+
export declare function createStateMachine<T extends readonly string[]>(states: T, transition?: StateMachineTransition<T>): StateStore<T>;
|
|
30
|
+
export {};
|
package/stateMachine.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
/** **IMPORTANT:** use the `as const` syntax on the states array to get type safety.
|
|
3
|
+
* *Example: `createStateMachine(['foo', 'bar'] as const)`*
|
|
4
|
+
*
|
|
5
|
+
* Returns a new state machine with the default state set to the first element of the `states` argument. */
|
|
6
|
+
export function createStateMachine(states, transition = {}) {
|
|
7
|
+
const defaultValue = {
|
|
8
|
+
states,
|
|
9
|
+
currentState: states[0]
|
|
10
|
+
};
|
|
11
|
+
const defaultStore = writable(defaultValue);
|
|
12
|
+
const stateStore = {
|
|
13
|
+
subscribe: defaultStore.subscribe,
|
|
14
|
+
setState: (nextState) => {
|
|
15
|
+
defaultStore.update((prev) => {
|
|
16
|
+
const previousState = prev.currentState;
|
|
17
|
+
const beforeFunc = transition?.from && transition.from[previousState];
|
|
18
|
+
const afterFunc = transition?.to && transition.to[nextState];
|
|
19
|
+
let returnState = nextState;
|
|
20
|
+
if (beforeFunc) {
|
|
21
|
+
returnState = beforeFunc({
|
|
22
|
+
states,
|
|
23
|
+
currentState: previousState,
|
|
24
|
+
desiredState: nextState
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
if (afterFunc) {
|
|
28
|
+
returnState = afterFunc({
|
|
29
|
+
states,
|
|
30
|
+
currentState: returnState,
|
|
31
|
+
previousState
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
prev.currentState = returnState;
|
|
35
|
+
return prev;
|
|
36
|
+
});
|
|
37
|
+
return { states, currentState: nextState };
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
return stateStore;
|
|
41
|
+
}
|
package/utils.d.ts
CHANGED
|
@@ -13,7 +13,9 @@ export declare function sendUserToast(message: string, error?: boolean): void;
|
|
|
13
13
|
export declare function truncateHash(hash: string): string;
|
|
14
14
|
export declare function sleep(ms: number): Promise<void>;
|
|
15
15
|
export declare function validatePassword(password: string): boolean;
|
|
16
|
-
export declare function clickOutside(node:
|
|
16
|
+
export declare function clickOutside(node: Node): {
|
|
17
|
+
destroy(): void;
|
|
18
|
+
};
|
|
17
19
|
export declare type DropdownType = 'action' | 'delete';
|
|
18
20
|
export interface DropdownItem {
|
|
19
21
|
displayName: string;
|
package/utils.js
CHANGED
|
@@ -92,11 +92,10 @@ export function validatePassword(password) {
|
|
|
92
92
|
const re = /^(?=.*[\d])(?=.*[!@#$%^&*])[\w!@#$%^&*]{8,30}$/;
|
|
93
93
|
return re.test(password);
|
|
94
94
|
}
|
|
95
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
96
95
|
export function clickOutside(node) {
|
|
97
96
|
const handleClick = (event) => {
|
|
98
97
|
if (node && !node.contains(event.target) && !event.defaultPrevented) {
|
|
99
|
-
node.dispatchEvent(new CustomEvent('click_outside',
|
|
98
|
+
node.dispatchEvent(new CustomEvent('click_outside', { detail: event }));
|
|
100
99
|
}
|
|
101
100
|
};
|
|
102
101
|
document.addEventListener('click', handleClick, true);
|