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

Optimize modal navigation #4947

Closed
wants to merge 5 commits into from
Closed

Conversation

benjaminpkane
Copy link
Contributor

@benjaminpkane benjaminpkane commented Oct 18, 2024

What changes are proposed in this pull request?

Optimizes modal navigation when a large number of sidebar fields are present. Sample routing introduced unnecessary overhead in recoil data flow, which this PR removes. Before and after can be tested with a dataset like the below

import fiftyone as fo
import fiftyone.zoo as foz

dataset = foz.load_zoo_dataset("quickstart")
dataset = dataset.select_fields().clone()
dataset.name = "large-sidebar"
dataset.persistent = True

for i in range(0, 75):
    dataset.add_sample_field(f"{i}", fo.StringField)

How is this patch tested? If it is not, please explain why.

Existing coverage

Release Notes

  • Fixed browser performance issues related to modal navigation

What areas of FiftyOne does this PR affect?

  • App: FiftyOne application changes
  • Build: Build and test infrastructure changes
  • Core: Core fiftyone Python library changes
  • Documentation: FiftyOne documentation changes
  • Other

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new selector, gatheredPaths, to enhance path processing.
  • Bug Fixes

    • Improved error handling in routing logic for better reliability.
  • Refactor

    • Restructured routing context for improved clarity and maintainability.
    • Simplified event handling in various components to streamline interactions.
    • Removed unnecessary side effects from Recoil atom definitions for a cleaner state management.
  • Tests

    • Updated test suite to reflect changes in navigation flow during modal selection.

@benjaminpkane benjaminpkane marked this pull request as ready for review October 21, 2024 15:18
Copy link
Contributor

coderabbitai bot commented Oct 21, 2024

Walkthrough

The changes in this pull request primarily involve significant refactoring within the routing and state management components of the application. Key modifications include the restructuring of the getEntryResource function in RouterContext.ts, enhancements to the LocationState type in matchPath.ts, and updates to routing logic in useSetGroupSlice.ts and onSetGroupSlice.ts. New selectors were introduced in the Recoil state management files, while several existing functions had their event handling and control flows simplified. Overall, the changes aim to improve clarity, maintainability, and functionality across various components.

Changes

File Change Summary
app/packages/app/src/routing/RouterContext.ts Refactored getEntryResource function to accept an object parameter; added makeGetEntryResource function; enhanced error handling; removed standalone getEntryResource.
app/packages/app/src/routing/matchPath.ts Updated LocationState type to include optional event property with values "modal" or "slice".
app/packages/app/src/useEvents/useSetGroupSlice.ts Modified router.push to include event: "slice" in the state object.
app/packages/app/src/useWriters/onSetGroupSlice.ts Updated router.push to include event: "slice" in the state object.
app/packages/core/src/components/Grid/useRefreshers.ts Simplified event check in subscribe callback; early return for event: "fieldVisibility".
app/packages/state/src/recoil/pathData/counts.ts Added gatheredPaths selector; modified cumulativeCounts to use gatheredPaths.
app/packages/state/src/recoil/sidebarExpanded.ts Removed effects property from sidebarExpandedStore and granularSidebarExpandedStore.
e2e-pw/src/oss/poms/grid/index.ts Removed pageChange method calls from openNthSample and selectSlice methods.
e2e-pw/src/oss/poms/modal/index.ts Removed await this.url.pageChange(...) from navigateSample and close methods.
e2e-pw/src/oss/specs/selection.spec.ts Altered navigation flow in modal selection test to close modal directly instead of navigating back.

Possibly related PRs

Suggested labels

bug, app

Suggested reviewers

  • brimoor
  • sashankaryal

🐇 In the code, I hop and play,
Refactoring keeps the bugs at bay!
With events and paths all in line,
Our routing's now simply divine!
So let’s celebrate this code so bright,
Hooray for changes that feel just right! 🌟


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.

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
Contributor

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

🧹 Outside diff range and nitpick comments (5)
app/packages/app/src/useEvents/useSetGroupSlice.ts (2)

18-22: LGTM! Consider adding type safety for the event value.

The addition of the event property to the router state object is a good improvement. It provides more context about the nature of the navigation, which can be useful for routing logic or analytics.

To enhance type safety, consider defining a union type for possible event values:

type RouterEvent = 'slice' | /* other possible events */;

