mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-30 15:03:57 +00:00
message view UX
This commit is contained in:
@@ -4,20 +4,30 @@
|
|||||||
import JSONNode from './JSONNode.svelte';
|
import JSONNode from './JSONNode.svelte';
|
||||||
import JSONKey from './JSONKey.svelte';
|
import JSONKey from './JSONKey.svelte';
|
||||||
|
|
||||||
export let key, keys, colon = ':', label = '', isParentExpanded, isParentArray, isArray = false, bracketOpen, bracketClose;
|
export let key,
|
||||||
|
keys,
|
||||||
|
colon = ':',
|
||||||
|
label = '',
|
||||||
|
isParentExpanded,
|
||||||
|
isParentArray,
|
||||||
|
isArray = false,
|
||||||
|
bracketOpen,
|
||||||
|
bracketClose;
|
||||||
export let previewKeys = keys;
|
export let previewKeys = keys;
|
||||||
export let getKey = key => key;
|
export let getKey = key => key;
|
||||||
export let getValue = key => key;
|
export let getValue = key => key;
|
||||||
export let getPreviewValue = getValue;
|
export let getPreviewValue = getValue;
|
||||||
export let expanded = false, expandable = true;
|
export let expanded = false,
|
||||||
|
expandable = true;
|
||||||
export let elementValue = null;
|
export let elementValue = null;
|
||||||
|
export let onRootExpandedChanged = null;
|
||||||
|
|
||||||
const context = getContext('json-tree-context-key');
|
const context = getContext('json-tree-context-key');
|
||||||
setContext('json-tree-context-key', { ...context, colon })
|
setContext('json-tree-context-key', { ...context, colon });
|
||||||
const elementData=getContext('json-tree-element-data');
|
const elementData = getContext('json-tree-element-data');
|
||||||
const slicedKeyCount = getContext('json-tree-sliced-key-count');
|
const slicedKeyCount = getContext('json-tree-sliced-key-count');
|
||||||
|
|
||||||
$: slicedKeys = expanded ? keys: previewKeys.slice(0, slicedKeyCount || 5);
|
$: slicedKeys = expanded ? keys : previewKeys.slice(0, slicedKeyCount || 5);
|
||||||
|
|
||||||
$: if (!isParentExpanded) {
|
$: if (!isParentExpanded) {
|
||||||
expanded = false;
|
expanded = false;
|
||||||
@@ -25,6 +35,9 @@
|
|||||||
|
|
||||||
function toggleExpand() {
|
function toggleExpand() {
|
||||||
expanded = !expanded;
|
expanded = !expanded;
|
||||||
|
if (onRootExpandedChanged) {
|
||||||
|
onRootExpandedChanged(expanded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function expand() {
|
function expand() {
|
||||||
@@ -34,10 +47,41 @@
|
|||||||
let domElement;
|
let domElement;
|
||||||
|
|
||||||
$: if (domElement && elementData && elementValue) {
|
$: if (domElement && elementData && elementValue) {
|
||||||
elementData.set(domElement, elementValue)
|
elementData.set(domElement, elementValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<li class:indent={isParentExpanded} class:jsonValueHolder={!!elementValue} bind:this={domElement}>
|
||||||
|
<label>
|
||||||
|
{#if expandable && isParentExpanded}
|
||||||
|
<JSONArrow on:click={toggleExpand} {expanded} />
|
||||||
|
{/if}
|
||||||
|
<JSONKey {key} colon={context.colon} {isParentExpanded} {isParentArray} on:click={toggleExpand} />
|
||||||
|
<span on:click={toggleExpand}><span>{label}</span>{bracketOpen}</span>
|
||||||
|
</label>
|
||||||
|
{#if isParentExpanded}
|
||||||
|
<ul class:collapse={!expanded} on:click={expand}>
|
||||||
|
{#each slicedKeys as key, index}
|
||||||
|
<JSONNode
|
||||||
|
key={getKey(key)}
|
||||||
|
isParentExpanded={expanded}
|
||||||
|
isParentArray={isArray}
|
||||||
|
value={expanded ? getValue(key) : getPreviewValue(key)}
|
||||||
|
/>
|
||||||
|
{#if !expanded && index < previewKeys.length - 1}
|
||||||
|
<span class="comma">,</span>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
{#if slicedKeys.length < previewKeys.length}
|
||||||
|
<span>…</span>
|
||||||
|
{/if}
|
||||||
|
</ul>
|
||||||
|
{:else}
|
||||||
|
<span>…</span>
|
||||||
|
{/if}
|
||||||
|
<span>{bracketClose}</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
label {
|
label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -60,28 +104,3 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<li class:indent={isParentExpanded} class:jsonValueHolder={!!elementValue} bind:this={domElement}>
|
|
||||||
<label>
|
|
||||||
{#if expandable && isParentExpanded}
|
|
||||||
<JSONArrow on:click={toggleExpand} {expanded} />
|
|
||||||
{/if}
|
|
||||||
<JSONKey {key} colon={context.colon} {isParentExpanded} {isParentArray} on:click={toggleExpand} />
|
|
||||||
<span on:click={toggleExpand}><span>{label}</span>{bracketOpen}</span>
|
|
||||||
</label>
|
|
||||||
{#if isParentExpanded}
|
|
||||||
<ul class:collapse={!expanded} on:click={expand}>
|
|
||||||
{#each slicedKeys as key, index}
|
|
||||||
<JSONNode key={getKey(key)} isParentExpanded={expanded} isParentArray={isArray} value={expanded ? getValue(key) : getPreviewValue(key)} />
|
|
||||||
{#if !expanded && index < previewKeys.length - 1}
|
|
||||||
<span class="comma">,</span>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
{#if slicedKeys.length < previewKeys.length }
|
|
||||||
<span>…</span>
|
|
||||||
{/if}
|
|
||||||
</ul>
|
|
||||||
{:else}
|
|
||||||
<span>…</span>
|
|
||||||
{/if}
|
|
||||||
<span>{bracketClose}</span>
|
|
||||||
</li>
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
export let isParentArray;
|
export let isParentArray;
|
||||||
export let expanded = !!getContext('json-tree-default-expanded');
|
export let expanded = !!getContext('json-tree-default-expanded');
|
||||||
export let labelOverride = null;
|
export let labelOverride = null;
|
||||||
|
export let onRootExpandedChanged = null;
|
||||||
|
|
||||||
$: nodeType = objType(value);
|
$: nodeType = objType(value);
|
||||||
$: componentType = getComponent(nodeType);
|
$: componentType = getComponent(nodeType);
|
||||||
@@ -79,4 +80,5 @@
|
|||||||
{valueGetter}
|
{valueGetter}
|
||||||
{expanded}
|
{expanded}
|
||||||
{labelOverride}
|
{labelOverride}
|
||||||
|
{onRootExpandedChanged}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
export let key, value, isParentExpanded, isParentArray, nodeType;
|
export let key, value, isParentExpanded, isParentArray, nodeType;
|
||||||
export let expanded = false;
|
export let expanded = false;
|
||||||
export let labelOverride = null;
|
export let labelOverride = null;
|
||||||
|
export let onRootExpandedChanged = null;
|
||||||
|
|
||||||
$: keys = Object.getOwnPropertyNames(value);
|
$: keys = Object.getOwnPropertyNames(value);
|
||||||
|
|
||||||
@@ -24,4 +25,5 @@
|
|||||||
bracketOpen={'{'}
|
bracketOpen={'{'}
|
||||||
bracketClose={'}'}
|
bracketClose={'}'}
|
||||||
elementValue={value}
|
elementValue={value}
|
||||||
|
{onRootExpandedChanged}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
export let labelOverride = null;
|
export let labelOverride = null;
|
||||||
export let slicedKeyCount = null;
|
export let slicedKeyCount = null;
|
||||||
export let disableContextMenu = null;
|
export let disableContextMenu = null;
|
||||||
|
export let onRootExpandedChanged = null;
|
||||||
|
|
||||||
export let isDeleted = false;
|
export let isDeleted = false;
|
||||||
export let isInserted = false;
|
export let isInserted = false;
|
||||||
@@ -66,7 +67,15 @@
|
|||||||
class:isInserted
|
class:isInserted
|
||||||
class:isModified
|
class:isModified
|
||||||
>
|
>
|
||||||
<JSONNode {key} {value} isParentExpanded={true} isParentArray={false} {expanded} {labelOverride} />
|
<JSONNode
|
||||||
|
{key}
|
||||||
|
{value}
|
||||||
|
isParentExpanded={true}
|
||||||
|
isParentArray={false}
|
||||||
|
{expanded}
|
||||||
|
{labelOverride}
|
||||||
|
{onRootExpandedChanged}
|
||||||
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -67,7 +67,12 @@
|
|||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<div class="messages">
|
<div class="messages">
|
||||||
<SocketMessageView eventName={runid ? `runner-info-${runid}` : null} {executeNumber} showNoMessagesAlert />
|
<SocketMessageView
|
||||||
|
eventName={runid ? `runner-info-${runid}` : null}
|
||||||
|
{executeNumber}
|
||||||
|
showNoMessagesAlert
|
||||||
|
showCaller
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<svelte:fragment slot="footer">
|
<svelte:fragment slot="footer">
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
export let items: any[];
|
export let items: any[];
|
||||||
export let showProcedure = false;
|
export let showProcedure = false;
|
||||||
export let showLine = false;
|
export let showLine = false;
|
||||||
|
export let showCaller = false;
|
||||||
export let startLine = 0;
|
export let startLine = 0;
|
||||||
|
|
||||||
$: time0 = items[0] && new Date(items[0].time).getTime();
|
$: time0 = items[0] && new Date(items[0].time).getTime();
|
||||||
@@ -25,6 +26,9 @@
|
|||||||
{#if showLine}
|
{#if showLine}
|
||||||
<td class="header">Line</td>
|
<td class="header">Line</td>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if showCaller}
|
||||||
|
<td class="header">Caller</td>
|
||||||
|
{/if}
|
||||||
</tr>
|
</tr>
|
||||||
{#each items as row, index}
|
{#each items as row, index}
|
||||||
<MessageViewRow
|
<MessageViewRow
|
||||||
@@ -32,6 +36,7 @@
|
|||||||
{index}
|
{index}
|
||||||
{showProcedure}
|
{showProcedure}
|
||||||
{showLine}
|
{showLine}
|
||||||
|
{showCaller}
|
||||||
{time0}
|
{time0}
|
||||||
{startLine}
|
{startLine}
|
||||||
previousRow={index > 0 ? items[index - 1] : null}
|
previousRow={index > 0 ? items[index - 1] : null}
|
||||||
|
|||||||
100
packages/web/src/query/MessageViewRow.svelte
Normal file
100
packages/web/src/query/MessageViewRow.svelte
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
<script lang="ts" context="module">
|
||||||
|
function formatDuration(duration) {
|
||||||
|
if (duration == 0) return '0';
|
||||||
|
if (duration < 1000) {
|
||||||
|
return `${Math.round(duration)} ms`;
|
||||||
|
}
|
||||||
|
if (duration < 10000) {
|
||||||
|
return `${Math.round(duration / 100) / 10} s`;
|
||||||
|
}
|
||||||
|
return `${Math.round(duration / 1000)} s`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
import moment from 'moment';
|
||||||
|
import JSONTree from '../jsontree/JSONTree.svelte';
|
||||||
|
import FontIcon from '../icons/FontIcon.svelte';
|
||||||
|
import { plusExpandIcon } from '../icons/expandIcons';
|
||||||
|
|
||||||
|
export let row;
|
||||||
|
export let index;
|
||||||
|
export let showProcedure = false;
|
||||||
|
export let showLine = false;
|
||||||
|
export let showCaller = false;
|
||||||
|
export let time0;
|
||||||
|
export let startLine;
|
||||||
|
|
||||||
|
export let previousRow = null;
|
||||||
|
|
||||||
|
let isExpanded = false;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<tr
|
||||||
|
class:isError={row.severity == 'error'}
|
||||||
|
class:isDebug={row.severity == 'debug'}
|
||||||
|
class:isActive={row.line}
|
||||||
|
on:click={() => dispatch('messageclick', row)}
|
||||||
|
>
|
||||||
|
<td>{index + 1}</td>
|
||||||
|
<td>
|
||||||
|
<span on:click={() => (isExpanded = !isExpanded)} class="expand-button">
|
||||||
|
<FontIcon icon={plusExpandIcon(isExpanded)} />
|
||||||
|
</span>
|
||||||
|
{row.message}
|
||||||
|
</td>
|
||||||
|
<td>{moment(row.time).format('HH:mm:ss')}</td>
|
||||||
|
<td>{formatDuration(new Date(row.time).getTime() - time0)}</td>
|
||||||
|
<td> {previousRow ? formatDuration(new Date(row.time).getTime() - new Date(previousRow.time).getTime()) : 'n/a'}</td>
|
||||||
|
{#if showProcedure}
|
||||||
|
<td>{row.procedure || ''}</td>
|
||||||
|
{/if}
|
||||||
|
{#if showLine}
|
||||||
|
<td>{row.line == null ? '' : row.line + 1 + startLine}</td>
|
||||||
|
{/if}
|
||||||
|
{#if showCaller}
|
||||||
|
<td>{row.caller || ''}</td>
|
||||||
|
{/if}
|
||||||
|
</tr>
|
||||||
|
{#if isExpanded}
|
||||||
|
<tr>
|
||||||
|
<td colspan={5 + (showProcedure ? 1 : 0) + (showLine ? 1 : 0) + (showCaller ? 1 : 0)}>
|
||||||
|
<JSONTree
|
||||||
|
value={row}
|
||||||
|
expanded
|
||||||
|
onRootExpandedChanged={() => {
|
||||||
|
isExpanded = false;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.expand-button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.header {
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 2px solid var(--theme-border);
|
||||||
|
background-color: var(--theme-bg-1);
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
td:not(.header) {
|
||||||
|
border-top: 1px solid var(--theme-border);
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
tr.isActive:hover {
|
||||||
|
background: var(--theme-bg-2);
|
||||||
|
}
|
||||||
|
tr.isError {
|
||||||
|
color: var(--theme-icon-red);
|
||||||
|
}
|
||||||
|
tr.isDebug {
|
||||||
|
color: var(--theme-font-3);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -11,7 +11,12 @@
|
|||||||
<HorizontalSplitter>
|
<HorizontalSplitter>
|
||||||
<div class="container" slot="1">
|
<div class="container" slot="1">
|
||||||
<WidgetTitle>Messages</WidgetTitle>
|
<WidgetTitle>Messages</WidgetTitle>
|
||||||
<SocketMessageView eventName={runnerId ? `runner-info-${runnerId}` : null} {executeNumber} showNoMessagesAlert />
|
<SocketMessageView
|
||||||
|
eventName={runnerId ? `runner-info-${runnerId}` : null}
|
||||||
|
{executeNumber}
|
||||||
|
showNoMessagesAlert
|
||||||
|
showCaller
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="container" slot="2">
|
<div class="container" slot="2">
|
||||||
<WidgetTitle>Output files</WidgetTitle>
|
<WidgetTitle>Output files</WidgetTitle>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
export let showProcedure = false;
|
export let showProcedure = false;
|
||||||
export let showLine = false;
|
export let showLine = false;
|
||||||
|
export let showCaller = false;
|
||||||
export let eventName;
|
export let eventName;
|
||||||
export let executeNumber;
|
export let executeNumber;
|
||||||
export let showNoMessagesAlert = false;
|
export let showNoMessagesAlert = false;
|
||||||
@@ -68,5 +69,5 @@
|
|||||||
{#if showNoMessagesAlert && (!displayedMessages || displayedMessages.length == 0)}
|
{#if showNoMessagesAlert && (!displayedMessages || displayedMessages.length == 0)}
|
||||||
<ErrorInfo message="No messages" icon="img alert" />
|
<ErrorInfo message="No messages" icon="img alert" />
|
||||||
{:else}
|
{:else}
|
||||||
<MessageView items={displayedMessages} on:messageclick {showProcedure} {showLine} {startLine} />
|
<MessageView items={displayedMessages} on:messageclick {showProcedure} {showLine} {showCaller} {startLine} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -386,7 +386,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="2">
|
<svelte:fragment slot="2">
|
||||||
<SocketMessageView eventName={runnerId ? `runner-info-${runnerId}` : null} {executeNumber} showNoMessagesAlert />
|
<SocketMessageView
|
||||||
|
eventName={runnerId ? `runner-info-${runnerId}` : null}
|
||||||
|
{executeNumber}
|
||||||
|
showNoMessagesAlert
|
||||||
|
showCaller
|
||||||
|
/>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</VerticalSplitter>
|
</VerticalSplitter>
|
||||||
|
|
||||||
|
|||||||
@@ -255,6 +255,7 @@
|
|||||||
eventName={runnerId ? `runner-info-${runnerId}` : null}
|
eventName={runnerId ? `runner-info-${runnerId}` : null}
|
||||||
{executeNumber}
|
{executeNumber}
|
||||||
showNoMessagesAlert
|
showNoMessagesAlert
|
||||||
|
showCaller
|
||||||
/>
|
/>
|
||||||
</WidgetColumnBarItem>
|
</WidgetColumnBarItem>
|
||||||
<WidgetColumnBarItem title="Preview" name="preview" skip={!$previewReaderStore}>
|
<WidgetColumnBarItem title="Preview" name="preview" skip={!$previewReaderStore}>
|
||||||
|
|||||||
Reference in New Issue
Block a user