Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle attachments web socket notifications on patient flow page #1371

Merged
merged 6 commits into from
Jan 2, 2025

Conversation

nmajor25
Copy link
Contributor

@nmajor25 nmajor25 commented Dec 20, 2024

Shortcut Story ID: [sc-56327] [sc-57309]

In this PR, these are being handled only in the action sidebar on the patient flow page.

Coinciding with the backend PR: https://github.com/RoundingWell/care-ops-backend/pull/8787.

  • Support AttachmentAdded notifications
  • Support FileReplaced notifications
  • Support FileRemoved notifications
  • Show paperclip icon in action list items when file is added/removed via websocket

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced WebSocket communication for comments and attachments
    • Improved file management functionality with real-time updates
  • Bug Fixes

    • Refined event handling for adding and removing attachments
    • Updated message processing for better resource tracking
  • Improvements

    • Streamlined integration of WebSocket notifications
    • Added support for file replacement and removal operations
  • Testing

    • Expanded test coverage for patient flow and file attachment scenarios

@nmajor25 nmajor25 requested a review from paulfalgout December 20, 2024 23:01
Copy link

cypress bot commented Dec 20, 2024

RoundingWell Care Ops Frontend    Run #7114

Run Properties:  status check passed Passed #7114  •  git commit 04b80372fb: Use `state:verb:subject` pattern for websocket trigger events
Project RoundingWell Care Ops Frontend
Branch Review attachments-ws-msgs
Run status status check passed Passed #7114
Run duration 02m 52s
Commit git commit 04b80372fb: Use `state:verb:subject` pattern for websocket trigger events
Committer Nick Major
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 1
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 312
View all changes introduced in this branch ↗︎

@coveralls
Copy link

coveralls commented Dec 20, 2024

Pull Request Test Coverage Report for Build b078a67b-a2e7-4662-867d-744bfcca0ea6

Details

  • 20 of 20 (100.0%) changed or added relevant lines in 3 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall first build on attachments-ws-msgs at 99.987%

Totals Coverage Status
Change from base Build fa19414b-7f77-4682-bc0d-993978c797f5: 100.0%
Covered Lines: 6073
Relevant Lines: 6073

💛 - Coveralls

});

this.set({ _files: newFilesRelationship });
},
Copy link
Contributor Author

@nmajor25 nmajor25 Dec 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The paperclip attachments icon on action list items is shown or hidden based on the length of action.get('_files').

We're currently not updating that when a file is removed manually by a user. And therefore it doesn't work out of the box for the FileRemoved ws notification.

So i added this method to the action entity service that filters out the file from _files by id. And then sets a new _files relationship array for the action.

This allows for the paperclip icon to be hidden after attachment deletion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is how we want to implement this, we would just need to call action.removeAttachment(model) in the action sidebar app when a file is manually deleted by a user.

Copy link
Contributor Author

@nmajor25 nmajor25 Dec 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently in the app, the .paperclip icon isn't shown when an attachment is added and isn't hidden when an attachment is removed manually by a user in the sidebar.

I created a separate story here, that I can tackle in a separate PR.

Copy link

coderabbitai bot commented Dec 20, 2024

Walkthrough

This pull request introduces comprehensive enhancements to the attachment management functionality across multiple files. The changes focus on improving how attachments are handled in the patient sidebar application, including adding new methods for attachment addition and removal, updating WebSocket communication, and extending the model's message handling capabilities. The modifications span across JavaScript files in the patient actions, entities service, and test integration, providing a more robust and interactive attachment management system.

Changes

File Change Summary
src/js/apps/patients/sidebar/action-sidebar_app.js - Added onWsAddAttachment method
- Updated onWsAddComment method
- Modified addSubscriptions and removeSubscriptions to handle attachments
- Updated onAddAttachment and onRemoveAttachment methods to include WebSocket requests
src/js/base/model.js - Updated handleMessage method to include resource parameter
- Added documentation comment to destroy method
src/js/entities-service/entities/actions.js - Added AttachmentAdded method
- Added removeAttachment method
- Updated CommentAdded method to change event trigger
src/js/entities-service/entities/files.js - Added messages object with FileReplaced and FileRemoved methods
test/integration/patients/patient/patient-flow.js - Extended test cases for file attachments
- Updated WebSocket notification handling
- Added new test scenarios for attachment management

