Hub lists (#989)
* fix(frontend): Adapt hub list design * fix(frontend): revert changes
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<div class="pb-6 h-fit-content">
|
||||
<div class="pb-8 h-fit-content">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 md:px-8 h-fit-content">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import { getScriptByPath, sendUserToast } from '$lib/utils'
|
||||
|
||||
import {
|
||||
faBuilding,
|
||||
faCube,
|
||||
faDollarSign,
|
||||
faEye,
|
||||
@@ -82,12 +81,12 @@
|
||||
<DrawerContent title="Code" on:close={scriptPicker.closeDrawer}>
|
||||
{#if pick_existing == 'hub'}
|
||||
<PickHubScript bind:filter {kind} on:pick={onScriptPick}>
|
||||
<ToggleHubWorkspace bind:selected={pick_existing} /></PickHubScript
|
||||
>
|
||||
<ToggleHubWorkspace bind:selected={pick_existing} />
|
||||
</PickHubScript>
|
||||
{:else}
|
||||
<WorkspaceScriptPicker bind:filter {kind} on:pick={onScriptPick}
|
||||
><ToggleHubWorkspace bind:selected={pick_existing} /></WorkspaceScriptPicker
|
||||
>
|
||||
<WorkspaceScriptPicker bind:filter {kind} on:pick={onScriptPick}>
|
||||
<ToggleHubWorkspace bind:selected={pick_existing} />
|
||||
</WorkspaceScriptPicker>
|
||||
{/if}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
<script lang="ts">
|
||||
import { faClose } from '@fortawesome/free-solid-svg-icons'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import Icon from 'svelte-awesome'
|
||||
import Button from '../button/Button.svelte'
|
||||
|
||||
export let title: string | undefined = undefined
|
||||
export let overflow_y = true
|
||||
export let noPadding = false
|
||||
export let forceOverflowVisible = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col divide-y h-screen max-h-screen">
|
||||
<div class="flex justify-between items-center gap-x-2">
|
||||
<Button
|
||||
btnClasses="m-1"
|
||||
variant="border"
|
||||
size="lg"
|
||||
color="dark"
|
||||
on:click={() => {
|
||||
dispatch('close')
|
||||
}}
|
||||
>
|
||||
<Icon data={faClose} />
|
||||
</Button>
|
||||
<span class="font-bold truncate">{title}</span>
|
||||
<div class="flex flex-row m-1">
|
||||
{#if $$slots.submission}
|
||||
<slot name="submission" class="sticky" />
|
||||
{/if}
|
||||
<div class="flex justify-between w-wull items-center px-4 py-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<Button
|
||||
size="lg"
|
||||
color="light"
|
||||
on:click={() => dispatch('close')}
|
||||
startIcon={{ icon: faClose }}
|
||||
iconOnly
|
||||
/>
|
||||
|
||||
<span class="font-semibold truncate text-gray-800">{title}</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex gap-2 items-center">
|
||||
{#if $$slots.submission}
|
||||
<slot name="submission" class="sticky" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="{noPadding ? '' : 'py-2 px-6'} grow h-full max-h-full {forceOverflowVisible
|
||||
class="{noPadding ? '' : 'p-4'} grow h-full max-h-full {forceOverflowVisible
|
||||
? '!overflow-visible'
|
||||
: ''}"
|
||||
class:overflow-y-auto={overflow_y}
|
||||
|
||||
@@ -127,12 +127,12 @@
|
||||
>Use pre-made <span class="text-blue-500">{kind == 'script' ? 'common' : kind}</span> script</h3
|
||||
>
|
||||
{#if pick_existing == 'hub'}
|
||||
<PickHubScript bind:filter {kind} on:pick
|
||||
><ToggleHubWorkspace bind:selected={pick_existing} /></PickHubScript
|
||||
>
|
||||
<PickHubScript bind:filter {kind} on:pick>
|
||||
<ToggleHubWorkspace bind:selected={pick_existing} />
|
||||
</PickHubScript>
|
||||
{:else}
|
||||
<WorkspaceScriptPicker bind:filter {kind} on:pick
|
||||
><ToggleHubWorkspace bind:selected={pick_existing} /></WorkspaceScriptPicker
|
||||
>
|
||||
<WorkspaceScriptPicker bind:filter {kind} on:pick>
|
||||
<ToggleHubWorkspace bind:selected={pick_existing} />
|
||||
</WorkspaceScriptPicker>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
import { hubScripts } from '$lib/stores'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import type { HubItem } from './model'
|
||||
import IconedResourceType from '$lib/components/IconedResourceType.svelte'
|
||||
import { Badge, Skeleton } from '$lib/components/common'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import { loadHubScripts } from '$lib/utils'
|
||||
import { capitalize, classNames, loadHubScripts } from '$lib/utils'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
import { APP_TO_ICON_COMPONENT } from '$lib/components/icons'
|
||||
import ListFilters from '$lib/components/home/ListFilters.svelte'
|
||||
|
||||
export let kind: 'script' | 'trigger' | 'approval' | 'failure' = 'script'
|
||||
export let filter = ''
|
||||
|
||||
$: items = ($hubScripts ?? []).filter((i) => i.kind === kind)
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let filteredItems: (HubItem & { marked?: string })[] = []
|
||||
let appFilter: string | undefined = undefined
|
||||
|
||||
$: items = ($hubScripts ?? []).filter((i) => i.kind === kind)
|
||||
$: prefilteredItems = appFilter ? (items ?? []).filter((i) => i.app == appFilter) : items ?? []
|
||||
|
||||
$: apps = Array.from(new Set(filteredItems?.map((x) => x.app) ?? [])).sort()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
onMount(() => {
|
||||
if (!$hubScripts) {
|
||||
loadHubScripts()
|
||||
@@ -29,60 +29,60 @@
|
||||
</script>
|
||||
|
||||
<SearchItems {filter} items={prefilteredItems} bind:filteredItems f={(x) => x.summary} />
|
||||
|
||||
<div class="flex flex-col min-h-0">
|
||||
<div class="w-full flex mt-1 items-center gap-2 mb-5">
|
||||
<slot />
|
||||
<input type="text" placeholder="Search Hub Scripts" bind:value={filter} class="text-2xl grow" />
|
||||
</div>
|
||||
|
||||
<div class="gap-2 w-full flex flex-wrap pb-3">
|
||||
{#each apps as app}
|
||||
<Badge
|
||||
class="cursor-pointer hover:bg-gray-200 border"
|
||||
on:click={() => {
|
||||
appFilter = appFilter == app ? undefined : app
|
||||
}}
|
||||
capitalize
|
||||
color={app === appFilter ? 'blue' : 'gray'}
|
||||
>
|
||||
{app}
|
||||
{#if app === appFilter}✗{/if}
|
||||
</Badge>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="overflow-auto">
|
||||
<ul class="divide-y divide-gray-200">
|
||||
{#if $hubScripts}
|
||||
{#if filter.length > 0 && filteredItems.length == 0}
|
||||
<p>No items found</p>
|
||||
{/if}
|
||||
{#each filteredItems as obj}
|
||||
<li class="flex flex-row w-full">
|
||||
<button
|
||||
class="py-4 px-1 gap-1 flex flex-row grow hover:bg-blue-50 bg-white transition-all"
|
||||
on:click={() => {
|
||||
dispatch('pick', obj)
|
||||
}}
|
||||
>
|
||||
<div class="mr-2 text-sm text-left truncate w-32 shrink-0">
|
||||
<IconedResourceType after={true} silent={false} name={obj['app']} />
|
||||
</div>
|
||||
<div class="mr-2 text-left">
|
||||
{#if obj.marked}
|
||||
{@html obj.marked ?? ''}
|
||||
{:else}
|
||||
{obj.summary ?? ''}
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each Array(10).fill(0) as sk}
|
||||
<Skeleton layout={[[4], 0.5]} />
|
||||
{/each}
|
||||
{/if}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="w-full flex mt-1 items-center gap-2 mb-5">
|
||||
<slot />
|
||||
<input type="text" placeholder="Search Hub Scripts" bind:value={filter} class="text-2xl grow" />
|
||||
</div>
|
||||
<ListFilters filters={apps} bind:selectedFilter={appFilter} />
|
||||
|
||||
{#if $hubScripts}
|
||||
{#if filteredItems.length == 0}
|
||||
<NoItemFound />
|
||||
{:else}
|
||||
<ul class="divide-y divide-gray-200 border rounded-md overflow-hidden">
|
||||
{#each filteredItems as item (item.path)}
|
||||
<li class="flex flex-row w-full">
|
||||
<button
|
||||
class="p-4 gap-4 flex flex-row grow hover:bg-gray-50 bg-white transition-all items-center"
|
||||
on:click={() => dispatch('pick', item)}
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<div
|
||||
class={classNames(
|
||||
'rounded-md p-1 flex justify-center items-center border',
|
||||
'bg-gray-50 border-gray-200'
|
||||
)}
|
||||
>
|
||||
<svelte:component
|
||||
this={APP_TO_ICON_COMPONENT[item['app']]}
|
||||
height={18}
|
||||
width={18}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="w-full text-left font-normal ">
|
||||
<div class="text-gray-900 flex-wrap text-md font-semibold mb-1">
|
||||
{#if item.marked}
|
||||
{@html item.marked ?? ''}
|
||||
{:else}
|
||||
{item.summary ?? ''}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-gray-600 text-xs ">
|
||||
{item.path}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{#if kind !== 'script'}
|
||||
<Badge color="gray" baseClass="border">{capitalize(kind)}</Badge>
|
||||
{/if}
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{:else}
|
||||
{#each Array(10).fill(0) as _}
|
||||
<Skeleton layout={[[4], 0.5]} />
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
import {
|
||||
AppService,
|
||||
FlowService,
|
||||
Job,
|
||||
JobService,
|
||||
ListableApp,
|
||||
Script,
|
||||
ScriptService,
|
||||
@@ -13,22 +11,10 @@
|
||||
} from '$lib/gen'
|
||||
import { superadmin, userStore, workspaceStore } from '$lib/stores'
|
||||
import VirtualList from '@sveltejs/svelte-virtual-list'
|
||||
import {
|
||||
Button,
|
||||
Drawer,
|
||||
DrawerContent,
|
||||
Skeleton,
|
||||
ToggleButton,
|
||||
ToggleButtonGroup
|
||||
} from '$lib/components/common'
|
||||
import { Drawer, Skeleton, ToggleButton, ToggleButtonGroup } from '$lib/components/common'
|
||||
import { canWrite, classNames, pluralize } from '$lib/utils'
|
||||
import type { HubItem } from '$lib/components/flows/pickers/model'
|
||||
import ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import { faCodeFork, faGlobe } from '@fortawesome/free-solid-svg-icons'
|
||||
import FlowViewer from '$lib/components/FlowViewer.svelte'
|
||||
import HighlightCode from '$lib/components/HighlightCode.svelte'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import Badge from '$lib/components/common/badge/Badge.svelte'
|
||||
import type uFuzzy from '@leeoniya/ufuzzy'
|
||||
import { Code2, LayoutDashboard, Wind } from 'svelte-lucide'
|
||||
|
||||
@@ -36,10 +22,9 @@
|
||||
import FlowRow from '$lib/components/common/table/FlowRow.svelte'
|
||||
import AppRow from '$lib/components/common/table/AppRow.svelte'
|
||||
|
||||
import { fade } from 'svelte/transition'
|
||||
import { flip } from 'svelte/animate'
|
||||
|
||||
let jobs: Job[] = []
|
||||
import NoItemFound from './NoItemFound.svelte'
|
||||
import ListFilters from './ListFilters.svelte'
|
||||
import SearchItems from '../SearchItems.svelte'
|
||||
|
||||
type TableItem<T, U extends 'script' | 'flow' | 'app'> = T & {
|
||||
canWrite: boolean
|
||||
@@ -66,13 +51,6 @@
|
||||
let shareModalFlows: ShareModal
|
||||
|
||||
let loading = true
|
||||
let flowViewer: Drawer
|
||||
let flowViewerFlow: { flow?: OpenFlow & { id?: number } } | undefined
|
||||
|
||||
let codeViewer: Drawer
|
||||
let codeViewerContent: string = ''
|
||||
let codeViewerLanguage: 'deno' | 'python3' | 'go' | 'bash' = 'deno'
|
||||
let codeViewerObj: HubItem | undefined = undefined
|
||||
|
||||
async function loadScripts(): Promise<void> {
|
||||
const loadedScripts = await ScriptService.listScripts({
|
||||
@@ -152,24 +130,14 @@
|
||||
|
||||
let ownerFilter: string | undefined = undefined
|
||||
|
||||
async function loadJobs() {
|
||||
jobs = await JobService.listJobs({
|
||||
workspace: $workspaceStore!,
|
||||
success: true,
|
||||
createdBy: $userStore?.username,
|
||||
jobKinds: 'flow,script'
|
||||
})
|
||||
loading = false
|
||||
}
|
||||
|
||||
$: {
|
||||
if (($userStore || $superadmin) && $workspaceStore) {
|
||||
loadScripts()
|
||||
loadFlows()
|
||||
loadApps()
|
||||
loadJobs()
|
||||
}
|
||||
}
|
||||
|
||||
const cmp = new Intl.Collator('en').compare
|
||||
|
||||
const opts: uFuzzy.Options = {
|
||||
@@ -258,50 +226,6 @@
|
||||
}}
|
||||
/>
|
||||
|
||||
<Drawer bind:this={codeViewer} size="900px">
|
||||
<DrawerContent title={codeViewerObj?.summary ?? ''} on:close={codeViewer.closeDrawer}>
|
||||
<div slot="submission" class="flex flex-row gap-2 pr-2">
|
||||
<Button
|
||||
href="https://hub.windmill.dev/scripts/{codeViewerObj?.app ?? ''}/{codeViewerObj?.ask_id ??
|
||||
0}"
|
||||
startIcon={{ icon: faGlobe }}
|
||||
variant="border"
|
||||
>
|
||||
View on the Hub
|
||||
</Button>
|
||||
<Button
|
||||
href="/scripts/add?hub={encodeURIComponent(codeViewerObj?.path ?? '')}"
|
||||
startIcon={{ icon: faCodeFork }}
|
||||
>
|
||||
Fork
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<HighlightCode language={codeViewerLanguage} code={codeViewerContent} />
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
<Drawer bind:this={flowViewer} size="900px">
|
||||
<DrawerContent title="Hub flow" on:close={flowViewer.closeDrawer}>
|
||||
<div slot="submission" class="flex flex-row gap-2 pr-2">
|
||||
<Button
|
||||
href="https://hub.windmill.dev/flows/{flowViewerFlow?.flow?.id}"
|
||||
startIcon={{ icon: faGlobe }}
|
||||
variant="border"
|
||||
>
|
||||
View on the Hub
|
||||
</Button>
|
||||
<Button href="/flows/add?hub={flowViewerFlow?.flow?.id}" startIcon={{ icon: faCodeFork }}>
|
||||
Fork
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{#if flowViewerFlow?.flow}
|
||||
<FlowViewer flow={flowViewerFlow.flow} />
|
||||
{/if}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
<CenteredPage>
|
||||
<div class="flex flex-col md:flex-row gap-2 items-center sm:justify-between w-full">
|
||||
<div>
|
||||
@@ -358,25 +282,8 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{#if owners.length > 0}
|
||||
<div class="gap-2 w-full flex flex-wrap my-4">
|
||||
{#each owners as owner (owner)}
|
||||
<div in:fade={{ duration: 50 }} animate:flip={{ duration: 100 }}>
|
||||
<Badge
|
||||
class="cursor-pointer hover:bg-gray-200"
|
||||
on:click={() => {
|
||||
ownerFilter = ownerFilter == owner ? undefined : owner
|
||||
}}
|
||||
color={owner === ownerFilter ? 'blue' : 'gray'}
|
||||
baseClass={owner === ownerFilter ? 'border border-blue-500' : 'border'}
|
||||
>
|
||||
{owner}
|
||||
{#if owner === ownerFilter}✗{/if}
|
||||
</Badge>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<ListFilters bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
<div>
|
||||
{#if filteredItems == undefined}
|
||||
<div class="mt-4" />
|
||||
@@ -385,12 +292,7 @@
|
||||
<Skeleton layout={[[4], 0.5]} />
|
||||
{/each}
|
||||
{:else if filteredItems.length === 0}
|
||||
<div class="flex justify-center items-center h-48">
|
||||
<div class="text-gray-500 text-center">
|
||||
<div class="text-2xl font-bold">No items found</div>
|
||||
<div class="text-sm">Try changing your search or filters</div>
|
||||
</div>
|
||||
</div>
|
||||
<NoItemFound />
|
||||
{:else}
|
||||
<div
|
||||
class={classNames('border rounded-md')}
|
||||
|
||||
32
frontend/src/lib/components/home/ListFilters.svelte
Normal file
32
frontend/src/lib/components/home/ListFilters.svelte
Normal file
@@ -0,0 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils'
|
||||
import { flip } from 'svelte/animate'
|
||||
import { fade } from 'svelte/transition'
|
||||
import { Badge } from '../common'
|
||||
|
||||
export let filters: string[]
|
||||
export let selectedFilter: string | undefined = undefined
|
||||
</script>
|
||||
|
||||
{#if Array.isArray(filters) && filters.length > 0}
|
||||
<div class="gap-2 w-full flex flex-wrap my-4">
|
||||
{#each filters as filter (filter)}
|
||||
<div in:fade={{ duration: 50 }} animate:flip={{ duration: 100 }}>
|
||||
<Badge
|
||||
class={classNames(
|
||||
'cursor-pointer',
|
||||
filter === selectedFilter ? 'hover:bg-blue-200' : 'hover:bg-gray-200'
|
||||
)}
|
||||
on:click={() => {
|
||||
selectedFilter = selectedFilter == filter ? undefined : filter
|
||||
}}
|
||||
color={filter === selectedFilter ? 'blue' : 'gray'}
|
||||
baseClass={filter === selectedFilter ? 'border border-blue-500' : 'border'}
|
||||
>
|
||||
{filter}
|
||||
{#if filter === selectedFilter}✗{/if}
|
||||
</Badge>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
6
frontend/src/lib/components/home/NoItemFound.svelte
Normal file
6
frontend/src/lib/components/home/NoItemFound.svelte
Normal file
@@ -0,0 +1,6 @@
|
||||
<div class="flex justify-center items-center h-48">
|
||||
<div class="text-gray-500 text-center">
|
||||
<div class="text-2xl font-bold">No items found</div>
|
||||
<div class="text-sm">Try changing your search or filters</div>
|
||||
</div>
|
||||
</div>
|
||||
8
frontend/src/lib/components/icons/QRCodeIcon.svelte
Normal file
8
frontend/src/lib/components/icons/QRCodeIcon.svelte
Normal file
@@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { QrCode } from 'svelte-lucide'
|
||||
|
||||
export let height = '24px'
|
||||
export let width = '24px'
|
||||
</script>
|
||||
|
||||
<QrCode size={height} />
|
||||
16
frontend/src/lib/components/icons/SendflakeIcon.svelte
Normal file
16
frontend/src/lib/components/icons/SendflakeIcon.svelte
Normal file
@@ -0,0 +1,16 @@
|
||||
<script lang="ts">
|
||||
export let height = '24px'
|
||||
export let width = '24px'
|
||||
</script>
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1565 1559"
|
||||
{height}
|
||||
{width}
|
||||
style="fill:#000000"
|
||||
>
|
||||
<path
|
||||
d="M522.63 807.57C515.63 830.07 500.44 850.06 478.07 862.84L146.72 1052.69C99.92 1079.39 40.3 1063.56 13.44 1017.38C-13.59 970.94 2.32 911.86 49.08 885.08L234.26 779.17L49.08 672.98C2.32 646.24 -13.67 587.15 13.44 540.88C40.3 494.58 99.92 478.7 146.72 505.4L478.07 695.13C501.37 708.46 516.94 729.6 523.48 753.24C525.68 760.84 526.66 768.44 527.04 776.08C527.3 786.6 525.94 797.26 522.63 807.57ZM612.54 985.38C663 988.98 702.84 1030.84 702.84 1081.77L702.84 1461.36C702.84 1514.89 659.05 1558.22 605.29 1558.22C551.27 1558.22 507.65 1514.89 507.65 1461.36L507.65 1249.05L321.84 1355.29C275.25 1382.2 215.67 1366.28 188.6 1320.06C161.7 1273.75 177.61 1214.37 224.29 1187.63L555.9 998.02C573.72 987.71 593.49 983.76 612.54 985.38ZM952.17 572.85C901.59 569.15 861.83 527.22 861.83 476.33L861.83 96.69C861.83 43.34 905.37 0 959.43 0C1013.44 0 1057.07 43.34 1057.07 96.69L1057.07 309.13L1242.75 202.72C1289.43 175.98 1349.04 191.85 1375.95 238.08C1402.8 284.56 1386.98 343.68 1340.26 370.42L1008.69 560.2C990.87 570.38 971.14 574.37 952.17 572.85ZM224.29 370.42C177.61 343.68 161.7 284.56 188.6 238.08C215.67 191.85 275.25 175.98 321.84 202.72L507.65 309.13L507.65 96.69C507.65 43.34 551.27 0 605.29 0C659.05 0 702.84 43.34 702.84 96.69L702.84 476.33C702.84 527.22 663 569.15 612.54 572.85C593.49 574.37 573.72 570.38 555.9 560.2L224.29 370.42ZM819.83 952.74C815.88 956.77 808.28 960.04 802.51 960.04L761.99 960.04C756.43 960.04 748.71 956.77 744.68 952.74L606.94 816.27C603 812.41 599.81 804.68 599.81 799.25L599.81 758.97C599.81 753.41 603 745.69 606.94 741.78L744.68 605.27C748.71 601.29 756.43 598.1 761.99 598.1L802.51 598.1C808.16 598.1 815.88 601.29 819.83 605.27L957.65 741.78C961.59 745.69 964.77 753.41 964.77 758.97L964.77 799.25C964.77 804.68 961.59 812.41 957.65 816.27L819.83 952.74ZM847.49 778.37C847.49 772.85 844.14 765.17 840.19 761.09L800.26 721.7C796.36 717.8 788.6 714.57 783.04 714.57L781.47 714.57C775.91 714.57 768.19 717.8 764.32 721.7L724.4 761.09C720.41 765.17 717.35 772.85 717.35 778.37L717.35 779.94C717.35 785.37 720.41 792.97 724.4 796.96L764.32 836.43C768.23 840.34 775.91 843.56 781.47 843.56L783.04 843.56C788.6 843.56 796.36 840.34 800.26 836.43L840.19 796.96C844.14 792.97 847.49 785.37 847.49 779.94L847.49 778.37ZM1340.26 1187.63C1386.98 1214.37 1402.8 1273.75 1375.95 1320.06C1349.04 1366.28 1289.38 1382.2 1242.75 1355.29L1057.07 1249.05L1057.07 1461.36C1057.07 1514.89 1013.44 1558.22 959.43 1558.22C905.37 1558.22 861.83 1514.89 861.83 1461.36L861.83 1081.77C861.83 1030.84 901.59 988.98 952.17 985.38C971.14 983.76 990.87 987.71 1008.69 998.02L1340.26 1187.63ZM1330.37 779.17L1515.55 885.08C1562.31 911.86 1578.31 970.94 1551.28 1017.38C1524.29 1063.56 1464.59 1079.39 1418 1052.69L1086.39 862.84C1064.24 850.06 1048.92 830.07 1042.09 807.57C1038.86 797.26 1037.33 786.6 1037.72 776.08C1037.89 768.44 1039.03 760.84 1041.15 753.24C1047.77 729.6 1063.35 708.46 1086.39 695.13L1418 505.4C1464.59 478.7 1524.29 494.58 1551.28 540.88C1578.31 587.15 1562.31 646.24 1515.55 672.98L1330.37 779.17Z"
|
||||
/>
|
||||
</svg>
|
||||
@@ -20,8 +20,10 @@ import TogglIcon from './TogglIcon.svelte'
|
||||
import WindmillIcon from './WindmillIcon.svelte'
|
||||
import MailchimpIcon from './MailchimpIcon.svelte'
|
||||
import SendgridIcon from './SendgridIcon.svelte'
|
||||
import SendflakeIcon from './SendflakeIcon.svelte'
|
||||
import QRCodeIcon from './QRCodeIcon.svelte'
|
||||
|
||||
export const APP_TO_ICON_COMPONENT = {
|
||||
export const APP_TO_ICON_COMPONENT = {
|
||||
postgresql: PostgresIcon,
|
||||
mysql: Mysql,
|
||||
smtp: Mail,
|
||||
@@ -45,6 +47,8 @@ export const APP_TO_ICON_COMPONENT = {
|
||||
http: HttpIcon,
|
||||
mailchimp: MailchimpIcon,
|
||||
sendgrid: SendgridIcon,
|
||||
snowflake: SendflakeIcon,
|
||||
qrcode: QRCodeIcon
|
||||
} as const
|
||||
|
||||
export {
|
||||
@@ -69,5 +73,5 @@ export {
|
||||
TogglIcon,
|
||||
WindmillIcon,
|
||||
MailchimpIcon,
|
||||
SendgridIcon,
|
||||
}
|
||||
SendgridIcon
|
||||
}
|
||||
|
||||
@@ -50,18 +50,24 @@
|
||||
|
||||
<Drawer bind:this={codeViewer} size="900px">
|
||||
<DrawerContent title={codeViewerObj?.summary ?? ''} on:close={codeViewer.closeDrawer}>
|
||||
<div slot="submission" class="flex flex-row gap-2 pr-2">
|
||||
<div slot="submission">
|
||||
<Button
|
||||
href="https://hub.windmill.dev/scripts/{codeViewerObj?.app ?? ''}/{codeViewerObj?.ask_id ??
|
||||
0}"
|
||||
startIcon={{ icon: faGlobe }}
|
||||
variant="border"
|
||||
variant="contained"
|
||||
color="light"
|
||||
size="sm"
|
||||
>
|
||||
View on the Hub
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
<Globe2 size="18px" />
|
||||
View on the Hub
|
||||
</div>
|
||||
</Button>
|
||||
<Button
|
||||
href="/scripts/add?hub={encodeURIComponent(codeViewerObj?.path ?? '')}"
|
||||
startIcon={{ icon: faCodeFork }}
|
||||
color="dark"
|
||||
size="sm"
|
||||
>
|
||||
Fork
|
||||
</Button>
|
||||
@@ -72,7 +78,7 @@
|
||||
</Drawer>
|
||||
|
||||
<Drawer bind:this={flowViewer} size="900px">
|
||||
<DrawerContent title="Hub flow" on:close={flowViewer.closeDrawer}>
|
||||
<DrawerContent title="Hub flow" on:close={flowViewer.closeDrawer} noPadding>
|
||||
<div slot="submission" class="flex flex-row gap-2 pr-2">
|
||||
<Button
|
||||
href="https://hub.windmill.dev/flows/{flowViewerFlow?.flow?.id}"
|
||||
@@ -87,7 +93,9 @@
|
||||
</div>
|
||||
|
||||
{#if flowViewerFlow?.flow}
|
||||
<FlowViewer flow={flowViewerFlow.flow} />
|
||||
<div class="p-4">
|
||||
<FlowViewer flow={flowViewerFlow.flow} />
|
||||
</div>
|
||||
{/if}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
@@ -114,7 +122,6 @@
|
||||
</div>
|
||||
</PageHeader>
|
||||
|
||||
<div class="my-6" />
|
||||
<Tabs bind:selected={tab}>
|
||||
<Tab size="md" value="workspace">
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
|
||||
Reference in New Issue
Block a user