Compare commits
19 Commits
v1.670.0
...
glm/use-me
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97406f2745 | ||
|
|
dbdb166a39 | ||
|
|
af4e9ee728 | ||
|
|
607ea89ef1 | ||
|
|
4636166029 | ||
|
|
a5e2c20ceb | ||
|
|
5ac162a1eb | ||
|
|
fc222fdd4a | ||
|
|
13e0fbc57d | ||
|
|
3f1cff2411 | ||
|
|
8dda89b513 | ||
|
|
48dbc7cb37 | ||
|
|
be2dcdd369 | ||
|
|
56913f8d93 | ||
|
|
63f259edcf | ||
|
|
ef4472cfa0 | ||
|
|
f6687c782a | ||
|
|
0a5872bec5 | ||
|
|
3b76e54175 |
@@ -1,9 +1,23 @@
|
||||
<script>
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import Scroll from '$lib/components/Scroll.svelte'
|
||||
import { layoutStore } from '$lib/layout-context'
|
||||
|
||||
export let useScroll = false
|
||||
</script>
|
||||
|
||||
<div class="pb-8">
|
||||
<div class={twMerge('max-w-7xl mx-auto px-4 sm:px-6 md:px-8', $$restProps.class)}>
|
||||
<slot />
|
||||
{#if useScroll}
|
||||
<Scroll style={`height: calc(100vh - ${$layoutStore.topBarHeight}px)`}>
|
||||
<div class="pb-8">
|
||||
<div class={twMerge('max-w-7xl mx-auto px-4 sm:px-6 md:px-8', $$restProps.class)}>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</Scroll>
|
||||
{:else}
|
||||
<div class="pb-8">
|
||||
<div class={twMerge('max-w-7xl mx-auto px-4 sm:px-6 md:px-8', $$restProps.class)}>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
17
frontend/src/lib/components/Scroll.svelte
Normal file
17
frontend/src/lib/components/Scroll.svelte
Normal file
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={twMerge('h-full w-full overflow-y-auto scrollbar', $$props.class)}
|
||||
style={$$props.style}
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div {
|
||||
/* Prevent layout shift from scrollbar appearance */
|
||||
scrollbar-gutter: stable both-edges;
|
||||
}
|
||||
</style>
|
||||
15
frontend/src/lib/layout-context.ts
Normal file
15
frontend/src/lib/layout-context.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { writable } from 'svelte/store'
|
||||
|
||||
export const LAYOUT_CONTEXT_KEY = 'layoutContext'
|
||||
|
||||
export interface LayoutContext {
|
||||
topBarHeight: number
|
||||
}
|
||||
|
||||
export const layoutStore = writable<LayoutContext>({
|
||||
topBarHeight: 0
|
||||
})
|
||||
|
||||
export const setTopBarHeight = (height: number) => {
|
||||
layoutStore.update((state) => ({ ...state, topBarHeight: height }))
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
import { setContext } from 'svelte'
|
||||
import { base } from '$app/paths'
|
||||
import { Menubar } from '$lib/components/meltComponents'
|
||||
import { setTopBarHeight } from '$lib/layout-context'
|
||||
|
||||
OpenAPI.WITH_CREDENTIALS = true
|
||||
let menuOpen = false
|
||||
@@ -340,6 +341,19 @@
|
||||
|
||||
muteSettings = { global: g_muted, workspace: ws_muted }
|
||||
}
|
||||
|
||||
let topBarHeight = 0
|
||||
let trackedHeight = 0
|
||||
function updateTopBarHeight(newHeight: number) {
|
||||
if (newHeight == trackedHeight) {
|
||||
return
|
||||
}
|
||||
setTopBarHeight(newHeight)
|
||||
trackedHeight = newHeight
|
||||
}
|
||||
|
||||
// Track when the element is hidden based on conditions and media queries
|
||||
$: updateTopBarHeight(devOnly || $userStore?.operator || innerWidth >= 768 ? 0 : topBarHeight)
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerWidth />
|
||||
@@ -613,12 +627,13 @@
|
||||
)}
|
||||
>
|
||||
<main class="min-h-screen">
|
||||
<div class="relative w-full h-full">
|
||||
<div class="relative w-full h-full flex flex-col">
|
||||
<div
|
||||
class={classNames(
|
||||
'py-2 px-2 sm:px-4 md:px-8 flex justify-between items-center shadow-sm max-w-7xl mx-auto md:hidden',
|
||||
'py-2 px-2 sm:px-4 md:px-8 w-full justify-start shadow-sm max-w-7xl mx-auto md:hidden',
|
||||
devOnly || $userStore?.operator ? 'hidden' : ''
|
||||
)}
|
||||
bind:clientHeight={topBarHeight}
|
||||
>
|
||||
<button
|
||||
aria-label="Menu"
|
||||
@@ -641,7 +656,10 @@
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<slot />
|
||||
|
||||
<div class="grow min-h-0">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
import { Building, ExternalLink, GitFork, Globe2, Loader2 } from 'lucide-svelte'
|
||||
import { hubBaseUrlStore } from '$lib/stores'
|
||||
import { base } from '$lib/base'
|
||||
import { layoutStore } from '$lib/layout-context'
|
||||
|
||||
import ItemsList from '$lib/components/home/ItemsList.svelte'
|
||||
import CreateActionsApp from '$lib/components/flows/CreateActionsApp.svelte'
|
||||
@@ -23,6 +24,7 @@
|
||||
import { setQuery } from '$lib/navigation'
|
||||
import { page } from '$app/stores'
|
||||
import { goto, replaceState } from '$app/navigation'
|
||||
import Scroll from '$lib/components/Scroll.svelte'
|
||||
|
||||
type Tab = 'hub' | 'workspace'
|
||||
|
||||
@@ -213,7 +215,7 @@
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
<div>
|
||||
<Scroll style={`height: calc(100vh - ${$layoutStore.topBarHeight}px)`}>
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8 h-fit-content">
|
||||
{#if $workspaceStore == 'admins'}
|
||||
<div class="my-4"></div>
|
||||
@@ -314,8 +316,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if tab == 'workspace'}
|
||||
<ItemsList bind:filter bind:subtab />
|
||||
{/if}
|
||||
{#if tab == 'workspace'}
|
||||
<ItemsList bind:filter bind:subtab />
|
||||
{/if}
|
||||
</Scroll>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{:else}
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="Folders"
|
||||
tooltip="Folders allow to group items such as scripts/flows/resources/schedule together and to grant homogenous RBAC permissions to groups and individual users towards them."
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{:else}
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="Groups"
|
||||
tooltip="Group users together to grant roles and homegenous permissions. Same users can be in many groups at the same time."
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{:else}
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="Kafka triggers"
|
||||
tooltip="Windmill can consume kafka events and trigger scripts or flows based on them."
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
f={(x) => (x.summary ?? '') + ' ' + x.path + ' (' + x.script_path + ')'}
|
||||
/>
|
||||
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="MQTT triggers"
|
||||
tooltip="Windmill can connect to an MQTT broker, subscribe to specific topics, and trigger scripts or flows based on those topics."
|
||||
|
||||
@@ -233,7 +233,7 @@
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{:else}
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="NATS triggers"
|
||||
tooltip="Windmill can consume NATS events and trigger scripts or flows based on them."
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
f={(x) => (x.summary ?? '') + ' ' + x.path + ' (' + x.script_path + ')'}
|
||||
/>
|
||||
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="Postgres triggers"
|
||||
tooltip="Windmill enables real-time responsiveness by listening to specific database transactions—such as inserts, updates, and deletes—and automatically triggering scripts or workflows in response."
|
||||
|
||||
@@ -609,7 +609,7 @@
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{:else}
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="Resources"
|
||||
tooltip="Save and permission rich objects (JSON) including credentials obtained through OAuth."
|
||||
|
||||
@@ -193,17 +193,19 @@
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{:else}
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="Custom HTTP routes"
|
||||
tooltip="Every script and flow already has a canonical HTTP API endpoint/webhook attached to it, this is to create additional parametrizable ones."
|
||||
documentationLink="https://www.windmill.dev/docs/core_concepts/http_routing"
|
||||
>
|
||||
{#if $userStore?.is_admin || $userStore?.is_super_admin}
|
||||
<Button size="md" startIcon={{ icon: Plus }} on:click={() => routeEditor.openNew(false)}>
|
||||
New route
|
||||
</Button>
|
||||
{/if}
|
||||
<div class="min-h-[41px]">
|
||||
{#if $userStore?.is_admin || $userStore?.is_super_admin}
|
||||
<Button size="md" startIcon={{ icon: Plus }} on:click={() => routeEditor.openNew(false)}>
|
||||
New route
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div class="w-full h-full flex flex-col">
|
||||
<div class="w-full pb-4 pt-6">
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{:else}
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="Schedules"
|
||||
tooltip="Trigger Scripts and Flows according to a cron schedule"
|
||||
|
||||
@@ -227,7 +227,7 @@
|
||||
f={(x) => (x.summary ?? '') + ' ' + x.path + ' (' + x.script_path + ')'}
|
||||
/>
|
||||
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader title="SQS triggers" tooltip="SQS trigger">
|
||||
<Button size="md" startIcon={{ icon: Plus }} on:click={() => sqsTriggerEditor.openNew(false)}>
|
||||
New SQS trigger
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{:else}
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="Variables"
|
||||
tooltip="Save and permission strings to be reused in Scripts and Flows."
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
f={(x) => (x.summary ?? '') + ' ' + x.path + ' (' + x.script_path + ')'}
|
||||
/>
|
||||
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="WebSocket triggers"
|
||||
tooltip="Windmill can listen to WebSocket events and trigger scripts or flows based on them."
|
||||
|
||||
@@ -285,7 +285,7 @@
|
||||
<p>Page not available for operators</p>
|
||||
</div>
|
||||
{:else}
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
<PageHeader
|
||||
title="Workers"
|
||||
tooltip="The workers are the dutiful servants that execute the jobs."
|
||||
|
||||
@@ -633,7 +633,7 @@
|
||||
<S3FilePicker bind:this={s3FileViewer} readOnlyMode={false} fromWorkspaceSettings={true} />
|
||||
</Portal>
|
||||
|
||||
<CenteredPage>
|
||||
<CenteredPage useScroll>
|
||||
{#if $userStore?.is_admin || $superadmin}
|
||||
<PageHeader title="Workspace settings: {$workspaceStore}"
|
||||
>{#if $superadmin}
|
||||
|
||||
Reference in New Issue
Block a user