first commit
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
<ul class="p-2 space-y-1">
|
||||
@for (node of nodes(); track node.name) {
|
||||
<li>
|
||||
@if (node.type === 'folder') {
|
||||
@let folder = node;
|
||||
<div>
|
||||
<button (click)="toggleFolder(folder)" class="w-full flex items-center text-left p-1.5 rounded hover:bg-gray-200 dark:hover:bg-gray-600">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2 transition-transform" [class.rotate-90]="folder.isOpen" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">{{ folder.name }}</span>
|
||||
</button>
|
||||
@if (folder.isOpen) {
|
||||
<div class="pl-4">
|
||||
<app-file-explorer [nodes]="folder.children" [selectedNoteId]="selectedNoteId()" (fileSelected)="onFileSelected($event)"></app-file-explorer>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
} @else {
|
||||
@let file = node;
|
||||
<button (click)="onFileSelected(file.id)"
|
||||
class="w-full text-left p-1.5 rounded text-sm transition-colors"
|
||||
[class]="file.id === selectedNoteId()
|
||||
? 'bg-obs-l-accent text-white dark:bg-obs-d-accent'
|
||||
: 'hover:bg-gray-200 dark:hover:bg-gray-600'">
|
||||
<span class="pl-6">{{ file.name }}</span>
|
||||
</button>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
@@ -0,0 +1,78 @@
|
||||
import { Component, ChangeDetectionStrategy, input, output, inject } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { VaultNode, VaultFile, VaultFolder } from '../../types';
|
||||
import { VaultService } from '../../services/vault.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-file-explorer',
|
||||
template: `
|
||||
<ul class="space-y-0.5">
|
||||
@for(node of nodes(); track node.path) {
|
||||
<li>
|
||||
@if (isFolder(node)) {
|
||||
@let folder = node;
|
||||
<div>
|
||||
<div
|
||||
(click)="toggleFolder(folder)"
|
||||
class="flex items-center cursor-pointer p-2 rounded my-0.5 text-sm hover:bg-obs-l-bg-main dark:hover:bg-obs-d-bg-main"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2 transition-transform text-obs-l-text-muted dark:text-obs-d-text-muted" [class.rotate-90]="folder.isOpen" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2 flex-shrink-0 text-obs-l-text-muted dark:text-obs-d-text-muted" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"></path></svg>
|
||||
<span class="font-semibold truncate">{{ folder.name }}</span>
|
||||
</div>
|
||||
@if (folder.isOpen) {
|
||||
<div class="pl-5">
|
||||
<app-file-explorer
|
||||
[nodes]="folder.children"
|
||||
[selectedNoteId]="selectedNoteId()"
|
||||
(fileSelected)="onFileSelected($event)"
|
||||
></app-file-explorer>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
} @else {
|
||||
@let file = node;
|
||||
<div
|
||||
(click)="onFileSelected(file.id)"
|
||||
class="flex items-center cursor-pointer p-2 rounded my-0.5 text-sm ml-5"
|
||||
[class.bg-obs-l-bg-main]="selectedNoteId() === file.id"
|
||||
[class.dark:bg-obs-d-bg-main]="selectedNoteId() === file.id"
|
||||
[class.hover:bg-obs-l-bg-main]="selectedNoteId() !== file.id"
|
||||
[class.dark:hover:bg-obs-d-bg-main]="selectedNoteId() !== file.id"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2 flex-shrink-0 text-obs-l-text-muted dark:text-obs-d-text-muted" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||
</svg>
|
||||
<span class="truncate">{{ file.name }}</span>
|
||||
</div>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [CommonModule],
|
||||
})
|
||||
export class FileExplorerComponent {
|
||||
nodes = input.required<VaultNode[]>();
|
||||
selectedNoteId = input<string | null>(null);
|
||||
fileSelected = output<string>();
|
||||
|
||||
private vaultService = inject(VaultService);
|
||||
|
||||
onFileSelected(noteId: string) {
|
||||
if(noteId) {
|
||||
this.fileSelected.emit(noteId);
|
||||
}
|
||||
}
|
||||
|
||||
toggleFolder(folder: VaultFolder) {
|
||||
this.vaultService.toggleFolder(folder.path);
|
||||
}
|
||||
|
||||
isFolder(node: VaultNode): node is VaultFolder {
|
||||
return node.type === 'folder';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user