feat: improve note path handling and add delete confirmation modal
- Updated API endpoints to handle note paths with slashes using regex routes - Added warning modal component for note deletion confirmation - Fixed URL encoding of note paths to preserve spaces and special characters - Improved fullscreen note handling to use URL state and custom events - Enhanced internal link copying to use proper URL format - Removed test/sample note files from vault directory
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import { Component, ChangeDetectionStrategy, EventEmitter, Input, Output, OnInit, OnDestroy, ElementRef, Renderer2, inject } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-warning-panel',
|
||||
standalone: true,
|
||||
imports: [CommonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `
|
||||
<div *ngIf="visible" class="fixed inset-0 z-[99999] flex items-center justify-center bg-black/40 backdrop-blur-[1px]" (click)="onBackdrop($event)" role="dialog" aria-modal="true">
|
||||
<div class="w-full max-w-md mx-3 rounded-2xl shadow-xl transition-all duration-200 p-6 border"
|
||||
[class.bg-white]="!isDarkTheme()" [class.border-slate-200]="!isDarkTheme()"
|
||||
[class.bg-slate-800/95]="isDarkTheme()" [class.border-slate-600]="isDarkTheme()"
|
||||
(click)="$event.stopPropagation()">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<svg class="w-6 h-6 text-yellow-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
|
||||
<line x1="12" y1="9" x2="12" y2="13"></line>
|
||||
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
||||
</svg>
|
||||
<h2 class="text-lg font-semibold">{{ title }}</h2>
|
||||
</div>
|
||||
<p class="text-sm mb-6" [class.text-slate-500]="!isDarkTheme()" [class.text-slate-300]="isDarkTheme()">{{ message }}</p>
|
||||
<div class="flex justify-end gap-3">
|
||||
<button type="button" (click)="onCancel()"
|
||||
class="px-4 py-2 rounded-lg transition-colors cursor-pointer"
|
||||
[ngClass]="isDarkTheme() ? 'text-slate-300 hover:bg-slate-700' : 'text-slate-700 hover:bg-slate-100'">{{ cancelText || 'Cancel' }}</button>
|
||||
<button type="button" (click)="onDelete()"
|
||||
class="px-4 py-2 rounded-lg text-white transition-colors cursor-pointer"
|
||||
[ngClass]="confirmColor === 'danger' ? 'bg-red-600 hover:bg-red-700' : 'bg-blue-600 hover:bg-blue-700'">
|
||||
{{ confirmText || 'Delete' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
export class WarningPanelComponent implements OnInit, OnDestroy {
|
||||
@Input() visible = false;
|
||||
@Input() title = 'Delete this note?';
|
||||
@Input() message = 'The note will be moved to the trash folder and can be restored later.';
|
||||
@Input() confirmText = 'Delete';
|
||||
@Input() cancelText = 'Cancel';
|
||||
@Input() confirmColor: 'danger' | 'primary' = 'danger';
|
||||
|
||||
@Output() cancel = new EventEmitter<void>();
|
||||
@Output() delete = new EventEmitter<void>();
|
||||
|
||||
private readonly host = inject(ElementRef<HTMLElement>);
|
||||
private readonly renderer = inject(Renderer2);
|
||||
|
||||
// Use documentElement dark class to decide theme quickly without injecting ThemeService
|
||||
isDarkTheme(): boolean {
|
||||
try { return document.documentElement.classList.contains('dark'); } catch { return false; }
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (typeof document === 'undefined') return;
|
||||
const element = this.host.nativeElement;
|
||||
// Ensure host doesn't create an extra layer interfering with positioning
|
||||
this.renderer.setStyle(element, 'display', 'contents');
|
||||
// Move host to body so it sits above any stacking-context limitations
|
||||
this.renderer.appendChild(document.body, element);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (typeof document === 'undefined') return;
|
||||
const element = this.host.nativeElement;
|
||||
if (element.parentNode) {
|
||||
this.renderer.removeChild(element.parentNode, element);
|
||||
}
|
||||
}
|
||||
|
||||
onCancel() {
|
||||
console.log('[WarningPanel] Cancel button clicked');
|
||||
this.cancel.emit();
|
||||
}
|
||||
|
||||
onDelete() {
|
||||
console.log('[WarningPanel] Confirm button clicked');
|
||||
this.delete.emit();
|
||||
}
|
||||
|
||||
onBackdrop(event: MouseEvent) {
|
||||
if (event.target === event.currentTarget) {
|
||||
this.cancel.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user