Skip to content

[WEB-2442] chore: Refactor timeline store#5926

Merged
pushya22 merged 1 commit intopreviewfrom
chore-refactor-timeline-store
Oct 29, 2024
Merged

[WEB-2442] chore: Refactor timeline store#5926
pushya22 merged 1 commit intopreviewfrom
chore-refactor-timeline-store

Conversation

@rahulramesha
Copy link
Contributor

@rahulramesha rahulramesha commented Oct 29, 2024

This PR refactors timeline stores to enable effective code splitting

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a timeline management structure, enhancing the application's ability to manage timelines for issues, modules, and projects.
    • Expanded the timeline type options by adding a new PROJECT type.
  • Bug Fixes

    • Improved handling of sort_order values to prevent errors when they are undefined.
  • Refactor

    • Simplified the autorun logic in timeline stores for better performance and readability.
    • Updated various interfaces and classes to enhance type safety and flexibility in handling optional properties.
  • Chores

    • Removed deprecated timeline-related functionality from the core store.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 29, 2024

Walkthrough

The changes in this pull request involve modifications to various store classes and interfaces within the application. Key updates include changing the constructor parameters from RootStore to CoreRootStore in several classes, the introduction of a timeline management structure, and updates to properties within the timeline store classes. Additionally, certain properties were removed, and some types were adjusted to allow for more flexible data handling. Overall, the changes enhance the application's state management and structure without altering the core functionality.

Changes

File Path Change Summary
web/ce/store/issue/issue-details/activity.store.ts Constructor parameter type changed from RootStore to CoreRootStore in IssueActivityStore.
web/ce/store/root.store.ts Added property timelineStore: ITimelineStore and instantiated it in the RootStore constructor.
web/ce/store/timeline/base-timeline.store.ts Updated sort_order property to allow null, added isDependencyEnabled property.
web/ce/store/timeline/index.ts Introduced ITimelineStore interface and TimeLineStore class for timeline management.
web/core/components/gantt-chart/contexts/index.tsx Added PROJECT value to ETimeLineTypeType enum.
web/core/components/gantt-chart/sidebar/utils.ts Modified handleOrderChange to use nullish coalescing for sort_order.
web/core/components/gantt-chart/types/index.ts Updated sort_order, start_date, and target_date properties to be optional.
web/core/hooks/use-timeline-chart.ts Updated import paths and added case for ETimeLineTypeType.PROJECT in useTimeLineChart.
web/core/store/issue/root.store.ts Changed rootStore property type from RootStore to CoreRootStore in IIssueRootStore.
web/core/store/root.store.ts Removed timelineStore property and related instantiation from CoreRootStore.
web/core/store/timeline/index.ts Deleted ITimelineStore interface and TimeLineStore class.
web/core/store/timeline/issues-timeline.store.ts Removed isDependencyEnabled property and simplified autorun logic.
web/core/store/timeline/modules-timeline.store.ts Removed isDependencyEnabled property and simplified autorun logic.

Possibly related PRs

Suggested labels

🛠️refactor, 🌟improvement

Suggested reviewers

  • SatishGandham

🐰 In the fields where bunnies play,
New stores and types have come our way.
With timelines neat and orders bright,
We hop along, all feels just right!
So let’s rejoice and cheer with glee,
For changes made, oh what a spree! 🥕✨


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

🧹 Outside diff range and nitpick comments (11)
web/ce/store/root.store.ts (1)

1-12: Clean architectural separation of timeline functionality.

The refactoring moves timeline management from CoreRootStore to RootStore, which aligns well with the goal of effective code splitting. This separation of concerns allows for better modularity and maintainability.

This change:

  • Keeps core functionality lean in CoreRootStore
  • Allows timeline features to be managed independently in the CE version
  • Facilitates easier testing and maintenance
web/core/store/timeline/modules-timeline.store.ts (2)

Line range hint 6-8: Fix interface-implementation mismatch.

The IModulesTimeLineStore interface requires an isDependencyEnabled property, but the implementing class ModulesTimeLineStore doesn't provide it. This violates the TypeScript contract and could lead to runtime issues.

Consider one of these solutions:

