feat: enhance notes list UI with improved visual hierarchy
- Added new folder creation endpoint with support for path or parent/name parameters - Updated notes list styling with consistent row cards and active state indicators - Improved theme-aware color variables for better light/dark mode contrast - Added visual depth with subtle gradient overlays and active item highlighting - Implemented consistent styling between virtual and standard note list views - Enhanced new note button styling for better visibility
This commit is contained in:
@@ -27,6 +27,8 @@ export function setupRenameFolderEndpoint(app, vaultDir, broadcastVaultEvent, me
|
||||
if (!oldPath || typeof oldPath !== 'string') {
|
||||
return res.status(400).json({ error: 'Missing or invalid oldPath' });
|
||||
}
|
||||
|
||||
|
||||
if (!newName || typeof newName !== 'string') {
|
||||
return res.status(400).json({ error: 'Missing or invalid newName' });
|
||||
}
|
||||
@@ -202,6 +204,59 @@ export function setupDeleteFolderEndpoint(app, vaultDir, broadcastVaultEvent, me
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ENDPOINT 7: /api/folders (POST) - Create a folder (supports { path } or { parentPath, newFolderName })
|
||||
// ============================================================================
|
||||
export function setupCreateFolderEndpoint(app, vaultDir, broadcastVaultEvent, metadataCache) {
|
||||
app.post('/api/folders', express.json(), async (req, res) => {
|
||||
try {
|
||||
const body = req.body || {};
|
||||
let rel = '';
|
||||
if (typeof body.path === 'string' && body.path.trim()) {
|
||||
rel = body.path.trim();
|
||||
} else if (typeof body.parentPath === 'string' && typeof body.newFolderName === 'string') {
|
||||
const parent = body.parentPath.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '');
|
||||
const name = body.newFolderName.trim();
|
||||
if (!name) {
|
||||
return res.status(400).json({ error: 'New folder name cannot be empty' });
|
||||
}
|
||||
rel = parent ? `${parent}/${name}` : name;
|
||||
} else {
|
||||
return res.status(400).json({ error: 'Missing path or (parentPath, newFolderName)' });
|
||||
}
|
||||
|
||||
const sanitizedRel = String(rel).replace(/\\/g, '/').replace(/^\/+|\/+$/g, '');
|
||||
if (!sanitizedRel) {
|
||||
return res.status(400).json({ error: 'Invalid folder path' });
|
||||
}
|
||||
|
||||
const abs = path.join(vaultDir, sanitizedRel);
|
||||
const vaultAbs = path.resolve(vaultDir);
|
||||
const absResolved = path.resolve(abs);
|
||||
if (!absResolved.startsWith(vaultAbs)) {
|
||||
return res.status(400).json({ error: 'Path escapes vault root' });
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.mkdir(absResolved, { recursive: true });
|
||||
} catch (mkErr) {
|
||||
console.error('[POST /api/folders] mkdir failed:', mkErr);
|
||||
return res.status(500).json({ error: 'Failed to create folder' });
|
||||
}
|
||||
|
||||
if (metadataCache) metadataCache.clear();
|
||||
if (broadcastVaultEvent) {
|
||||
broadcastVaultEvent({ event: 'folder-create', path: sanitizedRel, timestamp: Date.now() });
|
||||
}
|
||||
|
||||
return res.json({ success: true, path: sanitizedRel });
|
||||
} catch (error) {
|
||||
console.error('[POST /api/folders] Unexpected error:', error);
|
||||
return res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ENDPOINT 1: /api/vault/metadata - with cache read-through and monitoring
|
||||
// ============================================================================
|
||||
|
||||
+5
-1
@@ -32,7 +32,8 @@ import {
|
||||
setupDeferredIndexing,
|
||||
setupCreateNoteEndpoint,
|
||||
setupRenameFolderEndpoint,
|
||||
setupDeleteFolderEndpoint
|
||||
setupDeleteFolderEndpoint,
|
||||
setupCreateFolderEndpoint
|
||||
} from './index-phase3-patch.mjs';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
@@ -1532,6 +1533,9 @@ setupRenameFolderEndpoint(app, vaultDir, broadcastVaultEvent, metadataCache);
|
||||
// Setup delete folder endpoint (must be before catch-all)
|
||||
setupDeleteFolderEndpoint(app, vaultDir, broadcastVaultEvent, metadataCache);
|
||||
|
||||
// Setup create folder endpoint (must be before catch-all)
|
||||
setupCreateFolderEndpoint(app, vaultDir, broadcastVaultEvent, metadataCache);
|
||||
|
||||
app.get('/', sendIndex);
|
||||
app.use((req, res) => {
|
||||
if (req.path.startsWith('/api/')) {
|
||||
|
||||
Reference in New Issue
Block a user