Commit Graph

8170 Commits

Author SHA1 Message Date
Nuwan b7cec1ff34 test(17-01): add JKSessionSettingsModal test file with setup
- Create __tests__ directory for client components
- Add test file with imports and mocks for react-i18next
- Create renderModal helper function with default props
- Add placeholder test verifying setup works
2026-02-08 12:20:04 +05:30
Nuwan 6b4acce615 docs(17): plan Jest unit tests for JKSessionSettingsModal
Plan 17-01: Create unit tests covering:
- UNIT-01: Modal renders with currentSession props
- UNIT-02: Save button calls onSave with correct payload
- UNIT-03: Loading state disables form interactions

Plan verification passed.
2026-02-08 12:17:14 +05:30
Nuwan 44cc57ad85 docs(17): create phase plan for Jest unit tests
Phase 17: Unit Tests (Jest)
- 1 plan in 1 wave
- 1 parallel, 0 sequential
- Covers UNIT-01, UNIT-02, UNIT-03 requirements
- Ready for execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 12:15:30 +05:30
Nuwan c5600e9315 docs: create milestone v1.3 roadmap (2 phases)
Phases:
17. Unit Tests (Jest): UNIT-01, UNIT-02, UNIT-03
18. Integration Tests (Playwright): INT-01, INT-02, INT-03

All 6 requirements mapped to phases.
2026-02-08 12:05:50 +05:30
Nuwan 2c78e39ab8 docs: define milestone v1.3 requirements
6 requirements across 2 categories:
- UNIT-01 through UNIT-03: Jest unit tests
- INT-01 through INT-03: Playwright integration tests
2026-02-08 11:59:55 +05:30
Nuwan 98183f7efa docs: start milestone v1.3 Session Settings Tests 2026-02-07 21:28:37 +05:30
Nuwan 86420c85de feat: wire up Resync button in session toolbar
Connect the existing Resync button to the resyncAudio hook from useGearUtils.
Calls jamClient.SessionAudioResync() via native C++ bridge to perform audio
resync, with loading state and error handling via toast notifications.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 02:38:21 +05:30
Nuwan 1278002a07 right align unread message count on the chat button 2026-02-07 02:20:07 +05:30
Nuwan 460dd5b4cb chore: complete v1.2 Session Attachments milestone
Archived:
- milestones/v1.2-ROADMAP.md (full phase details)
- milestones/v1.2-REQUIREMENTS.md (all 24 requirements marked complete)

Deleted (fresh for next milestone):
- REQUIREMENTS.md

Updated:
- MILESTONES.md (new entry with stats and accomplishments)
- ROADMAP.md (collapsed v1.2 phases into details tag)
- STATE.md (reset for next milestone)

v1.2 Session Attachments shipped 2026-02-07:
- 5 phases (12-16), 11 plans
- 12 files, 1,868 lines
- 5 days from start to ship

Key features delivered:
- File upload with validation (10 MB, approved types)
- Attachment display in chat with clickable links
- Real-time sync via WebSocket
- Error handling with toast notifications
- Unread badge persistence

Bugs fixed during UAT:
- Attachment message deduplication race condition
- Unread count not persisting across page reloads

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 02:19:32 +05:30
Nuwan 3273d4972c docs(16): complete Phase 16 and v1.2 milestone
- Create 16-02-SUMMARY.md documenting UAT completion and bug fixes
- Update ROADMAP.md to mark Phase 16 as complete (2/2 plans)
- Mark v1.2 Session Attachments milestone as shipped (2026-02-07)

UAT discovered and fixed 2 bugs:
1. Attachment message deduplication race condition
2. Unread count not persisting across page reloads

All 26 requirements for v1.2 Session Attachments validated.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 02:14:49 +05:30
Nuwan 7110e7cdf9 fix(16): persist unread count across page reloads
Problem: After page reload, the unread badge on chat button disappeared
even though there were unread messages.

Root cause:
1. unreadCounts was reset to {} on page reload
2. fetchChatHistory was only called when chat window opened
3. By that time, openChatWindow already reset the count to 0

Fix:
1. Fetch chat history when session joins (not just when chat opens)
2. In fetchChatHistory.fulfilled, calculate unread count based on
   lastReadAt timestamp from localStorage
3. Only calculate unread if chat window is NOT open for that channel

