mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-05 16:03:47 +00:00
apps improvements
This commit is contained in:
@@ -220,18 +220,23 @@
|
||||
return
|
||||
}
|
||||
loading.save = true
|
||||
await computeTriggerables()
|
||||
await AppService.updateApp({
|
||||
workspace: $workspaceStore!,
|
||||
path: $page.params.path,
|
||||
requestBody: {
|
||||
value: $app!,
|
||||
summary: $summary,
|
||||
policy
|
||||
}
|
||||
})
|
||||
loading.save = false
|
||||
sendUserToast('App saved')
|
||||
try {
|
||||
await computeTriggerables()
|
||||
await AppService.updateApp({
|
||||
workspace: $workspaceStore!,
|
||||
path: $page.params.path,
|
||||
requestBody: {
|
||||
value: $app!,
|
||||
summary: $summary,
|
||||
policy
|
||||
}
|
||||
})
|
||||
sendUserToast('App saved')
|
||||
loading.save = false
|
||||
} catch (e) {
|
||||
loading.save = false
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
let selectedJobId: string | undefined = undefined
|
||||
|
||||
@@ -23,7 +23,13 @@
|
||||
<label class="block pb-2">
|
||||
<div class="text-xs font-medium pb-0.5"> Style </div>
|
||||
<div class="relative">
|
||||
<input type="text" class="!pr-7" bind:value={value.style} on:focus />
|
||||
<input
|
||||
on:keydown|stopPropagation
|
||||
type="text"
|
||||
class="!pr-7"
|
||||
bind:value={value.style}
|
||||
on:focus
|
||||
/>
|
||||
{#if value?.style}
|
||||
<button
|
||||
transition:fade|local={{ duration: 100 }}
|
||||
@@ -41,7 +47,13 @@
|
||||
<label class="block">
|
||||
<div class="text-xs font-medium pb-0.5"> Tailwind classes </div>
|
||||
<div class="relative">
|
||||
<input type="text" class="!pr-7" bind:value={value.class} on:focus />
|
||||
<input
|
||||
on:keydown|stopPropagation
|
||||
type="text"
|
||||
class="!pr-7"
|
||||
bind:value={value.class}
|
||||
on:focus
|
||||
/>
|
||||
{#if value?.class}
|
||||
<button
|
||||
transition:fade|local={{ duration: 100 }}
|
||||
|
||||
+6
-1
@@ -82,7 +82,12 @@
|
||||
<div class="h-full flex flex-col gap-1">
|
||||
<div class="flex justify-between w-full gap-2 px-2 pt-1 flex-row items-center">
|
||||
{#if name !== undefined}
|
||||
<input bind:value={name} placeholder="Inline script name" class="!text-xs !rounded-xs" />
|
||||
<input
|
||||
on:keydown|stopPropagation
|
||||
bind:value={name}
|
||||
placeholder="Inline script name"
|
||||
class="!text-xs !rounded-xs"
|
||||
/>
|
||||
{/if}
|
||||
<div class="flex w-full flex-row gap-2 items-center justify-end">
|
||||
{#if validCode}
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<div class="w-full flex gap-2 flex-col mt-2">
|
||||
{#each panes as value, index (index)}
|
||||
<div class="w-full flex flex-row gap-2 items-center relative">
|
||||
<input type="number" bind:value />
|
||||
<input on:keydown|stopPropagation type="number" bind:value />
|
||||
|
||||
<div class="absolute top-1 right-1">
|
||||
<Button
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<div class="w-full flex gap-2 flex-col mt-2">
|
||||
{#each tabs as value, index (index)}
|
||||
<div class="w-full flex flex-row gap-2 items-center relative">
|
||||
<input type="text" bind:value />
|
||||
<input on:keydown|stopPropagation type="text" bind:value />
|
||||
|
||||
<div class="absolute top-1 right-1">
|
||||
<Button
|
||||
|
||||
+7
-1
@@ -73,7 +73,13 @@
|
||||
<Loader2 class="animate-spin" size={18} />
|
||||
</div>
|
||||
{:else if filteredItems}
|
||||
<input bind:value={search} type="text" placeholder="Search" class="col-span-4 mb-2" />
|
||||
<input
|
||||
on:keydown|stopPropagation
|
||||
bind:value={search}
|
||||
type="text"
|
||||
placeholder="Search"
|
||||
class="col-span-4 mb-2"
|
||||
/>
|
||||
<div class="grid gap-1 grid-cols-4 max-h-[300px] overflow-auto">
|
||||
{#each filteredItems as { label, icon }}
|
||||
{@const formatedLabel = formatName(label)}
|
||||
|
||||
+6
-1
@@ -42,7 +42,12 @@
|
||||
{:else if componentInput.fieldType === 'labeledresource'}
|
||||
{#if componentInput?.value && typeof componentInput?.value == 'object' && 'label' in componentInput?.value}
|
||||
<div class="flex flex-col gap-1 w-full">
|
||||
<input placeholder="Label" type="text" bind:value={componentInput.value['label']} />
|
||||
<input
|
||||
on:keydown|stopPropagation
|
||||
placeholder="Label"
|
||||
type="text"
|
||||
bind:value={componentInput.value['label']}
|
||||
/>
|
||||
<ResourcePicker
|
||||
initialValue={componentInput.value?.['value']?.split('$res:')[1] || ''}
|
||||
on:change={(e) => {
|
||||
|
||||
+1
@@ -19,6 +19,7 @@
|
||||
<div class="w-full flex mt-1 items-center gap-2">
|
||||
<slot />
|
||||
<input
|
||||
on:keydown|stopPropagation
|
||||
type="text"
|
||||
placeholder="Search inline scripts"
|
||||
bind:value={filter}
|
||||
|
||||
@@ -96,7 +96,8 @@
|
||||
{
|
||||
displayName: 'Edit',
|
||||
icon: faPen,
|
||||
href: `/apps/edit/${path}?nodraft=true`
|
||||
href: `/apps/edit/${path}?nodraft=true`,
|
||||
disabled: !canWrite
|
||||
},
|
||||
{
|
||||
displayName: 'Use as template',
|
||||
|
||||
@@ -3,7 +3,6 @@ import { goto } from '$app/navigation'
|
||||
import {
|
||||
AppService,
|
||||
FlowService,
|
||||
FolderService,
|
||||
Script,
|
||||
ScriptService,
|
||||
UserService,
|
||||
@@ -234,6 +233,7 @@ export function canWrite(
|
||||
if (user.folders.findIndex((x) => path.startsWith('f/' + x)) != -1) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,20 @@
|
||||
import AppPreview from '$lib/components/apps/editor/AppPreview.svelte'
|
||||
import type { EditorBreakpoint } from '$lib/components/apps/types'
|
||||
|
||||
import { Skeleton } from '$lib/components/common'
|
||||
import { Button, Skeleton } from '$lib/components/common'
|
||||
import { AppService, AppWithLastVersion } from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { classNames } from '$lib/utils'
|
||||
import { canWrite } from '$lib/utils'
|
||||
import { faPen } from '@fortawesome/free-solid-svg-icons'
|
||||
import { writable } from 'svelte/store'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
let app: AppWithLastVersion | undefined = undefined
|
||||
let can_write = false
|
||||
|
||||
async function loadApp() {
|
||||
app = await AppService.getAppByPath({ workspace: $workspaceStore!, path: $page.params.path })
|
||||
can_write = canWrite(app?.path, app?.extra_perms!, $userStore)
|
||||
}
|
||||
|
||||
let queryId = $page.url.searchParams.get('workspace_id')
|
||||
@@ -49,6 +52,13 @@
|
||||
isEditor={false}
|
||||
noBackend={false}
|
||||
/>
|
||||
{#if can_write}
|
||||
<div class="absolute bottom-4 z-20 right-4">
|
||||
<Button size="sm" startIcon={{ icon: faPen }} variant="border" href="/apps/edit/{app.path}"
|
||||
>Edit</Button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<Skeleton layout={[10]} />
|
||||
|
||||
@@ -171,10 +171,9 @@
|
||||
<CenteredPage>
|
||||
{#if flow}
|
||||
<div class="prose-sm mx-auto mt-6">
|
||||
<div class="flex flex-row w-full justify-between item-center">
|
||||
<h1 class="mb-1 truncate">
|
||||
{defaultIfEmptyString(flow.summary, flow.path)}
|
||||
</h1>
|
||||
<div
|
||||
class="flex flex-row-reverse w-full flex-wrap md:flex-nowrap justify-between gap-x-2 gap-y-4"
|
||||
>
|
||||
<div class="flex flex-row-reverse gap-2 h-full">
|
||||
<Button
|
||||
href="/flows/run/{path}"
|
||||
@@ -198,7 +197,7 @@
|
||||
</Button>
|
||||
<Button
|
||||
href="/flows/add?template={flow.path}"
|
||||
variant="contained"
|
||||
variant="border"
|
||||
color="blue"
|
||||
size="md"
|
||||
startIcon={{ icon: faCodeFork }}
|
||||
@@ -206,10 +205,19 @@
|
||||
Fork
|
||||
</Button>
|
||||
{/if}
|
||||
<Button href="/runs/{flow.path}" color="blue" size="md" startIcon={{ icon: faList }}>
|
||||
<Button
|
||||
href="/runs/{flow.path}"
|
||||
variant="border"
|
||||
color="blue"
|
||||
size="md"
|
||||
startIcon={{ icon: faList }}
|
||||
>
|
||||
View runs
|
||||
</Button>
|
||||
</div>
|
||||
<h1 class="mb-1 truncate grow">
|
||||
{defaultIfEmptyString(flow.summary, flow.path)}
|
||||
</h1>
|
||||
</div>
|
||||
{#if !emptyString(flow.summary)}
|
||||
<span class="text-lg font-semibold">{flow.path}</span>
|
||||
@@ -218,7 +226,7 @@
|
||||
{/if}
|
||||
<ShareModal bind:this={shareModal} />
|
||||
|
||||
<div class="grid grid-cols-1 gap-6 max-w-7xl pb-6 mt-2">
|
||||
<div class="grid grid-cols-1 gap-6 max-w-7xl pb-6">
|
||||
<Skeleton
|
||||
loading={!flow}
|
||||
layout={[[{ h: 1.5, w: 40 }], 1, [4], 2.25, [{ h: 1.5, w: 30 }], 1, [10]]}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
import RunForm from '$lib/components/RunForm.svelte'
|
||||
import { Button, Kbd, Skeleton } from '$lib/components/common'
|
||||
import { faEye, faPlay, faScroll } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faEye, faPen, faPlay } from '@fortawesome/free-solid-svg-icons'
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
|
||||
const path = $page.params.path
|
||||
@@ -87,9 +87,21 @@
|
||||
<div
|
||||
class="flex flex-row-reverse w-full flex-wrap md:flex-nowrap justify-between gap-x-1"
|
||||
>
|
||||
<div class="flex flex-row">
|
||||
<div>
|
||||
<div class="flex flex-row gap-4">
|
||||
{#if !$userStore?.operator && can_write}
|
||||
<div>
|
||||
<Button
|
||||
size="sm"
|
||||
startIcon={{ icon: faPen }}
|
||||
disabled={flow == undefined}
|
||||
variant="border"
|
||||
href="/flows/edit/{flow?.path}">Edit</Button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="md:pr-4">
|
||||
<Button
|
||||
size="sm"
|
||||
startIcon={{ icon: faEye }}
|
||||
disabled={flow == undefined}
|
||||
btnClasses="mr-4"
|
||||
|
||||
@@ -281,7 +281,7 @@
|
||||
><Badge color="gray">{truncateHash(job.script_hash)}</Badge></a
|
||||
>
|
||||
{/if}
|
||||
{#if job && 'job_kind' in job}<Badge color="blue">{job.job_kind}</Badge>
|
||||
{#if job && 'job_kind' in job}<Badge baseClass="ml-2" color="blue">{job.job_kind}</Badge>
|
||||
{/if}
|
||||
{#if !job.visible_to_owner}<Badge color="red"
|
||||
>only visible to you <Tooltip
|
||||
|
||||
@@ -200,9 +200,9 @@
|
||||
<Skeleton {loading} layout={[[{ h: 1.5, w: 40 }], 1, [{ h: 1, w: 30 }]]} />
|
||||
|
||||
<div class="prose-sm mx-auto mt-6">
|
||||
<div class="flex flex-row w-full justify-between item-center">
|
||||
<h1 class="mb-1 truncate">{defaultIfEmptyString(script.summary, script.path)}</h1>
|
||||
|
||||
<div
|
||||
class="flex flex-row-reverse w-full flex-wrap md:flex-nowrap justify-between gap-x-2 gap-y-4"
|
||||
>
|
||||
<div class="flex flex-row-reverse gap-2 h-full">
|
||||
<Button
|
||||
href={`/scripts/run/${script.hash}`}
|
||||
@@ -243,13 +243,16 @@
|
||||
View Runs
|
||||
</Button>
|
||||
</div>
|
||||
<div class="grow truncate">
|
||||
<h1 class="mb-1 truncate">{defaultIfEmptyString(script.summary, script.path)}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if !emptyString(script.summary)}
|
||||
<span class="text-lg font-semibold">{script.path}</span>
|
||||
{/if}
|
||||
|
||||
<div class="flex flex-row gap-x-2 flex-wrap items-center mt-4">
|
||||
<div class="flex flex-row gap-x-2 flex-wrap items-center mt-2">
|
||||
<span class="text-sm text-gray-600">
|
||||
Edited {displayDaysAgo(script.created_at || '')} by {script.created_by || 'unknown'}
|
||||
</span>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import RunForm from '$lib/components/RunForm.svelte'
|
||||
import { Alert, Badge, Button, Kbd, Skeleton } from '$lib/components/common'
|
||||
import SharedBadge from '$lib/components/SharedBadge.svelte'
|
||||
import { faPlay, faScroll } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faEye, faPen, faPlay, faScroll } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
$: hash = $page.params.hash
|
||||
let script: Script | undefined
|
||||
@@ -112,15 +112,25 @@
|
||||
<div
|
||||
class="flex flex-row-reverse w-full flex-wrap md:flex-nowrap justify-between gap-x-1 gap-y-2"
|
||||
>
|
||||
<div class="flex flex-row">
|
||||
<div>
|
||||
<div class="flex flex-row gap-4">
|
||||
{#if !$userStore?.operator && can_write}
|
||||
<div>
|
||||
<Button
|
||||
size="sm"
|
||||
startIcon={{ icon: faPen }}
|
||||
disabled={script == undefined}
|
||||
variant="border"
|
||||
href="/scripts/edit/{script?.hash}?step=2">Edit</Button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="md:pr-4">
|
||||
<Button
|
||||
startIcon={{ icon: faScroll }}
|
||||
size="sm"
|
||||
startIcon={{ icon: faEye }}
|
||||
disabled={script == undefined}
|
||||
btnClasses="mr-4"
|
||||
variant="border"
|
||||
href="/scripts/get/{script?.hash}?workspace_id={$workspaceStore}"
|
||||
>View script</Button
|
||||
href="/scripts/get/{script?.hash}?workspace_id={$workspaceStore}">View</Button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user