Add basic csv view inside a table loaded through duckdb
This commit is contained in:
125
src/app/file-viewer/file-viewer.component.ts
Normal file
125
src/app/file-viewer/file-viewer.component.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
effect,
|
||||
inject,
|
||||
input,
|
||||
signal,
|
||||
viewChild,
|
||||
} from '@angular/core';
|
||||
import { Skeleton } from 'primeng/skeleton';
|
||||
import { Table, TableLazyLoadEvent, TableModule } from 'primeng/table';
|
||||
import * as duckdb from '@duckdb/duckdb-wasm';
|
||||
import { Column, DuckdbService } from '../duckdb.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-file-viewer',
|
||||
standalone: true,
|
||||
imports: [TableModule, Skeleton],
|
||||
template: `
|
||||
@if (file() && columns().length > 0) {
|
||||
<p-table
|
||||
[columns]="columns()"
|
||||
[value]="currentValue()"
|
||||
[scrollable]="true"
|
||||
scrollHeight="400px"
|
||||
[rows]="100"
|
||||
[virtualScroll]="true"
|
||||
[virtualScrollItemSize]="46"
|
||||
[lazy]="true"
|
||||
(onLazyLoad)="onLazyLoad($event)"
|
||||
>
|
||||
<ng-template #header let-columns>
|
||||
<tr>
|
||||
@for (col of columns; track $index) {
|
||||
<th style="width: 20%">
|
||||
{{ col.name }}
|
||||
</th>
|
||||
}
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template #body let-rowData let-columns="columns">
|
||||
<tr style="height: 46px">
|
||||
@for (col of columns; track $index) {
|
||||
<td>
|
||||
{{ rowData[col.name] }}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template #loadingbody let-columns="columns">
|
||||
<tr style="height: 46px">
|
||||
@for (col of columns; track $index) {
|
||||
<td>
|
||||
<p-skeleton />
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
}
|
||||
`,
|
||||
styleUrl: './file-viewer.component.css',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class FileViewerComponent {
|
||||
file = input<File | undefined>();
|
||||
|
||||
private duckdbService = inject(DuckdbService);
|
||||
|
||||
// Can't be computed since effect has to run first so file exists in duckdb
|
||||
protected columns = signal<Column[]>([]);
|
||||
|
||||
private table = viewChild(Table);
|
||||
|
||||
// TODO: Basically make this an array of the same length as the number of rows, but an empty array.
|
||||
// We'll then store the actual current values in a separate array, then use the offset + row index
|
||||
// to get the actual value. This is so we don't store a crazy amount of data.
|
||||
// Alternative is to store current page data in the array (but keep the array length), and clear out the array each
|
||||
// time the page changes.
|
||||
protected currentValue = signal<any[]>([]);
|
||||
|
||||
constructor() {
|
||||
effect(async () => {
|
||||
const file = this.file();
|
||||
if (file) {
|
||||
await this.duckdbService.addFile(file);
|
||||
this.columns.set(await this.duckdbService.getColumns(file));
|
||||
const rows = await this.duckdbService.getRows(
|
||||
file,
|
||||
0,
|
||||
100,
|
||||
this.columns(),
|
||||
[],
|
||||
[],
|
||||
);
|
||||
const newValue = Array.from({ length: Number(rows.totalRows) });
|
||||
newValue.splice(0, 100, ...rows.rows);
|
||||
this.currentValue.set(newValue);
|
||||
}
|
||||
// TODO: Refresh table? Or is this automatic when columns change?
|
||||
// this.table().
|
||||
//TODO: Get rows in file
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Getting an infinite loop
|
||||
protected async onLazyLoad(event: TableLazyLoadEvent) {
|
||||
const file = this.file();
|
||||
if (file) {
|
||||
const rows = await this.duckdbService.getRows(
|
||||
file,
|
||||
event.first ?? 0,
|
||||
event.rows ?? 0,
|
||||
this.columns(),
|
||||
[],
|
||||
[],
|
||||
);
|
||||
if (!this.currentValue()) {
|
||||
this.currentValue.set(Array.from({ length: Number(rows.totalRows) }));
|
||||
}
|
||||
this.currentValue().splice(event.first!, event.rows!, ...rows.rows);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user