Commit Graph

105 Commits

Author SHA1 Message Date
bvandeusen f30e90ef8d feat: narrator empty states, scroll fades, glow buttons, violet color sweep 2026-04-08 11:17:06 -04:00
bvandeusen f953a36b86 feat(header): pill nav bar, brand shortening, status pulse, header gradient 2026-04-08 11:11:35 -04:00
bvandeusen 4bc7f9eaac feat(theme): shift palette from indigo to deep violet + muted gold
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 11:09:23 -04:00
bvandeusen a684d84edf feat: deprecate /notes and /tasks routes; redirect to Knowledge view 2026-04-08 10:35:21 -04:00
bvandeusen 56b687c9f4 fix(voice): show mic button on HTTP; graceful error for non-secure contexts 2026-04-07 20:06:57 -04:00
bvandeusen 7f37cee49f refactor(voice): integrate click-to-toggle mic into ChatInputBar; remove VoiceOverlay 2026-04-07 13:17:25 -04:00
bvandeusen d290bebad2 feat(stt): pass conversation context as Whisper initial_prompt to reduce mishearings 2026-04-07 08:48:27 -04:00
bvandeusen 853dc810ff feat: click-to-toggle silence detection and amplitude bars in VoiceOverlay 2026-04-06 20:01:44 -04:00
bvandeusen b9d0716b01 feat: add News link to main navigation header
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 17:49:22 -04:00
bvandeusen 9af8ab8f70 fix(briefing): use briefing context for follow-ups; add slot separator
- build_context: when conversation_type is 'briefing', inject a system
  prompt instruction telling the model to answer from conversation history
  and article context instead of searching the web
- Consolidate briefing conversation type detection to one DB query (was
  being checked twice — once for the system prompt addition, once for
  article context injection)
- ChatPanel: render a visual 'New Briefing Update' separator line before
  2nd+ briefing slot messages (identified by metadata.rss_item_ids)
- types/chat.ts: add metadata field to Message interface

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 06:15:18 -04:00
bvandeusen 358534efbf fix(events): audit pass — 7 correctness fixes across the events system
Backend:
- tools.py: apply UTC normalization to update_event datetime fields
  (matched create_event which already did this)
- events.py service: allow end_dt/recurrence/project_id to be cleared
  via update_event by permitting None for nullable fields
- events.py service: find_events_by_query now returns upcoming events
  first, falling back to past — prevents AI tools from mutating stale
  past events when a future match exists
- events.py service: list_events now uses overlap logic (start <= to
  AND end >= from) so multi-day events spanning the query boundary
  are included; previously only start_dt was checked

Frontend:
- ToolCallCard: fire fable:calendar-changed on created/updated/deleted
  so CalendarView refetches without requiring a manual page refresh
- KnowledgeView: replace raw apiGet('/api/events') with listEvents()
  client function; also fix today bar which was reading .events off a
  flat array (always empty) — now correctly receives EventEntry[]
- HomeView: use full ISO strings for event date range instead of naive
  UTC-midnight strings; deduplicate inline date math via _dateRange()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 12:02:10 -04:00
bvandeusen 7677ab4028 fix(calendar): use date-only strings for all-day events to prevent timezone shift
UTC midnight passed to FullCalendar's timeZone:'local' was being
converted to local time, shifting all-day events back by 1+ days for
users in UTC-X zones. The edit form had the same bug via new Date().

Fix: pass YYYY-MM-DD slices (UTC date) for all-day events in both
toFcEvent and EventSlideOver resetForm, bypassing timezone conversion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 11:01:51 -04:00
bvandeusen eda9c5ce43 feat: migrate KnowledgeView mini-chat to ChatPanel + enable note picker everywhere
- KnowledgeView: replace custom mini-chat (voice, PTT, manual scroll, message
  rendering) with ChatPanel variant="full"; gains RAG scope chip, TTS listen
  mode, volume control, and note picker automatically (-218 lines)
- ChatInputBar: remove briefingMode guard on note picker so attach/search works
  in briefing, workspace, widget, and knowledge chat surfaces

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 20:16:36 -04:00
bvandeusen d624d38412 fix: KnowledgeView infinite scroll root + calendar event refresh
- KnowledgeView: IntersectionObserver was watching the viewport instead
  of the card-grid scroll container, causing infinite scroll to stop
  loading after only ~29 items. Pass card-grid element as `root`.
