handle JSON in text cells

This commit is contained in:
Jan Prochazka
2022-02-10 09:46:07 +01:00
parent a768547e80
commit 253ec934ed
4 changed files with 32 additions and 15 deletions

View File

@@ -44,3 +44,18 @@ export function stringifyCellValue(value) {
if (_isPlainObject(value) || _isArray(value)) return JSON.stringify(value); if (_isPlainObject(value) || _isArray(value)) return JSON.stringify(value);
return value; return value;
} }
export function safeJsonParse(json, defaultValue?, logError = false) {
try {
return JSON.parse(json);
} catch (err) {
if (logError) {
console.error(`Error parsing JSON value "${json}"`, err);
}
return defaultValue;
}
}
export function isJsonLikeLongString(value) {
return _isString(value) && value.length > 100 && value.match(/^\s*\{.*\}\s*$|^\s*\[.*\]\s*$/);
}

View File

@@ -37,7 +37,7 @@
import _ from 'lodash'; import _ from 'lodash';
import ShowFormButton from '../formview/ShowFormButton.svelte'; import ShowFormButton from '../formview/ShowFormButton.svelte';
import { getBoolSettingsValue } from '../settings/settingsTools'; import { getBoolSettingsValue } from '../settings/settingsTools';
import { arrayToHexString } from 'dbgate-tools'; import { arrayToHexString, isJsonLikeLongString, safeJsonParse } from 'dbgate-tools';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import DictionaryLookupModal from '../modals/DictionaryLookupModal.svelte'; import DictionaryLookupModal from '../modals/DictionaryLookupModal.svelte';
import { openJsonDocument } from '../tabs/JsonTab.svelte'; import { openJsonDocument } from '../tabs/JsonTab.svelte';
@@ -84,6 +84,7 @@
$: style = computeStyle(maxWidth, col); $: style = computeStyle(maxWidth, col);
$: isJson = _.isPlainObject(value) && !(value?.type == 'Buffer' && _.isArray(value.data)) && !value.$oid; $: isJson = _.isPlainObject(value) && !(value?.type == 'Buffer' && _.isArray(value.data)) && !value.$oid;
$: jsonParsedValue = isJsonLikeLongString(value) ? safeJsonParse(value) : null;
</script> </script>
<td <td
@@ -114,7 +115,7 @@
<span class="value">false</span> <span class="value">false</span>
{:else if _.isNumber(value)} {:else if _.isNumber(value)}
<span class="value">{formatNumber(value)}</span> <span class="value">{formatNumber(value)}</span>
{:else if _.isString(value)} {:else if _.isString(value) && !jsonParsedValue}
{#if dateTimeRegex.test(value)} {#if dateTimeRegex.test(value)}
<span class="value"> <span class="value">
{formatDateTime(value)} {formatDateTime(value)}
@@ -134,6 +135,10 @@
<span class="null" title={JSON.stringify(value, undefined, 2)}>(JSON)</span> <span class="null" title={JSON.stringify(value, undefined, 2)}>(JSON)</span>
{:else if _.isArray(value)} {:else if _.isArray(value)}
<span class="null">[{value.length} items]</span> <span class="null">[{value.length} items]</span>
{:else if _.isPlainObject(jsonParsedValue)}
<span class="null" title={JSON.stringify(jsonParsedValue, undefined, 2)}>(JSON)</span>
{:else if _.isArray(jsonParsedValue)}
<span class="null">[{jsonParsedValue.length} items]</span>
{:else} {:else}
{value.toString()} {value.toString()}
{/if} {/if}
@@ -156,7 +161,11 @@
<ShowFormButton icon="icon open-in-new" on:click={() => openJsonDocument(value, undefined, true)} /> <ShowFormButton icon="icon open-in-new" on:click={() => openJsonDocument(value, undefined, true)} />
{/if} {/if}
{#if _.isArray(value)} {#if jsonParsedValue && _.isPlainObject(jsonParsedValue)}
<ShowFormButton icon="icon open-in-new" on:click={() => openJsonDocument(jsonParsedValue, undefined, true)} />
{/if}
{#if _.isArray(jsonParsedValue || value)}
<ShowFormButton <ShowFormButton
icon="icon open-in-new" icon="icon open-in-new"
on:click={() => on:click={() =>
@@ -169,7 +178,7 @@
}, },
{ {
editor: { editor: {
rows: value, rows: jsonParsedValue || value,
structure: { __isDynamicStructure: true, columns: [] }, structure: { __isDynamicStructure: true, columns: [] },
}, },
} }

View File

@@ -3,6 +3,7 @@ import { SeriesSizes } from './SeriesSizes';
import { CellAddress } from './selection'; import { CellAddress } from './selection';
import { GridDisplay } from 'dbgate-datalib'; import { GridDisplay } from 'dbgate-datalib';
import Grider from './Grider'; import Grider from './Grider';
import { isJsonLikeLongString, safeJsonParse } from 'dbgate-tools';
export function countColumnSizes(grider: Grider, columns, containerWidth, display: GridDisplay) { export function countColumnSizes(grider: Grider, columns, containerWidth, display: GridDisplay) {
const columnSizes = new SeriesSizes(); const columnSizes = new SeriesSizes();
@@ -68,6 +69,7 @@ export function countColumnSizes(grider: Grider, columns, containerWidth, displa
let text = value; let text = value;
if (_.isArray(value)) text = `[${value.length} items]`; if (_.isArray(value)) text = `[${value.length} items]`;
else if (value?.$oid) text = `ObjectId("${value.$oid}")`; else if (value?.$oid) text = `ObjectId("${value.$oid}")`;
else if (isJsonLikeLongString(value) && safeJsonParse(value)) text = '(JSON)';
const width = context.measureText(text).width + 8; const width = context.measureText(text).width + 8;
// console.log('colName', colName, text, width); // console.log('colName', colName, text, width);
columnSizes.putSizeOverride(colIndex, width); columnSizes.putSizeOverride(colIndex, width);

View File

@@ -2,9 +2,9 @@ import { writable, derived, readable } from 'svelte/store';
import { ExtensionsDirectory } from 'dbgate-types'; import { ExtensionsDirectory } from 'dbgate-types';
import invalidateCommands from './commands/invalidateCommands'; import invalidateCommands from './commands/invalidateCommands';
import getElectron from './utility/getElectron'; import getElectron from './utility/getElectron';
import { GlobalCommand } from './commands/registerCommand';
import { useConfig, useSettings } from './utility/metadataLoaders'; import { useConfig, useSettings } from './utility/metadataLoaders';
import _ from 'lodash'; import _ from 'lodash';
import { safeJsonParse } from 'dbgate-tools';
export interface TabDefinition { export interface TabDefinition {
title: string; title: string;
@@ -18,18 +18,9 @@ export interface TabDefinition {
tabOrder?: number; tabOrder?: number;
} }
function safeJsonParse(json, defaultValue) {
try {
return JSON.parse(json);
} catch (err) {
console.error(`Error parsing JSON value "${json}"`, err);
return defaultValue;
}
}
export function writableWithStorage<T>(defaultValue: T, storageName) { export function writableWithStorage<T>(defaultValue: T, storageName) {
const init = localStorage.getItem(storageName); const init = localStorage.getItem(storageName);
const res = writable<T>(init ? safeJsonParse(init, defaultValue) : defaultValue); const res = writable<T>(init ? safeJsonParse(init, defaultValue, true) : defaultValue);
res.subscribe(value => { res.subscribe(value => {
localStorage.setItem(storageName, JSON.stringify(value)); localStorage.setItem(storageName, JSON.stringify(value));
}); });