diff --git a/.planning/phases/14-chat-integration-and-display/14-01-PLAN.md b/.planning/phases/14-chat-integration-and-display/14-01-PLAN.md index 8ee1dc6e9..659d07275 100644 --- a/.planning/phases/14-chat-integration-and-display/14-01-PLAN.md +++ b/.planning/phases/14-chat-integration-and-display/14-01-PLAN.md @@ -7,6 +7,7 @@ depends_on: [] files_modified: - jam-ui/src/components/client/chat/JKChatMessage.js - jam-ui/src/components/client/JKSessionScreen.js + autonomous: true must_haves: @@ -15,6 +16,7 @@ must_haves: - "Attachment messages include file size (KB/MB), uploader name, and timestamp" - "Attachment messages have visual distinction from regular text messages (paperclip icon, different styling)" - "Attachment messages sort chronologically with regular chat messages" + - "Edge cases handled: missing senderName shows 'Unknown', missing attachmentName handled gracefully" artifacts: - path: "jam-ui/src/components/client/chat/JKChatMessage.js" provides: "Attachment message rendering with metadata display" @@ -101,6 +103,8 @@ WebSocket CHAT_MESSAGE handler transforms attachment fields into Redux message f Modify JKChatMessage to detect and render attachment messages differently from regular text messages. +NOTE: This is primarily styling/conditional rendering work (similar to Phase 8-02 visual component work). Per CLAUDE.md, TDD is optional for styling-only changes. The component behavior (conditional rendering based on attachmentId presence) is straightforward and will be verified via integration tests in Plan 02. + 1. Import formatFileSize from attachmentValidation service: ```javascript import { formatFileSize } from '../../../services/attachmentValidation'; @@ -122,7 +126,12 @@ const isAttachmentMessage = (message) => { 4. Keep existing rendering for regular text messages unchanged. -5. Update PropTypes to include new optional fields: +5. Handle edge cases: + - Missing senderName: Display "Unknown" (already handled in existing code) + - Missing attachmentName: Fall back to regular message rendering (handled by isAttachmentMessage check) + - Null/undefined attachmentSize: Don't show size, just filename + +6. Update PropTypes to include new optional fields: ```javascript JKChatMessage.propTypes = { message: PropTypes.shape({ @@ -141,7 +150,7 @@ JKChatMessage.propTypes = { }; ``` -6. Styling for attachment message (inline styles, consistent with existing pattern): +7. Styling for attachment message (inline styles, consistent with existing pattern): ```javascript const attachmentStyle = { display: 'flex', @@ -159,7 +168,7 @@ const fileIconStyle = { }; ``` -7. Conditional rendering structure: +8. Conditional rendering structure: ```javascript if (isAttachmentMessage(message)) { return ( @@ -201,9 +210,10 @@ React.memo should remain in place for performance optimization. 3. Attachment messages render with paperclip icon, "[name] attached [filename]" format 4. File size displays when available (formatted as KB/MB) 5. Visual distinction: attachment messages have light blue background +6. Edge cases: missing senderName shows "Unknown", missing attachmentSize shows no size -JKChatMessage detects attachment messages and renders them with distinct styling, paperclip icon, sender name, filename, size (if available), and timestamp. Regular messages render unchanged. +JKChatMessage detects attachment messages and renders them with distinct styling, paperclip icon, sender name, filename, size (if available), and timestamp. Regular messages render unchanged. Edge cases handled gracefully. @@ -230,6 +240,7 @@ JKChatMessage detects attachment messages and renders them with distinct styling - Timestamp displays using existing formatTimestamp utility - Regular text messages render unchanged - Messages sort chronologically (existing behavior preserved) +- Edge cases handled: missing senderName, missing attachmentSize diff --git a/.planning/phases/14-chat-integration-and-display/14-02-PLAN.md b/.planning/phases/14-chat-integration-and-display/14-02-PLAN.md index f34d148dd..fca32f163 100644 --- a/.planning/phases/14-chat-integration-and-display/14-02-PLAN.md +++ b/.planning/phases/14-chat-integration-and-display/14-02-PLAN.md @@ -2,11 +2,14 @@ phase: 14-chat-integration-and-display plan: 02 type: execute -wave: 1 -depends_on: [] +wave: 2 +depends_on: ["14-01"] files_modified: - jam-ui/src/components/client/chat/JKChatMessage.js - - jam-ui/src/helpers/rest.js + +# autonomous: true because tasks are straightforward implementation (similar to Phase 13-03) +# The checkpoint is included for final integration verification since this is the last plan +# of the phase and involves user-visible behavior (clicking to download files) autonomous: false must_haves: @@ -20,9 +23,6 @@ must_haves: - path: "jam-ui/src/components/client/chat/JKChatMessage.js" provides: "Clickable attachment links with signed URL fetching" contains: "handleAttachmentClick" - - path: "jam-ui/src/helpers/rest.js" - provides: "getMusicNotationUrl helper for signed S3 URLs" - contains: "getMusicNotationUrl" key_links: - from: "JKChatMessage.js" to: "getMusicNotationUrl" @@ -51,7 +51,7 @@ Output: Attachment filenames are clickable links that fetch signed S3 URLs and o @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md -@.planning/phases/14-chat-integration-and-display/14-01-PLAN.md +@.planning/phases/14-chat-integration-and-display/14-01-SUMMARY.md @jam-ui/src/components/client/chat/JKChatMessage.js @jam-ui/src/helpers/rest.js @.planning/phases/12-attachment-research-&-backend-validation/12-RESEARCH.md @@ -64,9 +64,11 @@ Output: Attachment filenames are clickable links that fetch signed S3 URLs and o jam-ui/src/components/client/chat/JKChatMessage.js Add click handler for attachment filename that: -1. Fetches signed S3 URL via getMusicNotationUrl REST helper +1. Fetches signed S3 URL via getMusicNotationUrl REST helper (already exists in rest.js line 1054) 2. Opens URL in new browser tab (target="_blank") +IMPORTANT: getMusicNotationUrl already exists in rest.js (created in Phase 12-02). Verify it returns {url: string} format before using. + Import the REST helper: ```javascript import { getMusicNotationUrl } from '../../../helpers/rest'; @@ -131,10 +133,11 @@ Note: Browser will handle file display based on Content-Type returned by S3: The backend sets Content-Disposition based on file type. -1. Code compiles without errors -2. Clicking attachment filename triggers handleAttachmentClick -3. isLoadingUrl state prevents rapid multiple clicks -4. Error handling logs to console (no crash on failure) +1. Verify getMusicNotationUrl exists in rest.js and returns {url: string} +2. Code compiles without errors +3. Clicking attachment filename triggers handleAttachmentClick +4. isLoadingUrl state prevents rapid multiple clicks +5. Error handling logs to console (no crash on failure) Attachment filenames are clickable links that fetch signed S3 URLs and open in new browser tabs. Loading state prevents rapid clicks. Errors logged to console without crashing.