- CalendarView: listen for 'fable:calendar-changed' custom event and
  call refetchEvents() so tool-created events appear without navigation.
- ChatPanel: dispatch 'fable:calendar-changed' when create_event,
  update_event, or delete_event tool calls succeed.
- tools.py: normalize naive datetimes to UTC before storing events so
  timezone comparisons in list_events queries are always consistent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 19:28:33 -04:00
bvandeusen 86e718dda1 refactor: migrate HomeView to ChatPanel widget, delete DashboardChatInput
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:36:13 -04:00
bvandeusen 927f137aaf feat: rewrite ChatPanel with full and widget variants
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 16:37:20 -04:00
bvandeusen 7eaf4d9dca feat: add ChatStreamingBubble extracted streaming state component
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 16:30:05 -04:00
bvandeusen 89a9088b94 feat: add ChatInputBar unified input bar component
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:57:51 -04:00
bvandeusen 9549eb85bc feat: live card refresh, list checkboxes, minichat width cap
KnowledgeView:
- Watch streamingToolCalls; call fetchItems+fetchTags on create/update
  note or task so the card grid reflects changes made via the minichat
- Cap minichat to max-width: var(--page-max-width) so it matches chat column width

WorkspaceView + WorkspaceNoteEditor:
- Expose reload() from WorkspaceNoteEditor via defineExpose
- Call noteEditorRef.reload() alongside taskPanelRef.reload() when
  create_note/update_note tools succeed in the SSE watcher

KnowledgeView list cards:
- Backend: parse markdown task list into list_items [{text, checked}] + body
- Card renders up to 6 items with real checkboxes; toggleListItem()
  does an optimistic update then PATCHes /api/notes/:id
- Progress bar kept below items; "+N more" shown when list is long

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 21:30:28 -04:00
bvandeusen 5924e565b1 fix: floating mini-chat overlay style + weather precip fallback
- KnowledgeView mini-chat: replace harsh border-top with upward box-shadow
  and rounded top corners (16px); remove padding-bottom from content area
  so widget truly overlays cards without pushing layout; add collapse
  toggle (chevron) that hides messages without closing the conversation
- WeatherCard: show precip_mm as fallback when precipitation_probability_max
  is null but actual rainfall is expected (Open-Meteo omits probability for
  some forecast days even when rain is shown)
- Pass precip_mm through weather service → frontend type definitions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 09:04:47 -04:00
bvandeusen 80f30b705d feat: Knowledge view + entity types (People, Places, Lists)
Data model:
- Migration 0036: adds note_type TEXT (default 'note') and metadata JSONB
  to the notes table; index on note_type
- Note model: entity_type property, note_type/metadata in to_dict()
- create_note() accepts note_type and metadata params

Backend:
- /api/knowledge — unified paginated endpoint: type/tag/sort/q filters,
  semantic search via embeddings, excludes tasks
- /api/knowledge/tags — distinct tags across knowledge objects
- New LLM tools: create_person, create_place, create_list, add_to_list,
  clear_checked_items — all wired into execute_tool()
- People and places auto-injected as compact summary into LLM system prompt

Frontend:
- KnowledgeView replaces HomeView at /; left filter panel (type+tag),
  toolbar (search, sort, graph toggle), card grid with type-aware cards
  (indigo=note, emerald=person, amber=place, sky=list), load-more pagination
- Today bar: upcoming events, overdue task count, Briefing/Chat links
- Floating mini-chat sticky to bottom: creates/continues a conversation
  inline, message history expands upward, close button ends session
- Graph panel: toggles as a 420px right panel at full viewport width
- AppHeader: Knowledge, Chat, Briefing, Calendar, Tasks, Projects
- Router: / → KnowledgeView; /knowledge redirect; HomeView import removed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 18:01:03 -04:00
bvandeusen ea23f16bd7 feat: weather card — precip probability %, condition text, unit-aware wind
- Fetch precipitation_probability_max from Open-Meteo (replaces precip_sum
  in the card display — probability is more useful at a glance than mm)
- Show WMO condition description text on each forecast day
- Convert wind speed to mph when temp unit is F; pass wind_unit in response
- Display 💧 X% chance of rain; 💨 X mph/km/h wind per day

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 13:02:36 -04:00
bvandeusen 71ca0ecb5c fix: voice status global store, per-view mic reactivity, single-voice preview
- Move voice status into settings store (voiceSttReady, voiceTtsReady),
  checked once at login and refreshed after admin model reload