This ensures the badge shows correct unread count after page reload.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 02:07:01 +05:30
Nuwan 20d0259433 fix(16): fix attachment deduplication in uploadAttachment.fulfilled
The previous fix only added deduplication by attachmentId in addMessageFromWebSocket
and fetchChatHistory.fulfilled, but missed the uploadAttachment.fulfilled handler.

Race condition: WebSocket message can arrive BEFORE the upload API returns.
When this happens:
1. WebSocket delivers message with id='456', attachmentId=123
2. addMessageFromWebSocket adds it to state
3. Upload API returns
4. uploadAttachment.fulfilled only checked for id='attachment-123' → not found
5. Duplicate message added

Fix: Also check by attachmentId in uploadAttachment.fulfilled handler.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 01:44:23 +05:30
Nuwan c1ed8470ae fix(16): improve attachment deduplication by attachmentId
The optimistic message uses 'attachment-{notation.id}' as ID while
REST API and WebSocket use the chat message ID. This caused duplicates
when fetchChatHistory ran after an optimistic upload.

Now deduplication checks both message ID and attachmentId for attachment
messages, preventing duplicates regardless of ID format.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-07 01:38:50 +05:30
Nuwan 08283e24ef docs(16-02): create comprehensive UAT checklist for v1.2 Session Attachments
- 74 test cases across 7 requirement categories
- Covers all 26 requirements (REQ-1 through REQ-7)
- 283 lines including test tables, bug report template, sign-off section
- Organized with prerequisites, edge cases, and summary table
2026-02-07 01:25:42 +05:30
Nuwan f2138f8d0d docs(16-01): complete error handling & user feedback plan
Tasks completed: 5/5
- Upload success toast (REQ-5.4)
- Validation error messages (REQ-5.1, REQ-5.2)
- Network error message (REQ-5.3)
- S3 404 error handling (REQ-5.5)
- Integration tests for error scenarios

SUMMARY: .planning/phases/16-attachment-finalization/16-01-SUMMARY.md
2026-02-07 01:23:23 +05:30
Nuwan 4bb3fa2065 test(16-01): add error handling integration tests
- Create error-handling.spec.ts with 5 test scenarios
- Test REQ-5.1: File size exceeded validation
- Test REQ-5.4: Upload success toast with auto-dismiss
- Test REQ-5.3: Network error handling with retry capability
- Test REQ-5.5: S3 404 error handling (missing file)
- Test edge case: Prevent rapid clicks during upload
- Uses test-helpers.ts for login and session creation
2026-02-06 18:45:36 +05:30
Nuwan 1d026c3d30 fix(16-01): add S3 404 error handling with toast notification
- Add react-toastify import for toast notifications
- Show toast.error('File no longer available') when attachment fetch fails
- Handles S3 404 errors gracefully per REQ-5.5
- Replaces silent failure with user-friendly error message
2026-02-06 18:44:14 +05:30
Nuwan 744c735817 fix(16-01): update network error message per REQ-5.3
- Change uploadAttachment error message to 'Upload failed. Please try again.'
- Provides actionable feedback to retry on network errors
- Matches exact wording from REQ-5.3
2026-02-06 18:43:53 +05:30
Nuwan 1ecc1d7987 fix(16-01): improve validation error messages per requirements
- Update validateFileSize error: 'File size exceeds 10 MB limit' (REQ-5.1)
- Update validateFileType error: 'File type not supported. Allowed: [list]' (REQ-5.2)
- Hardcode error messages for clarity per requirements
- Update unit tests to match new error messages
- All 37 unit tests passing
2026-02-06 18:43:37 +05:30
Nuwan 354492bc1a feat(16-01): add upload success toast notification
- Add selectUploadStatus selector to track upload state transitions
- Track previous upload status with useRef
- Show toast.success when upload completes (uploading -> idle)
- Auto-dismiss after 3 seconds per REQ-5.4
- Success toast provides clear feedback on successful file uploads
2026-02-06 18:42:35 +05:30
Nuwan 9499934ea4 docs(16): create phase plan for Attachment Finalization
Phase 16: Attachment Finalization
- 2 plans in 2 waves
- Plan 16-01: Error handling, success toast, S3 404 handling (Wave 1)
- Plan 16-02: UAT checklist and final integration testing (Wave 2)
- Ready for execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 18:30:18 +05:30
Nuwan 85fd4916e2 style(chat): update chat button to match nav button style
Changed JKSessionChatButton from bare icon to proper Button component:
- Uses Button from reactstrap with btn-custom-outline class
- Matches other nav buttons (Invite, Volume, Video, etc.)
- Icon sized at 16x16px with 0.2rem right margin
- "Chat" text label added
- Unread badge repositioned for button layout
- Reduced opacity when window is open (visual feedback)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 18:23:59 +05:30
Nuwan 8cf0b661a7 docs(15): complete Phase 15 - Real-time Synchronization
Phase 15 verified and complete with bug fixes:
- WebSocket handler extracts attachment fields correctly
- Deduplication works for both WebSocket and REST API paths
- Integration tests created (test/attachments/real-time-sync.spec.ts)
- Human verification passed