Possibly related PRs

Suggested reviewers

  • paulfalgout

Poem

🐰 Attachments dance, a digital delight,
Sidebar whispers secrets, models take flight,
WebSocket weaves its magic thread,
Files hop in, no more to dread,
Code rabbits rejoice in this coding might! 🎉


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1d72f4 and 04b8037.

📒 Files selected for processing (2)
  • src/js/apps/patients/sidebar/action-sidebar_app.js (3 hunks)
  • src/js/entities-service/entities/actions.js (2 hunks)
🔇 Additional comments (7)
src/js/apps/patients/sidebar/action-sidebar_app.js (4)

50-51: Event listener naming follows the established pattern.

The WebSocket event names ws:add:comment and ws:add:attachment follow the recommended pattern of state:verb:subject.


80-90: Method naming is consistent with event patterns.

The handler methods onWsAddComment and onWsAddAttachment follow the same pattern as their corresponding events, maintaining consistency.

However, based on past review comments, there was a discussion about potential naming conflicts. The current implementation correctly addresses this by using the onWsAdd prefix to differentiate WebSocket handlers from manual action handlers.


239-240: WebSocket operations are properly integrated with attachment lifecycle.

The code correctly manages WebSocket subscriptions:

  • Line 239-240: Adds WebSocket subscription when attachment is created
  • Line 247-248: Removes WebSocket subscription when attachment is destroyed

Also applies to: 247-248


254-257: Guard clause prevents errors during cleanup.

The isRunning() check prevents potential errors when the sidebar is closed before beforeStart completes, which is a good defensive programming practice.

src/js/entities-service/entities/actions.js (3)

54-55: Event trigger matches the established pattern.

The ws:add:comment event trigger aligns with the WebSocket event naming pattern used throughout the application.


56-70: Comprehensive attachment model creation and relationship management.

The AttachmentAdded handler:

  1. Creates a new file model with complete metadata
  2. Updates the files relationship
  3. Triggers the appropriate WebSocket event

253-260: Verify paperclip icon visibility on attachment removal.

Based on past review comments, there's a known issue with the paperclip icon visibility not updating when attachments are manually removed. This implementation of removeAttachment addresses part of the solution, but the UI update is tracked in a separate story.

Run this script to verify the paperclip icon implementation:

✅ Verification successful

Paperclip icon visibility is correctly handled on attachment removal

Based on the verification results, I can confirm that the paperclip icon visibility is properly implemented and will update correctly when attachments are removed:

  1. The removeAttachment method correctly updates the _files relationship state by filtering out the removed file.
  2. The templates use the hasAttachments condition to show/hide the paperclip icon, which is computed based on the _files relationship:
    • hasAttachments is used in multiple templates: action-item.hbs across different views (worklist, dashboard, archive, flow)
    • The icon is rendered using {{#if hasAttachments}}<span class="...">{{far "paperclip"}}</span>{{/if}}
  3. Integration tests verify this behavior:
    • Tests check for paperclip icon existence after file addition
    • Tests verify paperclip icon disappearance after file removal
    • Tests cover this across different views (worklist, patient flow, dashboard, archive)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for paperclip icon visibility logic in action list items

# Search for paperclip icon visibility logic
rg -A 5 "paperclip.*icon"

# Search for file relationship usage in templates
ast-grep --pattern 'get("_files")'

Length of output: 64


Script:

#!/bin/bash
# Let's try different search patterns to find paperclip icon related code

# Search for paperclip-related UI components or icons
rg -i "paperclip|attachment.*icon" -A 5

# Search for files-related template conditions
rg "files\?.length|hasFiles" -A 5

# Search for attachment-related template logic
rg "attachment" --type html -A 5

# Look for file relationship getters in actions
ast-grep --pattern 'get("files")'

# Search for file-related template conditions using different pattern
ast-grep --pattern 'if ($_.files)'

Length of output: 9183


Script:

#!/bin/bash
# Let's search for the hasAttachments property definition and usage

# Search for hasAttachments property definition
ast-grep --pattern 'hasAttachments() {
  $$$
}'

# Search for _files relationship usage
rg "_files" -A 5

# Search for files relationship computed property
rg "computed.*files" -A 5

# Look for attachment-related model properties
ast-grep --pattern 'extend({
  $$$
  files: $_,
  $$$
})'

