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

Change updated_at attribute when action/flow model is updated via web socket #1352

Merged
merged 1 commit into from
Nov 21, 2024

Conversation

nmajor25
Copy link
Contributor

@nmajor25 nmajor25 commented Nov 14, 2024

Shortcut Story ID: [sc-56745]

When we receive a web socket notification of any kind for a flow or action, its updated_at attribute will now be updated to the current date-time.

This change is applied on the base model level. But will only be put to use on the patient flow page since that's the only place we currently subscribe to web socket notifications.

On the patient flow page, that is displayed in these UI locations:

  1. Each flow action list item.
  2. Footer section of action sidebar.
  3. Footer section of flow sidebar.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced message handling to include a timestamp (updated_at) for better tracking.
    • Introduced real-time updates in the UI for timestamp changes, improving responsiveness.
  • Bug Fixes

    • Improved integration tests to ensure accurate display of updated timestamps and real-time changes in the patient flow management system.
  • Documentation

    • Updated test cases to validate the new timestamp functionality and websocket event handling.

@nmajor25 nmajor25 requested a review from paulfalgout November 14, 2024 22:59
@@ -76,6 +76,7 @@ const LayoutView = View.extend({
modelEvents: {
'change:_state': 'showOwner',
'change:_owner': 'showFlow',
'change:updated_at': 'showTimestamps',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This doesn't do anything. But the updated timestamp in the flow sidebar is updating correctly on model change.

So I'm not sure what's going on here yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm noticing other weird things with the flow sidebar, in terms of updating on a web socket model change.

Name and owner update correctly. But details and state do not.

I'm going to investigate/address those in this story here.

Copy link
Contributor Author

@nmajor25 nmajor25 Nov 19, 2024

Choose a reason for hiding this comment

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

For the first comment above, the change:updated_at model event is indeed working. I just had the test setup incorrectly. The flow sidebar needs to be open before the web socket notification comes in. I updated the test to do that.

I still plan on investigating the second comment in a separate story.

payload.attributes.updated_at = dayjs.utc().format();
} else {
payload.attributes = { updated_at: dayjs.utc().format() };
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably a better way to do this. But just attaching attributes.updated_at to the payload data before its passed to the individual entity services.

Copy link
Member

Choose a reason for hiding this comment

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

payload.attributes = extend(payload.attributes, { updated_at: day...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That would be much cleaner 👍

Copy link

coderabbitai bot commented Nov 14, 2024

Walkthrough

The pull request introduces enhancements to the Backbone model and related views. A new timestamp property updated_at is added to the payload.attributes in the handleMessage method using the dayjs library for date formatting. Additionally, event listeners are implemented in the TimestampsView and LayoutView classes to ensure the UI updates reflect changes to the updated_at attribute. Integration tests are also updated to verify the correct handling and display of these timestamps in the UI.

Changes

File Path Change Summary
src/js/base/model.js - Updated handleMessage method to include updated_at in payload.attributes using dayjs.
src/js/views/patients/sidebar/action/action-sidebar-activity-views.js - Added modelEvents property in TimestampsView to listen for changes to updated_at and trigger render.
src/js/views/patients/sidebar/flow/flow-sidebar_views.js - Added showTimestamps method in LayoutView to respond to updated_at changes and call showTimestamps during onRender.
test/integration/patients/patient/patient-flow.js - Updated tests to include updated_at in testFlowAction and testSocketAction, and added new tests for websocket events.

Possibly related PRs

Suggested reviewers

  • paulfalgout

🐰 In the code, I hop and play,
With timestamps bright, I save the day.
A little change, a little cheer,
Updated views are finally here!
So let’s rejoice, let’s sing and dance,
For every message gets a chance! 🐇✨


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 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.

Copy link

cypress bot commented Nov 14, 2024

RoundingWell Care Ops Frontend    Run #6964

Run Properties:  status check passed Passed #6964  •  git commit 7df44f46b7: Change `updated_at` attribute when the action/flow model is updated via socket n...
Project RoundingWell Care Ops Frontend
Branch Review ws-updated-at
Run status status check passed Passed #6964
Run duration 02m 48s
Commit git commit 7df44f46b7: Change `updated_at` attribute when the action/flow model is updated via socket n...
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 Nov 14, 2024

Pull Request Test Coverage Report for Build e1cef074-1d57-494e-a1a8-cc157d870451

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.05%) to 99.936%

Totals Coverage Status
Change from base Build a84d2c3d-c6b3-4ab8-be63-55537f71a710: -0.05%
Covered Lines: 5957
Relevant Lines: 5957

💛 - Coveralls

payload.attributes.updated_at = dayjs.utc().format();
} else {
payload.attributes = { updated_at: dayjs.utc().format() };
}
Copy link
Member

Choose a reason for hiding this comment

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

payload.attributes = extend(payload.attributes, { updated_at: day...

@nmajor25 nmajor25 force-pushed the ws-updated-at branch 2 times, most recently from 1a115de to 5e52dfc Compare November 19, 2024 21:47
@nmajor25 nmajor25 marked this pull request as ready for review November 19, 2024 21:48
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: 0

🧹 Outside diff range and nitpick comments (8)
src/js/base/model.js (1)

88-89: Consider creating a new payload object for better immutability.

The implementation looks good and follows the suggested approach from previous comments. However, consider creating a new payload object instead of modifying the input parameter directly:

- payload.attributes = extend(payload.attributes || {}, { updated_at: dayjs.utc().format() });
+ const updatedPayload = {
+   ...payload,
+   attributes: extend(payload.attributes || {}, { updated_at: dayjs.utc().format() })
+ };

This would prevent potential side effects if the payload object is used elsewhere in the codebase.

src/js/views/patients/sidebar/flow/flow-sidebar_views.js (2)

Line range hint 26-33: Add model event bindings for timestamp changes

The TimestampsView should listen for changes to the timestamps to ensure the UI stays in sync with the model. Consider adding:

 const TimestampsView = View.extend({
   className: 'sidebar__footer flex',
+  modelEvents: {
+    'change:updated_at': 'render',
+    'change:created_at': 'render'
+  },
   template: hbs`
     <div class="sidebar__footer-left"><h4 class="sidebar__label">{{ @intl.patients.sidebar.flow.flowSidebarViews.timestampsView.createdAt }}</h4><div>{{formatDateTime created_at "AT_TIME"}}</div></div>
     <div><h4 class="sidebar__label">{{ @intl.patients.sidebar.flow.flowSidebarViews.timestampsView.updatedAt }}</h4><div>{{formatDateTime updated_at "AT_TIME"}}</div></div>
   `,
 });

79-79: Optimize view lifecycle management

While the model event binding is correct, creating a new TimestampsView instance on every timestamp update is inefficient. Consider reusing the existing view instance by letting it handle its own updates through model events as suggested in the previous comment.

 showTimestamps() {
-  this.showChildView('timestamps', new TimestampsView({ model: this.model }));
+  if (!this.getChildView('timestamps')) {
+    this.showChildView('timestamps', new TimestampsView({ model: this.model }));
+  }
 }
src/js/views/patients/sidebar/action/action-sidebar-activity-views.js (1)

267-269: LGTM! Consider adding error handling for invalid dates.

The addition of the modelEvents property to automatically re-render on updated_at changes is a clean implementation that follows Backbone's best practices. This ensures the UI stays in sync with the model when updates occur via web socket.

Consider adding date validation in the template to handle cases where updated_at might be invalid:

 template: hbs`
   <div class="sidebar__footer-left"><h4 class="sidebar__label">{{ @intl.patients.sidebar.action.activityViews.createdAt }}</h4><div>{{formatDateTime createdAt "AT_TIME"}}</div></div>
-  <div><h4 class="sidebar__label">{{ @intl.patients.sidebar.action.activityViews.updatedAt }}</h4><div>{{formatDateTime updated_at "AT_TIME"}}</div></div>
+  <div><h4 class="sidebar__label">{{ @intl.patients.sidebar.action.activityViews.updatedAt }}</h4><div>{{#if updated_at}}{{formatDateTime updated_at "AT_TIME"}}{{else}}-{{/if}}</div></div>
 `,
test/integration/patients/patient/patient-flow.js (4)

195-201: Use fixed timestamps to prevent flaky tests

Using dayjs.utc().format() can lead to flaky tests due to timing differences. Consider using a fixed test timestamp to ensure consistent test results.

Apply this diff to modify the timestamp to use the test timestamp helper:

-          .should('contain', formatDate(dayjs.utc().format(), 'AT_TIME'));
+          .should('contain', formatDate(testTs(), 'AT_TIME'));

2409-2412: Unnecessary click action on '[data-header-region]'

The click action on [data-header-region] may be unnecessary if it does not contribute to the test's purpose. Removing it can improve test performance.

Apply this diff to remove the unnecessary click:

-        cy
-          .get('[data-header-region]')
-          .click('top');

2431-2437: Use fixed timestamps to prevent flaky tests

Similar to the previous comment, using dayjs.utc().format() can cause intermittent test failures. Consider using a fixed test timestamp.

Apply this diff:

-          .should('contain', formatDate(dayjs.utc().format(), 'AT_TIME'));
+          .should('contain', formatDate(testTs(), 'AT_TIME'));

2479-2483: Use fixed timestamps to prevent flaky tests

Using dynamic timestamps can result in flaky tests. It's better to use a fixed timestamp or mock the system time to ensure consistent results.

Apply this diff:

-        cy
-          .get('.patient-flow__list')
-          .find('.table-list__item .patient__action-ts')
-          .should('contain', formatDate(dayjs.utc().format(), 'TIME_OR_DAY'));
+        cy
+          .get('.patient-flow__list')
+          .find('.table-list__item .patient__action-ts')
+          .should('contain', formatDate(testTs(), 'TIME_OR_DAY'));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3579198 and 5e52dfc.

📒 Files selected for processing (4)
  • src/js/base/model.js (2 hunks)
  • src/js/views/patients/sidebar/action/action-sidebar-activity-views.js (1 hunks)
  • src/js/views/patients/sidebar/flow/flow-sidebar_views.js (1 hunks)
  • test/integration/patients/patient/patient-flow.js (9 hunks)
🔇 Additional comments (6)
src/js/base/model.js (2)

3-3: LGTM! Good choice of date library.

The addition of dayjs is appropriate for handling UTC timestamps. It's a lightweight and modern alternative to moment.js.


88-89: Verify the timestamp handling in related views.

The addition of updated_at to the payload affects the UI components. Let's verify the implementation in related files:

✅ Verification successful

Based on the search results, I can now provide a final response as there is sufficient evidence to verify the timestamp handling in related views.

The timestamp handling is properly implemented across views

The updated_at timestamp is consistently used across the application with proper formatting:

  • Program views format timestamps using formatDateTime helper:
    • Program sidebars show detailed time with "AT_TIME" format
    • Program lists show relative time with "TIME_OR_DAY" format
  • Patient views handle timestamps similarly:
    • Patient action/flow sidebars display detailed time
    • Patient worklist and dashboard views show relative time
  • Form views display update times in activity logs

The implementation is consistent and the timestamp changes will be properly reflected in all UI components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the handling of updated_at attribute in related views

# Check for views listening to updated_at changes
rg -A 5 "updated_at|handleMessage" "src/js/views/"

# Check for potential test coverage
rg -A 5 "updated_at.*test" "test/"

Length of output: 54506

src/js/views/patients/sidebar/flow/flow-sidebar_views.js (1)

78-80: Verify complete model synchronization via websockets

Based on the past review comments, there are inconsistencies in how different attributes update via websockets. While name, owner, and now updated_at update correctly, details and state do not. This suggests potential issues with the websocket message handling.

Let's verify the model attribute synchronization:

test/integration/patients/patient/patient-flow.js (3)

2-2: Importing 'dayjs' library is appropriate

The addition of the dayjs import ensures proper date handling in the test cases.


125-125: Adding 'updated_at' attribute to 'testFlowAction'

Including updated_at: testTsSubtract(1) in testFlowAction ensures that the action's last updated timestamp is correctly set for testing.


2397-2397: Including 'routeFlowActivity()' in test setup

Adding .routeFlowActivity() ensures that flow activity is properly intercepted during tests, which is necessary for accurate simulation of application behavior.

@nmajor25 nmajor25 requested a review from paulfalgout November 19, 2024 21:53
Copy link
Member

@paulfalgout paulfalgout left a comment

Choose a reason for hiding this comment

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

One tiny thing then this is good

@@ -84,6 +85,8 @@ export default Backbone.Model.extend(extend({
return isFunction(messages[category]) ? messages[category] : this[messages[category]];
},
handleMessage({ category, payload }) {
payload.attributes = extend(payload.attributes || {}, { updated_at: dayjs.utc().format() });
Copy link
Member

Choose a reason for hiding this comment

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

nitpick but I think extend({}, payload.attributes, updated_at is probably better since it'll remove the logic branch and it doesn't mutate the payload.attributes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, I updated it to that 👍

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: 0

🧹 Outside diff range and nitpick comments (2)
test/integration/patients/patient/patient-flow.js (2)

2409-2412: Consider adding negative test cases for UI interactions.

The test covers basic UI interactions like clicking and closing, but consider adding test cases for:

  1. Multiple rapid clicks
  2. Interaction during socket updates
  3. Edge cases with null/undefined timestamps
 cy
   .get('[data-header-region]')
   .click('top');

+// Add test for rapid clicks
+cy
+  .get('[data-header-region]')
+  .click('top')
+  .click('top')
+  .click('top');
+
+// Add test for interaction during socket update
+cy.sendWs({
+  category: 'NameChanged',
+  resource: {
+    type: 'flows',
+    id: testSocketFlow.id,
+  },
+  payload: {
+    attributes: {
+      name: 'New Flow Name',
+      updated_at: null
+    },
+  },
+});

Also applies to: 2438-2442


2479-2482: Enhance timestamp format verification in list view.

The test verifies the timestamp format in the list view, but it would be beneficial to add assertions for different time scenarios (same day, previous day, etc.).

 cy
   .get('.patient-flow__list')
   .find('.table-list__item .patient__action-ts')
   .should('contain', formatDate(dayjs.utc().format(), 'TIME_OR_DAY'));
+
+// Add test for same day timestamp
+const sameDayTime = dayjs.utc().subtract(1, 'hour');
+cy.clock(sameDayTime.valueOf());
+cy
+  .get('.patient-flow__list')
+  .find('.table-list__item .patient__action-ts')
+  .should('contain', formatDate(sameDayTime.format(), 'TIME_OR_DAY'));
+
+// Add test for previous day timestamp
+const previousDayTime = dayjs.utc().subtract(1, 'day');
+cy.clock(previousDayTime.valueOf());
+cy
+  .get('.patient-flow__list')
+  .find('.table-list__item .patient__action-ts')
+  .should('contain', formatDate(previousDayTime.format(), 'TIME_OR_DAY'));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5e52dfc and 7df44f4.

📒 Files selected for processing (4)
  • src/js/base/model.js (2 hunks)
  • src/js/views/patients/sidebar/action/action-sidebar-activity-views.js (1 hunks)
  • src/js/views/patients/sidebar/flow/flow-sidebar_views.js (1 hunks)
  • test/integration/patients/patient/patient-flow.js (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/js/base/model.js
  • src/js/views/patients/sidebar/action/action-sidebar-activity-views.js
  • src/js/views/patients/sidebar/flow/flow-sidebar_views.js
🔇 Additional comments (4)
test/integration/patients/patient/patient-flow.js (4)

125-125: LGTM: Test data setup includes timestamp.

The addition of updated_at timestamp in the test action data properly simulates the real-world scenario where actions have timestamps.


2356-2356: LGTM: Socket test data includes timestamps.

The test data for socket notifications properly includes updated_at timestamps for both flow and action objects.

Also applies to: 2371-2371


2397-2397: LGTM: Flow activity routing is properly set up.

The test correctly sets up routing for flow activity which is essential for timestamp updates.


195-200: Verify timestamp format consistency.

The test verifies the timestamp display in the sidebar footer using formatDate with the 'AT_TIME' format. However, it would be good to ensure this format matches the requirements across all timestamp displays.

✅ Verification successful

Based on the search results, I can provide the final response as we have comprehensive information about timestamp format usage across the codebase. The search reveals two main timestamp formats being used consistently:

Timestamp format usage is consistent across the codebase

The codebase consistently uses two distinct timestamp formats for different contexts:

  • AT_TIME: Used in sidebars and detailed views to show precise timestamps
  • TIME_OR_DAY: Used in list views and summary displays for relative time representation

The test's usage of formatDate with AT_TIME format in the sidebar footer aligns perfectly with the established pattern across similar components, as evidenced by multiple sidebar implementations using the same format (e.g., in action-sidebar, program-sidebar, flow-sidebar).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent timestamp format usage across the codebase

# Search for formatDate usage with AT_TIME format
rg "formatDate.*AT_TIME" -A 2

# Search for other timestamp format patterns
rg "formatDate.*TIME" -A 2

Length of output: 33135

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