- export interface IModulesTimeLineStore extends IBaseTimelineStore {
-   isDependencyEnabled: boolean;
- }
+ export interface IModulesTimeLineStore extends IBaseTimelineStore {}

Or implement the property in the class:

 export class ModulesTimeLineStore extends BaseTimeLineStore implements IModulesTimeLineStore {
+   isDependencyEnabled: boolean = false;
   
   constructor(_rootStore: RootStore) {

14-17: Consider preserving debugging capabilities in autorun.

The simplified autorun implementation removes the previous reaction.trace() capability, which could make debugging more difficult in development.

Consider preserving the debugging capability in development:

-    autorun(() => {
+    autorun((reaction) => {
       const getModuleById = this.rootStore.module.getModuleById;
       this.updateBlocks(getModuleById);
+      if (process.env.NODE_ENV === 'development') {
+        reaction.trace();
+      }
     });
web/core/store/timeline/issues-timeline.store.ts (1)

Line range hint 6-8: Fix interface-implementation mismatch.

The interface IIssuesTimeLineStore requires isDependencyEnabled property, but the implementation IssuesTimeLineStore doesn't provide it. This will cause TypeScript compilation errors.

Either remove the property from the interface or implement it in the class:

export interface IIssuesTimeLineStore extends IBaseTimelineStore {
-  isDependencyEnabled: boolean;
}
web/ce/store/timeline/index.ts (1)

1-4: Consider standardizing import paths.

The imports mix different path styles (@/plane-web/store, @/store, and relative paths). Consider standardizing them for better maintainability.

web/core/hooks/use-timeline-chart.ts (2)

16-19: Maintain consistent type casting across all cases.

The MODULE and PROJECT cases use explicit type casting to IBaseTimelineStore, while the ISSUE case doesn't. For consistency and type safety, consider applying the same type casting pattern to all cases.

 switch (timeLineType) {
   case ETimeLineTypeType.ISSUE:
-    return context.timelineStore.issuesTimeLineStore;
+    return context.timelineStore.issuesTimeLineStore as IBaseTimelineStore;
   case ETimeLineTypeType.MODULE:
     return context.timelineStore.modulesTimeLineStore as IBaseTimelineStore;
   case ETimeLineTypeType.PROJECT:
     return context.timelineStore.projectTimeLineStore as IBaseTimelineStore;
 }

Line range hint 9-21: Consider adding JSDoc documentation for the timeline types.

The useTimeLineChart hook handles multiple timeline types (ISSUE, MODULE, PROJECT) but lacks documentation explaining the differences and use cases for each type. Adding JSDoc comments would improve maintainability and developer experience.

+/**
+ * Hook to access the appropriate timeline store based on the timeline type.
+ * @param timeLineType - The type of timeline to access:
+ *   - ISSUE: For issue-based timelines
+ *   - MODULE: For module-based timelines
+ *   - PROJECT: For project-based timelines
+ * @returns The corresponding timeline store instance
+ * @throws {Error} If used outside of StoreProvider
+ */
 export const useTimeLineChart = (timeLineType: ETimeLineTypeType): IBaseTimelineStore => {
web/core/components/gantt-chart/sidebar/utils.ts (2)

22-22: Consider using a configurable offset value.

While the current implementation works, the hardcoded value of 1000 for the offset might be better as a named constant or configuration parameter for maintainability.

+ const SORT_ORDER_OFFSET = 1000;
- updatedSortOrder = (getBlockById(blockIds[0])?.sort_order ?? 0) - 1000;
+ updatedSortOrder = (getBlockById(blockIds[0])?.sort_order ?? 0) - SORT_ORDER_OFFSET;

19-31: Consider implementing sort order normalization.

The current approach of using division for middle insertions could lead to very small differences between sort orders after multiple insertions. Consider implementing a normalization function that redistributes sort orders when they get too close.

Would you like me to propose a sort order normalization implementation that:

  1. Detects when sort orders become too close
  2. Redistributes them evenly
  3. Maintains relative ordering
web/core/store/issue/root.store.ts (1)

Line range hint 1-224: Architecture feedback on store refactoring.

The transition from RootStore to CoreRootStore aligns well with the PR's objective of facilitating effective code splitting. This change suggests a move towards a more modular store architecture where core functionality is separated from feature-specific stores.

Consider documenting the architectural decision and migration strategy for other teams who might need to perform similar refactoring in their stores.

web/ce/store/timeline/base-timeline.store.ts (1)

Line range hint 179-194: Consider enhancing error handling in updateBlocks.

The block update logic could benefit from more robust error handling, especially for edge cases:

  1. Invalid block data validation
  2. Error reporting for failed updates
  3. Logging for debugging purposes

Consider wrapping the block creation in a try-catch and adding validation:

try {
  const block: IGanttBlock = {
    data: validateBlockData(blockData), // Add validation
    id: blockData?.id,
    name: blockData.name,
    sort_order: blockData?.sort_order ?? undefined,
    start_date: blockData?.start_date ?? undefined,
    target_date: blockData?.target_date ?? undefined,
  };
  // ... rest of the code
} catch (error) {
  console.error(`Failed to update block ${blockId}:`, error);
  // Handle or report error appropriately
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b4bbe3a and e392ad1.

📒 Files selected for processing (13)
  • web/ce/store/issue/issue-details/activity.store.ts (2 hunks)
  • web/ce/store/root.store.ts (1 hunks)
  • web/ce/store/timeline/base-timeline.store.ts (4 hunks)
  • web/ce/store/timeline/index.ts (1 hunks)
  • web/core/components/gantt-chart/contexts/index.tsx (1 hunks)
  • web/core/components/gantt-chart/sidebar/utils.ts (1 hunks)
  • web/core/components/gantt-chart/types/index.ts (1 hunks)
  • web/core/hooks/use-timeline-chart.ts (2 hunks)
  • web/core/store/issue/root.store.ts (4 hunks)
  • web/core/store/root.store.ts (0 hunks)
  • web/core/store/timeline/index.ts (0 hunks)
  • web/core/store/timeline/issues-timeline.store.ts (1 hunks)
  • web/core/store/timeline/modules-timeline.store.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • web/core/store/root.store.ts
  • web/core/store/timeline/index.ts
🔇 Additional comments (19)
web/ce/store/root.store.ts (1)

10-11: Verify timeline functionality after store initialization.

The timeline store is properly initialized with the parent store reference. However, we should ensure that any existing timeline features continue to work as expected after this architectural change.

✅ Verification successful

Let me gather more information about the timeline store implementation and its dependencies.


Let me check one more aspect to verify the timeline store's integration and dependencies.


Based on the gathered information, I can now provide the final response:

Timeline store initialization and integration is properly implemented

The verification shows that:

  • TimeLineStore is correctly initialized with proper parent store reference
  • All child stores (issues, modules, project) are properly instantiated
  • The store is well-integrated with components through the useTimelineChart hook
  • No circular dependencies were found in the implementation

The architectural change maintains the expected structure and dependencies, and the timeline functionality should continue to work as intended.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify timeline store usage and dependencies

# Check for timeline store references in components and other stores
echo "Checking timeline store usage patterns:"
rg -A 3 "timelineStore" --type ts

# Look for potential circular dependencies
echo "Checking for potential circular dependencies:"
rg -l "import.*from.*timeline" --type ts | xargs rg "import.*from.*root.store"

Length of output: 1592


Script:

#!/bin/bash
# Check timeline store implementation and interfaces
echo "Checking timeline store implementation:"
ast-grep --pattern 'class TimeLineStore {
  $$$
}'

echo "\nChecking timeline store interface:"
ast-grep --pattern 'interface ITimelineStore {
  $$$
}'

echo "\nChecking timeline store initialization and usage in components:"
rg -A 5 "useTimelineChart" --type ts

echo "\nChecking timeline-related imports in the root store:"
rg "import.*Timeline" web/ce/store/root.store.ts

Length of output: 1028


Script:

#!/bin/bash
# Check timeline store's child stores and their initialization
echo "Checking timeline store's child stores:"
rg -A 10 "class TimeLineStore" --type ts

echo "\nChecking timeline store's usage in components:"
rg -B 2 -A 2 "useTimelineChart|timelineStore" web/core/components/ --type ts

echo "\nChecking timeline-related tests:"
fd -e test.ts -e spec.ts | xargs rg "timeline|Timeline" -l

Length of output: 3228

web/core/store/timeline/issues-timeline.store.ts (2)

14-17: LGTM! Simplified autorun logic.

The autorun callback has been simplified by removing the unused reaction parameter, making the code cleaner while maintaining the same functionality.


Line range hint 1-17: Verify the removal of isDependencyEnabled property.

The removal of isDependencyEnabled property might affect consumers of this class.

Let's verify its usage in the codebase:

web/core/components/gantt-chart/types/index.ts (1)

9-11: LGTM! Consider adding JSDoc comments.

The changes to make sort_order, start_date, and target_date optional align well with the timeline store refactoring objective. However, to improve maintainability:

  1. Consider adding JSDoc comments to document why these fields are optional and how they should be handled.
  2. Ensure all consumers of IGanttBlock properly handle the undefined cases.

Let's verify the impact on consumers:

✅ Verification successful

Based on the extensive search results, I can now generate the final response since I have enough context to verify the review comment.

Optional fields in IGanttBlock are properly handled throughout the codebase

The changes to make sort_order, start_date, and target_date optional in IGanttBlock interface are safe and align with the codebase's implementation:

  1. The base timeline store handles undefined values with nullish coalescing:
sort_order: blockData?.sort_order ?? undefined,
start_date: blockData?.start_date ?? undefined,
target_date: blockData?.target_date ?? undefined,
  1. All consumers properly check for existence before using these fields:
  • Gantt blocks: if (!block || (!showAllBlocks && !(block.start_date && block.target_date)))
  • Position calculations: const { start_date, target_date } = itemData; if (!itemStartDate || !itemTargetDate) return;
  • Sidebar components: const isBlockVisibleOnChart = !!block?.start_date && !!block?.target_date;

The changes are part of a well-structured refactoring that maintains type safety while providing more flexibility in the timeline stores.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usages of IGanttBlock to ensure proper handling of optional fields

# Search for IGanttBlock usage
echo "Searching for IGanttBlock implementations and usage..."
rg -A 5 "IGanttBlock" 

# Search for direct property access that might need null checks
echo "Checking for direct property access..."
rg -A 2 "(sort_order|start_date|target_date)\s*[^?]" web/

Length of output: 113764

web/ce/store/timeline/index.ts (3)

6-10: LGTM! Well-structured interface definition.

The interface is well-defined with proper typing for each timeline store component.


20-21: Clarify the purpose of the dummy store.

The comment indicates this is a "Dummy store". Please clarify:

  1. Is this a temporary implementation?
  2. What's the intended final implementation?
  3. Should this be tracked as a TODO item?

Would you like me to create a GitHub issue to track the implementation of the actual project timeline store?


17-22: Verify the RootStore type usage.

The AI summary mentions changes from RootStore to CoreRootStore, but this file still uses RootStore. Please verify if this is intentional.

web/core/hooks/use-timeline-chart.ts (1)

Line range hint 23-29: LGTM! Well-structured hook composition.

The useTimeLineChartStore hook demonstrates good practices:

  • Proper error handling for missing context
  • Clear composition of hooks
  • Single responsibility principle
web/core/components/gantt-chart/sidebar/utils.ts (2)

19-19: LGTM: Safely handle undefined sort_order.

The addition of nullish coalescing operator ensures a default value of 0 when sort_order is undefined, preventing potential NaN or undefined arithmetic operations.


25-25: Verify sort order calculations for edge cases.

The current implementation assumes there's always enough space between sort orders for new items. We should verify this assumption and potentially implement a rebalancing mechanism.

Also applies to: 28-29

✅ Verification successful

Based on the search results, I can now provide a final response since I have enough context about the sort order implementation:

The sort order implementation has sufficient spacing and rebalancing mechanisms in place.

The codebase shows a well-designed sort order system with:

  • Default spacing of 1000 units between items when reordering at top/bottom (+/- 1000)
  • Average-based positioning for items dropped between two existing items ((destinationSortingOrder + relativeDestinationSortingOrder) / 2)
  • Large default value of 65535 for initial items
  • Backend support for rebalancing with 10000-unit spacing when needed

The implementation follows best practices for ordered lists by:

  • Using float values to allow infinite subdivisions between any two positions
  • Maintaining large enough gaps between items to minimize rebalancing needs
  • Having fallback default values when sort orders are missing
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential sort order collisions in the codebase
# Look for places where sort orders are very close together

# Search for sort_order assignments or comparisons
rg -A 3 'sort_order.*=|sort_order.*<|sort_order.*>' --type typescript

# Search for any rebalancing logic that might already exist
rg -A 5 'rebalance|normalize.*sort' --type typescript

Length of output: 197


Script:

#!/bin/bash
# Let's try without type filtering since typescript extension isn't recognized
# Search for sort order related patterns
rg -A 3 'sort_order.*=|sort_order.*<|sort_order.*>'

# Search for any rebalancing logic
rg -A 5 'rebalance|normalize.*sort'

# Also look for the specific increment value (1000) usage
rg -A 2 '[\+\-\*\/]\s*1000'

# Look for the getBlockById implementation
ast-grep --pattern 'function getBlockById'

Length of output: 27201


Script:

#!/bin/bash
# Let's search for the specific increment value (1000) with proper escaping
rg -A 2 '[+\-*/]\s*1000'

# Look for sort order calculations and potential edge cases
rg -A 3 'sort_order.*[+\-*/]'

# Search for getBlockById implementation
rg -A 5 'getBlockById'

Length of output: 187676

web/ce/store/issue/issue-details/activity.store.ts (2)

15-16: LGTM: Import changes align with store refactoring.

The import of CoreRootStore from the core store module aligns with the PR's objective of refactoring timeline stores for better code splitting.


50-50: Verify store functionality access after type change.

The change from RootStore to CoreRootStore looks good, but let's verify that all required store functionalities are still accessible through CoreRootStore.

✅ Verification successful

Let me gather more information about CoreRootStore to ensure it's properly defined.


Let me check one more thing to understand the CoreRootStore definition since we see it's imported from "@/store/root.store".


Based on the shell script results, I can now provide a final response since I have enough information about CoreRootStore and its usage:

Type change from RootStore to CoreRootStore is safe and properly implemented

The change is verified to be correct because:

  • CoreRootStore contains the required issue.issueDetail.comment structure that's being accessed in the activity store
  • All store accesses in the file (this.store.issue.issueDetail.comment) are compatible with CoreRootStore's structure
  • RootStore extends CoreRootStore, so the type change is a safe narrowing of the interface
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that CoreRootStore provides all necessary functionality used in this class

# Test 1: Check if CoreRootStore contains the required issue store structure
ast-grep --pattern 'export (type|interface|class) CoreRootStore {
  $$$
  issue: {
    $$$
    issueDetail: {
      $$$
      comment: $$$
    }
    $$$
  }
  $$$
}'

# Test 2: Look for any other usages of store properties in this file
rg -A 2 'this\.store\.' web/ce/store/issue/issue-details/activity.store.ts

Length of output: 528


Script:

#!/bin/bash
# Search for CoreRootStore definition and its inheritance/implementation
ast-grep --pattern 'export (type|interface|class) CoreRootStore'

# Also check for any type definitions or interfaces that CoreRootStore implements/extends
rg -A 3 'CoreRootStore' web/ce/store

Length of output: 1635


Script:

#!/bin/bash
# Find the actual CoreRootStore definition in the main store directory
fd root.store.ts --exec cat {}

# Also check if there are any interfaces that CoreRootStore implements
ast-grep --pattern 'interface ICoreRootStore'

Length of output: 37291

web/core/store/issue/root.store.ts (4)

6-6: LGTM! Import change aligns with store refactoring.

The import of CoreRootStore is correctly specified and aligns with the PR's objective of refactoring stores.


110-110: Verify CoreRootStore property access.

The autorun block accesses multiple properties from rootStore. Please ensure that all these properties (user, router, state, label, memberRoot, projectRoot, module, cycle) exist in CoreRootStore.

Let's verify the CoreRootStore structure:

✅ Verification successful

Let me verify the autorun block's property access by first checking what properties it uses.


Based on the CoreRootStore definition and the autorun block's property access, I can now provide the final response:

All required properties exist in CoreRootStore

The autorun block accesses the following properties from rootStore which are all present in CoreRootStore:

  • user: Line 52
  • router: Line 47
  • state: Line 43
  • label: Line 44
  • memberRoot: Line 35
  • projectRoot: Line 34
  • module: Line 38
  • cycle: Line 36
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for CoreRootStore definition and properties
ast-grep --pattern 'class CoreRootStore {
  $$$
}'

Length of output: 9929


Script:

#!/bin/bash
# Find the autorun block in the issue store to see what properties it accesses from rootStore
ast-grep --pattern 'autorun(() => {
  $$$
})'

