cell data view

This commit is contained in:
Jan Prochazka 2021-03-22 21:18:44 +01:00
parent 15c9e93e8a
commit 4e4447de8a
11 changed files with 204 additions and 19 deletions

View File

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

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

View File

@ -0,0 +1,5 @@
<script lang="ts">
export let selection;
</script>
<textarea class="flex1" wrap="no" readonly value={selection[0].value} />

View File

@ -0,0 +1,5 @@
<script lang="ts">
export let selection;
</script>
<textarea class="flex1" wrap="hard" readonly value={selection[0].value} />

View File

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

View File

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

View File

@ -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();

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

View File

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

View File

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

View File

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