Length of output: 1978


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@nmajor25 nmajor25 marked this pull request as ready for review December 23, 2024 21:58
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (7)
test/integration/patients/patient/patient-flow.js (3)

111-112: Use descriptive test IDs
Using separate UUIDs is appropriate for file-related tests, but consider clarifying their usage with a more descriptive variable name or comment to improve test readability.


124-129: Ensure multi-file extension testing
Defining allowed_uploads as only ['pdf'] is fine for this test, but consider adding more file types or creating separate tests for other file extensions if needed.


2630-2631: Maintain consistent naming
Another UUID for socket attachments is consistent. Consider naming it more descriptively (e.g., testSocketFileIdForFlow) if it helps clarity.

src/js/entities-service/entities/files.js (1)

21-35: Handle file replacement and removal carefully
The messages object effectively updates file paths on FileReplaced and cleans up references in FileRemoved. Ensure you handle any concurrency issues if multiple replacements arrive in quick succession.

src/js/apps/patients/sidebar/action-sidebar_app.js (2)

247-248: Unsubscribe before destroy
Destroying the model after unsubscribing is logical but consider reversing the order if unsubscribing depends on the model’s existence.


251-251: Bulk subscription approach
Combining comments and attachments is convenient. Potentially skip duplicates if a model appears in both arrays.

src/js/entities-service/entities/actions.js (1)

56-71: Append-based approach for AttachmentAdded
Appended file references correctly expand _files. Consider checking for duplicates if the same file ID arrives twice.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c102601 and 916d41f.

📒 Files selected for processing (5)
  • src/js/apps/patients/sidebar/action-sidebar_app.js (3 hunks)
  • src/js/base/model.js (2 hunks)
  • src/js/entities-service/entities/actions.js (2 hunks)
  • src/js/entities-service/entities/files.js (2 hunks)
  • test/integration/patients/patient/patient-flow.js (6 hunks)
🔇 Additional comments (21)
test/integration/patients/patient/patient-flow.js (15)

137-137: Keep consistent approach for allowed_uploads
Line 137 matches the approach in lines 124-129. This is consistent. Ensure both places reflect any future expansions of allowed uploads.


140-146: Relationship definitions look correct
All relationships—flow, state, owner, form, patient, program-action, files—are properly set for the test scenario.


169-170: Including program action in fixture
Pushing the testProgramAction into fx.included is correct for ensuring backend returns the new program action.


178-194: Fixture for existing file clarity
Providing an existing file id and path ensures coverage for scenarios where an action already has attachments. Nicely done.


453-466: Check for new attachments in DOM
Verifying the UI updates for the newly added file is good. Keep an eye on potential slow DOM updates in real scenarios.


467-472: Download link test
Ensuring the download link is correct improves coverage for file retrieval paths.


473-490: FileReplaced scenario coverage
Replacing the file and verifying updated path/urls is valuable for ensuring re-upload logic works as expected.


491-507: UI checks after FileReplaced
Ensuring UI re-renders and shows the updated file is crucial for user experience.


508-526: Ensure FileRemoved test coverage
This confirms file removal updates the UI. Nicely done.


2935-2960: Real-time AttachmentAdded coverage
Good test verifying real-time file addition via WebSocket. No issues spotted.


2961-2965: Paperclip icon verification
Ensuring the paperclip icon appears gives confidence that attachment awareness is correct.