- ChatView, BriefingView, DashboardChatInput now use computed refs from
  the store — mic buttons appear reactively without needing a page reload
- BriefingView: separate STT-only guard for mic PTT vs TTS-only guard for
  listen mode / speak buttons
- Add ▶ Preview button to Voice & Speed section in Settings for single-
  voice testing without enabling blend mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:53:06 -04:00
bvandeusen b4b4b0d9d6 feat: weather precip/wind, dashboard mic, remove global voice overlay
- WeatherCard: show precipitation (mm) and max wind speed per forecast day
- DashboardChatInput: add PTT mic button (transcribe-to-input, voice-gated)
- Remove global VoiceOverlay floating button and Space PTT shortcut from
  App.vue — inline mic buttons in chat/briefing/dashboard are the right UX;
  global overlay had focus/latency/context issues

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:00:06 -04:00
bvandeusen 76c3dbc4b7 fix: stop TTS playback when PTT is activated
Pressing push-to-talk now immediately stops any ongoing TTS audio before
opening the microphone, preventing the assistant from hearing itself.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:43:15 -04:00
bvandeusen 98b3cdb593 feat: add weather condition icons to WeatherCard
Maps WMO condition strings to emoji icons for current conditions and
forecast days. No external dependencies — pure emoji lookup by condition text.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 18:08:18 -04:00
bvandeusen 6f84d90dff feat: voice S2S — faster-whisper STT, Kokoro TTS, PTT overlay
Implements full speech-to-speech pipeline (all 4 phases):

Backend (Phase 1):
- services/stt.py: lazy WhisperModel singleton, run_in_executor transcription
- services/tts.py: lazy KPipeline singleton, WAV synthesis at 24kHz/16-bit
- routes/voice.py: /api/voice/status, /voices, /transcribe, /synthesise
- config.py: VOICE_ENABLED, STT_BACKEND, STT_MODEL, TTS_BACKEND env vars
- app.py: load STT/TTS models at startup when VOICE_ENABLED=true
- llm.py: voice_mode + voice_speech_style params inject speak-naturally prefix
- generation_task.py: voice_mode passed through from chat route
- chat.py: "voice" conversation type allowed + excluded from retention cleanup
- pyproject.toml + Dockerfile: faster-whisper, kokoro, soundfile dependencies

Frontend (Phases 2–4):
- composables/useVoiceRecorder.ts: MediaRecorder PTT wrapper
- composables/useVoiceAudio.ts: AudioContext WAV playback wrapper
- BriefingView.vue: Listen button (TTS read-aloud), auto-TTS mode, mic PTT
- VoiceOverlay.vue: global floating PTT button; creates/reuses voice conv;
  full record→transcribe→stream→TTS flow; Space bar hold-to-talk via App.vue
- SettingsView.vue: Voice tab (status badge, speech style, voice/speed)
- App.vue: mounts VoiceOverlay; Space keydown/keyup fires voice:ptt-toggle
- api/client.ts: getVoiceStatus, getVoiceList, transcribeAudio, synthesiseSpeech

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 20:03:38 -04:00
bvandeusen 00643c778e security: fix 10 vulnerabilities from security audit
- SSRF: block private/internal URLs in image cache fetch
- SSRF: block private/internal URLs in RSS feed fetch (scheme guard)
- SSRF: block private/internal URLs in CalDAV URL setting
- Auth: require login for GET /api/images/<id> (was unauthenticated)
- Auth: restrict Ollama model pull/delete to admin users only
- Info disclosure: remove email from /api/users/search response
- OAuth: skip email-based account linking when email_verified is false
- Config: raise hard error on default SECRET_KEY when SECURE_COOKIES=true
- Rate limit: document proxy header requirement; add startup warning
- XSS: remove src/alt from global DOMPurify ADD_ATTR allowlist

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 00:37:13 -04:00
bvandeusen ac90548823 feat: task management enhancements (cancelled status, recurrence, timestamps)
- Add 'cancelled' status to TaskStatus type, StatusBadge, TaskCard,
  TaskEditorView, TaskViewerView, TasksListView
- Add RecurrenceEditor component (none / interval / calendar rules)
- TaskEditorView: wire RecurrenceEditor, show started_at/completed_at
  timestamps read-only, include recurrence_rule in save payload
