diff --git a/README.md b/README.md index 5a76b66..4ef24a2 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,9 @@ # 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 -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. +`bun run build` diff --git a/src/app/duckdb.service.ts b/src/app/duckdb.service.ts index 1a9e85f..5b0b9d8 100644 --- a/src/app/duckdb.service.ts +++ b/src/app/duckdb.service.ts @@ -1,21 +1,39 @@ import { Injectable, OnInit } from '@angular/core'; import * as duckdb from '@duckdb/duckdb-wasm'; -import { connect } from 'rxjs'; +import { z } from 'zod'; -export interface Column { - name: string; - type: string; -} +export const Column = z.object({ + name: z.string(), + type: z.string(), +}); -export interface SortColumn { - name: string; - sortType: 'asc' | 'desc'; -} +const SortColumn = z.object({ + name: z.string(), + sortType: z.enum(['asc', 'desc']), +}); -export interface RowsResponse { - rows: any[]; - totalRows: bigint; -} +const Filter = z.object({ + value: z.string().array(), + 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; +export type SortColumn = z.infer; +export type Filter = z.infer; +export type RowsResponse = z.infer; const sanitisedFileName = (file: File) => file.name.toLowerCase().replaceAll("'", '').replaceAll(/\s*/g, ''); @@ -104,7 +122,7 @@ export class DuckdbService { numRows: number, columns: Column[], sorts: SortColumn[], - filters: unknown[], + filters: Filter[], aggregations: unknown[], ): Promise { const conn = await this.db.connect(); diff --git a/src/app/file-viewer/file-viewer.component.ts b/src/app/file-viewer/file-viewer.component.ts index cfc5bc5..4e1fb80 100644 --- a/src/app/file-viewer/file-viewer.component.ts +++ b/src/app/file-viewer/file-viewer.component.ts @@ -1,16 +1,13 @@ import { ChangeDetectionStrategy, - ChangeDetectorRef, Component, - computed, effect, inject, input, signal, - viewChild, } from '@angular/core'; import { Skeleton } from 'primeng/skeleton'; -import { Table, TableLazyLoadEvent, TableModule } from 'primeng/table'; +import { TableLazyLoadEvent, TableModule } from 'primeng/table'; import { Column, DuckdbService } from '../duckdb.service'; @Component({ @@ -34,6 +31,8 @@ import { Column, DuckdbService } from '../duckdb.service'; [virtualScrollItemSize]="46" [lazy]="true" (onLazyLoad)="onLazyLoad($event)" + [multiSortMeta]="[{ field: columns()[0].name, order: 1 }]" + stripedRows > @@ -43,7 +42,9 @@ import { Column, DuckdbService } from '../duckdb.service'; pResizableColumn [pSortableColumn]="col.name" > - {{ col.name }} + {{ col.name }} + + } @@ -116,7 +117,15 @@ export class FileViewerComponent { name: meta.field, 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