Length of output: 3266


52-52: Verify the impact of interface type change.

The change from RootStore to CoreRootStore is a breaking change that could affect consumers of IIssueRootStore.

Let's verify the usage:

✅ Verification successful

The previous search didn't yield results for implementations, so let's try a broader search to understand the interface and its usage. We'll also look for references to the old type RootStore to understand the impact of the change.


Based on the search results, I can now provide a conclusive response about the type change from RootStore to CoreRootStore.

Type change is safe and intentional

The change from RootStore to CoreRootStore is actually a safe change as RootStore extends CoreRootStore in both web and admin implementations:

  • In web: web/ce/store/root.store.ts: export class RootStore extends CoreRootStore
  • In admin: admin/ce/store/root.store.ts: export class RootStore extends CoreRootStore

The property type change to CoreRootStore makes the interface more precise by using the base class type, while still being compatible with RootStore through inheritance. This follows the Liskov Substitution Principle where a base class can be used in place of any of its derived classes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for implementations and usages of IIssueRootStore
rg "implements IIssueRootStore|: IIssueRootStore" -A 2

Length of output: 9929


Script:

#!/bin/bash
# Search for IIssueRootStore interface definition and its usages
rg "interface IIssueRootStore|IIssueRootStore" -A 2

# Search for RootStore references to understand the type change
rg "RootStore" -A 2