Bug fixes applied during UAT:
- Optimistic update for uploader (sender excluded from WebSocket)
- fetchChatHistory dispatch on channel activation
- API field name (chats not messages)
- API parameter name (music_session not session_id)
- Infinite loop prevention in fetch

Known limitation documented:
- WebSocket only broadcasts to musicians (as_musician: true filter)
- Pre-existing backend behavior, not introduced by v1.2

Requirements satisfied: REQ-3.1*, REQ-3.2
* REQ-3.1 has known limitation for non-musician participants

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 18:20:44 +05:30
Nuwan e24c655905 fix(15): use correct parameter name for chat API (music_session)
Backend's check_session filter expects 'music_session' parameter:
  @music_session = ActiveMusicSession.find(params[:music_session])

But we were sending 'session_id', causing ActiveMusicSession.find(nil)
to fail.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 16:34:36 +05:30
Nuwan fce74152f8 fix(15): prevent infinite loop in chat history fetch
The useEffect condition allowed fetching when fetchStatus was 'failed',
causing infinite retry loops when the API returned an error.

Changed condition from:
  fetchStatus !== 'loading' && fetchStatus !== 'succeeded'
To:
  fetchStatus === 'idle'

This ensures we only fetch once per channel on initial load, and don't
retry automatically on failure.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 16:32:52 +05:30
Nuwan 5df60ad6cf fix(15): pass sessionId to fetchChatHistory for session messages
The fetchChatHistory thunk needs sessionId to determine channel type:
- With sessionId: fetches 'session' channel messages
- Without sessionId: fetches 'global' channel messages

The useEffect was only passing `channel` (which is the sessionId for
session chats), but not the `sessionId` parameter. This caused the
API to fetch global chat instead of session chat, so session messages
disappeared after page reload.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 16:04:41 +05:30
Nuwan da4e864ab7 fix(15): correct API response field name (chats not messages)
The chat history API returns { chats: [...], next: ... } but the
fetchChatHistory.fulfilled handler was expecting { messages: [...] }.

This caused a TypeError when opening the chat window because
`messages` was undefined.

Fixed:
- sessionChatSlice.js: Extract `chats` from payload, default to []
- Updated all test payloads to use `chats` field name

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 15:45:06 +05:30
Nuwan bfee9acdfb fix(15): resolve UAT issues - uploader message visibility and chat history
Issues found during UAT:
1. Uploader doesn't see their own attachment message
2. Chat history doesn't load on page refresh/rejoin

Root causes:
1. Backend's server_publish_to_session excludes sender from WebSocket
   broadcast (exclude_client_id: sender[:client_id])
2. fetchChatHistory was imported but never called in JKChatMessageList

Fixes:
- Add optimistic message in uploadAttachment.fulfilled for uploader
  Since sender is excluded from WebSocket, we add the message locally
  using the MusicNotation response + user info
- Add useEffect in JKChatMessageList to dispatch fetchChatHistory
  when channel becomes active

