autoscroll + status viewer auto update

This commit is contained in:
Ruben Fiszel
2022-07-30 00:02:03 +02:00
parent 2ecec4b34c
commit 93a18b2c4d
9 changed files with 97 additions and 36 deletions

View File

@@ -3,6 +3,7 @@
import github from 'svelte-highlight/styles/github'
import { json } from 'svelte-highlight/languages'
import TableCustom from './TableCustom.svelte'
import { truncate } from '$lib/utils'
export let result: any
@@ -65,13 +66,13 @@
{#if resultKind == 'table-col'}
<div class="grid grid-flow-col-dense border border-gray-200 rounded-md ">
{#each Object.keys(result) as col}
<div class="flex flex-col min-w-full">
<div class="flex flex-col max-h-40 min-w-full overflow-auto">
<div class="px-12 text-left uppercase border-b bg-gray-50 overflow-hidden rounded-t-md ">
{col}
</div>
{#if Array.isArray(result[col])}
{#each result[col] as item}
<div class="px-12 text-left">
<div class="px-12 text-left whitespace-nowrap">
{typeof item === 'string' ? item : JSON.stringify(item)}
</div>
{/each}
@@ -87,7 +88,7 @@
{#each asListOfList(Object.values(result)[0]) as row}
<tr>
{#each row as v}
<td>{v ?? ''}</td>
<td>{truncate(v, 200) ?? ''}</td>
{/each}
</tr>
{/each}

View File

@@ -48,8 +48,8 @@
})
scheduleEnabled = schedule.enabled
scheduleCron = schedule.schedule
scheduleArgs = scheduleArgs
console.log(schedule.enabled, schedule.schedule)
scheduleArgs = schedule.args ?? {}
console.log(scheduleArgs)
}
}

View File

@@ -18,7 +18,7 @@
</div>
<div>
<ChevronButton text="logs" viewOptions={true}>
<div class="text-xs p-4 bg-gray-50 overflow-auto max-h-lg">
<div class="text-xs p-4 bg-gray-50 overflow-auto max-h-80 border mt-1">
<pre class="w-full">{job.logs}</pre>
</div>
</ChevronButton>

View File

@@ -15,7 +15,27 @@
let forloop_selected = ''
function loadResults() {
let logs: { [key: number]: string } = {}
let pres: { [key: number]: HTMLElement } = {}
async function loadResults() {
if (!('success' in job)) {
const mods = job?.flow_status?.modules
if (mods) {
let i = mods?.findIndex((x) => x.type == FlowStatusModule.type.IN_PROGRESS)
if (i != -1) {
let last = mods[i]
if (last?.type == FlowStatusModule.type.IN_PROGRESS) {
logs[i] =
(await JobService.getJob({ workspace: $workspaceStore ?? '', id: last.job ?? '' }))
.logs ?? ''
console.log(logs[i])
logs = logs
pres[i].scroll({ top: pres[i]?.scrollHeight, behavior: 'smooth' })
}
}
}
}
job?.flow_status?.modules?.forEach(async (x, i) => {
if (
(i >= jobs.length && x.type == FlowStatusModule.type.SUCCESS) ||
@@ -49,7 +69,7 @@
$: $workspaceStore && job && loadResults()
</script>
<div class="flow-root max-w-lg w-full p-4">
<div class="flow-root w-full p-4">
<div class="flex flex-row-reverse">
{#if job}
<div class="flex-col">
@@ -133,28 +153,33 @@
</div>
<div class="text-right text-sm whitespace-nowrap text-gray-500">
{job.flow_status?.modules[i].type}
{#if job.flow_status?.modules[i].forloop_jobs}
{#each job.flow_status?.modules[i].forloop_jobs ?? [] as job}
<div class="flex flex-col">
<a href="/run/{job}" class="font-medium text-blue-600"
>{truncateRev(job ?? '', 10)}</a
>
</div>
{/each}
{:else if job.flow_status?.modules[i].job}
<a href="/run/{job.flow_status?.modules[i].job}" class="font-medium text-blue-600"
>{truncateRev(job.flow_status?.modules[i].job ?? '', 10)}</a
>
{/if}
<div class=" max-h-40 overflow-y-auto">
{#if job.flow_status?.modules[i].forloop_jobs}
{#each job.flow_status?.modules[i].forloop_jobs ?? [] as job}
<div class="flex flex-col">
<a href="/run/{job}" class="font-medium text-blue-600"
>{truncateRev(job ?? '', 10)}</a
>
</div>
{/each}
{:else if job.flow_status?.modules[i].job}
<a
href="/run/{job.flow_status?.modules[i].job}"
class="font-medium text-blue-600"
>{truncateRev(job.flow_status?.modules[i].job ?? '', 10)}</a
>
{/if}
</div>
</div>
</div>
</div>
{#if jobs[i]}
{#if Array.isArray(jobs[i])}
<div class="flex flex-col space-y-2">
<div class="flex flex-col mt-2 space-y-2 max-h-60 overflow-y-auto shadow-inner">
{#each toCompletedJobs(jobs[i]) as job, i}
<button
class="underline text-blue-600 hover:text-blue-700"
class:text-red-600={!job.success}
on:click={() => {
if (forloop_selected == job.id) {
forloop_selected = ''
@@ -172,6 +197,15 @@
{:else}
<FlowJobResult job={toCompletedJob(jobs[i])} />
{/if}
{:else}
<div class="mx-20">
<pre
bind:this={pres[i]}
class="break-all p-4 relative h-full mx-2 bg-gray-50 text-xs max-h-40 overflow-y-auto border">{logs[
i
] ?? ''}
</pre>
</div>
{/if}
</div>
</li>

View File

@@ -9,22 +9,28 @@
export let format: string
export let value: any
console.log(value)
function isString(value: any) {
return typeof value === 'string' || value instanceof String
}
let path: string =
isString(value) && value.length >= '$res:'.length ? value.substr('$res:'.length) : undefined
let path: string = ''
let args: Record<string, any> = {}
if (!isString(value) && value) {
args = value
}
valueToPath()
let schema: any | undefined = undefined
let isValid = true
let resourceTypeName: string = ''
let option: 'resource' | 'raw' = isString(value) || value == undefined ? 'resource' : 'raw'
$: format.startsWith('resource-') && loadSchema(format)
async function loadSchema(format: string) {
resourceTypeName = format.substring('resource-'.length)
schema = (
@@ -32,16 +38,19 @@
).schema
}
let option: 'resource' | 'raw' = isString(value) || value == undefined ? 'resource' : 'raw'
$: {
function argToValue() {
if (option == 'resource') {
value = `$res:${path}`
} else {
value = args
}
}
$: format.startsWith('resource-') && loadSchema(format)
function valueToPath() {
path =
isString(value) && value.length >= '$res:'.length ? value.substr('$res:'.length) : undefined
}
$: value && valueToPath()
</script>
<div class="flex flex-row w-full gap-2">
@@ -51,12 +60,18 @@
[`Resource (${resourceTypeName})`, 'resource'],
[`Raw object value`, 'raw']
]}
on:change={argToValue}
bind:value={option}
/>
</div>
<div class="grow">
{#if option == 'resource'}
<ResourcePicker
on:refresh={() => loadSchema(format)}
on:change={(e) => {
path = e.detail
argToValue()
}}
bind:value={path}
resourceType={format.split('-').length > 1
? format.substring('resource-'.length)

View File

@@ -1,28 +1,32 @@
<script lang="ts">
import { type Resource, ResourceService } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
import { createEventDispatcher } from 'svelte'
import ResourceEditor from './ResourceEditor.svelte'
const dispatch = createEventDispatcher()
let resources: Resource[] = []
export let value: string | undefined = undefined
export let initialValue: string | undefined = undefined
export let value: string | undefined = initialValue
export let resourceType: string | undefined = undefined
let resourceEditor: ResourceEditor
async function loadResources(resourceType: string | undefined) {
const v = value
resources = await ResourceService.listResource({ workspace: $workspaceStore!, resourceType })
value = v
}
$: {
if ($workspaceStore) {
loadResources(resourceType)
}
}
$: dispatch('change', value)
</script>
<ResourceEditor bind:this={resourceEditor} on:refresh={() => loadResources(resourceType)} />
<select class="mt-1" bind:value placeholder="Pick a resource {resourceType}">
<option value={undefined} />
{#each resources as r}

View File

@@ -75,6 +75,8 @@
return editor
}
let div: HTMLElement | null = null
export async function runPreview(): Promise<void> {
try {
if (previewIntervalId) {
@@ -145,6 +147,7 @@
previewIsLoading = false
loadPastPreviews()
}
div?.scroll({ top: div?.scrollHeight, behavior: 'smooth' })
} catch (err) {
console.error(err)
}
@@ -367,7 +370,7 @@
</div>
</div>
</div>
<div class="preview flex-1 overflow-hidden p-3">
<div bind:this={div} class="preview flex-1 overflow-hidden p-3">
{#if previewTab === 'logs'}
<pre
class="break-all relative h-full mx-2">{#if previewJob && previewJob.logs}{previewJob.logs}

View File

@@ -206,10 +206,12 @@
}}
/>
</div>
<div class:bg-gray-300={!schedule.enabled}>
<div>
<div>
<h3 class="text-gray-700 ">Schedule</h3>
{schedule.schedule}
<h3 class="text-gray-700">Schedule</h3>
<span class="font-mono p-1 border" class:bg-gray-300={!schedule.enabled}
>{schedule.schedule}</span
>
</div>
<div>
<h3 class="text-gray-700 ">Args</h3>

View File

@@ -330,7 +330,9 @@
{#if job?.job_kind == 'flow' || job?.job_kind == 'flowpreview'}
<div class="mt-10" />
<FlowStatusViewer {job} bind:jobs />
<div class="max-w-lg">
<FlowStatusViewer {job} bind:jobs />
</div>
{/if}
</div>
<div>