Length of output: 66027


Line range hint 148-224: Verify store initialization compatibility.

The constructor initializes multiple store instances with this as a parameter. Since this now contains a CoreRootStore, verify that all these store classes (IssueStore, StateStore, IssueDetail, etc.) are compatible with the new type.

Let's check the store constructors:

✅ Verification successful

Let me analyze the constructors of the stores that are initialized in the issue root store. I need to check their parameter types.


Let me try a different approach to check the store class definitions.


Let me check the base classes and interfaces these stores implement to fully understand the type requirements.


Based on the analysis of the code, I can now provide a final response:

Store initialization compatibility verified.

The change from RootStore to CoreRootStore in the constructor is compatible with all initialized store instances because:

  1. All filter stores (WorkspaceIssuesFilter, ProjectIssuesFilter, etc.) extend IssueFilterHelperStore which doesn't require any root store type in its constructor.
  2. Issue stores (WorkspaceIssues, ProjectIssues, etc.) extend BaseIssuesStore and receive the root store through their filter store implementations.
  3. The StateStore explicitly accepts CoreRootStore in its constructor.
  4. The IssueStore and IssueDetail implementations work with the IIssueRootStore interface, which defines the required properties that are present in CoreRootStore.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for store class constructors
rg "constructor.*\(.*\)" -A 2 --type ts