// Then use it in the router.push call
router.push(pathname, {
  ...router.location.state,
  event: 'slice' as RouterEvent,
  groupSlice: slice,
});

This will help prevent typos and ensure consistency across the application.


Line range hint 1-29: Summary: Good optimization for modal navigation

The changes in this file, particularly the addition of the event property in the router.push call, align well with the PR objectives of optimizing modal navigation. This modification provides more context about the navigation event, which could be leveraged for more efficient routing or analytics.

As you continue to optimize the navigation system:

  1. Ensure consistent usage of the event property across all relevant navigation calls.
  2. Consider updating any routing logic that might benefit from this additional context.
  3. If not already planned, think about adding analytics to track these navigation events, which could provide valuable insights for further optimizations.
app/packages/app/src/useWriters/onSetGroupSlice.ts (1)

16-20: LGTM! Consider enhancing type safety.

The addition of the event property to the router state aligns well with the broader refactoring efforts mentioned in the PR objectives. This change should improve the consistency of modal navigation handling.

To further enhance type safety and maintainability, consider defining a constant for the "slice" event string:

const SLICE_EVENT = "slice" as const;

// Then use it in the router.push call
router.push(pathname, {
  ...router.location.state,
  event: SLICE_EVENT,
  groupSlice: slice,
});

This approach would make it easier to refactor in the future and prevent typos.

e2e-pw/src/oss/poms/grid/index.ts (1)

Line range hint 1-161: Summary: Optimized grid interactions for improved performance.

The changes in this file contribute to the overall goal of optimizing modal navigation by simplifying the openNthSample and selectSlice methods. The removal of the pageChange wrapper in both methods should reduce unnecessary overhead in the recoil data flow, as mentioned in the PR objectives. These modifications are minimal and focused, which reduces the risk of introducing new issues while potentially improving the performance of the FiftyOne application, especially when dealing with a large number of sidebar fields.

Consider documenting these changes in the component's documentation or comments to explain the performance optimization strategy for future maintainers.

app/packages/state/src/recoil/pathData/counts.ts (1)

Line range hint 178-189: Excellent optimization in cumulativeCounts selector

The modification to use the new gatheredPaths selector in cumulativeCounts is a great improvement. This change enhances code reusability and maintainability while preserving the existing functionality. It aligns well with the PR's objective of optimizing modal navigation and improving performance, especially when dealing with a large number of sidebar fields.

Consider adding a brief comment explaining the performance benefit of using gatheredPaths here, to help future maintainers understand the rationale behind this change.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7cf9d3c and 3c5109d.

📒 Files selected for processing (10)
  • app/packages/app/src/routing/RouterContext.ts (4 hunks)
  • app/packages/app/src/routing/matchPath.ts (1 hunks)
  • app/packages/app/src/useEvents/useSetGroupSlice.ts (1 hunks)
  • app/packages/app/src/useWriters/onSetGroupSlice.ts (1 hunks)
  • app/packages/core/src/components/Grid/useRefreshers.ts (1 hunks)
  • app/packages/state/src/recoil/pathData/counts.ts (2 hunks)
  • app/packages/state/src/recoil/sidebarExpanded.ts (0 hunks)
  • e2e-pw/src/oss/poms/grid/index.ts (3 hunks)
  • e2e-pw/src/oss/poms/modal/index.ts (3 hunks)
  • e2e-pw/src/oss/specs/selection.spec.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • app/packages/state/src/recoil/sidebarExpanded.ts
🧰 Additional context used
📓 Path-based instructions (9)
app/packages/app/src/routing/RouterContext.ts (1)

Pattern **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

app/packages/app/src/routing/matchPath.ts (1)

Pattern **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

app/packages/app/src/useEvents/useSetGroupSlice.ts (1)

Pattern **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

app/packages/app/src/useWriters/onSetGroupSlice.ts (1)

Pattern **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

app/packages/core/src/components/Grid/useRefreshers.ts (1)

Pattern **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

app/packages/state/src/recoil/pathData/counts.ts (1)

Pattern **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

e2e-pw/src/oss/poms/grid/index.ts (1)

Pattern **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

e2e-pw/src/oss/poms/modal/index.ts (1)

Pattern **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

e2e-pw/src/oss/specs/selection.spec.ts (1)

Pattern **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

