This commit is contained in:
@@ -49,6 +49,7 @@
|
|||||||
<app-file-viewer
|
<app-file-viewer
|
||||||
class="flex w-full flex-1"
|
class="flex w-full flex-1"
|
||||||
[file]="selectedFile()"
|
[file]="selectedFile()"
|
||||||
|
[(columns)]="selectedFileColumns"
|
||||||
></app-file-viewer>
|
></app-file-viewer>
|
||||||
} @else {
|
} @else {
|
||||||
<p-button
|
<p-button
|
||||||
@@ -69,7 +70,12 @@
|
|||||||
</p-splitter>
|
</p-splitter>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #panel>
|
<ng-template #panel>
|
||||||
<div class="flex items-center justify-center h-full">Panel 4</div>
|
@if (selectedFile()) {
|
||||||
|
<app-column-editor
|
||||||
|
class="w-full"
|
||||||
|
[(columns)]="selectedFileColumns"
|
||||||
|
></app-column-editor>
|
||||||
|
}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-splitter>
|
</p-splitter>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import { SplitButtonModule } from 'primeng/splitbutton';
|
|||||||
import { InputTextModule } from 'primeng/inputtext';
|
import { InputTextModule } from 'primeng/inputtext';
|
||||||
import { FileTreeComponent } from './file-tree/file-tree.component';
|
import { FileTreeComponent } from './file-tree/file-tree.component';
|
||||||
import { FileViewerComponent } from './file-viewer/file-viewer.component';
|
import { FileViewerComponent } from './file-viewer/file-viewer.component';
|
||||||
|
import { ColumnEditorComponent } from './column-editor/column-editor.component';
|
||||||
|
import { Column } from './duckdb.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
@@ -29,12 +31,14 @@ import { FileViewerComponent } from './file-viewer/file-viewer.component';
|
|||||||
SplitButtonModule,
|
SplitButtonModule,
|
||||||
FileTreeComponent,
|
FileTreeComponent,
|
||||||
FileViewerComponent,
|
FileViewerComponent,
|
||||||
|
ColumnEditorComponent,
|
||||||
],
|
],
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrl: './app.component.scss',
|
styleUrl: './app.component.scss',
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
protected selectedFile = signal<File | undefined>(undefined);
|
protected selectedFile = signal<File | undefined>(undefined);
|
||||||
|
protected selectedFileColumns = signal<Column[]>([]);
|
||||||
protected tabs = signal<File[]>([]);
|
protected tabs = signal<File[]>([]);
|
||||||
protected selectedTab = signal(0);
|
protected selectedTab = signal(0);
|
||||||
protected dragging = signal(false);
|
protected dragging = signal(false);
|
||||||
|
|||||||
55
src/app/column-editor/column-editor.component.ts
Normal file
55
src/app/column-editor/column-editor.component.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, model } from '@angular/core';
|
||||||
|
import { AccordionModule } from 'primeng/accordion';
|
||||||
|
import { Column } from '../duckdb.service';
|
||||||
|
import { Checkbox, CheckboxChangeEvent } from 'primeng/checkbox';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-column-editor',
|
||||||
|
standalone: true,
|
||||||
|
imports: [AccordionModule, Checkbox, FormsModule],
|
||||||
|
template: `
|
||||||
|
<p-accordion [value]="0">
|
||||||
|
<p-accordion-panel [value]="0">
|
||||||
|
<p-accordion-header>Columns</p-accordion-header>
|
||||||
|
<p-accordion-content>
|
||||||
|
<ul>
|
||||||
|
@for (column of columns(); track $index) {
|
||||||
|
<li>
|
||||||
|
<p-checkbox
|
||||||
|
(ngModelChange)="checkboxChanged($index)"
|
||||||
|
[binary]="true"
|
||||||
|
[inputId]="column.name"
|
||||||
|
name="group"
|
||||||
|
[ngModel]="column.enabled"
|
||||||
|
/>
|
||||||
|
<label [for]="column.name" class="ml-2">
|
||||||
|
{{ column.name }}
|
||||||
|
</label>
|
||||||
|
{{ column.name }}
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</p-accordion-content>
|
||||||
|
</p-accordion-panel>
|
||||||
|
</p-accordion>
|
||||||
|
`,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class ColumnEditorComponent {
|
||||||
|
columns = model<Column[]>();
|
||||||
|
|
||||||
|
protected checkboxChanged(index: number) {
|
||||||
|
this.columns.update((columns) => {
|
||||||
|
if (columns) {
|
||||||
|
let enabledColumns = columns?.slice();
|
||||||
|
enabledColumns[index] = {
|
||||||
|
...enabledColumns[index],
|
||||||
|
enabled: !enabledColumns[index].enabled,
|
||||||
|
};
|
||||||
|
return enabledColumns;
|
||||||
|
}
|
||||||
|
return columns;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import { z } from 'zod';
|
|||||||
export const Column = z.object({
|
export const Column = z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
type: z.string(),
|
type: z.string(),
|
||||||
|
enabled: z.boolean().default(true),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SortColumn = z.object({
|
export const SortColumn = z.object({
|
||||||
@@ -142,6 +143,7 @@ export class DuckdbService {
|
|||||||
cols.push({
|
cols.push({
|
||||||
name: jsonData['column_name'],
|
name: jsonData['column_name'],
|
||||||
type: jsonData['column_type'],
|
type: jsonData['column_type'],
|
||||||
|
enabled: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return cols;
|
return cols;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
effect,
|
effect,
|
||||||
inject,
|
inject,
|
||||||
input,
|
input,
|
||||||
|
model,
|
||||||
signal,
|
signal,
|
||||||
viewChild,
|
viewChild,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
@@ -43,14 +44,14 @@ import { PaginatorModule, PaginatorState } from 'primeng/paginator';
|
|||||||
PaginatorModule,
|
PaginatorModule,
|
||||||
],
|
],
|
||||||
template: `
|
template: `
|
||||||
@if (file() && columns().length > 0) {
|
@if (file() && enabledColumns().length > 0) {
|
||||||
<div class="h-full">
|
<div class="h-full">
|
||||||
<p-table
|
<p-table
|
||||||
#table
|
#table
|
||||||
sortMode="multiple"
|
sortMode="multiple"
|
||||||
[resizableColumns]="true"
|
[resizableColumns]="true"
|
||||||
columnResizeMode="expand"
|
columnResizeMode="expand"
|
||||||
[columns]="columns()"
|
[columns]="enabledColumns()"
|
||||||
[value]="currentValue()"
|
[value]="currentValue()"
|
||||||
showGridlines
|
showGridlines
|
||||||
[scrollable]="true"
|
[scrollable]="true"
|
||||||
@@ -124,7 +125,7 @@ import { PaginatorModule, PaginatorState } from 'primeng/paginator';
|
|||||||
@if (hasAggregates()) {
|
@if (hasAggregates()) {
|
||||||
<ng-template #footer>
|
<ng-template #footer>
|
||||||
<tr>
|
<tr>
|
||||||
@for (col of columns(); track $index) {
|
@for (col of enabledColumns(); track $index) {
|
||||||
<td #attachment>
|
<td #attachment>
|
||||||
@if (col.type === 'DOUBLE' || col.type === 'BIGINT') {
|
@if (col.type === 'DOUBLE' || col.type === 'BIGINT') {
|
||||||
<div class="flex items-baseline">
|
<div class="flex items-baseline">
|
||||||
@@ -174,7 +175,7 @@ export class FileViewerComponent {
|
|||||||
private duckdbService = inject(DuckdbService);
|
private duckdbService = inject(DuckdbService);
|
||||||
|
|
||||||
// Can't be computed since effect has to run first so file exists in duckdb
|
// Can't be computed since effect has to run first so file exists in duckdb
|
||||||
protected columns = signal<Column[]>([]);
|
columns = model<Column[]>([]);
|
||||||
protected aggregates = signal<(Aggregate | undefined)[]>([]);
|
protected aggregates = signal<(Aggregate | undefined)[]>([]);
|
||||||
protected currentAggregateColumn = signal<number | undefined>(undefined);
|
protected currentAggregateColumn = signal<number | undefined>(undefined);
|
||||||
protected aggregateValues = signal<(number | undefined)[]>([]);
|
protected aggregateValues = signal<(number | undefined)[]>([]);
|
||||||
@@ -195,6 +196,10 @@ export class FileViewerComponent {
|
|||||||
() => !!this.columns().find((col) => this.isAggregateColumn(col)),
|
() => !!this.columns().find((col) => this.isAggregateColumn(col)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
protected enabledColumns = computed(() =>
|
||||||
|
this.columns().filter((col) => col.enabled),
|
||||||
|
);
|
||||||
|
|
||||||
protected aggregateItems: MenuItem[] = aggregateTypes.map((type) => ({
|
protected aggregateItems: MenuItem[] = aggregateTypes.map((type) => ({
|
||||||
label: type,
|
label: type,
|
||||||
command: () => this.updateAggregateValue(type),
|
command: () => this.updateAggregateValue(type),
|
||||||
|
|||||||
Reference in New Issue
Block a user