mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 20:26:23 +00:00
cell data view
This commit is contained in:
parent
15c9e93e8a
commit
4e4447de8a
@ -45,6 +45,7 @@
|
||||
"file-selector": "^0.2.4",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"sirv-cli": "^1.0.0",
|
||||
"svelte-json-tree": "^0.1.0",
|
||||
"svelte-markdown": "^0.1.4",
|
||||
"svelte-select": "^3.17.0"
|
||||
}
|
||||
|
41
packages/web/src/celldata/JsonCellView.svelte
Normal file
41
packages/web/src/celldata/JsonCellView.svelte
Normal file
@ -0,0 +1,41 @@
|
||||
<script lang="ts">
|
||||
import JSONTree from 'svelte-json-tree';
|
||||
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||
|
||||
export let selection;
|
||||
|
||||
let json = null;
|
||||
let error = null;
|
||||
|
||||
$: try {
|
||||
json = JSON.parse(selection[0].value);
|
||||
error = null;
|
||||
} catch (err) {
|
||||
error = err.message;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if error}
|
||||
<ErrorInfo message="Error parsing JSON" />
|
||||
{:else}
|
||||
<div class="outer">
|
||||
<div class="inner">
|
||||
<JSONTree value={json} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.outer {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
.inner {
|
||||
overflow: scroll;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
5
packages/web/src/celldata/TextCellViewNoWrap.svelte
Normal file
5
packages/web/src/celldata/TextCellViewNoWrap.svelte
Normal file
@ -0,0 +1,5 @@
|
||||
<script lang="ts">
|
||||
export let selection;
|
||||
</script>
|
||||
|
||||
<textarea class="flex1" wrap="no" readonly value={selection[0].value} />
|
5
packages/web/src/celldata/TextCellViewWrap.svelte
Normal file
5
packages/web/src/celldata/TextCellViewWrap.svelte
Normal file
@ -0,0 +1,5 @@
|
||||
<script lang="ts">
|
||||
export let selection;
|
||||
</script>
|
||||
|
||||
<textarea class="flex1" wrap="hard" readonly value={selection[0].value} />
|
@ -234,7 +234,7 @@
|
||||
import DataFilterControl from './DataFilterControl.svelte';
|
||||
import createReducer from '../utility/createReducer';
|
||||
import keycodes from '../utility/keycodes';
|
||||
import { activeTabId, getActiveTabId, nullStore } from '../stores';
|
||||
import { activeTabId, getActiveTabId, nullStore, selectedCellsCallback } from '../stores';
|
||||
import memberStore from '../utility/memberStore';
|
||||
import axiosInstance from '../utility/axiosInstance';
|
||||
import { copyTextToClipboard } from '../utility/clipboard';
|
||||
@ -259,7 +259,7 @@
|
||||
export let focusOnVisible = false;
|
||||
export let onExportGrid = null;
|
||||
export let onOpenQuery = null;
|
||||
export let onOpenActiveChart=null;
|
||||
export let onOpenActiveChart = null;
|
||||
export let formViewAvailable = false;
|
||||
|
||||
export let isLoadedAll;
|
||||
@ -563,16 +563,13 @@
|
||||
domFocusField.focus();
|
||||
}
|
||||
|
||||
const lastPublishledRef = createRef('');
|
||||
$: if (onSelectionChanged) {
|
||||
const published = getCellsPublished(selectedCells);
|
||||
const stringified = stableStringify(published);
|
||||
if (lastPublishledRef.get() != stringified) {
|
||||
// console.log('PUBLISH', published);
|
||||
// console.log('lastPublishledRef.current', lastPublishledRef.current);
|
||||
// console.log('stringified', stringified);
|
||||
lastPublishledRef.set(stringified);
|
||||
onSelectionChanged(published);
|
||||
const lastPublishledSelectedCellsRef = createRef('');
|
||||
$: {
|
||||
const stringified = stableStringify(selectedCells);
|
||||
if (lastPublishledSelectedCellsRef.get() != stringified) {
|
||||
lastPublishledSelectedCellsRef.set(stringified);
|
||||
if (onSelectionChanged) onSelectionChanged(getCellsPublished(selectedCells));
|
||||
$selectedCellsCallback = () => getCellsPublished(selectedCells);
|
||||
}
|
||||
}
|
||||
|
||||
@ -589,13 +586,20 @@
|
||||
|
||||
function getCellsPublished(cells) {
|
||||
const regular = cellsToRegularCells(cells);
|
||||
// @ts-ignore
|
||||
return regular
|
||||
.map(cell => ({
|
||||
row: cell[0],
|
||||
column: realColumnUniqueNames[cell[1]],
|
||||
}))
|
||||
const res = regular
|
||||
.map(cell => {
|
||||
const row = cell[0];
|
||||
const rowData = grider.getRowData(row);
|
||||
const column = realColumnUniqueNames[cell[1]];
|
||||
return {
|
||||
row,
|
||||
rowData,
|
||||
column,
|
||||
value: rowData && rowData[column],
|
||||
};
|
||||
})
|
||||
.filter(x => x.column);
|
||||
return res;
|
||||
}
|
||||
|
||||
function scrollIntoView(cell) {
|
||||
|
@ -15,6 +15,7 @@
|
||||
'icon share': 'mdi mdi-share-variant',
|
||||
'icon add': 'mdi mdi-plus-circle',
|
||||
'icon connection': 'mdi mdi-connection',
|
||||
'icon cell-data': 'mdi mdi-details',
|
||||
|
||||
'icon database': 'mdi mdi-database',
|
||||
'icon server': 'mdi mdi-server',
|
||||
|
@ -46,6 +46,7 @@ export const openedModals = writable([]);
|
||||
export const nullStore = readable(null, () => {});
|
||||
export const currentArchive = writable('default');
|
||||
export const isFileDragActive = writable(false);
|
||||
export const selectedCellsCallback = writable(null);
|
||||
|
||||
const electron = getElectron();
|
||||
|
||||
|
113
packages/web/src/widgets/CellDataWidget.svelte
Normal file
113
packages/web/src/widgets/CellDataWidget.svelte
Normal file
@ -0,0 +1,113 @@
|
||||
<script lang="ts" context="module">
|
||||
const formats = [
|
||||
{
|
||||
type: 'textWrap',
|
||||
title: 'Text (wrap)',
|
||||
component: TextCellViewWrap,
|
||||
single: true,
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
title: 'Text (no wrap)',
|
||||
component: TextCellViewNoWrap,
|
||||
single: true,
|
||||
},
|
||||
{
|
||||
type: 'json',
|
||||
title: 'Json',
|
||||
component: JsonCellView,
|
||||
single: true,
|
||||
},
|
||||
];
|
||||
|
||||
function autodetect(selection) {
|
||||
const value = selection.length == 1 ? selection[0].value : null;
|
||||
if (_.isString(value)) {
|
||||
if (value.startsWith('[') || value.startsWith('{')) return 'json';
|
||||
}
|
||||
return 'textWrap';
|
||||
}
|
||||
|
||||
let cellSelectionListener = null;
|
||||
|
||||
export const getCellSelectionListener = () => cellSelectionListener;
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import _ from 'lodash';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import JsonCellView from '../celldata/JsonCellView.svelte';
|
||||
import TextCellViewNoWrap from '../celldata/TextCellViewNoWrap.svelte';
|
||||
import TextCellViewWrap from '../celldata/TextCellViewWrap.svelte';
|
||||
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||
import SelectField from '../forms/SelectField.svelte';
|
||||
import { selectedCellsCallback } from '../stores';
|
||||
import WidgetTitle from './WidgetTitle.svelte';
|
||||
|
||||
let selectedFormatType = 'autodetect';
|
||||
|
||||
export let selection = undefined;
|
||||
|
||||
$: autodetectFormatType = autodetect(selection);
|
||||
$: autodetectFormat = formats.find(x => x.type == autodetectFormatType);
|
||||
|
||||
$: usedFormatType = selectedFormatType == 'autodetect' ? autodetectFormatType : selectedFormatType;
|
||||
$: usedFormat = formats.find(x => x.type == usedFormatType);
|
||||
|
||||
$: selection = $selectedCellsCallback();
|
||||
</script>
|
||||
|
||||
<div class="wrapper">
|
||||
<WidgetTitle>Cell data view</WidgetTitle>
|
||||
<div class="main">
|
||||
<div class="toolbar">
|
||||
Format:
|
||||
<SelectField
|
||||
isNative
|
||||
value={selectedFormatType}
|
||||
on:change={e => (selectedFormatType = e.detail)}
|
||||
options={[
|
||||
{ value: 'autodetect', label: `Autodetect - ${autodetectFormat.title}` },
|
||||
...formats.map(fmt => ({ label: fmt.title, value: fmt.type })),
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div class="data">
|
||||
{#if usedFormat.single && selection?.length != 1}
|
||||
<ErrorInfo message="Must be selected one cell" />
|
||||
{:else if usedFormat == null}
|
||||
<ErrorInfo message="Format not selected" />
|
||||
{:else if !selection || selection.length == 0}
|
||||
<ErrorInfo message="No data selected" />
|
||||
{:else}
|
||||
<svelte:component this={usedFormat?.component} {selection} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.main {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
background: var(--theme-bg-1);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.data {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
@ -5,6 +5,7 @@
|
||||
import FilesWidget from './FilesWidget.svelte';
|
||||
import PluginsWidget from './PluginsWidget.svelte';
|
||||
import FavoritesWidget from './FavoritesWidget.svelte';
|
||||
import CellDataWidget from './CellDataWidget.svelte';
|
||||
</script>
|
||||
|
||||
{#if $selectedWidget == 'database'}
|
||||
@ -22,3 +23,6 @@
|
||||
{#if $selectedWidget == 'favorites'}
|
||||
<FavoritesWidget />
|
||||
{/if}
|
||||
{#if $selectedWidget == 'cell-data'}
|
||||
<CellDataWidget />
|
||||
{/if}
|
||||
|
@ -33,6 +33,11 @@
|
||||
name: 'favorites',
|
||||
title: 'Favorites',
|
||||
},
|
||||
{
|
||||
icon: 'icon cell-data',
|
||||
name: 'cell-data',
|
||||
title: 'Selected cell data detail view',
|
||||
},
|
||||
// {
|
||||
// icon: 'fa-cog',
|
||||
// name: 'settings',
|
||||
@ -56,7 +61,7 @@
|
||||
{/if}
|
||||
{#each widgets as item}
|
||||
<div class="wrapper" class:selected={item.name == $selectedWidget} on:click={() => handleChangeWidget(item.name)}>
|
||||
<FontIcon icon={item.icon} />
|
||||
<FontIcon icon={item.icon} title={item.title} />
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
|
@ -7022,6 +7022,11 @@ svelte-check@^1.0.0:
|
||||
svelte-preprocess "^4.0.0"
|
||||
typescript "*"
|
||||
|
||||
svelte-json-tree@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/svelte-json-tree/-/svelte-json-tree-0.1.0.tgz#2711e36162046a10766dfbef69739168a5eaafa6"
|
||||
integrity sha512-ufKWvS94z5m6Je9Hu0yosvdALy0mOPcaexbTcQQ/jW+3Rzi4oaHkOeg4RQ3cNpOlOQlIs0lfsF9FBlyquZ7XuQ==
|
||||
|
||||
svelte-markdown@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/svelte-markdown/-/svelte-markdown-0.1.4.tgz#03bec6dcd8ff1c09126e7c62c8a5a481905881d7"
|
||||
|
Loading…
Reference in New Issue
Block a user