Length of output: 35139


Script:

#!/bin/bash
# Search for store class definitions and their constructors
ast-grep --pattern 'class $className {
  constructor($params) {
    $$$
  }
  $$$
}'

Length of output: 86


Script:

#!/bin/bash
# Search for IssueStore, StateStore, and other store class definitions
rg "^(export )?class (IssueStore|StateStore|IssueDetail|WorkspaceIssuesFilter|WorkspaceIssues|ProfileIssuesFilter|ProfileIssues|WorkspaceDraftIssuesFilter|WorkspaceDraftIssues|ProjectIssuesFilter|ProjectIssues|CycleIssuesFilter|CycleIssues|ModuleIssuesFilter|ModuleIssues|ProjectViewIssuesFilter|ProjectViewIssues|ArchivedIssuesFilter|ArchivedIssues|DraftIssuesFilter|DraftIssues)" -A 5 --type ts

Length of output: 12381


Script:

#!/bin/bash
# Search for BaseIssuesStore and IssueFilterHelperStore definitions and their constructors
rg "class (BaseIssuesStore|IssueFilterHelperStore)" -B 2 -A 10 --type ts

# Search for relevant interfaces
rg "interface (IIssueRootStore|IBaseIssueFilterStore)" -B 2 -A 10 --type ts

