Start adding filters, migrate types to zod, update readme
All checks were successful
build / build (push) Successful in 1m22s

This commit is contained in:
2025-04-25 09:30:38 +09:30
parent d225ff9048
commit 7bc6ca8a39
3 changed files with 51 additions and 74 deletions

View File

@@ -1,59 +1,9 @@
# IngeyEager # IngeyEager
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.1.8. A simple CSV viewer and analytics tool showcasing PrimeNG, Zod and DuckDB WASM. It all runs locally in the browser.
## Development server ## Build
To start a local development server, run: `bun install`
```bash `bun run build`
ng serve
```
Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
## Code scaffolding
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
```bash
ng generate component component-name
```
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
```bash
ng generate --help
```
## Building
To build the project run:
```bash
ng build
```
This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
## Running unit tests
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
```bash
ng test
```
## Running end-to-end tests
For end-to-end (e2e) testing, run:
```bash
ng e2e
```
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
## Additional Resources
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.

View File

@@ -1,21 +1,39 @@
import { Injectable, OnInit } from '@angular/core'; import { Injectable, OnInit } from '@angular/core';
import * as duckdb from '@duckdb/duckdb-wasm'; import * as duckdb from '@duckdb/duckdb-wasm';
import { connect } from 'rxjs'; import { z } from 'zod';
export interface Column { export const Column = z.object({
name: string; name: z.string(),
type: string; type: z.string(),
} });
export interface SortColumn { const SortColumn = z.object({
name: string; name: z.string(),
sortType: 'asc' | 'desc'; sortType: z.enum(['asc', 'desc']),
} });
export interface RowsResponse { const Filter = z.object({
rows: any[]; value: z.string().array(),
totalRows: bigint; operator: z.enum(['and', 'or']),
} matchType: z.enum([
'startsWith',
'contains',
'notContains',
'endsWith',
'equals',
'notEquals',
]),
});
const RowsResponse = z.object({
rows: z.any(),
totalRows: z.bigint(),
});
export type Column = z.infer<typeof Column>;
export type SortColumn = z.infer<typeof SortColumn>;
export type Filter = z.infer<typeof Filter>;
export type RowsResponse = z.infer<typeof RowsResponse>;
const sanitisedFileName = (file: File) => const sanitisedFileName = (file: File) =>
file.name.toLowerCase().replaceAll("'", '').replaceAll(/\s*/g, ''); file.name.toLowerCase().replaceAll("'", '').replaceAll(/\s*/g, '');
@@ -104,7 +122,7 @@ export class DuckdbService {
numRows: number, numRows: number,
columns: Column[], columns: Column[],
sorts: SortColumn[], sorts: SortColumn[],
filters: unknown[], filters: Filter[],
aggregations: unknown[], aggregations: unknown[],
): Promise<RowsResponse> { ): Promise<RowsResponse> {
const conn = await this.db.connect(); const conn = await this.db.connect();

View File

@@ -1,16 +1,13 @@
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef,
Component, Component,
computed,
effect, effect,
inject, inject,
input, input,
signal, signal,
viewChild,
} from '@angular/core'; } from '@angular/core';
import { Skeleton } from 'primeng/skeleton'; import { Skeleton } from 'primeng/skeleton';
import { Table, TableLazyLoadEvent, TableModule } from 'primeng/table'; import { TableLazyLoadEvent, TableModule } from 'primeng/table';
import { Column, DuckdbService } from '../duckdb.service'; import { Column, DuckdbService } from '../duckdb.service';
@Component({ @Component({
@@ -34,6 +31,8 @@ import { Column, DuckdbService } from '../duckdb.service';
[virtualScrollItemSize]="46" [virtualScrollItemSize]="46"
[lazy]="true" [lazy]="true"
(onLazyLoad)="onLazyLoad($event)" (onLazyLoad)="onLazyLoad($event)"
[multiSortMeta]="[{ field: columns()[0].name, order: 1 }]"
stripedRows
> >
<ng-template #header let-columns> <ng-template #header let-columns>
<tr> <tr>
@@ -43,7 +42,9 @@ import { Column, DuckdbService } from '../duckdb.service';
pResizableColumn pResizableColumn
[pSortableColumn]="col.name" [pSortableColumn]="col.name"
> >
{{ col.name }} <p-sortIcon [field]="col.name" /> {{ col.name }}
<p-columnFilter type="text" [field]="col.name" display="menu" />
<p-sortIcon [field]="col.name" />
</th> </th>
} }
</tr> </tr>
@@ -116,7 +117,15 @@ export class FileViewerComponent {
name: meta.field, name: meta.field,
sortType: meta.order < 0 ? 'desc' : 'asc', sortType: meta.order < 0 ? 'desc' : 'asc',
})) ?? [], })) ?? [],
[], Array.isArray(event.filters)
? Object.values(event.filters).map((filter) => ({
value: Array.isArray(filter.value)
? filter.value
: [filter.value],
matchType: filter.matchMode,
operator: filter.operator,
}))
: [],
[], [],
); );
// First clear out existing data, don't want to risk loading entire file into memory // First clear out existing data, don't want to risk loading entire file into memory