mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-24 08:01:38 +00:00
Menu refactor (#1372)
* wip menu refactor * wip * wip * feat(frontend): finish menu refactor * feat(frontend): finish menu refactor
This commit is contained in:
Generated
+17
@@ -37,6 +37,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.31.1",
|
||||
"@rgossiaux/svelte-headlessui": "^1.0.2",
|
||||
"@sveltejs/adapter-static": "^2.0.1",
|
||||
"@sveltejs/kit": "^1.0.0-next.589",
|
||||
"@sveltejs/package": "^1.0.2",
|
||||
@@ -902,6 +903,15 @@
|
||||
"resolved": "https://registry.npmjs.org/@redocly/json-to-json-schema/-/json-to-json-schema-0.0.1.tgz",
|
||||
"integrity": "sha512-dSMyuNPN2k+tFeNZ0+QJ7S1zDJ0UeNL+lpnPFR9K5avj2V4uG4m6FdjrApQ9Zi35AIocaDp/KGfBD9gR5MLUbQ=="
|
||||
},
|
||||
"node_modules/@rgossiaux/svelte-headlessui": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rgossiaux/svelte-headlessui/-/svelte-headlessui-1.0.2.tgz",
|
||||
"integrity": "sha512-sauopYTSivhzXe1kAvgawkhyYJcQlK8Li3p0d2OtcCIVprOzdbard5lbqWB4xHDv83zAobt2mR08oizO2poHLQ==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"svelte": "^3.44.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/adapter-static": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-2.0.1.tgz",
|
||||
@@ -7846,6 +7856,13 @@
|
||||
"resolved": "https://registry.npmjs.org/@redocly/json-to-json-schema/-/json-to-json-schema-0.0.1.tgz",
|
||||
"integrity": "sha512-dSMyuNPN2k+tFeNZ0+QJ7S1zDJ0UeNL+lpnPFR9K5avj2V4uG4m6FdjrApQ9Zi35AIocaDp/KGfBD9gR5MLUbQ=="
|
||||
},
|
||||
"@rgossiaux/svelte-headlessui": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@rgossiaux/svelte-headlessui/-/svelte-headlessui-1.0.2.tgz",
|
||||
"integrity": "sha512-sauopYTSivhzXe1kAvgawkhyYJcQlK8Li3p0d2OtcCIVprOzdbard5lbqWB4xHDv83zAobt2mR08oizO2poHLQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@sveltejs/adapter-static": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-2.0.1.tgz",
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.31.1",
|
||||
"@rgossiaux/svelte-headlessui": "^1.0.2",
|
||||
"@sveltejs/adapter-static": "^2.0.1",
|
||||
"@sveltejs/kit": "^1.0.0-next.589",
|
||||
"@sveltejs/package": "^1.0.2",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import { setContext } from 'svelte'
|
||||
import { writable, type Writable } from 'svelte/store'
|
||||
import CenteredPage from './CenteredPage.svelte'
|
||||
import { Badge, Button, ButtonPopup, ButtonPopupItem, UndoRedo } from './common'
|
||||
import { Badge, Button, UndoRedo } from './common'
|
||||
import { dirtyStore } from './common/confirmationModal/dirtyStore'
|
||||
import FlowEditor from './flows/FlowEditor.svelte'
|
||||
import ScriptEditorDrawer from './flows/content/ScriptEditorDrawer.svelte'
|
||||
@@ -263,6 +263,23 @@
|
||||
...dfs($flowStore.value.modules, (module) => module.id)
|
||||
]
|
||||
}
|
||||
|
||||
const dropdownItems: Array<{
|
||||
label: string
|
||||
onClick: () => void
|
||||
}> = [
|
||||
{
|
||||
label: 'Save and exit',
|
||||
onClick: () => saveFlow(true)
|
||||
}
|
||||
]
|
||||
|
||||
if (initialPath != '') {
|
||||
dropdownItems.push({
|
||||
label: 'Fork',
|
||||
onClick: () => window.open(`/flows/add?template=${initialPath}`)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={onKeyDown} />
|
||||
@@ -273,7 +290,7 @@
|
||||
<div class="flex flex-col flex-1 h-screen">
|
||||
<!-- Nav between steps-->
|
||||
<div
|
||||
class="justify-between flex flex-row items-center pl-2.5 pr-6 space-x-4 overflow-x-auto scrollbar-hidden max-h-12 h-full"
|
||||
class="justify-between flex flex-row items-center pl-2.5 pr-6 space-x-4 scrollbar-hidden max-h-12 h-full"
|
||||
>
|
||||
<div class="flex w-full max-w-md gap-4 items-center">
|
||||
<div class="min-w-64 w-full">
|
||||
@@ -297,7 +314,7 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="gap-4 flex-row hidden md:flex w-full max-w-md overflow-hidden">
|
||||
<div class="gap-4 flex-row hidden md:flex w-full max-w-md">
|
||||
{#if $scheduleStore.enabled}
|
||||
<Button
|
||||
btnClasses="hidden lg:inline-flex"
|
||||
@@ -344,22 +361,15 @@
|
||||
|
||||
<FlowPreviewButtons />
|
||||
<div class="center-center">
|
||||
<ButtonPopup
|
||||
<Button
|
||||
loading={loadingSave}
|
||||
size="xs"
|
||||
startIcon={{ icon: faSave }}
|
||||
on:click={() => saveFlow(false)}
|
||||
{dropdownItems}
|
||||
>
|
||||
<svelte:fragment slot="main">Save</svelte:fragment>
|
||||
<ButtonPopupItem on:click={() => saveFlow(true)}>Save and exit</ButtonPopupItem>
|
||||
{#if initialPath != ''}
|
||||
<ButtonPopupItem
|
||||
on:click={() => {
|
||||
window.open(`/flows/add?template=${initialPath}`)
|
||||
}}>Fork</ButtonPopupItem
|
||||
>
|
||||
{/if}
|
||||
</ButtonPopup>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import ScriptEditor from './ScriptEditor.svelte'
|
||||
import ScriptSchema from './ScriptSchema.svelte'
|
||||
import { dirtyStore } from './common/confirmationModal/dirtyStore'
|
||||
import { Badge, Button, ButtonPopup, ButtonPopupItem, Drawer } from './common'
|
||||
import { Badge, Button, Drawer } from './common'
|
||||
import { faSave } from '@fortawesome/free-solid-svg-icons'
|
||||
import LanguageIcon from './common/languageIcons/LanguageIcon.svelte'
|
||||
import type { SupportedLanguage } from '$lib/common'
|
||||
@@ -125,6 +125,22 @@
|
||||
}
|
||||
loadingSave = false
|
||||
}
|
||||
|
||||
const dropdownItems: Array<{ label: string; onClick: () => void }> = [
|
||||
{
|
||||
label: 'Save and leave',
|
||||
onClick: () => editScript(true)
|
||||
}
|
||||
]
|
||||
|
||||
if (initialPath != '') {
|
||||
dropdownItems.push({
|
||||
label: 'Fork',
|
||||
onClick: () => {
|
||||
window.open(`/scripts/add?template=${initialPath}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if !$userStore?.operator}
|
||||
@@ -269,23 +285,16 @@
|
||||
>
|
||||
Customise
|
||||
</Button>
|
||||
<ButtonPopup
|
||||
<Button
|
||||
color="dark"
|
||||
loading={loadingSave}
|
||||
size="sm"
|
||||
startIcon={{ icon: faSave }}
|
||||
on:click={() => editScript(false)}
|
||||
{dropdownItems}
|
||||
>
|
||||
<svelte:fragment slot="main">Save</svelte:fragment>
|
||||
<ButtonPopupItem on:click={() => editScript(true)}>Save and exit</ButtonPopupItem>
|
||||
{#if initialPath != ''}
|
||||
<ButtonPopupItem
|
||||
on:click={() => {
|
||||
window.open(`/scripts/add?template=${initialPath}`)
|
||||
}}>Fork</ButtonPopupItem
|
||||
>
|
||||
{/if}
|
||||
</ButtonPopup>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { page } from '$app/stores'
|
||||
import {
|
||||
Alert,
|
||||
Badge,
|
||||
ButtonPopup,
|
||||
ButtonPopupItem,
|
||||
Drawer,
|
||||
DrawerContent,
|
||||
UndoRedo
|
||||
} from '$lib/components/common'
|
||||
import { Alert, Badge, Drawer, DrawerContent, UndoRedo } from '$lib/components/common'
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
|
||||
import Skeleton from '$lib/components/common/skeleton/Skeleton.svelte'
|
||||
@@ -672,20 +664,23 @@
|
||||
<span class="hidden md:inline">Save</span>
|
||||
</Button>
|
||||
{:else}
|
||||
<ButtonPopup
|
||||
<Button
|
||||
loading={loading.save}
|
||||
startIcon={{ icon: faSave }}
|
||||
on:click={save}
|
||||
color="dark"
|
||||
size="xs"
|
||||
dropdownItems={[
|
||||
{
|
||||
label: 'Fork',
|
||||
onClick: () => {
|
||||
window.open(`/apps/add?template=${appPath}`)
|
||||
}
|
||||
}
|
||||
]}
|
||||
>
|
||||
<svelte:fragment slot="main">Save</svelte:fragment>
|
||||
<ButtonPopupItem
|
||||
on:click={() => {
|
||||
window.open(`/apps/add?template=${appPath}`)
|
||||
}}>Fork</ButtonPopupItem
|
||||
>
|
||||
</ButtonPopup>
|
||||
Save
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
import { ButtonType } from './model'
|
||||
import { goto } from '$app/navigation'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import ButtonDropdown from './ButtonDropdown.svelte'
|
||||
import { MenuItem } from '@rgossiaux/svelte-headlessui'
|
||||
|
||||
export let size: ButtonType.Size = 'md'
|
||||
export let spacingSize: ButtonType.Size = size
|
||||
@@ -26,6 +27,13 @@
|
||||
export let title: string | undefined = undefined
|
||||
export let style: string = ''
|
||||
|
||||
type MenuItem = {
|
||||
label: string
|
||||
onClick?: () => void
|
||||
href?: string
|
||||
}
|
||||
export let dropdownItems: MenuItem[] | undefined = undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
// Order of classes: border, border modifier, bg, bg modifier, text, text modifier, everything else
|
||||
const colorVariants: Record<ButtonType.Color, Record<ButtonType.Variant, string>> = {
|
||||
@@ -76,8 +84,8 @@
|
||||
variant === 'border' ? 'border' : '',
|
||||
ButtonType.FontSizeClasses[size],
|
||||
ButtonType.SpacingClasses[spacingSize][variant],
|
||||
'focus:ring-2 font-semibold',
|
||||
'rounded-md',
|
||||
'focus:ring-2 font-semibold h-full',
|
||||
dropdownItems ? 'rounded-l-md' : 'rounded-md',
|
||||
'justify-center items-center text-center whitespace-nowrap inline-flex',
|
||||
btnClasses,
|
||||
disabled ? '!bg-gray-300 !text-gray-600 !cursor-not-allowed' : '',
|
||||
@@ -113,28 +121,46 @@
|
||||
$: endIconClass = twMerge(iconOnly ? undefined : isSmall ? 'ml-1' : 'ml-2', endIcon?.classes)
|
||||
</script>
|
||||
|
||||
<svelte:element
|
||||
this={href ? 'a' : 'button'}
|
||||
bind:this={element}
|
||||
on:pointerdown
|
||||
on:click={onClick}
|
||||
on:focus
|
||||
on:blur
|
||||
{...buttonProps}
|
||||
disabled={disabled || loading}
|
||||
type="submit"
|
||||
{style}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class="animate-spin mr-1" size={14} />
|
||||
{:else if startIcon}
|
||||
<Icon data={startIcon.icon} class={startIconClass} scale={ButtonType.IconScale[size]} />
|
||||
{/if}
|
||||
<div class="flex flex-row divide-x divide-frost-600">
|
||||
<svelte:element
|
||||
this={href ? 'a' : 'button'}
|
||||
bind:this={element}
|
||||
on:pointerdown
|
||||
on:click={onClick}
|
||||
on:focus
|
||||
on:blur
|
||||
{...buttonProps}
|
||||
disabled={disabled || loading}
|
||||
type="submit"
|
||||
{style}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class="animate-spin mr-1" size={14} />
|
||||
{:else if startIcon}
|
||||
<Icon data={startIcon.icon} class={startIconClass} scale={ButtonType.IconScale[size]} />
|
||||
{/if}
|
||||
|
||||
{#if !iconOnly}
|
||||
<slot />
|
||||
{#if !iconOnly}
|
||||
<slot />
|
||||
{/if}
|
||||
{#if endIcon}
|
||||
<Icon data={endIcon.icon} class={endIconClass} scale={ButtonType.IconScale[size]} />
|
||||
{/if}
|
||||
</svelte:element>
|
||||
|
||||
{#if dropdownItems}
|
||||
<div class={twMerge(buttonProps.class, 'rounded-r-md rounded-l-none m-0 p-0 h-auto')}>
|
||||
<ButtonDropdown>
|
||||
<svelte:fragment slot="items">
|
||||
{#each dropdownItems as item}
|
||||
<MenuItem on:click={item.onClick} href={item.href}>
|
||||
<div class="!text-gray-700 px-4 py-2 my-1 cursor-pointer hover:bg-gray-100 !text-sm">
|
||||
{item.label}
|
||||
</div>
|
||||
</MenuItem>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
</ButtonDropdown>
|
||||
</div>
|
||||
{/if}
|
||||
{#if endIcon}
|
||||
<Icon data={endIcon.icon} class={endIconClass} scale={ButtonType.IconScale[size]} />
|
||||
{/if}
|
||||
</svelte:element>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<script>
|
||||
import { Menu, Transition, MenuButton, MenuItems } from '@rgossiaux/svelte-headlessui'
|
||||
import { ChevronDown } from 'lucide-svelte'
|
||||
</script>
|
||||
|
||||
<Menu let:open as="div" class="relative z-50 flex w-full h-full">
|
||||
<MenuButton class="h-full w-full px-2">
|
||||
<ChevronDown class="w-5 h-5" />
|
||||
</MenuButton>
|
||||
<Transition
|
||||
show={open}
|
||||
enter="transition ease-out duration-25"
|
||||
enterFrom="transform opacity-0 scale-95"
|
||||
enterTo="transform opacity-100 scale-100"
|
||||
leave="transition ease-in duration-25"
|
||||
leaveFrom="transform opacity-100 scale-100"
|
||||
leaveTo="transform opacity-0 scale-95"
|
||||
>
|
||||
<MenuItems
|
||||
class="absolute right-0 z-50 mt-2 w-56 origin-top-right top-8 divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
|
||||
>
|
||||
<slot name="items" />
|
||||
</MenuItems>
|
||||
</Transition>
|
||||
</Menu>
|
||||
@@ -1,81 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { faChevronDown } from '@fortawesome/free-solid-svg-icons'
|
||||
import { setContext } from 'svelte'
|
||||
import Icon from 'svelte-awesome'
|
||||
import { Button, ButtonType, Popup } from '..'
|
||||
|
||||
export let size: ButtonType.Size = 'md'
|
||||
export let color: ButtonType.Color = 'blue'
|
||||
export let variant: ButtonType.Variant = 'contained'
|
||||
export let mainClasses: string = ''
|
||||
export let toggleClasses: string = ''
|
||||
export let listClasses: string = ''
|
||||
export let disabled: boolean = false
|
||||
export let href: string | undefined = undefined
|
||||
export let target: ButtonType.Target = '_self'
|
||||
export let startIcon: ButtonType.Icon | undefined = undefined
|
||||
export let endIcon: ButtonType.Icon | undefined = undefined
|
||||
export let spacingSize: ButtonType.Size = size
|
||||
export let loading = false
|
||||
|
||||
let ref: ButtonType.Element
|
||||
|
||||
setContext<ButtonType.ItemProps>(ButtonType.ItemContextKey, { size, color })
|
||||
|
||||
$: separator = color === 'red' || color === 'blue' ? 'border-frost-600' : 'border-gray-400'
|
||||
</script>
|
||||
|
||||
<div class="flex justy-start items-center">
|
||||
{#if $$slots.main}
|
||||
<Button
|
||||
{loading}
|
||||
{size}
|
||||
{color}
|
||||
{variant}
|
||||
{disabled}
|
||||
{spacingSize}
|
||||
{href}
|
||||
{target}
|
||||
{startIcon}
|
||||
{endIcon}
|
||||
btnClasses="!rounded-r-none !border-r-0 {mainClasses}"
|
||||
on:click
|
||||
>
|
||||
<slot name="main" />
|
||||
</Button>
|
||||
{/if}
|
||||
<span class={$$slots.main && variant === 'contained' ? 'border-l ' + separator : ''}>
|
||||
<Button
|
||||
bind:element={ref}
|
||||
{size}
|
||||
{color}
|
||||
{variant}
|
||||
{disabled}
|
||||
{spacingSize}
|
||||
btnClasses="{$$slots.main ? '!rounded-l-none !ring-0' : ''} {toggleClasses}"
|
||||
on:click={() => {}}
|
||||
>
|
||||
<slot name="toggle">
|
||||
<!-- Invisible, but needed to match the height of the 'main' button -->
|
||||
<span class="!opacity-0 !w-0">A</span>
|
||||
<Icon data={faChevronDown} scale={ButtonType.IconScale[size]} />
|
||||
</slot>
|
||||
</Button>
|
||||
</span>
|
||||
</div>
|
||||
{#if ref}
|
||||
<Popup
|
||||
{ref}
|
||||
let:open
|
||||
let:close
|
||||
options={{
|
||||
placement: $$slots.main ? 'bottom-end' : 'bottom',
|
||||
strategy: 'absolute',
|
||||
modifiers: [{ name: 'offset', options: { offset: [0, 5] } }]
|
||||
}}
|
||||
>
|
||||
<ul class="bg-white rounded-sm border shadow pt-1 pb-2 max-h-40 overflow-auto {listClasses}">
|
||||
<slot {open} {close} />
|
||||
</ul>
|
||||
</Popup>
|
||||
{/if}
|
||||
@@ -1,53 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { Button, ButtonType } from '..'
|
||||
import { classNames } from '../../../utils'
|
||||
|
||||
export let btnClasses: string = ''
|
||||
export let disabled: boolean = false
|
||||
export let href: string | undefined = undefined
|
||||
export let target: ButtonType.Target = '_self'
|
||||
export let iconOnly: boolean = false
|
||||
export let startIcon: ButtonType.Icon | undefined = undefined
|
||||
export let endIcon: ButtonType.Icon | undefined = undefined
|
||||
export let wrapperClasses = ''
|
||||
|
||||
const props = getContext<ButtonType.ItemProps | undefined>(ButtonType.ItemContextKey)
|
||||
const iconWidthClass: Record<ButtonType.Size, string> = {
|
||||
xs: '!w-[12px]',
|
||||
sm: '!w-[14px]',
|
||||
md: '!w-[16px]',
|
||||
lg: '!w-[18px]',
|
||||
xl: '!w-[20px]'
|
||||
}
|
||||
|
||||
const getWidthClass = () => (props?.size ? iconWidthClass[props.size] : undefined)
|
||||
|
||||
$: buttonProps = {
|
||||
...props,
|
||||
variant: <ButtonType.Variant>'border',
|
||||
btnClasses: classNames(btnClasses, '!justify-start !border-0 !rounded-none !w-full'),
|
||||
disabled,
|
||||
href,
|
||||
target,
|
||||
iconOnly,
|
||||
startIcon: startIcon
|
||||
? {
|
||||
icon: startIcon.icon,
|
||||
classes: classNames(startIcon?.classes, getWidthClass())
|
||||
}
|
||||
: undefined,
|
||||
endIcon: endIcon
|
||||
? {
|
||||
icon: endIcon.icon,
|
||||
classes: classNames(endIcon?.classes, getWidthClass())
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
</script>
|
||||
|
||||
<li class="mt-1 {wrapperClasses}">
|
||||
<Button {...buttonProps} on:click>
|
||||
<slot />
|
||||
</Button>
|
||||
</li>
|
||||
@@ -1,9 +1,8 @@
|
||||
export const BUTTON_COLORS = ['blue', 'red', 'dark', 'light', 'green', 'gray', 'none'] as const
|
||||
|
||||
export namespace ButtonType {
|
||||
|
||||
export type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||
export type Color = typeof BUTTON_COLORS[number]
|
||||
export type Color = (typeof BUTTON_COLORS)[number]
|
||||
export type Variant = 'contained' | 'border'
|
||||
export type Target = '_self' | '_blank'
|
||||
export type Element = HTMLButtonElement | HTMLAnchorElement
|
||||
@@ -40,7 +39,7 @@ export namespace ButtonType {
|
||||
xl: {
|
||||
border: 'px-4 py-[8px]',
|
||||
contained: 'px-4 py-[9px]'
|
||||
},
|
||||
}
|
||||
} as const
|
||||
|
||||
export const IconScale: Record<ButtonType.Size, number> = {
|
||||
@@ -51,10 +50,6 @@ export namespace ButtonType {
|
||||
xl: 1.2
|
||||
} as const
|
||||
|
||||
// ButtonPopup types
|
||||
|
||||
export const ItemContextKey = 'popupItemProps' as const
|
||||
|
||||
export interface ItemProps {
|
||||
size: Size
|
||||
color: Color
|
||||
|
||||
@@ -2,8 +2,6 @@ export { default as ActionRow } from './actionRow/ActionRow.svelte'
|
||||
export { default as Alert } from './alert/Alert.svelte'
|
||||
export { default as Badge } from './badge/Badge.svelte'
|
||||
export { default as Button } from './button/Button.svelte'
|
||||
export { default as ButtonPopup } from './button/ButtonPopup.svelte'
|
||||
export { default as ButtonPopupItem } from './button/ButtonPopupItem.svelte'
|
||||
export { default as UndoRedo } from './button/UndoRedo.svelte'
|
||||
export { default as ClearableInput } from './clearableInput/ClearableInput.svelte'
|
||||
export { default as Drawer } from './drawer/Drawer.svelte'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { goto } from '$app/navigation'
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import { Button, ButtonPopup, ButtonPopupItem } from '$lib/components/common'
|
||||
import { Button } from '$lib/components/common'
|
||||
import Drawer from '$lib/components/common/drawer/Drawer.svelte'
|
||||
import DrawerContent from '$lib/components/common/drawer/DrawerContent.svelte'
|
||||
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
|
||||
@@ -21,17 +21,22 @@
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="flex flex-row gap-2">
|
||||
<ButtonPopup
|
||||
<Button
|
||||
size="sm"
|
||||
spacingSize="xl"
|
||||
startIcon={{ icon: faPlus }}
|
||||
href="/apps/add?nodraft=true"
|
||||
dropdownItems={[
|
||||
{
|
||||
label: 'Import from raw JSON',
|
||||
onClick: () => drawer?.toggleDrawer?.()
|
||||
}
|
||||
]}
|
||||
>
|
||||
<svelte:fragment slot="main">App <LayoutDashboard class="ml-1.5" size={18} /></svelte:fragment>
|
||||
<ButtonPopupItem on:click={() => drawer?.toggleDrawer?.()}>
|
||||
Import from raw JSON
|
||||
</ButtonPopupItem>
|
||||
</ButtonPopup>
|
||||
<div class="flex flex-row">
|
||||
App <LayoutDashboard class="ml-1.5" size={18} />
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<!-- Raw JSON -->
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
import { goto } from '$app/navigation'
|
||||
import { faBarsStaggered, faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import { Button, ButtonPopup, ButtonPopupItem } from '$lib/components/common'
|
||||
import { Button } from '$lib/components/common'
|
||||
import Drawer from '$lib/components/common/drawer/Drawer.svelte'
|
||||
import DrawerContent from '$lib/components/common/drawer/DrawerContent.svelte'
|
||||
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
|
||||
import { importFlowStore } from '$lib/components/flows/flowStore'
|
||||
import { Icon } from 'svelte-awesome'
|
||||
|
||||
let drawer: Drawer | undefined = undefined
|
||||
let pendingJson: string
|
||||
@@ -21,19 +20,21 @@
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="flex flex-row gap-2">
|
||||
<ButtonPopup
|
||||
<Button
|
||||
size="sm"
|
||||
spacingSize="xl"
|
||||
startIcon={{ icon: faPlus }}
|
||||
endIcon={{ icon: faBarsStaggered }}
|
||||
href="/flows/add?nodraft=true"
|
||||
dropdownItems={[
|
||||
{
|
||||
label: 'Import from raw JSON',
|
||||
onClick: () => drawer?.toggleDrawer?.()
|
||||
}
|
||||
]}
|
||||
>
|
||||
<svelte:fragment slot="main"
|
||||
>Flow <Icon data={faBarsStaggered} scale={0.8} class="ml-1.5" />
|
||||
</svelte:fragment>
|
||||
<ButtonPopupItem on:click={() => drawer?.toggleDrawer?.()}>
|
||||
Import from raw JSON
|
||||
</ButtonPopupItem>
|
||||
</ButtonPopup>
|
||||
Flow
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<!-- Raw JSON -->
|
||||
|
||||
@@ -7,13 +7,7 @@
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="flex flex-row gap-2">
|
||||
<Button size="sm" spacingSize="xl" startIcon={{ icon: faPlus }} href="/scripts/add"
|
||||
>Script <Code2 class="ml-1.5" size={18} /></Button
|
||||
>
|
||||
<!-- <ButtonPopup size="sm" spacingSize="xl" startIcon={{ icon: faPlus }} href="/scripts/add">
|
||||
<svelte:fragment slot="main">Script <Code2 class="ml-1.5" size={18} /></svelte:fragment>
|
||||
<ButtonPopupItem on:click={() => drawer?.toggleDrawer?.()}>
|
||||
Import from template
|
||||
</ButtonPopupItem>
|
||||
</ButtonPopup> -->
|
||||
<Button size="sm" spacingSize="xl" startIcon={{ icon: faPlus }} href="/scripts/add">
|
||||
Script <Code2 class="ml-1.5" size={18} />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -243,7 +243,7 @@
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-row gap-x-2 w-full mb-2">
|
||||
<div class="flex flex-row gap-x-2 w-full mb-2 mt-4">
|
||||
<div class="relative w-full"
|
||||
><span class="text-xs absolute -top-4">min datetime</span>
|
||||
<input type="text" value={minTs ?? 'zoom x axis to set min (drag with ctrl)'} disabled />
|
||||
|
||||
@@ -35,16 +35,7 @@
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
import { onDestroy } from 'svelte'
|
||||
import HighlightCode from '$lib/components/HighlightCode.svelte'
|
||||
import {
|
||||
Badge,
|
||||
Tabs,
|
||||
Tab,
|
||||
TabContent,
|
||||
Button,
|
||||
Alert,
|
||||
ButtonPopup,
|
||||
ButtonPopupItem
|
||||
} from '$lib/components/common'
|
||||
import { Badge, Tabs, Tab, TabContent, Button, Alert } from '$lib/components/common'
|
||||
import Skeleton from '$lib/components/common/skeleton/Skeleton.svelte'
|
||||
import UserSettings from '$lib/components/UserSettings.svelte'
|
||||
import Icon from 'svelte-awesome'
|
||||
@@ -333,26 +324,19 @@
|
||||
on:click={() => webhookElem.scrollIntoView()}>Webhooks</Button
|
||||
>
|
||||
{#if Array.isArray(script.parent_hashes) && script.parent_hashes.length > 0}
|
||||
<ButtonPopup
|
||||
<Button
|
||||
color="dark"
|
||||
variant="contained"
|
||||
size="xs"
|
||||
startIcon={{ icon: faArrowLeft }}
|
||||
href="/scripts/get/{script.parent_hashes[0]}?workspace_id={$workspaceStore}"
|
||||
dropdownItems={script.parent_hashes.map((hash) => ({
|
||||
href: `/scripts/get/${hash}?workspace_id={$workspaceStore}`,
|
||||
label: hash
|
||||
}))}
|
||||
>
|
||||
<svelte:fragment slot="main">
|
||||
Previous version ({script.parent_hashes.length})
|
||||
</svelte:fragment>
|
||||
|
||||
{#each script.parent_hashes as hash}
|
||||
<ButtonPopupItem
|
||||
href="/scripts/get/{hash}?workspace_id={$workspaceStore}"
|
||||
btnClasses="!m-0"
|
||||
>
|
||||
{hash}
|
||||
</ButtonPopupItem>
|
||||
{/each}
|
||||
</ButtonPopup>
|
||||
Previous version ({script.parent_hashes.length})
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user