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 { PerspectiveBindingGroup, PerspectiveCache } from './PerspectiveCache';
|
||||||
import { PerspectiveDataLoader } from './PerspectiveDataLoader';
|
import { PerspectiveDataLoader } from './PerspectiveDataLoader';
|
||||||
|
|
||||||
const PERSPECTIVE_PAGE_SIZE = 100;
|
export const PERSPECTIVE_PAGE_SIZE = 10;
|
||||||
|
|
||||||
export interface PerspectiveDatabaseConfig {
|
export interface PerspectiveDatabaseConfig {
|
||||||
conid: string;
|
conid: string;
|
||||||
|
@ -76,13 +76,14 @@ export class PerspectiveDisplayRow {
|
|||||||
rowCellSkips: boolean[] = null;
|
rowCellSkips: boolean[] = null;
|
||||||
|
|
||||||
rowJoinIds: number[] = [];
|
rowJoinIds: number[] = [];
|
||||||
incompleteRowsIndicator: string[] = null;
|
// incompleteRowsIndicator: string[] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PerspectiveDisplay {
|
export class PerspectiveDisplay {
|
||||||
columns: PerspectiveDisplayColumn[] = [];
|
columns: PerspectiveDisplayColumn[] = [];
|
||||||
rows: PerspectiveDisplayRow[] = [];
|
rows: PerspectiveDisplayRow[] = [];
|
||||||
readonly columnLevelCount: number;
|
readonly columnLevelCount: number;
|
||||||
|
loadIndicatorsCounts: { [uniqueName: string]: number } = {};
|
||||||
|
|
||||||
constructor(public root: PerspectiveTreeNode, rows: any[]) {
|
constructor(public root: PerspectiveTreeNode, rows: any[]) {
|
||||||
// dbg('source rows', rows);
|
// dbg('source rows', rows);
|
||||||
@ -92,7 +93,7 @@ export class PerspectiveDisplay {
|
|||||||
}
|
}
|
||||||
this.columnLevelCount = _max(this.columns.map(x => x.parentNodes.length)) + 1;
|
this.columnLevelCount = _max(this.columns.map(x => x.parentNodes.length)) + 1;
|
||||||
const collectedRows = this.collectRows(rows, root.childNodes);
|
const collectedRows = this.collectRows(rows, root.childNodes);
|
||||||
// dbg('collected rows', collectedRows);
|
dbg('collected rows', collectedRows);
|
||||||
// console.log('COLLECTED', JSON.stringify(collectedRows, null, 2));
|
// console.log('COLLECTED', JSON.stringify(collectedRows, null, 2));
|
||||||
// this.mergeRows(collectedRows);
|
// this.mergeRows(collectedRows);
|
||||||
this.mergeRows(collectedRows);
|
this.mergeRows(collectedRows);
|
||||||
@ -212,16 +213,22 @@ export class PerspectiveDisplay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mergeRow(collectedRow: CollectedPerspectiveDisplayRow, rowIndex: number): number {
|
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);
|
const mainRow = this.getRowAt(rowIndex);
|
||||||
for (let i = 0; i < collectedRow.columnIndexes.length; i++) {
|
for (let i = 0; i < collectedRow.columnIndexes.length; i++) {
|
||||||
mainRow.rowData[collectedRow.columnIndexes[i]] = collectedRow.rowData[i];
|
mainRow.rowData[collectedRow.columnIndexes[i]] = collectedRow.rowData[i];
|
||||||
}
|
}
|
||||||
if (collectedRow.incompleteRowsIndicator) {
|
|
||||||
mainRow.incompleteRowsIndicator = [
|
|
||||||
...(mainRow.incompleteRowsIndicator || []),
|
|
||||||
...collectedRow.incompleteRowsIndicator,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
let rowCount = 1;
|
let rowCount = 1;
|
||||||
for (const subrows of collectedRow.subRowCollections) {
|
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 root = new PerspectiveTableNode(artistTable, chinookDbInfo, createPerspectiveConfig(), null, null, null, null);
|
||||||
const display = new PerspectiveDisplay(root, artistDataFlat);
|
const display = new PerspectiveDisplay(root, artistDataFlat);
|
||||||
|
|
||||||
console.log(display.rows);
|
// console.log(display.loadIndicatorsCounts);
|
||||||
expect(display.rows.length).toEqual(5);
|
// console.log(display.rows);
|
||||||
|
expect(display.rows.length).toEqual(4);
|
||||||
expect(display.rows[0]).toEqual(
|
expect(display.rows[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
rowData: ['AC/DC'],
|
rowData: ['AC/DC'],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
expect(display.loadIndicatorsCounts).toEqual({
|
||||||
|
Artist: 4,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('test one level nesting', () => {
|
test('test one level nesting', () => {
|
||||||
@ -34,8 +38,9 @@ test('test one level nesting', () => {
|
|||||||
);
|
);
|
||||||
const display = new PerspectiveDisplay(root, artistDataAlbum);
|
const display = new PerspectiveDisplay(root, artistDataAlbum);
|
||||||
|
|
||||||
console.log(display.rows);
|
console.log(display.loadIndicatorsCounts);
|
||||||
expect(display.rows.length).toEqual(7);
|
// console.log(display.rows);
|
||||||
|
expect(display.rows.length).toEqual(6);
|
||||||
expect(display.rows[0]).toEqual(
|
expect(display.rows[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
rowData: ['AC/DC', 'For Those About To Rock We Salute You'],
|
rowData: ['AC/DC', 'For Those About To Rock We Salute You'],
|
||||||
@ -63,6 +68,11 @@ test('test one level nesting', () => {
|
|||||||
rowSpans: [1, 1],
|
rowSpans: [1, 1],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
expect(display.loadIndicatorsCounts).toEqual({
|
||||||
|
Artist: 6,
|
||||||
|
'Artist.Album': 6,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('test two level nesting', () => {
|
test('test two level nesting', () => {
|
||||||
@ -79,7 +89,7 @@ test('test two level nesting', () => {
|
|||||||
const display = new PerspectiveDisplay(root, artistDataAlbumTrack);
|
const display = new PerspectiveDisplay(root, artistDataAlbumTrack);
|
||||||
|
|
||||||
console.log(display.rows);
|
console.log(display.rows);
|
||||||
expect(display.rows.length).toEqual(9);
|
expect(display.rows.length).toEqual(8);
|
||||||
expect(display.rows[0]).toEqual(
|
expect(display.rows[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
rowData: ['AC/DC', 'For Those About To Rock We Salute You', 'For Those About To Rock (We Salute You)'],
|
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 [
|
export default [
|
||||||
{
|
{
|
||||||
"ArtistId": 1,
|
ArtistId: 1,
|
||||||
"Name": "AC/DC",
|
Name: 'AC/DC',
|
||||||
"Album": [
|
Album: [
|
||||||
{
|
{
|
||||||
"Title": "For Those About To Rock We Salute You",
|
Title: 'For Those About To Rock We Salute You',
|
||||||
"ArtistId": 1
|
ArtistId: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Title": "Let There Be Rock",
|
Title: 'Let There Be Rock',
|
||||||
"ArtistId": 1
|
ArtistId: 1,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ArtistId": 2,
|
ArtistId: 2,
|
||||||
"Name": "Accept",
|
Name: 'Accept',
|
||||||
"Album": [
|
Album: [
|
||||||
{
|
{
|
||||||
"Title": "Balls to the Wall",
|
Title: 'Balls to the Wall',
|
||||||
"ArtistId": 2
|
ArtistId: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Title": "Restless and Wild",
|
Title: 'Restless and Wild',
|
||||||
"ArtistId": 2
|
ArtistId: 2,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ArtistId": 3,
|
ArtistId: 3,
|
||||||
"Name": "Aerosmith",
|
Name: 'Aerosmith',
|
||||||
"Album": [
|
Album: [
|
||||||
{
|
{
|
||||||
"Title": "Big Ones",
|
Title: 'Big Ones',
|
||||||
"ArtistId": 3
|
ArtistId: 3,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ArtistId": 4,
|
ArtistId: 4,
|
||||||
"Name": "Alanis Morissette",
|
Name: 'Alanis Morissette',
|
||||||
"Album": [
|
Album: [
|
||||||
{
|
{
|
||||||
"Title": "Jagged Little Pill",
|
Title: 'Jagged Little Pill',
|
||||||
"ArtistId": 4
|
ArtistId: 4,
|
||||||
}
|
},
|
||||||
]
|
{
|
||||||
},
|
incompleteRowsIndicator: ['Artist.Album'],
|
||||||
{
|
},
|
||||||
"incompleteRowsIndicator": [
|
],
|
||||||
"Artist"
|
},
|
||||||
]
|
{
|
||||||
}
|
incompleteRowsIndicator: ['Artist'],
|
||||||
]
|
},
|
||||||
|
];
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
export let rootNode;
|
export let rootNode;
|
||||||
export let onLoadNext;
|
export let onLoadNext;
|
||||||
|
export let incompleteRowsIndicator;
|
||||||
|
|
||||||
let domObserved;
|
let domObserved;
|
||||||
|
|
||||||
@ -30,4 +31,4 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</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>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { PerspectiveDisplay, PerspectiveTreeNode } from 'dbgate-datalib';
|
import { PerspectiveDisplay, PerspectiveTreeNode, PERSPECTIVE_PAGE_SIZE } from 'dbgate-datalib';
|
||||||
import _, { values } from 'lodash';
|
import _, { values } from 'lodash';
|
||||||
import { onMount } from 'svelte';
|
import { onMount, tick } from 'svelte';
|
||||||
import resizeObserver from '../utility/resizeObserver';
|
import resizeObserver from '../utility/resizeObserver';
|
||||||
import PerspectiveIntersectionObserver from './PerspectiveIntersectionObserver.svelte';
|
import PerspectiveIntersectionObserver from './PerspectiveIntersectionObserver.svelte';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
let dataRows;
|
let dataRows;
|
||||||
let domWrapper;
|
let domWrapper;
|
||||||
|
let domTable;
|
||||||
let errorMessage;
|
let errorMessage;
|
||||||
let isLoading = false;
|
let isLoading = false;
|
||||||
|
|
||||||
@ -51,7 +52,7 @@
|
|||||||
const loadProps = node.getNodeLoadProps(parentRows);
|
const loadProps = node.getNodeLoadProps(parentRows);
|
||||||
let { rows, incomplete } = await node.dataProvider.loadData({
|
let { rows, incomplete } = await node.dataProvider.loadData({
|
||||||
...loadProps,
|
...loadProps,
|
||||||
topCount: counts[node.uniqueName] || 100,
|
topCount: counts[node.uniqueName] || PERSPECTIVE_PAGE_SIZE,
|
||||||
});
|
});
|
||||||
// console.log('ROWS', rows, node.isRoot);
|
// console.log('ROWS', rows, node.isRoot);
|
||||||
|
|
||||||
@ -111,7 +112,7 @@
|
|||||||
try {
|
try {
|
||||||
await loadLevelData(node, rows, counts);
|
await loadLevelData(node, rows, counts);
|
||||||
dataRows = rows;
|
dataRows = rows;
|
||||||
dbg('display rows', rows);
|
dbg('data rows', rows);
|
||||||
errorMessage = null;
|
errorMessage = null;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@ -142,6 +143,11 @@
|
|||||||
$: loadData(root, $loadedCounts);
|
$: loadData(root, $loadedCounts);
|
||||||
$: display = root && dataRows ? new PerspectiveDisplay(root, dataRows) : null;
|
$: display = root && dataRows ? new PerspectiveDisplay(root, dataRows) : null;
|
||||||
|
|
||||||
|
$: {
|
||||||
|
display;
|
||||||
|
checkLoadAdditionalData();
|
||||||
|
}
|
||||||
|
|
||||||
function buildMenu() {
|
function buildMenu() {
|
||||||
return [
|
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>
|
</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}
|
{#if display}
|
||||||
<table>
|
<table bind:this={domTable}>
|
||||||
<thead>
|
<thead>
|
||||||
{#each _.range(display.columnLevelCount) as columnLevel}
|
{#each _.range(display.columnLevelCount) as columnLevel}
|
||||||
<tr>
|
<tr>
|
||||||
{#each display.columns as column}
|
{#each display.columns as column}
|
||||||
<PerspectiveHeaderControl label={column.title} {column} {columnLevel} {setConfig} {config} />
|
<PerspectiveHeaderControl {column} {columnLevel} {setConfig} {config} />
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
@ -185,12 +261,13 @@
|
|||||||
<td colspan={display.columns.length}
|
<td colspan={display.columns.length}
|
||||||
><PerspectiveIntersectionObserver
|
><PerspectiveIntersectionObserver
|
||||||
rootNode={domWrapper}
|
rootNode={domWrapper}
|
||||||
|
incompleteRowsIndicator={row.incompleteRowsIndicator}
|
||||||
onLoadNext={() => {
|
onLoadNext={() => {
|
||||||
dbg('load next', row.incompleteRowsIndicator);
|
dbg('load next', row.incompleteRowsIndicator);
|
||||||
loadedCounts.update(counts => {
|
loadedCounts.update(counts => {
|
||||||
const res = { ...counts };
|
const res = { ...counts };
|
||||||
for (const id of row.incompleteRowsIndicator) {
|
for (const id of row.incompleteRowsIndicator) {
|
||||||
res[id] = (res[id] || 100) + 100;
|
res[id] = (res[id] || PERSPECTIVE_PAGE_SIZE) + PERSPECTIVE_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user