mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 20:26:23 +00:00
removed perspective intersection observer
This commit is contained in:
parent
fe31cfb552
commit
bf51f45934
@ -4,7 +4,7 @@ import { format } from 'path';
|
||||
import { PerspectiveBindingGroup, PerspectiveCache } from './PerspectiveCache';
|
||||
import { PerspectiveDataLoader } from './PerspectiveDataLoader';
|
||||
|
||||
const PERSPECTIVE_PAGE_SIZE = 100;
|
||||
export const PERSPECTIVE_PAGE_SIZE = 10;
|
||||
|
||||
export interface PerspectiveDatabaseConfig {
|
||||
conid: string;
|
||||
|
@ -76,13 +76,14 @@ export class PerspectiveDisplayRow {
|
||||
rowCellSkips: boolean[] = null;
|
||||
|
||||
rowJoinIds: number[] = [];
|
||||
incompleteRowsIndicator: string[] = null;
|
||||
// incompleteRowsIndicator: string[] = null;
|
||||
}
|
||||
|
||||
export class PerspectiveDisplay {
|
||||
columns: PerspectiveDisplayColumn[] = [];
|
||||
rows: PerspectiveDisplayRow[] = [];
|
||||
readonly columnLevelCount: number;
|
||||
loadIndicatorsCounts: { [uniqueName: string]: number } = {};
|
||||
|
||||
constructor(public root: PerspectiveTreeNode, rows: any[]) {
|
||||
// dbg('source rows', rows);
|
||||
@ -92,7 +93,7 @@ export class PerspectiveDisplay {
|
||||
}
|
||||
this.columnLevelCount = _max(this.columns.map(x => x.parentNodes.length)) + 1;
|
||||
const collectedRows = this.collectRows(rows, root.childNodes);
|
||||
// dbg('collected rows', collectedRows);
|
||||
dbg('collected rows', collectedRows);
|
||||
// console.log('COLLECTED', JSON.stringify(collectedRows, null, 2));
|
||||
// this.mergeRows(collectedRows);
|
||||
this.mergeRows(collectedRows);
|
||||
@ -212,16 +213,22 @@ export class PerspectiveDisplay {
|
||||
}
|
||||
|
||||
mergeRow(collectedRow: CollectedPerspectiveDisplayRow, rowIndex: number): number {
|
||||
if (collectedRow.incompleteRowsIndicator?.length > 0) {
|
||||
for (const indicator of collectedRow.incompleteRowsIndicator) {
|
||||
if (!this.loadIndicatorsCounts[indicator]) {
|
||||
this.loadIndicatorsCounts[indicator] = rowIndex;
|
||||
}
|
||||
if (rowIndex < this.loadIndicatorsCounts[indicator]) {
|
||||
this.loadIndicatorsCounts[indicator] = rowIndex;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const mainRow = this.getRowAt(rowIndex);
|
||||
for (let i = 0; i < collectedRow.columnIndexes.length; i++) {
|
||||
mainRow.rowData[collectedRow.columnIndexes[i]] = collectedRow.rowData[i];
|
||||
}
|
||||
if (collectedRow.incompleteRowsIndicator) {
|
||||
mainRow.incompleteRowsIndicator = [
|
||||
...(mainRow.incompleteRowsIndicator || []),
|
||||
...collectedRow.incompleteRowsIndicator,
|
||||
];
|
||||
}
|
||||
|
||||
let rowCount = 1;
|
||||
for (const subrows of collectedRow.subRowCollections) {
|
||||
|
@ -12,13 +12,17 @@ test('test flat view', () => {
|
||||
const root = new PerspectiveTableNode(artistTable, chinookDbInfo, createPerspectiveConfig(), null, null, null, null);
|
||||
const display = new PerspectiveDisplay(root, artistDataFlat);
|
||||
|
||||
console.log(display.rows);
|
||||
expect(display.rows.length).toEqual(5);
|
||||
// console.log(display.loadIndicatorsCounts);
|
||||
// console.log(display.rows);
|
||||
expect(display.rows.length).toEqual(4);
|
||||
expect(display.rows[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
rowData: ['AC/DC'],
|
||||
})
|
||||
);
|
||||
expect(display.loadIndicatorsCounts).toEqual({
|
||||
Artist: 4,
|
||||
});
|
||||
});
|
||||
|
||||
test('test one level nesting', () => {
|
||||
@ -34,8 +38,9 @@ test('test one level nesting', () => {
|
||||
);
|
||||
const display = new PerspectiveDisplay(root, artistDataAlbum);
|
||||
|
||||
console.log(display.rows);
|
||||
expect(display.rows.length).toEqual(7);
|
||||
console.log(display.loadIndicatorsCounts);
|
||||
// console.log(display.rows);
|
||||
expect(display.rows.length).toEqual(6);
|
||||
expect(display.rows[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
rowData: ['AC/DC', 'For Those About To Rock We Salute You'],
|
||||
@ -63,6 +68,11 @@ test('test one level nesting', () => {
|
||||
rowSpans: [1, 1],
|
||||
})
|
||||
);
|
||||
|
||||
expect(display.loadIndicatorsCounts).toEqual({
|
||||
Artist: 6,
|
||||
'Artist.Album': 6,
|
||||
});
|
||||
});
|
||||
|
||||
test('test two level nesting', () => {
|
||||
@ -79,7 +89,7 @@ test('test two level nesting', () => {
|
||||
const display = new PerspectiveDisplay(root, artistDataAlbumTrack);
|
||||
|
||||
console.log(display.rows);
|
||||
expect(display.rows.length).toEqual(9);
|
||||
expect(display.rows.length).toEqual(8);
|
||||
expect(display.rows[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
rowData: ['AC/DC', 'For Those About To Rock We Salute You', 'For Those About To Rock (We Salute You)'],
|
||||
|
@ -1,55 +1,56 @@
|
||||
export default [
|
||||
{
|
||||
"ArtistId": 1,
|
||||
"Name": "AC/DC",
|
||||
"Album": [
|
||||
ArtistId: 1,
|
||||
Name: 'AC/DC',
|
||||
Album: [
|
||||
{
|
||||
"Title": "For Those About To Rock We Salute You",
|
||||
"ArtistId": 1
|
||||
Title: 'For Those About To Rock We Salute You',
|
||||
ArtistId: 1,
|
||||
},
|
||||
{
|
||||
"Title": "Let There Be Rock",
|
||||
"ArtistId": 1
|
||||
}
|
||||
]
|
||||
Title: 'Let There Be Rock',
|
||||
ArtistId: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"ArtistId": 2,
|
||||
"Name": "Accept",
|
||||
"Album": [
|
||||
ArtistId: 2,
|
||||
Name: 'Accept',
|
||||
Album: [
|
||||
{
|
||||
"Title": "Balls to the Wall",
|
||||
"ArtistId": 2
|
||||
Title: 'Balls to the Wall',
|
||||
ArtistId: 2,
|
||||
},
|
||||
{
|
||||
"Title": "Restless and Wild",
|
||||
"ArtistId": 2
|
||||
}
|
||||
]
|
||||
Title: 'Restless and Wild',
|
||||
ArtistId: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"ArtistId": 3,
|
||||
"Name": "Aerosmith",
|
||||
"Album": [
|
||||
ArtistId: 3,
|
||||
Name: 'Aerosmith',
|
||||
Album: [
|
||||
{
|
||||
"Title": "Big Ones",
|
||||
"ArtistId": 3
|
||||
}
|
||||
]
|
||||
Title: 'Big Ones',
|
||||
ArtistId: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"ArtistId": 4,
|
||||
"Name": "Alanis Morissette",
|
||||
"Album": [
|
||||
ArtistId: 4,
|
||||
Name: 'Alanis Morissette',
|
||||
Album: [
|
||||
{
|
||||
"Title": "Jagged Little Pill",
|
||||
"ArtistId": 4
|
||||
}
|
||||
]
|
||||
Title: 'Jagged Little Pill',
|
||||
ArtistId: 4,
|
||||
},
|
||||
{
|
||||
"incompleteRowsIndicator": [
|
||||
"Artist"
|
||||
]
|
||||
}
|
||||
]
|
||||
incompleteRowsIndicator: ['Artist.Album'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
incompleteRowsIndicator: ['Artist'],
|
||||
},
|
||||
];
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
export let rootNode;
|
||||
export let onLoadNext;
|
||||
export let incompleteRowsIndicator;
|
||||
|
||||
let domObserved;
|
||||
|
||||
@ -30,4 +31,4 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div bind:this={domObserved}>... data to be loaded</div>
|
||||
<div bind:this={domObserved} on:click={onLoadNext}>... data to be loaded {incompleteRowsIndicator.join(',')}</div>
|
||||
|
@ -12,9 +12,9 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { PerspectiveDisplay, PerspectiveTreeNode } from 'dbgate-datalib';
|
||||
import { PerspectiveDisplay, PerspectiveTreeNode, PERSPECTIVE_PAGE_SIZE } from 'dbgate-datalib';
|
||||
import _, { values } from 'lodash';
|
||||
import { onMount } from 'svelte';
|
||||
import { onMount, tick } from 'svelte';
|
||||
import resizeObserver from '../utility/resizeObserver';
|
||||
import PerspectiveIntersectionObserver from './PerspectiveIntersectionObserver.svelte';
|
||||
import debug from 'debug';
|
||||
@ -40,6 +40,7 @@
|
||||
|
||||
let dataRows;
|
||||
let domWrapper;
|
||||
let domTable;
|
||||
let errorMessage;
|
||||
let isLoading = false;
|
||||
|
||||
@ -51,7 +52,7 @@
|
||||
const loadProps = node.getNodeLoadProps(parentRows);
|
||||
let { rows, incomplete } = await node.dataProvider.loadData({
|
||||
...loadProps,
|
||||
topCount: counts[node.uniqueName] || 100,
|
||||
topCount: counts[node.uniqueName] || PERSPECTIVE_PAGE_SIZE,
|
||||
});
|
||||
// console.log('ROWS', rows, node.isRoot);
|
||||
|
||||
@ -111,7 +112,7 @@
|
||||
try {
|
||||
await loadLevelData(node, rows, counts);
|
||||
dataRows = rows;
|
||||
dbg('display rows', rows);
|
||||
dbg('data rows', rows);
|
||||
errorMessage = null;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
@ -142,6 +143,11 @@
|
||||
$: loadData(root, $loadedCounts);
|
||||
$: display = root && dataRows ? new PerspectiveDisplay(root, dataRows) : null;
|
||||
|
||||
$: {
|
||||
display;
|
||||
checkLoadAdditionalData();
|
||||
}
|
||||
|
||||
function buildMenu() {
|
||||
return [
|
||||
{
|
||||
@ -152,16 +158,86 @@
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function getLastVisibleRowIndex() {
|
||||
var rows = domTable.querySelectorAll('tbody>tr');
|
||||
const wrapBox = domWrapper.getBoundingClientRect();
|
||||
|
||||
let rowIndex = 0;
|
||||
// let lastTr = null;
|
||||
for (const row of rows) {
|
||||
const box = row.getBoundingClientRect();
|
||||
// console.log('BOX', box);
|
||||
if (box.y > wrapBox.bottom) {
|
||||
break;
|
||||
}
|
||||
// if (box.y > domWrapper.scrollTop + wrapBox.height) {
|
||||
// break;
|
||||
// }
|
||||
// lastTr = row;
|
||||
rowIndex += 1;
|
||||
}
|
||||
return rowIndex;
|
||||
}
|
||||
|
||||
async function checkLoadAdditionalData() {
|
||||
if (!display) return;
|
||||
await tick();
|
||||
if (!domTable) return;
|
||||
|
||||
const rowIndex = getLastVisibleRowIndex();
|
||||
|
||||
const growIndicators = _.keys(display.loadIndicatorsCounts).filter(
|
||||
indicator => rowIndex >= display.loadIndicatorsCounts[indicator]
|
||||
);
|
||||
|
||||
// console.log('growIndicators', growIndicators);
|
||||
// console.log('display.loadIndicatorsCounts IN', display.loadIndicatorsCounts);
|
||||
// console.log('rowIndex', rowIndex);
|
||||
|
||||
if (growIndicators.length > 0) {
|
||||
dbg('load next', growIndicators);
|
||||
loadedCounts.update(counts => {
|
||||
const res = { ...counts };
|
||||
for (const id of growIndicators) {
|
||||
res[id] = (res[id] || PERSPECTIVE_PAGE_SIZE) + PERSPECTIVE_PAGE_SIZE;
|
||||
}
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
// console.log('LAST VISIBLE ROW', rowIndex, wrapBox.height, lastTr, lastTr.getBoundingClientRect());
|
||||
|
||||
// var start = 0;
|
||||
// var end = rows.length;
|
||||
// var count = 0;
|
||||
|
||||
// while (start != end) {
|
||||
// var mid = start + Math.floor((end - start) / 2);
|
||||
// if ($(rows[mid]).offset().top < document.documentElement.scrollTop) start = mid + 1;
|
||||
// else end = mid;
|
||||
// }
|
||||
|
||||
// console.log('SCROLL', domTable.querySelector('tr:visible:last'));
|
||||
}
|
||||
|
||||
// $: console.log('display.loadIndicatorsCounts', display?.loadIndicatorsCounts);
|
||||
</script>
|
||||
|
||||
<div class="wrapper" bind:this={domWrapper} use:resizeObserver={true} use:contextMenu={buildMenu}>
|
||||
<div
|
||||
class="wrapper"
|
||||
bind:this={domWrapper}
|
||||
use:resizeObserver={true}
|
||||
use:contextMenu={buildMenu}
|
||||
on:scroll={checkLoadAdditionalData}
|
||||
>
|
||||
{#if display}
|
||||
<table>
|
||||
<table bind:this={domTable}>
|
||||
<thead>
|
||||
{#each _.range(display.columnLevelCount) as columnLevel}
|
||||
<tr>
|
||||
{#each display.columns as column}
|
||||
<PerspectiveHeaderControl label={column.title} {column} {columnLevel} {setConfig} {config} />
|
||||
<PerspectiveHeaderControl {column} {columnLevel} {setConfig} {config} />
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
@ -185,12 +261,13 @@
|
||||
<td colspan={display.columns.length}
|
||||
><PerspectiveIntersectionObserver
|
||||
rootNode={domWrapper}
|
||||
incompleteRowsIndicator={row.incompleteRowsIndicator}
|
||||
onLoadNext={() => {
|
||||
dbg('load next', row.incompleteRowsIndicator);
|
||||
loadedCounts.update(counts => {
|
||||
const res = { ...counts };
|
||||
for (const id of row.incompleteRowsIndicator) {
|
||||
res[id] = (res[id] || 100) + 100;
|
||||
res[id] = (res[id] || PERSPECTIVE_PAGE_SIZE) + PERSPECTIVE_PAGE_SIZE;
|
||||
}
|
||||
return res;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user