2966-2974: Real-time FileRemoved coverage
This scenario confirms correct removal logic on dynamic WebSocket updates. Excellent coverage.


2975-2979: Final icon cleanup check
Ensuring the paperclip icon is gone prevents stale UI references. Good job.


152-156: Confirm forced setting usage in tests
Explicitly pushing { id: 'upload_attachments', attributes: { value: true } } ensures upload tests pass. Make sure this doesn't mask unexpected side effects if real settings differ.

✅ Verification successful

Let me gather more information about the usage of upload_attachments setting to verify if there are any potential side effects.


Let me search for more specific patterns to understand how this setting is used in the application.


Setting is properly implemented with safeguards
The upload_attachments setting is used correctly in the codebase. The implementation in src/js/apps/patients/sidebar/action-sidebar_app.js shows proper validation where uploads are only shown when both the setting is enabled (upload_attachments=true) AND the action has allowed uploads (hasAllowedUploads()). The test setting this to true is necessary to test the upload functionality and doesn't mask any side effects since the code has proper guards in place.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for other occurrences of upload_attachments setting
rg -l "upload_attachments" --type js

# Look for the actual implementation where this setting is used
ast-grep --pattern 'upload_attachments'

# Search for related test files and settings
rg "routeSettings.*upload_attachments" --type js -C 2

Length of output: 388


Script:

#!/bin/bash
# Look for the implementation details in action sidebar files
rg "upload_attachments" test/integration/programs/sidebar/action-sidebar.js test/integration/patients/sidebar/action-sidebar.js src/js/apps/programs/sidebar/action-sidebar_app.js src/js/apps/patients/sidebar/action-sidebar_app.js -C 3

# Search for any conditional logic related to upload_attachments
ast-grep --pattern 'if ($$$upload_attachments$$$) { $$$ }'

# Look for setting definitions or configurations
rg "upload_attachments.*value" -C 2

Length of output: 8792


427-452: WebSocket test: verify AttachmentAdded
This test thoroughly checks the AttachmentAdded category. Ensure that large file edge cases are covered in separate tests if necessary.

✅ Verification successful

Let me search for related test files and WebSocket handling to verify the coverage of large file edge cases.

These scripts will help us understand:

  1. Where AttachmentAdded tests are implemented
  2. If there are any existing large file tests
  3. File upload configurations and S3 related tests
  4. Any file size limitations in the codebase

Let me search for more specific information about file attachment tests and any size-related handling.

These scripts will help us understand:

  1. The complete context of the AttachmentAdded test
  2. Any file validation or size handling logic in tests
  3. Test suites dealing with file attachments

Based on the search results, I can now generate a final response:

WebSocket test: AttachmentAdded coverage is sufficient
The test adequately covers the AttachmentAdded WebSocket event handling. The test suite includes comprehensive attachment testing with:

  • File upload permission validation
  • Attachment display verification
  • Multiple attachment scenarios
  • Integration with patient actions and clinician data

No specific file size edge cases are needed as these should be handled at the API/backend level, not in WebSocket event handling tests which verify the UI updates after successful uploads.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for WebSocket-related test files and AttachmentAdded tests
rg -l "AttachmentAdded" test/

Length of output: 79


Script:

#!/bin/bash
# Search for file size or large file related tests
rg -i "file.*size|large.*file" test/

Length of output: 38


Script:

#!/bin/bash
# Look for any file upload or attachment related test configurations
rg "bucket.*name|\.s3\." test/

Length of output: 4041


Script:

#!/bin/bash
# Search for any file size limits or constraints in the codebase
rg -i "maxFileSize|file.*limit|size.*limit" .

Length of output: 65701


Script:

#!/bin/bash
# Search for the full context around AttachmentAdded test
rg -B 5 -A 10 "AttachmentAdded" test/integration/patients/patient/patient-flow.js

Length of output: 802


Script:

#!/bin/bash
# Look for any file validation or attachment handling code
rg -i "attachment|file.*validation|validate.*file" test/