🔇 Additional comments (10)
app/packages/app/src/routing/matchPath.ts (1)

13-13: LGTM! Verify usage of updated LocationState type.

The addition of "slice" as a possible value for the event property in LocationState type is a good enhancement that aligns with the PR objectives. It provides more flexibility in handling different types of navigation events.

To ensure consistency, let's verify the usage of this updated type across the codebase:

✅ Verification successful

Verification Successful! The LocationState type update is consistently applied across the codebase.
The addition of "slice" to the event property in the LocationState type is correctly utilized in all relevant parts of the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check usage of LocationState type and 'event' property

# Search for LocationState type usage
echo "LocationState usage:"
rg -t ts -t tsx "LocationState" --glob "!app/packages/app/src/routing/matchPath.ts"

# Search for event property access on LocationState
echo "\nEvent property access:"
rg -t ts -t tsx "LocationState.*\.event" --glob "!app/packages/app/src/routing/matchPath.ts"

# Search for assignments to event property
echo "\nEvent property assignments:"
rg -t ts -t tsx "event:\s*['\"](?:modal|slice)['\"]" --glob "!app/packages/app/src/routing/matchPath.ts"

Length of output: 552


Script:

#!/bin/bash
# Description: Check usage of LocationState type and 'event' property in .ts and .tsx files

# Search for LocationState type usage
echo "LocationState usage:"
rg "LocationState" --glob "!app/packages/app/src/routing/matchPath.ts" -g "*.ts" -g "*.tsx"

# Search for event property access on LocationState
echo "\nEvent property access:"
rg "LocationState.*\.event" --glob "!app/packages/app/src/routing/matchPath.ts" -g "*.ts" -g "*.tsx"

# Search for assignments to event property
echo "\nEvent property assignments:"
rg "event:\s*['\"](?:modal|slice)['\"]" --glob "!app/packages/app/src/routing/matchPath.ts" -g "*.ts" -g "*.tsx"

Length of output: 2616

e2e-pw/src/oss/specs/selection.spec.ts (1)

98-100: Improved modal closure method enhances test clarity and performance.

The change from await grid.url.back(); to await modal.close(); is a positive improvement. It directly uses the modal's close method, which is more semantically clear and likely more efficient. This change aligns well with the PR's objective of optimizing modal navigation and simplifying control flow.

e2e-pw/src/oss/poms/grid/index.ts (2)

81-81: LGTM: Streamlined slice selection process.

The removal of the pageChange wrapper in the selectSlice method simplifies the implementation, which is in line with the PR objectives to optimize modal navigation and eliminate unnecessary overhead. This change should contribute to improved performance when selecting slices.

To ensure this change doesn't introduce any regressions, please verify that the e2e tests related to slice selection still pass:

#!/bin/bash
# Description: Run e2e tests related to slice selection
# Note: Adjust the test command based on your project's setup

npm run test:e2e -- --grep "select.*slice"

55-55: LGTM: Simplified method implementation.

The removal of the pageChange wrapper simplifies the openNthSample method, which aligns with the PR objectives to optimize modal navigation and remove unnecessary overhead. This change is consistent with similar modifications in other files and should contribute to improved performance.

To ensure this change doesn't introduce any regressions, please verify that the e2e tests related to opening samples still pass:

app/packages/state/src/recoil/pathData/counts.ts (1)

149-162: LGTM: Well-implemented gatheredPaths selector

The new gatheredPaths selector is well-implemented using Recoil's selectorFamily. It correctly uses TypeScript for type safety and employs the Set data structure to ensure unique paths. The use of the existing gatherPaths utility function maintains consistency with the rest of the codebase.

e2e-pw/src/oss/poms/modal/index.ts (3)

1-1: LGTM: Import statement reordering.

The reordering of the import statement is a minor style improvement, alphabetically sorting the imports. This change doesn't affect functionality and improves code readability.


220-220: Simplified closing logic: Verify potential side effects.

The removal of this.url.pageChange(...) in favor of a direct click action on the body element simplifies the closing logic and potentially improves performance. This change aligns with the PR objective of optimizing modal navigation.

Please verify that removing pageChange doesn't have any unintended side effects. Run the following script to check for other usages of pageChange in the codebase:

#!/bin/bash
# Description: Check for other usages of pageChange method
rg "pageChange\(" --type ts