Length of output: 5443

web/ce/store/timeline/base-timeline.store.ts (3)

30-30: LGTM: Clean interface extension.

The addition of isDependencyEnabled to the interface aligns well with the refactoring goals, providing a clear contract for dependency-related functionality.


185-187: LGTM: Proper null handling.

The use of the nullish coalescing operator for sort_order and other fields is appropriate and consistent with TypeScript best practices.


18-18: Verify the impact of nullable sort_order.

The change from number to number | null for sort_order provides more flexibility but ensure that sorting operations handle the null case appropriately.

✅ Verification successful

Based on the search results, I can now generate the final response since I have comprehensive information about how sort_order is used throughout the codebase:

Nullable sort_order is safe and consistent with codebase patterns

The change from number to number | null for sort_order in base-timeline.store.ts is safe because:

  1. The codebase already handles null sort orders in multiple places:

    • Project models explicitly define sort_order: number | null in types
    • UI components have null handling: tooltipContent={sort_order === null ? "Join the project to rearrange" : "Drag to rearrange"}
    • Sorting operations use nullish coalescing: sort_order ?? undefined, sort_order || 0
  2. The sorting logic across the codebase consistently handles nullable sort orders:

    • Default values are provided: sort_order: number = 65535
    • Null checks are implemented: currentSortOrder = joinedProjects[destinationIndex].sort_order || 0
    • Sorting functions use safe accessors: sortBy(projects, [(p) => p.sort_order])
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for sort_order usage in sorting operations
rg -A 3 "sort_order" | rg -B 1 "sort|order"