Technical details:
- Pass userId/userName to uploadAttachment thunk for message construction
- Use 'attachment-{notation.id}' as message ID to avoid collision
- Fetch history when fetchStatus is not 'loading' or 'succeeded'

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 15:36:04 +05:30
Nuwan e9dd992e29 test(15-01): add real-time attachment sync integration tests
- Create test/attachments/real-time-sync.spec.ts
- Test WebSocket message receipt for attachments
- Test deduplication of duplicate messages
- Test REST API and WebSocket message deduplication
- Test attachment display in chat
- Uses Redux dispatch simulation approach for CI compatibility
2026-02-06 02:20:47 +05:30
Nuwan 86206e1992 refactor(15-01): clean up debug logging in WebSocket handler
- Remove console.log for received WebSocket messages
- Remove console.log for Redux dispatch
- Remove console.log for callback registration
- WebSocket handler verified: extracts all attachment fields correctly
2026-02-06 02:19:31 +05:30
Nuwan af40426a59 docs(15): create phase plan for Real-time Synchronization
Phase 15: Real-time Synchronization
- 1 plan in 1 wave
- Primarily verification phase confirming Phases 12-14 infrastructure
- Clean up debug logging, create integration tests
- Human verification checkpoint for multi-user sync testing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 02:11:40 +05:30
Nuwan 0124977723 docs(14): complete chat-integration-and-display phase
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 01:59:48 +05:30
Nuwan 24ce6a6beb docs(14-03): complete REST API attachment transformation gap closure plan
Tasks completed: 2/2
- Task 1: Add REST API attachment transformation (TDD)
- Task 2: Verify gap closure with integration test

SUMMARY: .planning/phases/14-chat-integration-and-display/14-03-SUMMARY.md
2026-02-06 01:55:07 +05:30
Nuwan 977d1a9b95 feat(14-03): transform REST API music_notation to flat attachment fields
- Transform nested music_notation object from REST API to flat attachment fields
- Map music_notation.id → attachmentId, file_name → attachmentName, attachment_type → attachmentType
- Include purpose field from API response root
- Set attachmentSize to null (not available from REST API, only WebSocket)
- Matches WebSocket message format for consistent JKChatMessage rendering

Tests:
- Add test for REST API attachment transformation
- Fix pre-existing test bugs: incorrect sendMessage.fulfilled payload format
- Fix pre-existing test bug: fetchChatHistory deduplication test used wrong format
- All 89 tests now pass (previously 3 failures)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 01:52:40 +05:30
Nuwan d2dc3a8d63 docs(14): create gap closure plan for REST API attachment transformation
Phase 14: Chat Integration & Display
- 1 gap closure plan (14-03)
- Fixes REQ-2.5: Chat history includes attachments
- Root cause: fetchChatHistory.fulfilled missing music_notation transform
- Small fix: 5 lines to map nested object to flat attachment fields

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 01:34:30 +05:30
Nuwan c9b2ba7f10 docs(14-02): complete clickable links and responsive layout plan
Tasks completed: 3/3
- Task 1: Add click handler to fetch signed URL and open file
- Task 2: Add responsive styling with filename truncation
- Task 3: Human verification checkpoint (approved)

SUMMARY: .planning/phases/14-chat-integration-and-display/14-02-SUMMARY.md
2026-02-06 00:55:44 +05:30
Nuwan 1143048ec3 feat(14-02): add responsive styling with filename truncation
- Add flexWrap to header (name + timestamp wrap on narrow windows)
- Change filename maxWidth from 200px to 100% (takes available width)
- Add flexShrink: 0 to file size and paperclip icon (never shrink)
- Add fontSize: 13px to file size for consistent sizing
- Remove marginRight from paperclip icon (gap handles spacing)
- Ensure minWidth: 0 on content container for text-overflow to work
- Add comment clarifying header layout
- Layout responsive at different window sizes with proper truncation
2026-02-05 19:49:01 +05:30
Nuwan 91cac19a52 feat(14-02): add clickable attachment links with signed URL fetching
- Import getMusicNotationUrl REST helper and useState/useCallback hooks
- Add handleAttachmentClick handler that fetches signed S3 URL and opens in new tab
- Implement loading state (isLoadingUrl) to prevent rapid clicks
- Make filename a clickable link with underline and blue color
- Add error handling that logs to console without crashing
- Show 'wait' cursor during URL fetch
- Browser handles file display based on Content-Type (PDF viewer, image display, audio player)
2026-02-05 19:48:11 +05:30
Nuwan 38fea32f22 docs(14-01): complete attachment message display plan
Tasks completed: 2/2
- Task 1: WebSocket transformation with attachment fields
- Task 2: JKChatMessage attachment rendering