121-123: Simplified navigation logic: Verify potential side effects.

The removal of this.url.pageChange(...) in favor of a direct click action simplifies the navigation logic and potentially improves performance. This change aligns with the PR objective of optimizing modal navigation.

Please verify that removing pageChange doesn't have any unintended side effects. Run the following script to check for other usages of pageChange in the codebase:

✅ Verification successful

Simplified navigation logic: No unintended side effects detected.

The removal of this.url.pageChange(...) does not impact other usages of pageChange in the codebase.

  • e2e-pw/src/oss/poms/url.ts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for other usages of pageChange method
rg "pageChange\(" --type ts

Length of output: 192

app/packages/app/src/routing/RouterContext.ts (2)

72-72: Initialization of getEntryResource with makeGetEntryResource

The getEntryResource function is correctly initialized using the generic factory function makeGetEntryResource<T>(), which enhances code modularity and readability.


145-151: Consistent Use of Updated getEntryResource Signature

The getEntryResource function is invoked with the updated parameter structure, ensuring alignment with the new function signature and improving maintainability.

@@ -160,7 +175,7 @@ export const cumulativeCounts = selectorFamily<
get:
({ extended, path: key, modal, ftype, embeddedDocType }) =>
({ get }) => {
return [...new Set(gatherPaths(get, ftype, embeddedDocType))].reduce(
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 functions becomes expensive as the dataset schema grows. The new gatheredPaths selector provides caching

handleError?: (error: unknown) => void;
}): Resource<Entry<T>> => {
if (isReusable(location)) {
throw currentResource;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Throw the current resource (page) if it can be used and skip the page change

Copy link
Contributor

@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: 1

🧹 Outside diff range and nitpick comments (3)
app/packages/app/src/routing/RouterContext.ts (3)

186-201: LGTM! Consider simplifying the isReusable function.

The introduction of SKIP_EVENTS and the makeGetEntryResource function improves the organization of the routing logic. The closure pattern allows for maintaining state between calls, which is a good approach.

Consider simplifying the isReusable function for better readability:

const isReusable = (location: FiftyOneLocation) =>
  currentLocation &&
  (SKIP_EVENTS.has(location.state.event || "") ||
   SKIP_EVENTS.has(currentLocation.state.event || ""));

203-216: Remove unused parameter from type definition.

The refactored getEntryResource function signature improves readability and flexibility. However, there's an unused parameter in the type definition.

Remove the unused current parameter from the type definition:

  }: {
    environment: Environment;
    routes: RouteDefinition<T>[];
    location: FiftyOneLocation;
    hard: boolean;
    handleError?: (error: unknown) => void;
  }): Resource<Entry<T>> => {

85-100: LGTM! Consider adding error logging.

The new error handling logic in the update function improves the robustness of the routing system. It correctly handles the case where a Resource is thrown to skip page changes.

Consider adding error logging for unexpected exceptions:

} catch (e) {
  if (e instanceof Resource) {
    // skip the page change if a resource is thrown
    return;
  }
  console.error('Unexpected error during update:', e);
  throw e;
}

This will help with debugging in case of unexpected errors.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 3c5109d and 21ef687.

📒 Files selected for processing (1)
  • app/packages/app/src/routing/RouterContext.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
app/packages/app/src/routing/RouterContext.ts (1)

Pattern **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

🔇 Additional comments (1)
app/packages/app/src/routing/RouterContext.ts (1)

150-156: LGTM! Consistent use of new getEntryResource signature.

The load method has been correctly updated to use the new object parameter format of getEntryResource. This change maintains consistency throughout the codebase and improves readability.

Comment on lines +217 to +220
if (isReusable(location)) {
// throw the current resource (page) if it can be reused
throw currentResource;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider alternative approach for handling reusable resources.

The current implementation throws the current resource as an exception to skip unnecessary page changes. While this achieves the desired result, it's an unconventional use of exceptions that might lead to confusion.

Consider returning the current resource instead of throwing it:

if (isReusable(location)) {
  return currentResource;
}

This approach maintains the same functionality while following more conventional control flow patterns.

@benjaminpkane benjaminpkane deleted the optimize-modal-navigation branch October 22, 2024 22:16
@benjaminpkane benjaminpkane restored the optimize-modal-navigation branch October 30, 2024 20:39
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.

1 participant