ObsiViewer/docs/NOTE_CONTEXT_MENU_IMPLEMENTATION.md
Bruno Charest 0f7cc552ca feat: add note context menu with color and metadata controls
- Added PATCH endpoint for updating note frontmatter with YAML parsing and merging
- Added DELETE endpoint to move notes to .trash directory with timestamped filenames
- Implemented note context menu with actions like duplicate, share, favorite, and delete
- Added color picker to context menu with gradient background visualization
- Extended NoteFrontmatter type with readOnly and color properties
- Added YAML frontmatter parser with support
2025-10-24 13:45:02 -04:00

8.4 KiB

Note Context Menu Implementation

Overview

This document describes the implementation of a comprehensive context menu for notes in the Notes-list component, providing quick access to common note operations.

Features Implemented

Core Actions

  • Duplicate - Create a copy of the note with "copy" suffix
  • Share page - Generate and copy shareable URL
  • Open in full screen - Open note in fullscreen mode
  • Copy internal link - Copy Obsidian-style internal link
  • Add to Favorites - Toggle favorite status
  • Page Information - Display note metadata and statistics
  • Read Only (toggle) - Toggle read-only protection
  • Delete - Move note to trash (with confirmation)

Visual Features

  • Color indicator - 8-color palette for note organization
  • Gradient backgrounds - Subtle right-to-left gradient based on note color
  • Consistent styling - Matches existing folder context menu design
  • Dark/Light theme support - Fully responsive to theme changes
  • Accessibility - Full keyboard navigation and ARIA support

Architecture

Components

1. NoteContextMenuComponent

  • Location: src/components/note-context-menu/note-context-menu.component.ts
  • Purpose: Renders the context menu UI with all actions and color palette
  • Features:
    • Standalone Angular component
    • OnPush change detection
    • Anti-overflow positioning
    • Keyboard navigation (↑↓, Enter, Esc)
    • Permission-based action disabling

2. NoteContextMenuService

  • Location: src/app/services/note-context-menu.service.ts
  • Purpose: Handles all context menu business logic and API calls
  • Features:
    • State management (position, visibility, target note)
    • API integration for all note operations
    • Toast notifications
    • Event emission for UI updates

3. Enhanced NotesListComponent

  • Location: src/app/features/list/notes-list.component.ts
  • Purpose: Integrates context menu into note list
  • Features:
    • Right-click event handling
    • Gradient background rendering based on note colors
    • Context menu action delegation

Server Endpoints

1. POST /api/vault/notes

  • Purpose: Create new note (existing)
  • Used by: Duplicate action

2. PATCH /api/vault/notes/:id

  • Purpose: Update note frontmatter
  • Used by: Favorite toggle, read-only toggle, color change
  • Implementation: server/index-phase3-patch.mjs

3. DELETE /api/vault/notes/:id

  • Purpose: Move note to trash
  • Used by: Delete action
  • Implementation: server/index-phase3-patch.mjs

Data Flow

User right-clicks on note
    ↓
NotesListComponent.openContextMenu()
    ↓
NoteContextMenuService.openForNote()
    ↓
NoteContextMenuComponent rendered
    ↓
User clicks action
    ↓
NoteContextMenuService.handleAction()
    ↓
API call to server
    ↓
Toast notification + UI update

API Endpoints

PATCH /api/vault/notes/:id

Updates note frontmatter properties.

Request:

{
  "frontmatter": {
    "favoris": true,
    "readOnly": false,
    "color": "#3B82F6"
  }
}

Response:

{
  "id": "path/to/note",
  "success": true,
  "frontmatter": {
    "favoris": true,
    "readOnly": false,
    "color": "#3B82F6"
  }
}

DELETE /api/vault/notes/:id

Moves note to trash directory.

Response:

{
  "id": "path/to/note",
  "success": true,
  "trashPath": ".trash/note_2025-10-24T17-13-28-456Z.md"
}

Color System

Available Colors

  • #00AEEF - Cyan
  • #3B82F6 - Blue
  • #22C55E - Green
  • #F59E0B - Orange
  • #EF4444 - Red
  • #A855F7 - Purple
  • #8B5CF6 - Indigo
  • #64748B - Slate

Implementation

  • Colors stored in frontmatter.color
  • Gradient backgrounds use 14% opacity
  • Consistent with folder color system