- TaskViewerView: show recurrence summary, timestamps in meta row
- tasks.ts: statusFilter/priorityFilter as arrays, add recurrence_rule
  to updateTask and createTask payloads

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 00:51:36 -04:00
bvandeusen 37e2420192 feat: add /news archive view with feed filter and pagination
- NewsView.vue: 90-day article archive, feed filter dropdown,
  load-more pagination, topic pills, thumbs up/down reactions
- Router: add /news route
- AppHeader: add News nav link (desktop + mobile)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 00:51:24 -04:00
bvandeusen f81c38df84 feat: redesign BriefingView into 3-column layout (weather · chat · news)
- Left column: weather loaded independently via /api/briefing/weather
- Center column: chat messages with input bar (unchanged behavior)
- Right column: news panel loaded from /api/briefing/news (last 2 days)
- Auto-scroll to bottom on mount and after streaming
- Background refresh also refreshes news panel
- Responsive: stacks to single column on narrow screens
- Fix TaskCard.vue to include 'cancelled' in status records

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 00:38:04 -04:00
bvandeusen a63e498067 fix: weather card spacing and sizing consistency
- Increase temp size to 2rem and add explicit font-size to condition
- Uniform 0.5rem spacing below current temp (was 0.35rem)
- Today row font-size explicit at 0.85rem
- Forecast gap 0.75rem (was 0.5rem), min-width 4.5rem (was 3.5rem)
- Padding-top on forecast strip 0.75rem to match overall rhythm

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 17:37:27 -04:00
bvandeusen 62dbb8d496 refactor: centralise user timezone as a standalone setting
Browser timezone is now synced to user_settings["user_timezone"] on
every login/page load (App.vue). The briefing scheduler and LLM context
both read from this single source, falling back to the legacy
briefing_config.timezone for existing users during migration.

- App.vue: PUT /api/settings with browser IANA timezone on startAppServices
- routes/chat.py: fall back to stored user_timezone when not sent in request
- briefing_scheduler: read user_timezone setting; briefing_config.timezone
  kept as fallback only
- routes/briefing.py: pass tz_override from user_timezone to live-patched scheduler
- Remove timezone field from BriefingConfig interface and all briefing UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 20:17:51 -04:00
bvandeusen fd05c65018 fix(calendar): correct event timezone handling
- Frontend sends user_timezone (IANA, from Intl.DateTimeFormat) with
  every message POST; threaded through route → generation_task → build_context
- System prompt now tells the LLM the user's timezone so it creates
  events with the correct UTC offset (e.g. 15:00+01:00 not 15:00Z)
- Calendar tool guidance updated to require UTC offset in all event
  datetimes
- EventSlideOver: dateFromIso/timeFromIso now use JS Date to convert
  stored UTC times to local time for display; toIso includes local
  timezone offset when saving so the correct UTC time is stored

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 20:06:09 -04:00
bvandeusen e0c3836fab feat: event cards in chat/briefing, upcoming events on dashboard, briefing uses internal store
- ToolCallCard: event list items replaced with rich clickable cards (color dot,
  title, time, location); clicking opens EventSlideOver for edit/delete; single
  create/update events in header are also clickable; updated all event types to
  use start_dt/end_dt fields from internal store
- HomeView: new upcoming events widget shows today + next 7 days as a card grid
  above the hero project; clicking any card opens EventSlideOver inline
- briefing_pipeline: _gather_internal now queries the internal events store for
  today's events; CalDAV events are still appended (deduped) if configured

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 15:39:13 -04:00
bvandeusen c3e201d26a feat(calendar): internal event store with FullCalendar UI and CalDAV push sync
- AI calendar tools now always available (moved from _CALDAV_TOOLS to _CORE_TOOLS);
  create/list/search/update/delete events go through the internal DB store first,
  with fire-and-forget CalDAV push sync when the user has CalDAV configured
- Add EventEntry interface and typed API helpers (listEvents, createEvent,
  getEvent, updateEvent, deleteEvent) to client.ts
- Install @fullcalendar/vue3, daygrid, timegrid, interaction, core packages
- Add EventSlideOver.vue: create/edit/delete slide-over with title, start/end,
  all-day toggle, location, description, color picker, and project selector
- Add CalendarView.vue: month/week/day FullCalendar with drag-drop and resize
  wired to PATCH /api/events/:id; click empty date opens create slide-over
