Merge pull request #48 from gamosoft/features/unified-create
Features/unified create
This commit is contained in:
commit
88c82e3965
|
|
@ -99,7 +99,7 @@ function noteApp() {
|
||||||
|
|
||||||
// Dropdown state
|
// Dropdown state
|
||||||
showNewDropdown: false,
|
showNewDropdown: false,
|
||||||
dropdownTargetFolder: '', // Folder context for "New" dropdown (empty = root)
|
dropdownTargetFolder: null, // Folder context for "New" dropdown ('' = root, null = not set)
|
||||||
dropdownPosition: { top: 0, left: 0 }, // Position for contextual dropdown
|
dropdownPosition: { top: 0, left: 0 }, // Position for contextual dropdown
|
||||||
|
|
||||||
// Template state
|
// Template state
|
||||||
|
|
@ -628,9 +628,16 @@ function noteApp() {
|
||||||
notePath += '.md';
|
notePath += '.md';
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a target folder context, create in that folder
|
// Determine target folder: use dropdown context if set, otherwise homepage folder
|
||||||
if (this.dropdownTargetFolder || this.selectedHomepageFolder) {
|
let targetFolder;
|
||||||
const targetFolder = this.dropdownTargetFolder || this.selectedHomepageFolder;
|
if (this.dropdownTargetFolder !== null && this.dropdownTargetFolder !== undefined) {
|
||||||
|
targetFolder = this.dropdownTargetFolder; // Can be '' for root or a folder path
|
||||||
|
} else {
|
||||||
|
targetFolder = this.selectedHomepageFolder || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a target folder, create note in that folder
|
||||||
|
if (targetFolder) {
|
||||||
notePath = `${targetFolder}/${notePath}`;
|
notePath = `${targetFolder}/${notePath}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1998,7 +2005,7 @@ function noteApp() {
|
||||||
|
|
||||||
closeDropdown() {
|
closeDropdown() {
|
||||||
this.showNewDropdown = false;
|
this.showNewDropdown = false;
|
||||||
this.dropdownTargetFolder = ''; // Reset folder context
|
this.dropdownTargetFolder = null; // Reset folder context
|
||||||
},
|
},
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
@ -2006,8 +2013,16 @@ function noteApp() {
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
async createNote(folderPath = null) {
|
async createNote(folderPath = null) {
|
||||||
// Use provided folder path, or dropdown target folder context
|
// Use provided folder path, or dropdown target folder context, or homepage folder
|
||||||
const targetFolder = folderPath !== null ? folderPath : this.dropdownTargetFolder;
|
// Note: Check dropdownTargetFolder !== null to distinguish between '' (root) and not set
|
||||||
|
let targetFolder;
|
||||||
|
if (folderPath !== null) {
|
||||||
|
targetFolder = folderPath;
|
||||||
|
} else if (this.dropdownTargetFolder !== null && this.dropdownTargetFolder !== undefined) {
|
||||||
|
targetFolder = this.dropdownTargetFolder; // Can be '' for root or a folder path
|
||||||
|
} else {
|
||||||
|
targetFolder = this.selectedHomepageFolder || '';
|
||||||
|
}
|
||||||
this.closeDropdown();
|
this.closeDropdown();
|
||||||
|
|
||||||
const promptText = targetFolder
|
const promptText = targetFolder
|
||||||
|
|
@ -2059,8 +2074,16 @@ function noteApp() {
|
||||||
},
|
},
|
||||||
|
|
||||||
async createFolder(parentPath = null) {
|
async createFolder(parentPath = null) {
|
||||||
// Use provided parent path, or dropdown target folder context
|
// Use provided parent path, or dropdown target folder context, or homepage folder
|
||||||
const targetFolder = parentPath !== null ? parentPath : this.dropdownTargetFolder;
|
// Note: Check dropdownTargetFolder !== null to distinguish between '' (root) and not set
|
||||||
|
let targetFolder;
|
||||||
|
if (parentPath !== null) {
|
||||||
|
targetFolder = parentPath;
|
||||||
|
} else if (this.dropdownTargetFolder !== null && this.dropdownTargetFolder !== undefined) {
|
||||||
|
targetFolder = this.dropdownTargetFolder; // Can be '' for root or a folder path
|
||||||
|
} else {
|
||||||
|
targetFolder = this.selectedHomepageFolder || '';
|
||||||
|
}
|
||||||
this.closeDropdown();
|
this.closeDropdown();
|
||||||
|
|
||||||
const promptText = targetFolder
|
const promptText = targetFolder
|
||||||
|
|
@ -2098,6 +2121,9 @@ function noteApp() {
|
||||||
}
|
}
|
||||||
this.expandedFolders.add(folderPath);
|
this.expandedFolders.add(folderPath);
|
||||||
await this.loadNotes();
|
await this.loadNotes();
|
||||||
|
|
||||||
|
// Navigate to the newly created folder on the homepage
|
||||||
|
this.goToHomepageFolder(folderPath);
|
||||||
} else {
|
} else {
|
||||||
ErrorHandler.handle('create folder', new Error('Server returned error'));
|
ErrorHandler.handle('create folder', new Error('Server returned error'));
|
||||||
}
|
}
|
||||||
|
|
@ -3397,6 +3423,12 @@ function noteApp() {
|
||||||
goToHomepageFolder(folderPath) {
|
goToHomepageFolder(folderPath) {
|
||||||
this.selectedHomepageFolder = folderPath || '';
|
this.selectedHomepageFolder = folderPath || '';
|
||||||
|
|
||||||
|
// Clear editor state to show landing page
|
||||||
|
this.currentNote = '';
|
||||||
|
this.currentNoteName = '';
|
||||||
|
this.noteContent = '';
|
||||||
|
this.currentImage = '';
|
||||||
|
|
||||||
// Invalidate cache to force recalculation
|
// Invalidate cache to force recalculation
|
||||||
this._homepageCache = {
|
this._homepageCache = {
|
||||||
folderPath: null,
|
folderPath: null,
|
||||||
|
|
|
||||||
|
|
@ -1129,19 +1129,19 @@
|
||||||
<!-- Welcome Hero - Show when app is empty -->
|
<!-- Welcome Hero - Show when app is empty -->
|
||||||
<template x-if="isAppEmpty">
|
<template x-if="isAppEmpty">
|
||||||
<div class="flex flex-col items-center justify-center h-full py-16 text-center">
|
<div class="flex flex-col items-center justify-center h-full py-16 text-center">
|
||||||
<svg class="mx-auto h-16 w-16 mb-4" style="color: var(--text-tertiary);" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="mx-auto h-24 w-24 mb-4" style="color: var(--text-tertiary); opacity: 0.5;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<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"></path>
|
<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"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<h1 class="text-4xl font-bold mb-4" style="color: var(--text-primary);" x-text="appName"></h1>
|
<h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary);">No notes yet</h2>
|
||||||
<p class="text-xl mb-8" style="color: var(--text-secondary);" x-text="appTagline"></p>
|
<p class="mb-6" style="color: var(--text-secondary);">Create your first note or folder</p>
|
||||||
<button
|
<button
|
||||||
@click="createNote()"
|
@click="dropdownTargetFolder = selectedHomepageFolder; toggleNewDropdown($event)"
|
||||||
class="px-8 py-4 text-base font-medium text-white rounded-lg transition-colors"
|
class="px-6 py-3 text-sm font-medium text-white rounded-lg transition-colors"
|
||||||
style="background-color: var(--accent-primary);"
|
style="background-color: var(--accent-primary);"
|
||||||
onmouseover="this.style.backgroundColor='var(--accent-hover)'"
|
onmouseover="this.style.backgroundColor='var(--accent-hover)'"
|
||||||
onmouseout="this.style.backgroundColor='var(--accent-primary)'"
|
onmouseout="this.style.backgroundColor='var(--accent-primary)'"
|
||||||
>
|
>
|
||||||
Create Your First Note
|
+ New
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1196,13 +1196,13 @@
|
||||||
<span x-text="homepageFolders().length === 1 ? 'folder' : 'folders'"></span>
|
<span x-text="homepageFolders().length === 1 ? 'folder' : 'folders'"></span>
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
@click="createNote()"
|
@click="dropdownTargetFolder = selectedHomepageFolder; toggleNewDropdown($event)"
|
||||||
class="ml-auto px-4 py-2 text-sm font-medium text-white rounded-lg transition-colors"
|
class="ml-auto px-4 py-2 text-sm font-medium text-white rounded-lg transition-colors"
|
||||||
style="background-color: var(--accent-primary);"
|
style="background-color: var(--accent-primary);"
|
||||||
onmouseover="this.style.backgroundColor='var(--accent-hover)'"
|
onmouseover="this.style.backgroundColor='var(--accent-hover)'"
|
||||||
onmouseout="this.style.backgroundColor='var(--accent-primary)'"
|
onmouseout="this.style.backgroundColor='var(--accent-primary)'"
|
||||||
>
|
>
|
||||||
+ New Note
|
+ New
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1214,16 +1214,16 @@
|
||||||
<svg class="mx-auto h-24 w-24 mb-4" style="color: var(--text-tertiary); opacity: 0.5;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="mx-auto h-24 w-24 mb-4" style="color: var(--text-tertiary); opacity: 0.5;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<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"></path>
|
<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"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary);">No notes yet</h2>
|
<h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary);" x-text="selectedHomepageFolder ? 'This folder is empty' : 'No notes yet'"></h2>
|
||||||
<p class="mb-6" style="color: var(--text-secondary);">Create your first note to get started</p>
|
<p class="mb-6" style="color: var(--text-secondary);" x-text="selectedHomepageFolder ? 'Create something to get started' : 'Create your first note or folder'"></p>
|
||||||
<button
|
<button
|
||||||
@click="createNote()"
|
@click="dropdownTargetFolder = selectedHomepageFolder; toggleNewDropdown($event)"
|
||||||
class="px-6 py-3 text-sm font-medium text-white rounded-lg transition-colors"
|
class="px-6 py-3 text-sm font-medium text-white rounded-lg transition-colors"
|
||||||
style="background-color: var(--accent-primary);"
|
style="background-color: var(--accent-primary);"
|
||||||
onmouseover="this.style.backgroundColor='var(--accent-hover)'"
|
onmouseover="this.style.backgroundColor='var(--accent-hover)'"
|
||||||
onmouseout="this.style.backgroundColor='var(--accent-primary)'"
|
onmouseout="this.style.backgroundColor='var(--accent-primary)'"
|
||||||
>
|
>
|
||||||
Create Your First Note
|
+ New
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1236,10 +1236,24 @@
|
||||||
<div
|
<div
|
||||||
@click="goToHomepageFolder(folder.path)"
|
@click="goToHomepageFolder(folder.path)"
|
||||||
class="p-4 rounded-lg border-2 cursor-pointer transition-all hover:shadow-lg"
|
class="p-4 rounded-lg border-2 cursor-pointer transition-all hover:shadow-lg"
|
||||||
style="background-color: var(--bg-secondary); border-color: var(--accent-primary); min-height: 140px; display: flex; flex-direction: column; border-width: 2px;"
|
style="background-color: var(--bg-secondary); border-color: var(--accent-primary); min-height: 140px; display: flex; flex-direction: column; border-width: 2px; position: relative;"
|
||||||
onmouseover="this.style.borderColor='var(--accent-hover)'; this.style.transform='translateY(-2px)'"
|
onmouseover="this.style.borderColor='var(--accent-hover)'; this.style.transform='translateY(-2px)'; this.querySelector('.card-delete-btn').style.opacity='1';"
|
||||||
onmouseout="this.style.borderColor='var(--accent-primary)'; this.style.transform='translateY(0)'"
|
onmouseout="this.style.borderColor='var(--accent-primary)'; this.style.transform='translateY(0)'; this.querySelector('.card-delete-btn').style.opacity='0';"
|
||||||
>
|
>
|
||||||
|
<!-- Delete Button -->
|
||||||
|
<button
|
||||||
|
@click.stop="deleteFolder(folder.path, folder.name)"
|
||||||
|
class="card-delete-btn"
|
||||||
|
style="position: absolute; top: 8px; right: 8px; opacity: 0; transition: opacity 0.2s; color: var(--error); padding: 4px; border-radius: 4px; background-color: var(--bg-secondary);"
|
||||||
|
onmouseover="this.style.backgroundColor='var(--bg-hover)'"
|
||||||
|
onmouseout="this.style.backgroundColor='var(--bg-secondary)'"
|
||||||
|
title="Delete folder"
|
||||||
|
>
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
<!-- Folder Icon -->
|
<!-- Folder Icon -->
|
||||||
<div class="mb-2 flex items-center gap-2">
|
<div class="mb-2 flex items-center gap-2">
|
||||||
<svg class="w-6 h-6" style="color: var(--accent-primary);" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-6 h-6" style="color: var(--accent-primary);" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
|
@ -1263,10 +1277,24 @@
|
||||||
<div
|
<div
|
||||||
@click="note.path.match(/\.(png|jpg|jpeg|gif|webp)$/i) ? (currentImage = note.path, currentNote = '') : loadNote(note.path)"
|
@click="note.path.match(/\.(png|jpg|jpeg|gif|webp)$/i) ? (currentImage = note.path, currentNote = '') : loadNote(note.path)"
|
||||||
class="p-4 rounded-lg border-2 cursor-pointer transition-all hover:shadow-lg"
|
class="p-4 rounded-lg border-2 cursor-pointer transition-all hover:shadow-lg"
|
||||||
style="background-color: var(--bg-secondary); border-color: var(--border-primary); min-height: 140px; display: flex; flex-direction: column;"
|
style="background-color: var(--bg-secondary); border-color: var(--border-primary); min-height: 140px; display: flex; flex-direction: column; position: relative;"
|
||||||
onmouseover="this.style.borderColor='var(--accent-primary)'; this.style.transform='translateY(-2px)'"
|
onmouseover="this.style.borderColor='var(--accent-primary)'; this.style.transform='translateY(-2px)'; this.querySelector('.card-delete-btn').style.opacity='1';"
|
||||||
onmouseout="this.style.borderColor='var(--border-primary)'; this.style.transform='translateY(0)'"
|
onmouseout="this.style.borderColor='var(--border-primary)'; this.style.transform='translateY(0)'; this.querySelector('.card-delete-btn').style.opacity='0';"
|
||||||
>
|
>
|
||||||
|
<!-- Delete Button -->
|
||||||
|
<button
|
||||||
|
@click.stop="note.type === 'image' ? deleteImage(note.path) : deleteNote(note.path, note.name)"
|
||||||
|
class="card-delete-btn"
|
||||||
|
style="position: absolute; top: 8px; right: 8px; opacity: 0; transition: opacity 0.2s; color: var(--error); padding: 4px; border-radius: 4px; background-color: var(--bg-secondary);"
|
||||||
|
onmouseover="this.style.backgroundColor='var(--bg-hover)'"
|
||||||
|
onmouseout="this.style.backgroundColor='var(--bg-secondary)'"
|
||||||
|
:title="note.type === 'image' ? 'Delete image' : 'Delete note'"
|
||||||
|
>
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
<!-- Note Title -->
|
<!-- Note Title -->
|
||||||
<h3 class="font-semibold text-base mb-2" style="color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical;" x-text="note.name"></h3>
|
<h3 class="font-semibold text-base mb-2" style="color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical;" x-text="note.name"></h3>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue