open JSON array as tabular view

This commit is contained in:
Jan Prochazka
2021-12-02 12:58:22 +01:00
parent 94b1a25252
commit ea42b2bce1
13 changed files with 94 additions and 25 deletions

View File

@@ -14,7 +14,6 @@
export let isJsonView = false;
let filter;
</script>
<SearchBoxWrapper>

View File

@@ -147,19 +147,34 @@
<HorizontalSplitter initialValue="300px" bind:size={managerSize} hideFirst={$collapsedLeftColumnStore}>
<div class="left" slot="1">
<WidgetColumnBar>
<WidgetColumnBarItem title="Columns" name="columns" height="45%" skip={freeTableColumn || isFormView}>
<WidgetColumnBarItem
title="Columns"
name="columns"
height="45%"
show={(!freeTableColumn || isDynamicStructure) && !isFormView}
>
<ColumnManager {...$$props} {managerSize} {isJsonView} />
</WidgetColumnBarItem>
<WidgetColumnBarItem title="Filters" name="jsonFilters" height="30%" skip={!isDynamicStructure}>
<WidgetColumnBarItem
title="Filters"
name="jsonFilters"
height="30%"
skip={!isDynamicStructure || !display?.filterable}
>
<JsonViewFilters {...$$props} {managerSize} />
</WidgetColumnBarItem>
<WidgetColumnBarItem title="Columns" name="freeColumns" height="40%" skip={!freeTableColumn}>
<WidgetColumnBarItem
title="Columns"
name="freeColumns"
height="40%"
show={freeTableColumn && !isDynamicStructure}
>
<FreeTableColumnEditor {...$$props} {managerSize} />
</WidgetColumnBarItem>
<WidgetColumnBarItem title="Filters" name="filters" height="30%" skip={!isFormView}>
<WidgetColumnBarItem title="Filters" name="filters" height="30%" show={isFormView}>
<FormViewFilters {...$$props} {managerSize} driver={formDisplay?.driver} />
</WidgetColumnBarItem>
@@ -168,12 +183,12 @@
name="references"
height="30%"
collapsed={isDetailView}
skip={!showReferences || !display?.hasReferences}
show={showReferences && display?.hasReferences}
>
<ReferenceManager {...$$props} {managerSize} />
</WidgetColumnBarItem>
<WidgetColumnBarItem title="Macros" name="macros" skip={!showMacros} collapsed>
<WidgetColumnBarItem title="Macros" name="macros" show={showMacros} collapsed>
<MacroManager {...$$props} {managerSize} />
</WidgetColumnBarItem>
</WidgetColumnBar>

View File

@@ -25,4 +25,5 @@
label="Array({value.length})"
bracketOpen="["
bracketClose="]"
elementValue={value}
/>

View File

@@ -10,9 +10,11 @@
export let getValue = key => key;
export let getPreviewValue = getValue;
export let expanded = false, expandable = true;
export let elementValue = null;
const context = getContext('json-tree-context-key');
setContext('json-tree-context-key', { ...context, colon })
const elementData=getContext('json-tree-element-data');
$: slicedKeys = expanded ? keys: previewKeys.slice(0, 5);
@@ -28,6 +30,12 @@
expanded = true;
}
let domElement;
$: if (domElement && elementData && elementValue) {
elementData.set(domElement, elementValue)
}
</script>
<style>
label {
@@ -51,7 +59,7 @@
position: relative;
}
</style>
<li class:indent={isParentExpanded}>
<li class:indent={isParentExpanded} class:jsonValueHolder={!!elementValue} bind:this={domElement}>
<label>
{#if expandable && isParentExpanded}
<JSONArrow on:click={toggleExpand} {expanded} />

View File

@@ -2,6 +2,8 @@
import JSONNode from './JSONNode.svelte';
import { setContext } from 'svelte';
import contextMenu, { getContextMenu } from '../utility/contextMenu';
import openNewTab from '../utility/openNewTab';
import _ from 'lodash';
setContext('json-tree-context-key', {});
@@ -15,10 +17,45 @@
export let isInserted;
export let isModified;
const elementData = new WeakMap();
if (elementData) {
setContext('json-tree-element-data', elementData);
}
const parentMenu = getContextMenu();
function getElementMenu({ targetElement }) {
if (!targetElement) return null;
const closest = targetElement.closest('.jsonValueHolder');
if (!closest) return;
const value = elementData.get(closest);
if (value && _.isArray(value)) {
return {
text: 'Open as data sheet',
onClick: () => {
openNewTab(
{
title: 'Data #',
icon: 'img free-table',
tabComponent: 'FreeTableTab',
props: {},
},
{
editor: {
rows: value,
structure: { __isDynamicStructure: true, columns: [] },
},
}
);
},
};
}
}
</script>
<ul use:contextMenu={[parentMenu, menu]} class:isDeleted class:isInserted class:isModified>
<ul use:contextMenu={[parentMenu, menu, getElementMenu]} class:isDeleted class:isInserted class:isModified>
<JSONNode {key} {value} isParentExpanded={true} isParentArray={false} {expanded} {labelOverride} />
</ul>

View File

@@ -9,6 +9,7 @@
left={$currentDropDownMenu.left}
top={$currentDropDownMenu.top}
items={$currentDropDownMenu.items}
targetElement={$currentDropDownMenu.targetElement}
on:close={() => ($currentDropDownMenu = null)}
/>
{/if}

View File

@@ -53,7 +53,6 @@
}
return item;
}
</script>
<script>
@@ -69,6 +68,7 @@
export let top;
export let left;
export let onCloseParent;
export let targetElement;
let element;
@@ -104,7 +104,7 @@
submenuOffset = hoverOffset;
}, 500);
$: extracted = extractMenuItems(items);
$: extracted = extractMenuItems(items, { targetElement });
$: compacted = _.compact(extracted.map(x => mapItem(x, $commandsCustomized)));
$: filtered = compacted.filter(x => !x.disabled || !x.hideDisabled);
@@ -121,7 +121,6 @@
document.removeEventListener('mousedown', handleClickOutside, true);
};
});
</script>
<ul class="dropDownMenuMarker" style={`left: ${left}px; top: ${top}px`} bind:this={element}>
@@ -217,5 +216,4 @@
position: relative;
left: 15px;
}
</style>