Length of output: 32446

export enum ETimeLineTypeType {
ISSUE = "ISSUE",
MODULE = "MODULE",
PROJECT = "PROJECT",
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Timeline store integration needs attention

The verification revealed that while the PROJECT enum is being used, its implementation is incomplete:

  • The projectTimeLineStore is currently using a dummy implementation: new BaseTimeLineStore(rootStore) with a comment "// Dummy store"
  • Other timeline types (ISSUE, MODULE) have dedicated store implementations (IssuesTimeLineStore, ModulesTimeLineStore), but PROJECT uses the base class

This suggests the PROJECT timeline functionality is not fully implemented yet.

Action items:

  • Implement a dedicated ProjectTimeLineStore class extending TimelineStore
  • Replace the dummy store with the proper implementation
  • Ensure all PROJECT timeline-specific functionality is implemented in the new store
🔗 Analysis chain

LGTM! Verify timeline store integration.

The addition of PROJECT to the enum follows the existing pattern and maintains consistency. The change aligns well with the timeline store refactoring objective.

Let's verify the integration with timeline stores:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that PROJECT timeline type is properly integrated with timeline stores
# and that there are no missing implementations.

# Test 1: Check for PROJECT timeline store implementation
ast-grep --pattern 'projectTimeLineStore'

# Test 2: Check for PROJECT case handling in timeline-related code
rg -l "PROJECT.*timeline" 

# Test 3: Look for any TODO or unimplemented cases
rg "TODO.*PROJECT.*timeline"

Length of output: 100


Script:

#!/bin/bash
# Let's try a more comprehensive search strategy

# Check for PROJECT enum usage in timeline-related files
rg -i "PROJECT.*timeline|timeline.*PROJECT" -A 3 -B 3

# Look for timeline store implementations
ast-grep --pattern 'class $_ extends TimelineStore'

# Check for switch/case statements handling timeline types
ast-grep --pattern 'switch ($timelineType) {
  $$$
}'

# Search for timeline type handling in general
rg "ETimeLineTypeType" -A 2 -B 2

# Look for store factory or initialization code
ast-grep --pattern 'new $_TimelineStore'