- Wire /calendar route, Calendar nav link in AppHeader, g+l keyboard shortcut

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 13:38:09 -04:00
bvandeusen a691fc043d feat(briefing): add WeatherCard.vue component
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 10:44:02 -04:00
bvandeusen 9cb3700a5c fix: add temp_unit and timezone to inline BriefingConfig literals
BriefingSetupWizard and SettingsView had hardcoded initial objects that
predated the new fields, causing TS2345 type errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 18:33:17 -04:00
bvandeusen 1686289af4 feat: daily briefing frontend — view, setup wizard, settings tab, nav
- BriefingView: soft chat UI with conversation history dropdown, SSE
  streaming via chat store, manual refresh trigger, today/past conv toggle
- BriefingSetupWizard: 4-step first-time setup overlay (welcome →
  locations → office days → RSS feeds)
- SettingsView: Briefing tab with enable toggle, location geocoding,
  office day picker, slot toggles, RSS feed management, notifications
- AppHeader + router: /briefing route and nav link (desktop + mobile)
- client.ts: briefing types and API functions (config, feeds, convs,
  geocode, trigger)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 20:30:45 -04:00
bvandeusen a63f06712f Fix ShareDialog transparent background — replace undefined CSS vars
--color-surface → --color-bg-card
--color-muted   → --color-text-muted
--color-hover   → --color-bg-secondary

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 17:38:51 -04:00
bvandeusen 6d593a0ef6 Move history to sidebar, simplify task assist, add content deduplication
- VersionHistorySection.vue: new sidebar component — collapsible timestamp list,
  click any snapshot to see inline diff + Restore/Back; replaces the modal
- NoteEditorView: remove History toolbar button + HistoryPanel modal, add
  VersionHistorySection at bottom of sidebar
- TaskEditorView: remove floating overlay assist panel + toggle button; add
  Writing Assistant section in sidebar matching note editor (scope selector,
  instruction textarea, generate/proofread/accept/reject); main area now shows
  streaming preview and DiffView like note editor; add VersionHistorySection
- note_versions.py: add content deduplication before time-gap check — identical
  body + title + tags skips snapshot regardless of interval (git semantics)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 16:56:30 -04:00
bvandeusen c7ef709633 Multi-user sharing, groups, and in-app notifications
Backend:
- Alembic migration 0025: groups, group_memberships, project_shares,
  note_shares, notifications tables
- models: Group, GroupMembership, ProjectShare, NoteShare, Notification
- services/access.py: permission resolution (viewer/editor/admin/owner)
- services/groups.py + routes/groups.py: full group CRUD + membership
- services/sharing.py + routes/shares.py: project/note sharing API
- services/notifications.py: in-app notification create/list/mark-read
- routes/in_app_notifications.py: GET/POST notification endpoints
- routes/users.py: user search endpoint
- services/projects.py + services/notes.py: *_for_user variants
- routes updated to use *_for_user on get/list; adds permission field
- app.py: register all new blueprints

Frontend:
- api/client.ts: ShareEntry, GroupEntry, NotificationEntry types + helpers
- stores/notifications.ts: Pinia store with polling
- NotificationBell.vue: bell icon + badge + dropdown toggle + 60s poll
- NotificationsPanel.vue: unread notification list with mark-all-read
- ShareDialog.vue: teleport modal for sharing projects/notes with users/groups
- SharedWithMeView.vue: /shared route listing shared projects and notes
- AppHeader: NotificationBell, Shared nav link
- ProjectView, NoteViewerView, TaskViewerView: Share button + ShareDialog
- SettingsView: Groups admin tab with create/delete groups + member mgmt
- router: /shared route

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 15:37:00 -04:00
bvandeusen 978a2627fb UI refinement: toolbar icons, gradient CTA, Fraunces title, viewer polish
MarkdownToolbar:
- Replace text labels with SVG icons (Material Design paths)
- Group buttons with visual separators: text / headings / lists / code / links
- Add Strikethrough and Blockquote buttons (previously missing)
- Active state: tinted bg + ring instead of solid fill; hover lift shadow
- Toolbar container: pill shape with border (matches rest of UI)

editor-shared.css:
- btn-save: gradient + glow (linear-gradient(135deg, #6366f1, #4f46e5))
- title-input: borderless with Fraunces font and focus underline

NoteEditorView:
- Back button label standardized to "← Notes" (was "Back")
- Write/Preview tabs and toolbar now share the same row (flex-direction row)

NoteViewerView:
- Shimmer skeleton loader replaces plain "Loading..." text
- Note title uses Fraunces font at 2rem
- Edit button becomes primary gradient CTA
- Meta line shows clock/pencil SVG icons alongside timestamps
- Backlinks section: card grid with colored type badges (note=indigo, task=amber)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 10:57:02 -04:00
bvandeusen 71301f631d Workspace UI overhaul: rail note panel, split task detail, project goal header
- WorkspaceNoteEditor: replace toggling list/editor views with always-visible
  left rail (155px) showing note list alongside editor pane; persist last-open
  note per project in localStorage (workspace_note_{projectId})
- WorkspaceTaskPanel: add priority dot + due date on task rows; replace full
  overlay detail with bottom-split (44% list / 56% detail); close button
  replaces back nav; active row highlighted; fade transition
- WorkspaceView: show project goal in header instead of 'Workspace'; non-equal
  panel widths (0.8fr / 1.1fr / 1.1fr); empty chat quick-action chips (Project
  status / New note / Add tasks); prefill() helper

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 23:51:17 -04:00
bvandeusen e4b2cd3aeb Tasks list: smart sections view (overdue / today / this week / upcoming / no date / done)
Replaces the flat sorted list with date-aware sections that surface what
needs attention first. Completed tasks go into a collapsed section at the
bottom. Grouped-by-project mode is preserved as the second toggle option.
TaskCard compact restored to card hover/lift style.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 23:12:07 -04:00
bvandeusen 6e9ec26c8e UI polish: notes/tasks list views
- NotesListView: skeleton shimmer for grid and list modes; grid columns change from fixed 3 to auto-fill(260px)
- NoteCard compact: flat border-bottom row style instead of stacked mini-cards; gradient fade mask on grid preview text
- TaskCard compact: flat border-bottom row style; show up to 2 tags
- TasksListView: gradient + shadow on New Task button (matches NotesListView)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 22:39:05 -04:00
bvandeusen befee1110b feat: replace gear dropdown with direct settings link
Remove the gear dropdown menu from AppHeader; cog icon is now a plain
router-link to /settings. Admin-only /admin/users and /admin/logs routes
are replaced with redirects to /settings. Mobile menu admin links removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 21:13:43 -04:00
bvandeusen bb1f29c8e2 Header: increase height and logo size for better visibility
- Nav padding: 0.5rem → 0.75rem vertical, 1.25rem → 1.5rem horizontal
- AppLogo size: 24px → 34px so the book detail is legible

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 18:36:10 -04:00
bvandeusen 474ed1fe05 UI polish: hover lift, skeleton loaders, empty states, badge contrast, transitions
Card & row interactions:
- NoteCard, TaskCard, ProjectCard: translateY(-2px) lift on hover + extended transitions
- Kanban task cards (ProjectView), note rows: same lift treatment
- Task rows in flat/grouped list: soft indigo bg tint on hover
- Chat conversation items: left-border accent + bg tint on hover (was border-only)
- HomeView project mini-cards: translateY(-2px) lift on hover

Global feedback:
- Buttons: scale(0.97) on :active press (theme.css, :not(:disabled) scoped)
- TagPill: color → primary + indigo bg tint on hover
- StatusBadge: increased opacity 15% → 22% + stronger text color for readability

Loading & empty states:
- TasksListView: shimmer skeleton loader (6 rows) + rich empty state with CTA
- ProjectListView: shimmer skeleton cards (4) + rich empty state with CTA
- HomeView: section-empty messages for overdue/high-priority/notes sections
- ProjectView kanban columns: dashed-border styled empty state

Transitions & graph:
- WorkspaceView panels: panel-fade opacity transition on show/hide (v-if inner wrap)
- GraphView D3 nodes: grow to r*1.3 + bold label on mouseover (150ms transition)
- Milestone action buttons: base opacity 0 → 0.35 for discoverability

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 18:34:52 -04:00
bvandeusen 16220c57a0 Fix user bubble text contrast, Chat nav active state, and update summary.md
- theme.css: darken user bubble text (#3a3a4a light / #b0b0c8 dark) for better readability
- AppHeader: highlight Chat nav link when on any /chat/* route (was only active on exact /chat)
- summary.md: document workspace, graph, queue persistence, ToolCallCard direct-API, dedup scoping

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 18:00:04 -04:00