Permissions & Security

Action Permissions

  • Duplicate: Disabled if note is read-only
  • Share: Disabled if note is private or publishing disabled
  • Read Only Toggle: Always available (configurable)
  • Delete: Always available with confirmation

Safety Features

  • All deletions move to .trash folder
  • Read-only notes show confirmation dialog for deletion
  • Frontmatter validation on server side
  • Proper error handling and user feedback

Testing

Manual Testing

  1. Right-click on any note in the list
  2. Verify all actions are present and functional
  3. Test color selection and gradient rendering
  4. Verify keyboard navigation (↑↓, Enter, Esc)
  5. Test permissions with read-only notes

Automated Testing

Run the test script:

node test-note-context-menu.mjs

Test Coverage

  • Note creation
  • Frontmatter updates (favorite, color)
  • Note deletion (trash)
  • Error handling (404, validation)
  • API response formats

Integration Points

Existing Services

  • VaultService: Note data and refresh
  • ToastService: User notifications
  • NotesListStateService: UI state management

Events Emitted

  • noteDuplicated - When note is duplicated
  • noteShared - When share URL is generated
  • noteOpenedFull - When fullscreen mode activated
  • noteCopiedLink - When internal link copied
  • noteFavoriteToggled - When favorite status changes
  • noteInfoRequested - When page info requested
  • noteReadOnlyToggled - When read-only status changes
  • noteDeleted - When note moved to trash
  • noteColorChanged - When note color changes

Performance Considerations

Optimizations

  • OnPush change detection strategy
  • Lazy menu rendering (only when visible)
  • Minimal DOM manipulation
  • Efficient gradient calculations

Memory Usage

  • Context menu state is lightweight
  • No heavy computations in UI thread
  • Proper cleanup on component destruction

Browser Compatibility

Supported Features

  • Modern browsers (Chrome, Firefox, Safari, Edge)
  • Clipboard API for copy operations
  • CSS custom properties for theming
  • Event handling and keyboard navigation

Fallbacks

  • Clipboard API falls back to modal display
  • Gradient backgrounds gracefully degrade
  • Toast notifications work without animation

Future Enhancements

Potential Improvements

  1. Batch operations - Select multiple notes for bulk actions
  2. Custom colors - Color picker for unlimited color options
  3. Keyboard shortcuts - Quick access to common actions
  4. Drag & drop - Move notes between folders
  5. Preview mode - Quick note preview in context menu

Extension Points

  • Additional context menu actions can be easily added
  • Custom permission systems can be integrated
  • Alternative color schemes can be implemented

Troubleshooting

Common Issues

Context menu doesn't appear

  • Check that NoteContextMenuComponent is imported
  • Verify right-click event is not prevented by other handlers
  • Check z-index conflicts with other overlays

Actions not working

  • Verify server endpoints are properly registered
  • Check API response formats in browser dev tools
  • Ensure note IDs are correctly formatted

Colors not applying

  • Check that color property is in frontmatter
  • Verify gradient calculation logic
  • Check CSS custom properties are defined

Performance issues

  • Ensure OnPush change detection is working
  • Check for unnecessary re-renders in dev tools
  • Verify menu cleanup on close

Debug Mode

Enable debug logging by setting:

localStorage.setItem('debug', 'true');

Files Modified

New Files

  • src/components/note-context-menu/note-context-menu.component.ts
  • src/app/services/note-context-menu.service.ts
  • test-note-context-menu.mjs
  • docs/NOTE_CONTEXT_MENU_IMPLEMENTATION.md

Modified Files

  • src/app/features/list/notes-list.component.ts - Added context menu integration
  • src/types.ts - Added color and readOnly to NoteFrontmatter
  • server/index-phase3-patch.mjs - Added PATCH/DELETE endpoints
  • server/index.mjs - Added endpoint imports and setup

Summary

The note context menu implementation provides a comprehensive, accessible, and performant solution for note management in ObsiViewer. It maintains consistency with existing UI patterns while adding powerful new functionality for users.

Key Achievements

  • Full feature parity with folder context menu
  • Consistent visual design and behavior
  • Comprehensive error handling and user feedback
  • Accessibility compliance
  • Performance optimized
  • Extensible architecture for future enhancements

The implementation is production-ready and can be safely deployed to users.