import { Component, ElementRef, effect, signal, viewChild, } from '@angular/core'; import { ButtonModule } from 'primeng/button'; import { SplitterModule } from 'primeng/splitter'; import { TabsModule } from 'primeng/tabs'; import { ToolbarModule } from 'primeng/toolbar'; import { IconField } from 'primeng/iconfield'; import { InputIcon } from 'primeng/inputicon'; import { SplitButtonModule } from 'primeng/splitbutton'; import { InputTextModule } from 'primeng/inputtext'; import { FileTreeComponent } from './file-tree/file-tree.component'; import { FileViewerComponent } from './file-viewer/file-viewer.component'; import { ColumnEditorComponent } from './column-editor/column-editor.component'; import { Column } from './duckdb.service'; @Component({ selector: 'app-root', imports: [ ButtonModule, SplitterModule, TabsModule, ToolbarModule, IconField, InputIcon, InputTextModule, SplitButtonModule, FileTreeComponent, FileViewerComponent, ColumnEditorComponent, ], templateUrl: './app.component.html', styleUrl: './app.component.scss', }) export class AppComponent { protected selectedFile = signal(undefined); protected selectedFileColumns = signal([]); protected tabs = signal([]); protected selectedTab = signal(0); protected dragging = signal(false); private fileInput = viewChild>('fileSelector'); constructor() { effect(() => { const selectedFile = this.selectedFile(); if (selectedFile) { this.addFile(selectedFile); } }); effect(() => { if (this.selectedFile() !== this.tabs()[this.selectedTab()]) { if (this.tabs().length > 0) { this.selectedFile.set(this.tabs()[Number(this.selectedTab())]); } else { this.selectedFile.set(undefined); } } }); } protected removeTab(index: number) { this.tabs.update((tabs) => { const copy = tabs.slice(); copy.splice(index, 1); return copy; }); if (this.selectedTab() === index) { if (this.selectedTab() > 0) { this.selectedTab.update((tab) => tab - 1); this.selectedFile.set(this.tabs()[this.selectedTab()]); } else if (this.tabs().length > 1) { this.selectedTab.update((tab) => tab + 1); this.selectedFile.set(this.tabs()[this.selectedTab()]); } else { this.selectedFile.set(undefined); } } } protected fileDropped(event: DragEvent) { event.preventDefault(); const files = event.dataTransfer?.files; if (files) { for (const file of files) { if (file.type === 'text/csv') { this.addFile(file); } } } this.dragging.set(false); } protected dragEnter(event: DragEvent) { event.preventDefault(); const numItems = event.dataTransfer?.items.length; if (numItems) { for (let i = 0; i < numItems; i++) { if (event.dataTransfer?.items[i].type === 'text/csv') { this.dragging.set(true); return; } } } } protected dragLeave(event: DragEvent) { event.preventDefault(); this.dragging.set(false); } protected fileChange(event: Event) { const files = this.fileInput()?.nativeElement.files; if (files) { for (const file of files) { if (file.type === 'text/csv') { this.addFile(file); } } this.selectedTab.set(this.tabs().length - 1); } } private addFile(file: File) { if ( this.tabs().find( (tab) => tab.webkitRelativePath === file.webkitRelativePath && tab.name === file.name, ) ) { this.selectedTab.set( this.tabs().findIndex( (tab) => tab.webkitRelativePath === file.webkitRelativePath && tab.name === file.name, ), ); } else { this.tabs.update((tabs) => [...tabs, file]); this.selectedTab.set(this.tabs().length - 1); } } }