master/detail working

This commit is contained in:
Jan Prochazka
2021-03-06 11:35:15 +01:00
parent ae9c4b4f98
commit b91cf18aee
6 changed files with 190 additions and 12 deletions

View File

@@ -70,6 +70,10 @@
export let frameSelection = undefined;
export let isLoading = false;
export let allRowCount = undefined;
export let onReferenceSourceChanged = undefined;
export let isLoadedAll;
export let loadedTime;
const wheelRowCount = 5;
const instance = get_current_component();
@@ -148,6 +152,13 @@
});
}
$: {
const _unused = selectedCells;
if (onReferenceSourceChanged && (grider.rowCount > 0 || isLoadedAll)) {
onReferenceSourceChanged(getSelectedRowData(), loadedTime);
}
}
function scrollIntoView(cell) {
const [row, col] = cell;

View File

@@ -6,6 +6,7 @@
export let loadRowCount;
export let grider;
export let display;
export let masterLoadedTime = undefined;
// export let griderFactory;
export let loadedRows = [];
@@ -87,6 +88,20 @@
$: if (display.cache.refreshTime > loadedTime) {
reload();
}
$: {
if (masterLoadedTime && masterLoadedTime > loadedTime) {
display.reload();
}
}
</script>
<DataGridCore {...$$props} loadNextData={handleLoadNextData} {grider} {isLoading} {allRowCount} />
<DataGridCore
{...$$props}
loadNextData={handleLoadNextData}
{grider}
{isLoading}
{allRowCount}
{isLoadedAll}
{loadedTime}
/>

View File

@@ -0,0 +1,39 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import FontIcon from '../icons/FontIcon.svelte';
import ToolbarButton from '../widgets/ToolbarButton.svelte';
const dispatch = createEventDispatcher();
export let reference;
</script>
<div class="container">
<div class="header">
<FontIcon icon="img reference" />
<div class="ml-2">
{reference.pureName} [{reference.columns.map(x => x.refName).join(', ')}] = master [
{reference.columns.map(x => x.baseName).join(', ')}]
</div>
</div>
<ToolbarButton icon="icon close" on:click={() => dispatch('close')}>Close</ToolbarButton>
</div>
<style>
.container {
display: flex;
justify-content: space-between;
align-items: center;
background: var(--theme-bg-modalheader);
height: var(--dim-toolbar-height);
min-height: var(--dim-toolbar-height);
overflow: hidden;
border-top: 1px solid var(--theme-border);
border-bottom: 1px solid var(--theme-border);
}
.header {
font-weight: bold;
margin-left: 10px;
display: flex;
}
</style>

View File

@@ -12,6 +12,7 @@
export let managerSize;
export let display: GridDisplay;
export let onReferenceClick = (ref) => {};
const dispatch = createEventDispatcher();
@@ -31,7 +32,7 @@
<div
class="link"
on:click={() =>
dispatch('referenceclick', {
onReferenceClick({
schemaName: fk.refSchemaName,
pureName: fk.refTableName,
columns: fk.columns.map(col => ({
@@ -50,12 +51,12 @@
{/if}
{#if dependencies.length > 0}
<div class="bold nowrap ml-1">References tables ({dependencies.length})</div>
<div class="bold nowrap ml-1">Dependend tables ({dependencies.length})</div>
{#each dependencies.filter(fk => filterName(filter, fk.pureName)) as fk}
<div
class="link"
on:click={() =>
dispatch('referenceclick', {
onReferenceClick({
schemaName: fk.schemaName,
pureName: fk.pureName,
columns: fk.columns.map(col => ({

View File

@@ -1,24 +1,36 @@
<script lang="ts">
import { createGridCache, TableFormViewDisplay, TableGridDisplay } from 'dbgate-datalib';
import { createGridCache, createGridConfig, TableFormViewDisplay, TableGridDisplay } from 'dbgate-datalib';
import { getFilterValueExpression } from 'dbgate-filterparser';
import { findEngineDriver } from 'dbgate-tools';
import _ from 'lodash';
import { writable } from 'svelte/store';
import VerticalSplitter from '../elements/VerticalSplitter.svelte';
import { extensions } from '../stores';
import stableStringify from 'json-stable-stringify';
import { useConnectionInfo, useDatabaseInfo } from '../utility/metadataLoaders';
import DataGrid from './DataGrid.svelte';
import ReferenceHeader from './ReferenceHeader.svelte';
import SqlDataGridCore from './SqlDataGridCore.svelte';
export let conid;
export let database;
export let schemaName;
export let pureName;
export let config;
export let setConfig;
export let cache;
export let setCache;
$: connection = useConnectionInfo({ conid });
$: dbinfo = useDatabaseInfo({ conid, database });
const cache = writable(createGridCache());
let myLoadedTime = 0;
const childCache = writable(createGridCache());
// $: console.log('display', display);
@@ -26,10 +38,10 @@
? new TableGridDisplay(
{ schemaName, pureName },
findEngineDriver($connection, $extensions),
$config,
config.update,
$cache,
cache.update,
config,
setConfig,
cache,
setCache,
$dbinfo
)
: // ? new TableFormViewDisplay(
@@ -42,6 +54,102 @@
// $dbinfo
// )
null;
const setChildConfig = (value, reference = undefined) => {
if (_.isFunction(value)) {
setConfig(x => ({
...x,
childConfig: value(x.childConfig),
}));
} else {
setConfig(x => ({
...x,
childConfig: value,
reference: reference === undefined ? x.reference : reference,
}));
}
};
const handleReferenceSourceChanged = (selectedRows, loadedTime) => {
myLoadedTime = loadedTime;
if (!reference) return;
const filtersBase = display && display.isGrouped ? config.filters : childConfig.filters;
const filters = {
...filtersBase,
..._.fromPairs(
reference.columns.map(col => [
col.refName,
selectedRows.map(x => getFilterValueExpression(x[col.baseName], col.dataType)).join(', '),
])
),
};
if (stableStringify(filters) != stableStringify(childConfig.filters)) {
setChildConfig(cfg => ({
...cfg,
filters,
}));
childCache.update(ca => ({
...ca,
refreshTime: new Date().getTime(),
}));
}
};
const handleCloseReference = () => {
setChildConfig(null, null);
};
$: reference = config.reference;
$: childConfig = config.childConfig;
</script>
<DataGrid {...$$props} gridCoreComponent={SqlDataGridCore} {display} />
<VerticalSplitter isSplitter={!!reference}>
<div slot="1">
<DataGrid
{...$$props}
gridCoreComponent={SqlDataGridCore}
{display}
onReferenceSourceChanged={reference ? handleReferenceSourceChanged : null}
onReferenceClick={reference => setChildConfig(createGridConfig(), reference)}
/>
</div>
<div slot="2" class="reference-container">
{#if reference}
<ReferenceHeader {reference} on:close={handleCloseReference} />
<div class="detail">
{#key `${reference.schemaName}.${reference.pureName}`}
<svelte:self
{...$$props}
pureName={reference.pureName}
schemaName={reference.schemaName}
config={childConfig}
setConfig={setChildConfig}
cache={$childCache}
setCache={childCache.update}
masterLoadedTime={myLoadedTime}
isDetailView
/>
{/key}
</div>
{/if}
</div>
</VerticalSplitter>
<style>
.reference-container {
position: absolute;
display: flex;
flex-direction: column;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.detail {
position: relative;
flex: 1;
}
</style>

View File

@@ -2,6 +2,9 @@
import App from '../App.svelte';
import TableDataGrid from '../datagrid/TableDataGrid.svelte';
import useGridConfig from '../utility/useGridConfig';
import { createGridCache, createGridConfig, TableFormViewDisplay, TableGridDisplay } from 'dbgate-datalib';
import { findEngineDriver } from 'dbgate-tools';
import { writable } from 'svelte/store';
export let tabid;
export let conid;
@@ -10,6 +13,7 @@
export let pureName;
const config = useGridConfig(tabid);
const cache = writable(createGridCache());
</script>
<TableDataGrid {...$$props} {config} />
<TableDataGrid {...$$props} config={$config} setConfig={config.update} cache={$cache} setCache={cache.update} />