message view UX

This commit is contained in:
SPRINX0\prochazka
2024-11-06 15:39:51 +01:00
parent 193940fd63
commit fbf288198b
11 changed files with 191 additions and 37 deletions

View File

@@ -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>

View File

@@ -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}
/> />

View File

@@ -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}
/> />

View File

@@ -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>

View File

@@ -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">

View File

@@ -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}

View 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>

View File

@@ -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>

View File

@@ -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}

View File

@@ -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>

View File

@@ -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}>