Length of output: 9402

Comment on lines +17 to +22
constructor(rootStore: RootStore) {
this.issuesTimeLineStore = new IssuesTimeLineStore(rootStore);
this.modulesTimeLineStore = new ModulesTimeLineStore(rootStore);
// Dummy store
this.projectTimeLineStore = new BaseTimeLineStore(rootStore);
}
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 adding initialization checks.

The constructor instantiates stores without any error handling. Consider adding checks to ensure rootStore is properly initialized and contains required dependencies.

 constructor(rootStore: RootStore) {
+  if (!rootStore) {
+    throw new Error("RootStore is required for TimeLineStore initialization");
+  }
   this.issuesTimeLineStore = new IssuesTimeLineStore(rootStore);
   this.modulesTimeLineStore = new ModulesTimeLineStore(rootStore);
   // Dummy store
   this.projectTimeLineStore = new BaseTimeLineStore(rootStore);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
constructor(rootStore: RootStore) {
this.issuesTimeLineStore = new IssuesTimeLineStore(rootStore);
this.modulesTimeLineStore = new ModulesTimeLineStore(rootStore);
// Dummy store
this.projectTimeLineStore = new BaseTimeLineStore(rootStore);
}
constructor(rootStore: RootStore) {
if (!rootStore) {
throw new Error("RootStore is required for TimeLineStore initialization");
}
this.issuesTimeLineStore = new IssuesTimeLineStore(rootStore);
this.modulesTimeLineStore = new ModulesTimeLineStore(rootStore);
// Dummy store
this.projectTimeLineStore = new BaseTimeLineStore(rootStore);
}

import { StoreContext } from "@/lib/store-context";
import { IBaseTimelineStore } from "ee/store/timeline/base-timeline.store";
// Plane-web
import { IBaseTimelineStore } from "@/plane-web/store/timeline/base-timeline.store";
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Import path change requires attention

The import path @/plane-web/store/timeline/base-timeline.store in the review file is incorrect. The search results show that:

  1. The base-timeline.store.ts exists in two locations:

    • web/ce/store/timeline/base-timeline.store.ts
    • web/ee/store/timeline/base-timeline.store.ts
  2. Current imports in the codebase use:

    • "ce/store/timeline/base-timeline.store"
    • "./base-timeline.store"
    • "ce/store/timeline/base-timeline.store"

The import path should be updated to use the correct path "ce/store/timeline/base-timeline.store" to maintain consistency with other files in the codebase.

🔗 Analysis chain

Verify the import path change impact.

The import path change from 'ee/store' to '@/plane-web/store' appears to be part of the code splitting objective. Let's verify that this change is consistent across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining references to the old import path
# and verify the new path exists

# Test 1: Check for any remaining references to the old path
echo "Checking for old import path references..."
rg "from ['\"]ee/store/timeline/base-timeline\.store['\"]"

# Test 2: Verify the new path exists
echo "Verifying new path exists..."
fd "base-timeline.store.ts" "web/plane-web/store/timeline"

Length of output: 399


Script:

#!/bin/bash
# Let's try a broader search approach

# Test 1: Find the base-timeline.store.ts file anywhere in the repo
echo "Searching for base-timeline.store.ts..."
fd "base-timeline.store.ts"

# Test 2: Check for any imports of base-timeline.store from any path
echo "Checking all imports of base-timeline.store..."
rg "from.*base-timeline\.store"

# Test 3: List all files in web directory to understand structure
echo "Listing web directory structure..."
fd . web -t d

Length of output: 21793

Comment on lines +64 to +65
isDependencyEnabled = false;

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add observable decorator for isDependencyEnabled.

The isDependencyEnabled property should be marked as observable since it's part of the store's state and might trigger UI updates when changed.

Apply this change to the makeObservable call:

 makeObservable(this, {
   // observables
   blocksMap: observable,
   blockIds: observable,
   isDragging: observable.ref,
   currentView: observable.ref,
   currentViewData: observable,
   activeBlockId: observable.ref,
   renderView: observable,
+  isDependencyEnabled: observable,
   // actions
   setIsDragging: action,
   setBlockIds: action.bound,

Also applies to: 67-85

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants