fix(frontend): fix large JSON viewer (#4273)

* fix(frontend): fix large JSON viewer

* fix(frontend): fix large JSON viewer

* fix(frontend): improve UX

* fix(frontend): improve show more button

* fix(frontend): add fading effect

* fix(frontend): remove show more when we reach the end

* fix(frontend): Add show more button to the raw tab

* fix(frontend): Add show more button to the raw tab
This commit is contained in:
Faton Ramadani
2024-08-21 16:23:53 +02:00
committed by GitHub
parent 9556d6f105
commit 86f7bd7f97
3 changed files with 141 additions and 86 deletions
+4 -47
View File
@@ -1,17 +1,12 @@
<script lang="ts">
import Highlight from 'svelte-highlight'
import json from 'svelte-highlight/languages/json'
import type { FlowValue } from '$lib/gen'
import { Tab, Tabs, TabContent, Button } from './common'
import { Tab, Tabs, TabContent } from './common'
import SchemaViewer from './SchemaViewer.svelte'
import FieldHeader from './FieldHeader.svelte'
import { copyToClipboard } from '../utils'
import FlowGraphViewer from './FlowGraphViewer.svelte'
import { Clipboard } from 'lucide-svelte'
import YAML from 'yaml'
import { yaml } from 'svelte-highlight/languages'
import HighlightTheme from './HighlightTheme.svelte'
import FlowViewerInner from './FlowViewerInner.svelte'
export let flow: {
summary: string
@@ -22,21 +17,12 @@
export let initialOpen: number | undefined = undefined
export let noSide = false
$: flowFiltered = {
summary: flow.summary,
description: flow.description,
value: flow.value,
schema: flow.schema
}
export let noGraph: boolean = false
export let tab: 'ui' | 'raw' | 'schema' = noGraph ? 'schema' : 'ui'
export let noSummary = false
export let noGraphDownload = false
let rawType: 'json' | 'yaml' = 'yaml'
let open: { [id: number]: boolean } = {}
if (initialOpen) {
open[initialOpen] = true
@@ -92,37 +78,8 @@
<FlowGraphViewer download={!noGraphDownload} {noSide} {flow} overflowAuto />
</div>
</TabContent>
<TabContent value="raw"
><Tabs bind:selected={rawType} wrapperClass="mt-4">
<Tab value="yaml">YAML</Tab>
<Tab value="json">JSON</Tab>
<svelte:fragment slot="content">
<div class="relative pt-2">
<Button
on:click={() =>
copyToClipboard(
rawType === 'yaml'
? YAML.stringify(flowFiltered)
: JSON.stringify(flowFiltered, null, 4)
)}
color="light"
variant="border"
size="xs"
startIcon={{ icon: Clipboard }}
btnClasses="absolute top-2 right-2 w-min"
>
Copy content
</Button>
<Highlight
class="overflow-auto px-1"
language={rawType === 'yaml' ? yaml : json}
code={rawType === 'yaml'
? YAML.stringify(flowFiltered)
: JSON.stringify(flowFiltered, null, 4)}
/>
</div>
</svelte:fragment>
</Tabs>
<TabContent value="raw">
<FlowViewerInner {flow} />
</TabContent>
<TabContent value="schema">
<div class="my-4" />
@@ -0,0 +1,132 @@
<script lang="ts">
import Highlight from 'svelte-highlight'
import json from 'svelte-highlight/languages/json'
import type { FlowValue } from '$lib/gen'
import { Tab, Tabs, Button } from './common'
import { copyToClipboard } from '../utils'
import { ArrowDown, Clipboard } from 'lucide-svelte'
import YAML from 'yaml'
import { yaml } from 'svelte-highlight/languages'
import HighlightTheme from './HighlightTheme.svelte'
export let flow: {
summary: string
description?: string
value: FlowValue
schema?: any
}
$: flowFiltered = {
summary: flow.summary,
description: flow.description,
value: flow.value,
schema: flow.schema
}
let rawType: 'json' | 'yaml' = 'yaml'
function trimStringToLines(inputString: string, maxLines: number = 100): string {
const lines = inputString?.split('\n') ?? []
const linesToKeep = lines.slice(0, maxLines)
return linesToKeep.join('\n')
}
let code: string = ''
function computeCode() {
const str =
rawType === 'json' ? JSON.stringify(flowFiltered, null, 4) : YAML.stringify(flowFiltered)
const numberOfLines = str.split('\n').length
if (numberOfLines > maxLines) {
shouldDisplayLoadMore = true
}
code = str
}
let shouldDisplayLoadMore = false
$: flowFiltered && rawType && computeCode()
let maxLines = 100
</script>
<HighlightTheme />
<div>
<Tabs
bind:selected={rawType}
on:selected={() => {
maxLines = 100
}}
>
<Tab value="yaml">YAML</Tab>
<Tab value="json">JSON</Tab>
<svelte:fragment slot="content">
<div class="relative pt-2">
<Button
on:click={() =>
copyToClipboard(
rawType === 'yaml'
? YAML.stringify(flowFiltered)
: JSON.stringify(flowFiltered, null, 4)
)}
color="light"
variant="border"
size="xs"
startIcon={{ icon: Clipboard }}
btnClasses="absolute top-2 right-2 w-min"
>
Copy content
</Button>
<div class={shouldDisplayLoadMore ? 'code-container' : ''}>
<Highlight
class="overflow-auto px-1"
language={rawType === 'yaml' ? yaml : json}
code={trimStringToLines(code, maxLines)}
/>
</div>
{#if shouldDisplayLoadMore}
<Button
on:click={() => {
maxLines += 500
// If the code is less than the max lines, we don't need to show the button
if (maxLines >= code?.split('\n').length) {
shouldDisplayLoadMore = false
}
}}
color="light"
size="xs"
btnClasses="mb-2 mx-2"
startIcon={{ icon: ArrowDown }}
>
Show more
</Button>
{/if}
</div>
</svelte:fragment>
</Tabs>
</div>
<style>
.code-container {
position: relative;
overflow: hidden;
}
.code-container::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 100px;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgb(var(--color-surface)));
pointer-events: none;
}
</style>
@@ -1,13 +1,10 @@
<script lang="ts">
import { Tabs, Tab, TabContent, Button } from '$lib/components/common'
import { copyToClipboard } from '$lib/utils'
import { CalendarCheck2, Clipboard, MailIcon, Terminal, Webhook } from 'lucide-svelte'
import { Highlight } from 'svelte-highlight'
import { yaml } from 'svelte-highlight/languages'
import json from 'svelte-highlight/languages/json'
import { Tabs, Tab, TabContent } from '$lib/components/common'
import { CalendarCheck2, MailIcon, Terminal, Webhook } from 'lucide-svelte'
import { Pane, Splitpanes } from 'svelte-splitpanes'
import YAML from 'yaml'
import HighlightTheme from '../HighlightTheme.svelte'
import FlowViewerInner from '../FlowViewerInner.svelte'
export let triggerSelected: 'webhooks' | 'email' | 'schedule' | 'cli' = 'webhooks'
export let flow_json: any | undefined = undefined
@@ -17,8 +14,6 @@
export let selected: string
let rawType: 'json' | 'yaml' = 'yaml'
$: if (hasStepDetails) {
selected = 'flow_step'
}
@@ -97,36 +92,7 @@
</Splitpanes>
</TabContent>
<TabContent value="raw" class="flex flex-col flex-1 h-full overflow-auto">
<Tabs bind:selected={rawType} wrapperClass="mt-4">
<Tab value="yaml">YAML</Tab>
<Tab value="json">JSON</Tab>
<svelte:fragment slot="content">
<div class="relative pt-2">
<Button
on:click={() =>
copyToClipboard(
rawType === 'yaml'
? YAML.stringify(flow_json)
: JSON.stringify(flow_json, null, 4)
)}
color="light"
variant="border"
size="xs"
startIcon={{ icon: Clipboard }}
btnClasses="absolute top-2 right-2 w-min"
>
Copy content
</Button>
<Highlight
class="overflow-auto px-1"
language={rawType === 'yaml' ? yaml : json}
code={rawType === 'yaml'
? YAML.stringify(flow_json)
: JSON.stringify(flow_json, null, 4)}
/>
</div>
</svelte:fragment>
</Tabs>
<FlowViewerInner flow={flow_json} />
</TabContent>
<TabContent value="flow_step" class="flex flex-col flex-1 h-full">
<slot name="flow_step" />