SUMMARY: .planning/phases/14-chat-integration-and-display/14-01-SUMMARY.md
2026-02-05 19:45:28 +05:30
Nuwan b8bfd23a9c feat(14-01): render attachment messages with distinct styling and metadata
- Import formatFileSize from attachmentValidation service
- Add isAttachmentMessage helper to detect attachment messages
- Render attachment messages with light blue background (#e3f2fd)
- Display paperclip icon with accessible aria-label
- Show '[name] attached [filename]' format with file size if available
- Update PropTypes to include optional attachment fields
- Maintain React.memo for performance
2026-02-05 19:43:46 +05:30
Nuwan 6d1cf489d7 feat(14-01): extend WebSocket message transformation for attachment fields
- Add attachment fields to CHAT_MESSAGE handler transformation
- Include attachmentId, attachmentName, attachmentType, purpose, attachmentSize
- Fields null/undefined for regular text messages
- WebSocket payload maps to Redux format with attachment metadata
2026-02-05 19:43:36 +05:30
Nuwan 5ed8b3d0ad fix(14): revise plans based on checker feedback
Addresses 3 blockers and 2 warnings:

BLOCKER 1: Plan 02 now depends on Plan 01 (wave: 2, depends_on: ["14-01"])
BLOCKER 2: Task 1 in Plan 02 now verifies existing getMusicNotationUrl
           instead of creating it; rest.js removed from files_modified
BLOCKER 3: Plan 01 Task 2 adds explicit TDD exception justification
           (styling-only change per CLAUDE.md)

WARNING 1: Plan 02 keeps autonomous: false with comment explaining
           checkpoint is for download flow verification
WARNING 2: Plan 01 must_haves.truths now includes edge case validation

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-05 19:21:51 +05:30
Nuwan 68229dd003 docs(14): create phase plan for Chat Integration & Display
Phase 14: Chat Integration & Display
- 2 plan(s) in 1 wave(s)
- 2 parallel (wave 1), 0 sequential
- Extends JKChatMessage for attachment display
- Adds clickable links with signed URL fetching
- Human verification checkpoint in plan 02
- Ready for execution
2026-02-05 19:16:42 +05:30
Nuwan 45e284096a docs(13): complete File Upload Infrastructure phase
- Mark all 3 plans complete (validation, Redux state, UI integration)
- Update phase status: Complete (2026-02-05)
- Mark 8 requirements as Complete (REQ-1.1-1.4, REQ-6.1-6.3, REQ-7.1)
- Phase verification: 14/14 must-haves verified (100%)
- User verified: file upload working end-to-end with backend 201 Created
2026-02-05 19:04:17 +05:30
Nuwan e28a4df876 docs(13-03): document bug fixes found during verification
Added deviations section documenting 2 auto-fixed bugs:
1. ESLint no-unused-expressions (optional chaining)
2. Duplicate /api/ prefix in REST endpoint URL

Both bugs found and fixed during user verification (Task 4).
2026-02-05 18:59:39 +05:30
Nuwan ff6042e884 docs(13-03): complete file upload UI integration plan
Tasks completed: 3/3
- Wire up Attach button in session toolbar
- Create upload progress component for chat window
- Display upload progress in chat message list

User verification: APPROVED
- File dialog opens on button click
- Invalid files rejected with error toast
- Valid files upload to backend (201 Created)
- Upload progress displayed in chat

SUMMARY: .planning/phases/13-file-upload-infrastructure/13-03-SUMMARY.md
2026-02-05 18:58:49 +05:30
Nuwan b1ed2247ba fix(13-03): correct API endpoint URL for music notation upload
Remove duplicate /api/ prefix - REACT_APP_API_BASE_URL already includes /api.
Fixed: /api/api/music_notations -> /api/music_notations
2026-02-05 11:42:56 +05:30
Nuwan edf74f7248 fix(13-03): resolve ESLint no-unused-expressions errors
Replace optional chaining expressions with explicit if checks to satisfy ESLint configuration.
2026-02-05 11:38:28 +05:30
Nuwan f2c07faede feat(13-03): display upload progress in chat message list
- Import selectIsUploading and selectUploadFileName from sessionChatSlice
- Import JKChatUploadProgress component
- Add useSelector hooks for upload state (isUploading, uploadFileName)
- Render JKChatUploadProgress at end of message list when upload in progress
- Upload indicator appears at bottom of chat for easy visibility
- Conditional rendering: only shows when isUploading is true AND fileName exists
2026-02-05 11:06:50 +05:30
Nuwan cd2d79b190 feat(13-03): create upload progress component for chat window
- Create JKChatUploadProgress component with Spinner and filename display
- Styled as system message (gray background, italic text)
- Display format: 'Uploading [filename]...'
- Uses React.memo for performance optimization
- PropTypes validation for fileName (required)
- 42 lines including component, styles, and PropTypes
2026-02-05 11:06:44 +05:30