View File

@@ -119,7 +119,7 @@
e.preventDefault();
const left = e.pageX;
const top = e.pageY;
currentDropDownMenu.set({ left, top, items: _.isFunction(menu) ? menu() : menu });
currentDropDownMenu.set({ left, top, items: menu, targetElement: e.target });
};
const handleKeyDown = (data, hash, keyString, keyCode, event) => {

View File

@@ -16,7 +16,7 @@
</script>
<script lang="ts">
import { createFreeTableModel, runMacro } from 'dbgate-datalib';
import { createFreeTableModel, FreeTableGridDisplay, runMacro } from 'dbgate-datalib';
import { setContext } from 'svelte';
import { writable } from 'svelte/store';
import registerCommand from '../commands/registerCommand';
@@ -87,6 +87,9 @@
setContext('collapsedLeftColumnStore', collapsedLeftColumnStore);
registerMenu({ command: 'freeTable.save', tag: 'save' });
// display is overridden in FreeTableGridCore, this is because of column manager
$: display = new FreeTableGridDisplay($modelState.value, $config, config.update, null, null);
</script>
{#if isLoading}
@@ -104,5 +107,7 @@
freeTableColumn
showMacros
onRunMacro={handleRunMacro}
isDynamicStructure={$modelState.value?.structure?.__isDynamicStructure}
{display}
/>
{/if}

View File

@@ -15,7 +15,7 @@ export default function contextMenu(node, items = []) {
if (items) {
const left = e.pageX;
const top = e.pageY;
currentDropDownMenu.set({ left, top, items });
currentDropDownMenu.set({ left, top, items, targetElement: e.target });
}
};
@@ -31,12 +31,12 @@ export default function contextMenu(node, items = []) {
};
}
function doExtractMenuItems(menu, res) {
function doExtractMenuItems(menu, res, options) {
if (_.isFunction(menu)) {
doExtractMenuItems(menu(), res);
doExtractMenuItems(menu(options), res, options);
} else if (_.isArray(menu)) {
for (const item of menu) {
doExtractMenuItems(item, res);
doExtractMenuItems(item, res, options);
}
} else if (_.isPlainObject(menu) && !menu._skip) {
res.push(menu);
@@ -77,9 +77,9 @@ function processTags(items) {
return res;
}
export function extractMenuItems(menu) {
export function extractMenuItems(menu, options = null) {
let res = [];
doExtractMenuItems(menu, res);
doExtractMenuItems(menu, res, options);
res = processTags(res);
return res;
}

View File

@@ -11,6 +11,7 @@
export let title;
export let name;
export let skip = false;
export let show = true;
export let height = null;
export let collapsed = null;
@@ -27,12 +28,12 @@
{
collapsed,
height,
skip,
skip: skip || !show,
},
dynamicProps
);
$: updateWidgetItemDefinition(widgetItemIndex, { collapsed: !visible, height, skip });
$: updateWidgetItemDefinition(widgetItemIndex, { collapsed: !visible, height, skip: skip || !show });
$: setInitialSize(height, $widgetColumnBarHeight);
@@ -46,7 +47,7 @@
let visible = !collapsed;
</script>
{#if !skip}
{#if !skip && show}
<WidgetTitle on:click={() => (visible = !visible)}>{title}</WidgetTitle>
{#if visible}