Files
windmill/frontend/src/lib/components/apps/editor/ComponentHeader.svelte
2023-03-20 08:26:02 +01:00

114 lines
3.4 KiB
Svelte

<script lang="ts">
import { classNames } from '$lib/utils'
import type { AppViewerContext } from '../types'
import { Anchor, Bug, Expand, Move } from 'lucide-svelte'
import { createEventDispatcher, getContext } from 'svelte'
import Popover from '$lib/components/Popover.svelte'
import { Alert, Button } from '$lib/components/common'
import type { AppComponent } from './component'
import { twMerge } from 'tailwind-merge'
export let component: AppComponent
export let selected: boolean
export let locked: boolean = false
export let hover: boolean = false
const dispatch = createEventDispatcher()
const { errorByComponent, openDebugRun } = getContext<AppViewerContext>('AppViewerContext')
$: error = Object.values($errorByComponent).find((e) => e.componentId === component.id)
function openDebugRuns() {
if ($openDebugRun) {
$openDebugRun(component.id)
}
}
</script>
{#if selected || hover}
<span
draggable="false"
title={`Id: ${component.id}`}
class={twMerge(
'px-2 text-2xs font-semibold w-fit absolute shadow -top-[9px] -left-[8px] border rounded-sm z-50 cursor-move',
selected
? 'bg-indigo-500/90 border-indigo-600 text-white'
: 'bg-blue-500/90 border-blue-600 text-white'
)}
>
{component.id}
</span>
{/if}
{#if selected}
<div class="top-[-9px] -right-[8px] flex flex-row absolute gap-1.5 z-50">
<button
title="Expand"
class={classNames(
'px-1 text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
)}
on:click={() => dispatch('expand')}
on:pointerdown|stopPropagation
>
<Expand aria-label="Expand position" size={14} />
</button>
<button
title="Lock Position"
class={classNames(
'px-1 text-2xs py-0.5 font-bold w-fit border rounded-sm cursor-pointer',
'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
)}
on:click={() => dispatch('lock')}
on:pointerdown|stopPropagation
>
{#if locked}
<Anchor aria-label="Unlock position" size={14} class="text-orange-500" />
{:else}
<Anchor aria-label="Lock position" size={14} />
{/if}
</button>
<span
draggable="false"
title="Move"
on:mousedown|stopPropagation|capture
class={classNames(
'px-1 text-2xs py-0.5 font-bold w-fit border cursor-move rounded-sm',
'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
)}
>
<Move size={14} />
</span>
</div>
{/if}
{#if error}
{@const json = JSON.parse(JSON.stringify(error.error))}
<span
title="Error"
class={classNames(
'text-red-500 px-1 text-2xs py-0.5 font-bold w-fit absolute border border-red-500 -bottom-1 shadow left-1/2 transform -translate-x-1/2 z-50 cursor-pointer',
'bg-red-100/80'
)}
>
<Popover notClickable placement="bottom" popupClass="!bg-white border w-96">
<Bug size={14} />
<span slot="text">
<div class="bg-white">
<Alert type="error" title={`${json?.name}: ${json?.message}`}>
<div class="flex flex-col gap-2">
<div>
<pre class=" whitespace-pre-wrap text-gray-900 bg-white border w-full p-4 text-xs"
>{json?.stack ?? ''}
</pre>
</div>
<Button color="red" variant="border" on:click={openDebugRuns}>Open Debug Runs</Button>
</div>
</Alert>
</div>
</span>
</Popover>
</span>
{/if}