Length of output: 5254


Script:

#!/bin/bash
# Search for any test setup or configuration related to file attachments
ast-grep --pattern 'describe($_, function() { $$$ file $$$ })'

Length of output: 64

src/js/base/model.js (1)

8-8: Clarify destroy behavior
The comment explaining isDeleted helps maintainers understand the difference between front-end and back-end deletion states. No issues here.

src/js/apps/patients/sidebar/action-sidebar_app.js (4)

51-51: Function naming conflict
“onAttachmentAdded” is very similar to the existing “onAddAttachment.” Consider renaming to onWsAttachmentAdded to reduce confusion.


255-255: Guard for incomplete requests
Exiting early if comments or attachments are not yet available avoids errors. This is a good defensive check.


257-257: Bulk unsubscribe approach
Unsubscribing from both collections is consistent. No immediate issues.


239-240: Check WebSocket subscription object
Using Radio.request('ws', 'add', file) might not subscribe to the final model. Evaluate whether to pass the newly created model for consistency with other events.

✅ Verification successful

Let me gather more information about the WebSocket subscription and model handling in the codebase.

This will help us understand:

  1. How WebSocket subscriptions are handled throughout the codebase
  2. The pattern of model subscriptions
  3. Context around the specific usage in question

Based on the search results, I can now generate the final response:

WebSocket subscription pattern is consistent
Looking at the codebase, passing file directly to Radio.request('ws', 'add', file) is consistent with the existing pattern. The same file shows multiple examples where both models and raw objects are passed to the WebSocket subscription system, including collections of models, individual models, and file objects. The implementation handles both cases appropriately.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for WebSocket related Radio requests
rg "Radio\.(request|trigger)\('ws'" -A 3 -B 3

# Search for file model creation patterns
ast-grep --pattern 'Radio.request("ws", "add", $_)'

# Look for other WebSocket subscriptions
ast-grep --pattern 'Radio.request("ws", $_)'

Length of output: 4082

src/js/entities-service/entities/actions.js (1)

253-260: Efficient removeAttachment
Filtering out the matching resource from _files is straightforward. If partial matches or type mismatches occur, ensure you handle them gracefully.

Comment on lines +94 to +96
handleMessage({ category, resource, author, payload }) {
payload.attributes = extend({}, payload.attributes, { updated_at: dayjs.utc().format() });
payload.resource = resource;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Potential mismatch in handleMessage parameters

The implementation in src/js/base/model.js expects an object with { category, resource, author, payload }, but in src/js/services/ws.js, the method is called with the entire data object directly. This could lead to runtime errors if the data structure doesn't match the expected parameters.

  • src/js/services/ws.js: resource.handleMessage(data)
  • src/js/base/model.js: handleMessage({ category, resource, author, payload })
🔗 Analysis chain

Expanded handleMessage signature
Including resource and updating updated_at is helpful for robust message handling. Confirm that external references to handleMessage are updated accordingly.


Let me search for references to handleMessage in the codebase to verify if external calls are aligned with the updated signature.


Let me check the implementation in ws.js to understand how the method is being called.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for handleMessage method calls
rg "handleMessage\(" -A 2

# Search for handleMessage method definitions
ast-grep --pattern 'handleMessage($_) { $$$  }'

Length of output: 439


Script:

#!/bin/bash
# Get more context around the handleMessage call in ws.js
rg -B 5 -A 5 "handleMessage\(" src/js/services/ws.js

Length of output: 322

Comment on lines 86 to 90
onAttachmentAdded(model) {
this.attachments.add(model);

Radio.request('ws', 'add', model);
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Separate from onAddAttachment
Having both onAttachmentAdded and onAddAttachment is potentially confusing. Following the suggestion to rename it clearly differentiates WS vs. manual additions.

…or to `beforeStart()` finishing

To protect the `removeSubscriptions()` function from running before comments or attachments api data is retrieved for the action sidebar
@nmajor25 nmajor25 requested a review from paulfalgout January 2, 2025 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants