Skip to content

Comments

chore: refactor project states to make way for new features#6156

Merged
pushya22 merged 1 commit intopreviewfrom
chore-refactor-project-state
Dec 5, 2024
Merged

chore: refactor project states to make way for new features#6156
pushya22 merged 1 commit intopreviewfrom
chore-refactor-project-state

Conversation

@rahulramesha
Copy link
Contributor

@rahulramesha rahulramesha commented Dec 4, 2024

This PR refactors the project states to make way for upcoming features.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for JSX content in tooltips via a new jsxContent property.
    • Introduced AddStateTransition, StateItemChild, StateOption, and StateTransitionCount components to enhance workflow management.
    • Implemented WorkFlowDisabledMessage and WorkFlowGroupTree components for better workflow state representation.
    • Enhanced drag-and-drop functionality with workflow state handling in various components.
  • Bug Fixes

    • Updated logic for handling project states and transitions to improve data fetching reliability.
  • Documentation

    • Improved export statements for better modular access across components and services.
  • Chores

    • Refactored code for better maintainability and organization, including updates to import paths and component structures.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 4, 2024

Walkthrough

The changes introduced in this pull request include the addition of new components and properties across various files, enhancing the functionality of tooltips and workflow management. A new optional property jsxContent is added to the ITooltipProps interface, allowing tooltips to accept JSX content. Additionally, several new components related to workflow management, such as AddStateTransition, StateItemChild, and StateOption, are introduced. The export statements are updated to facilitate access to these new components and types, improving modularity and organization throughout the codebase.

Changes

File Change Summary
packages/ui/src/tooltip/tooltip.tsx Added jsxContent property to ITooltipProps interface and updated Tooltip component to handle JSX content.
web/ce/components/workflow/add-state-transition.tsx Introduced AddStateTransition component with props for workspace and project IDs.
web/ce/components/workflow/index.tsx Added multiple export statements for various workflow components.
web/ce/components/workflow/state-item-child.tsx Introduced StateItemChild component for rendering child state items with MobX integration.
web/ce/components/workflow/state-option.tsx Introduced StateOption component for use with Combobox, accepting various props.
web/ce/components/workflow/state-transition-count.tsx Introduced StateTransitionCount component, currently rendering an empty fragment.
web/ce/components/workflow/use-workflow-drag-n-drop.ts Added useWorkFlowFDragNDrop hook for managing drag-and-drop functionality.
web/ce/components/workflow/workflow-disabled-message.tsx Introduced WorkFlowDisabledMessage component with props for displaying messages.
web/ce/components/workflow/workflow-group-tree.tsx Introduced WorkFlowGroupTree component for rendering group trees in workflows.
web/ce/services/index.ts Updated export statement to include workspace.service.
web/ce/services/project/project-state.service.ts Re-exported all entities from project state service.
web/ce/store/state.store.ts Re-exported all entities from state store.
web/ce/types/index.ts Added export for state.d types.
web/ce/types/state.d.ts Introduced IStateTransition and IStateWorkFlow interfaces.
web/core/components/dropdowns/state.tsx Updated StateDropdown component to use StateOption and handle new props.
web/core/components/issues/issue-layouts/group-drag-overlay.tsx Added workflowDisabledSource prop to conditionally render WorkFlowDisabledMessage.
web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx Integrated WorkFlowGroupTree into HeaderGroupByCard.
web/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx Added sub_group_by prop to HeaderSubGroupByCard.
web/core/components/issues/issue-layouts/kanban/kanban-group.tsx Enhanced drag-and-drop functionality with workflow state handling.
web/core/components/issues/issue-layouts/kanban/swimlanes.tsx Updated swimlane components to handle subgroup visibility.
web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx Updated to include groupBy prop and integrated WorkFlowGroupTree.
web/core/components/issues/issue-layouts/list/list-group.tsx Enhanced drag-and-drop functionality and updated HeaderGroupByCard.
web/core/components/project-states/index.ts Added export for state-item-title.
web/core/components/project-states/root.tsx Expanded data fetching logic to include state transitions.
web/core/components/project-states/state-item-title.tsx Introduced StateItemTitle component for displaying state details.
web/core/components/project-states/state-item.tsx Refactored to use StateItemChild for rendering state items.
web/core/hooks/store/use-project-state.ts Updated import path for IStateStore.
web/core/layouts/auth-layout/project-wrapper.tsx Updated data fetching logic to include state transitions.
web/core/store/issue/issue-details/issue.store.ts Modified method call hierarchy for fetching project states.
web/core/store/issue/issue-details/sub_issues.store.ts Updated state retrieval methods to centralize access through rootStore.
web/core/store/issue/root.store.ts Removed state property from IIssueRootStore interface and class.
web/core/store/root.store.ts Updated store initialization to use type assertions for RootStore.
web/core/store/state.store.ts Added new methods and updated constructor to accept RootStore.
web/ee/components/workflow/index.ts Re-exported all entities from ce/components/workflow.
web/ee/services/project/project-state.service.ts Re-exported all entities from project state service.
web/ee/store/state.store.ts Re-exported all entities from state store.
web/ee/types/index.ts Added export for ce/types/state.d.
web/helpers/array.helper.ts Introduced convertStringArrayToBooleanObject function.

Possibly related PRs

Suggested labels

✨feature

Suggested reviewers

  • SatishGandham

🐇 In the meadow, changes bloom,
New components chase away the gloom.
Tooltips now can hold more light,
Workflow magic, a joyful sight!
With every click, transitions flow,
In our code, new wonders grow! 🌼


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

🧹 Outside diff range and nitpick comments (16)
web/core/hooks/store/use-project-state.ts (1)

1-8: Consider documenting the state transition workflow

The introduction of IStateTransition and IStateWorkFlow types suggests a significant enhancement to state management. Consider adding documentation (e.g., in README or TSDoc comments) explaining:

  1. The purpose and lifecycle of state transitions
  2. The role of actors in state transitions
  3. Example usage of these interfaces

This will help team members understand the new state management system and facilitate the implementation of future features.

web/helpers/array.helper.ts (1)

111-119: Consider optimizing and adding input validation

While the implementation is functional, it could be improved for robustness and performance.

Consider this optimized version with input validation:

 export const convertStringArrayToBooleanObject = (arrayStrings: string[]) => {
+  if (!Array.isArray(arrayStrings)) return {};
+  
-  const obj: { [key: string]: boolean } = {};
-
-  for (const arrayString of arrayStrings) {
-    obj[arrayString] = true;
-  }
-
-  return obj;
+  return arrayStrings.reduce((acc, str) => {
+    if (typeof str === 'string') {
+      acc[str] = true;
+    }
+    return acc;
+  }, {} as Record<string, boolean>);
 };
web/core/store/root.store.ts (1)

77-78: Type assertions indicate potential architectural issues

The use of as unknown as RootStore type assertions in both the constructor and resetOnSignOut method suggests potential issues in the type hierarchy between CoreRootStore and RootStore.

Consider these alternatives:

  1. Properly extend CoreRootStore from RootStore
  2. Create an interface that both stores implement
  3. Refactor the stores to eliminate the need for type assertions

Example approach:

// Option 1: Proper inheritance
export class CoreRootStore extends RootStore {
  // ... existing properties and methods
}

// Option 2: Common interface
interface IBaseRootStore {
  // ... common properties and methods
}
export class CoreRootStore implements IBaseRootStore {
  // ... existing properties and methods
}
export class RootStore implements IBaseRootStore {
  // ... existing properties and methods
}

Also applies to: 108-109

web/core/store/issue/issue-details/sub_issues.store.ts (1)

Line range hint 324-349: Consider enhancing fetchOtherProjectProperties with error handling and parallel fetching

While the method comprehensively fetches all necessary project data, consider these improvements:

  1. Add error handling for individual fetch operations
  2. Use Promise.all for parallel fetching to improve performance
  3. Add progress tracking for better observability

Here's a suggested implementation:

 fetchOtherProjectProperties = async (workspaceSlug: string, projectIds: string[]) => {
   if (projectIds.length > 0) {
     for (const projectId of projectIds) {
-      // fetching other project states
-      this.rootIssueDetailStore.rootIssueStore.rootStore.state.fetchProjectStates(workspaceSlug, projectId);
-      // fetching other project members
-      this.rootIssueDetailStore.rootIssueStore.rootStore.memberRoot.project.fetchProjectMembers(
-        workspaceSlug,
-        projectId
-      );
-      // remaining sequential fetches...
+      try {
+        await Promise.all([
+          this.rootIssueDetailStore.rootIssueStore.rootStore.state.fetchProjectStates(workspaceSlug, projectId),
+          this.rootIssueDetailStore.rootIssueStore.rootStore.memberRoot.project.fetchProjectMembers(
+            workspaceSlug,
+            projectId
+          ),
+          this.rootIssueDetailStore.rootIssueStore.rootStore.label.fetchProjectLabels(workspaceSlug, projectId),
+          this.rootIssueDetailStore.rootIssueStore.rootStore.cycle.fetchAllCycles(workspaceSlug, projectId),
+          this.rootIssueDetailStore.rootIssueStore.rootStore.module.fetchModules(workspaceSlug, projectId),
+          this.rootIssueDetailStore.rootIssueStore.rootStore.projectEstimate.getProjectEstimates(
+            workspaceSlug,
+            projectId
+          )
+        ]);
+      } catch (error) {
+        console.error(`Failed to fetch properties for project ${projectId}:`, error);
+        // Consider implementing retry logic or error reporting
+      }
     }
   }
 };
web/core/components/issues/issue-layouts/kanban/kanban-group.tsx (1)

124-130: Consider refactoring duplicated code in onDragEnter and onDragStart handlers

The logic inside the onDragEnter and onDragStart handlers is identical. To adhere to the DRY (Don't Repeat Yourself) principle, consider extracting the shared logic into a separate function.

web/ce/components/workflow/add-state-transition.tsx (1)

14-18: Remove unnecessary fragment in JSX

The fragment <>...</> is unnecessary inside the div as it's already wrapping the content. Removing it simplifies the code.

Apply this diff to remove the fragment:

-    <>
      <Plus className="h-4 w-4" color="#8591AD" />
      <span className="text-custom-text-400 font-medium"> Add Transition</span>
      <div className="text-white bg-custom-background-80 font-semibold px-2 rounded-lg">Pro</div>
-    </>
web/ce/components/workflow/state-item-child.tsx (1)

1-8: Improve import organization

The import statements could be better organized:

  • Comments between imports break consistency
  • SetStateAction type should be explicitly imported from 'react'

Consider this organization:

-import { SetStateAction } from "react";
+import type { SetStateAction } from "react";
 import { observer } from "mobx-react";
-// Plane
 import { IState } from "@plane/types";
-// components
 import { StateItemTitle } from "@/components/project-states/state-item-title";
-//
 import { AddStateTransition } from "./add-state-transition";
web/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx (1)

Line range hint 23-26: Enhance accessibility for interactive elements

The div element is clickable but lacks proper accessibility attributes.

Consider adding these accessibility improvements:

 <div
   className={`relative flex w-full flex-shrink-0 flex-row items-center gap-1 rounded-sm py-1.5 cursor-pointer`}
   onClick={() => handleCollapsedGroups("sub_group_by", column_id)}
+  role="button"
+  aria-label={`Toggle ${title} group`}
+  tabIndex={0}
+  onKeyDown={(e) => {
+    if (e.key === 'Enter' || e.key === ' ') {
+      e.preventDefault();
+      handleCollapsedGroups("sub_group_by", column_id);
+    }
+  }}
 >
web/core/components/issues/issue-layouts/group-drag-overlay.tsx (1)

45-75: Consider extracting message rendering logic

The conditional rendering logic could be simplified by extracting the message content into separate components for better maintainability.

Consider refactoring like this:

- {workflowDisabledSource ? (
-   <WorkFlowDisabledMessage parentStateId={workflowDisabledSource} className="my-2" />
- ) : (
-   <div className={cn("p-3 my-8 flex flex-col rounded items-center",
-     {"text-custom-text-200": shouldOverlayBeVisible},
-     {"text-custom-text-error": isDropDisabled}
-   )}>
-     {dropErrorMessage ? (
-       <div className="flex items-center">
-         <AlertCircle width={13} height={13} /> &nbsp;
-         <span>{dropErrorMessage}</span>
-       </div>
-     ) : (
-       <>
-         {readableOrderBy && (
-           <span>
-             The layout is ordered by <span className="font-semibold">{readableOrderBy}</span>.
-           </span>
-         )}
-         <span>Drop here to move the issue.</span>
-       </>
-     )}
-   </div>
- )}
+ <OverlayMessage
+   workflowDisabledSource={workflowDisabledSource}
+   dropErrorMessage={dropErrorMessage}
+   readableOrderBy={readableOrderBy}
+   shouldOverlayBeVisible={shouldOverlayBeVisible}
+   isDropDisabled={isDropDisabled}
+ />
packages/ui/src/tooltip/tooltip.tsx (1)

84-99: Consider adding type guard for jsxContent

While the implementation is correct, adding a type guard could improve type safety.

Consider adding:

+ const isJSXContent = (content: string | React.ReactNode): content is React.ReactNode =>
+   typeof content !== 'string';

  content={
-   jsxContent ? (
+   jsxContent && isJSXContent(jsxContent) ? (
      <>{jsxContent}</>
    ) : (
web/core/components/project-states/state-item-title.tsx (2)

55-55: Simplify boolean expression

The ternary operator with boolean literals can be simplified.

- isDefault={state.default ? true : false}
+ isDefault={Boolean(state.default)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 55-55: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


26-71: Consider breaking down the component for better maintainability

The component has multiple logical sections that could be extracted into separate components.

Consider splitting into:

  • StateIcon (lines 35-37)
  • StateInfo (lines 39-42)
  • StateActions (lines 47-69)

This would improve readability and make the component easier to maintain.

🧰 Tools
🪛 Biome (1.9.4)

[error] 55-55: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

web/core/components/project-states/state-item.tsx (1)

131-143: Clean refactoring of state item presentation logic!

The extraction of presentation logic into StateItemChild improves modularity while maintaining the core drag-and-drop functionality. The component structure is now more maintainable and follows the Single Responsibility Principle.

Consider documenting the responsibilities of StateItemChild in a comment block to help future maintainers understand the separation of concerns.

web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx (1)

135-136: Consider handling vertical alignment for WorkFlowGroupTree

While the WorkFlowGroupTree integration looks good, it should respect the vertical alignment state when verticalAlignPosition is true.

Consider wrapping WorkFlowGroupTree with the same conditional styling:

-        <WorkFlowGroupTree groupBy={group_by} groupId={column_id} />
+        <div className={verticalAlignPosition ? 'flex flex-col items-center' : ''}>
+          <WorkFlowGroupTree groupBy={group_by} groupId={column_id} />
+        </div>
web/core/components/dropdowns/state.tsx (2)

35-36: LGTM! Consider adding JSDoc comments.

The new optional props enhance the component's flexibility for state filtering. Consider adding JSDoc comments to document their purpose and usage.

+/** List of specific state IDs to filter the dropdown options */
 stateIds?: string[];
+/** Flag to control whether to filter available state IDs */
 filterAvailableStateIds?: boolean;

91-91: Simplify boolean coercion.

The double negation (!!value) is redundant as the value will already be coerced to a boolean in this context.

-const stateValue = !!value ? value : showDefaultState ? defaultState?.id : undefined;
+const stateValue = value ? value : showDefaultState ? defaultState?.id : undefined;
🧰 Tools
🪛 Biome (1.9.4)

[error] 91-91: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3bccda0 and 02dbfc9.

📒 Files selected for processing (38)
  • packages/ui/src/tooltip/tooltip.tsx (3 hunks)
  • web/ce/components/workflow/add-state-transition.tsx (1 hunks)
  • web/ce/components/workflow/index.tsx (1 hunks)
  • web/ce/components/workflow/state-item-child.tsx (1 hunks)
  • web/ce/components/workflow/state-option.tsx (1 hunks)
  • web/ce/components/workflow/state-transition-count.tsx (1 hunks)
  • web/ce/components/workflow/use-workflow-drag-n-drop.ts (1 hunks)
  • web/ce/components/workflow/workflow-disabled-message.tsx (1 hunks)
  • web/ce/components/workflow/workflow-group-tree.tsx (1 hunks)
  • web/ce/services/index.ts (1 hunks)
  • web/ce/services/project/project-state.service.ts (1 hunks)
  • web/ce/store/state.store.ts (1 hunks)
  • web/ce/types/index.ts (1 hunks)
  • web/ce/types/state.d.ts (1 hunks)
  • web/core/components/dropdowns/state.tsx (6 hunks)
  • web/core/components/issues/issue-layouts/group-drag-overlay.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx (3 hunks)
  • web/core/components/issues/issue-layouts/kanban/kanban-group.tsx (7 hunks)
  • web/core/components/issues/issue-layouts/kanban/swimlanes.tsx (1 hunks)
  • web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx (5 hunks)
  • web/core/components/issues/issue-layouts/list/list-group.tsx (8 hunks)
  • web/core/components/project-states/index.ts (1 hunks)
  • web/core/components/project-states/root.tsx (1 hunks)
  • web/core/components/project-states/state-item-title.tsx (1 hunks)
  • web/core/components/project-states/state-item.tsx (2 hunks)
  • web/core/hooks/store/use-project-state.ts (1 hunks)
  • web/core/layouts/auth-layout/project-wrapper.tsx (3 hunks)
  • web/core/store/issue/issue-details/issue.store.ts (2 hunks)
  • web/core/store/issue/issue-details/sub_issues.store.ts (3 hunks)
  • web/core/store/issue/root.store.ts (0 hunks)
  • web/core/store/root.store.ts (3 hunks)
  • web/core/store/state.store.ts (6 hunks)
  • web/ee/components/workflow/index.ts (1 hunks)
  • web/ee/services/project/project-state.service.ts (1 hunks)
  • web/ee/store/state.store.ts (1 hunks)
  • web/ee/types/index.ts (1 hunks)
  • web/helpers/array.helper.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • web/core/store/issue/root.store.ts
✅ Files skipped from review due to trivial changes (11)
  • web/ee/store/state.store.ts
  • web/ee/components/workflow/index.ts
  • web/ce/services/index.ts
  • web/ee/services/project/project-state.service.ts
  • web/ce/components/workflow/state-transition-count.tsx
  • web/ce/components/workflow/workflow-disabled-message.tsx
  • web/ce/services/project/project-state.service.ts
  • web/ce/types/index.ts
  • web/ce/store/state.store.ts
  • web/ce/components/workflow/workflow-group-tree.tsx
  • web/ce/components/workflow/index.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
web/core/components/project-states/state-item-title.tsx

[error] 55-55: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

web/core/components/dropdowns/state.tsx

[error] 91-91: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

🔇 Additional comments (35)
web/ee/types/index.ts (1)

3-3: Verify import path and potential circular dependencies

The import path ce/types/state.d seems to reference a sibling directory. Consider using a more explicit import path to avoid potential issues with module resolution.

✅ Verification successful

Let me verify the import path and check for the actual state.d.ts file location.


Let me check the content of state.d.ts to understand what's being exported and verify if there are any circular dependencies.


Import path is valid and no circular dependencies found

The import path "ce/types/state.d" is valid as:

  • The target file exists at web/ce/types/state.d.ts
  • The file contains pure type definitions without any imports from "ee/"
  • While many EE files import from CE, the CE file doesn't import from EE, avoiding circular dependencies
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for potential circular dependencies between ee and ce
rg -l "from \"ee/" web/ce/
rg -l "from \"ce/" web/ee/

Length of output: 3179


Script:

#!/bin/bash
# Check if state.d.ts exists in the expected location and its content
fd state.d.ts web/ce/types/
fd state.d.ts web/ce/

Length of output: 101


Script:

#!/bin/bash
# Check the content of state.d.ts and look for any imports from ee
cat web/ce/types/state.d.ts
rg "from \"ee/" web/ce/types/state.d.ts

Length of output: 240

web/ce/types/state.d.ts (2)

1-4: LGTM: Well-structured state transition interface

The IStateTransition interface clearly defines the structure for state transitions with appropriate types.


6-8: Verify transition state ID references

The IStateWorkFlow interface looks good, but let's ensure that the transition_state_id references are properly handled in the codebase.

✅ Verification successful

Interface and its usage are properly typed and consistent

Based on the search results, the IStateTransition interface and its usage in IStateWorkFlow are properly defined and consistently used throughout the codebase. The interface correctly defines transition_state_id as a string type, and the workflow interface properly maps transition IDs to state transitions. The codebase shows appropriate usage in components like AddStateTransition and state management through fetchProjectStateTransitions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for transition_state_id usage to ensure consistent typing
ast-grep --pattern 'transition_state_id: $_'

Length of output: 46


Script:

#!/bin/bash
# Let's search for any usage of transitionId or transition patterns in the codebase
rg -i "transition.*id|transitionId" -A 2

# Also search for IStateTransition interface definition
ast-grep --pattern 'interface IStateTransition {
  $$$
}'

Length of output: 9582

web/core/components/project-states/root.tsx (2)

19-19: LGTM: Added state transitions fetching capability

The addition of fetchProjectStateTransitions aligns with the PR objective of refactoring project states.


23-29: Consider error handling for parallel fetches

While fetching both states and transitions in parallel is efficient, consider handling potential failures in either fetch operation.

Consider adding error handling:

 workspaceSlug && projectId
   ? () => {
-      fetchProjectStates(workspaceSlug.toString(), projectId.toString());
-      fetchProjectStateTransitions(workspaceSlug.toString(), projectId.toString());
+      return Promise.all([
+        fetchProjectStates(workspaceSlug.toString(), projectId.toString()),
+        fetchProjectStateTransitions(workspaceSlug.toString(), projectId.toString())
+      ]).catch((error) => {
+        console.error("Failed to fetch project states:", error);
+      });
     }
   : null,
web/core/store/root.store.ts (1)

2-4: Verify import dependencies

The addition of imports from "@/plane-web/store" suggests a potential circular dependency risk.

web/core/layouts/auth-layout/project-wrapper.tsx (1)

54-54: Verify implementation of fetchProjectStateTransitions

The fetchProjectStateTransitions function is called but appears to be a dummy implementation in the state store. This could lead to missing functionality in the state transition management.

Also applies to: 108-113

web/core/store/state.store.ts (1)

57-57: LGTM! Store restructuring and type safety improvements

The changes improve code organization and type safety by:

  1. Explicitly typing the stateService
  2. Properly integrating with the root store

Also applies to: 59-59, 61-61, 81-81

web/core/store/issue/issue-details/sub_issues.store.ts (1)

221-221: State retrieval refactoring looks good!

The changes consistently update the state retrieval path to use rootStore.state instead of accessing it through rootIssueStore. This centralization of state management aligns with the PR's objective and follows good practices.

Let's verify that this refactoring pattern is consistent across the codebase:

Also applies to: 226-226, 258-258, 293-293

✅ Verification successful

State retrieval pattern is consistently implemented

The codebase search confirms that all state retrievals follow the same pattern, accessing state through rootStore.state. No instances of direct state access through rootIssueStore.state were found, indicating successful and complete refactoring.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining direct state access through rootIssueStore
# that might have been missed during refactoring

# Search for potential missed refactoring spots
rg "rootIssueStore\.state\." --type ts

# Search for the new pattern to ensure consistency
rg "rootStore\.state\." --type ts

Length of output: 1501

web/core/components/issues/issue-layouts/kanban/kanban-group.tsx (6)

29-31: Approved import of useWorkFlowFDragNDrop

The import statement correctly adds useWorkFlowFDragNDrop from the specified path.


109-113: Correct initialization of useWorkFlowFDragNDrop hook

The useWorkFlowFDragNDrop hook is properly initialized with group_by and sub_group_by, and the returned values are correctly destructured.


Line range hint 150-157: Proper handling of drop disabled state

Including isWorkflowDropDisabled in the drop condition ensures that drops are correctly disabled when workflow constraints apply. The warning toast provides appropriate user feedback.


Line range hint 179-189: Updated dependency array in useEffect hook

Adding isWorkflowDropDisabled, dropErrorMessage, and handleOnDrop to the dependency array ensures that the effect responds correctly to changes in these variables.


259-260: Correctly updating overlay visibility logic

Adjusting canOverlayBeVisible to include isWorkflowDropDisabled ensures the overlay behaves appropriately under workflow constraints.


275-276: Properly propagating isDropDisabled prop

The GroupDragOverlay component now correctly receives the updated isDropDisabled prop, reflecting both workflow and drop states.

web/core/components/issues/issue-layouts/list/list-group.tsx (10)

29-31: Approved import of useWorkFlowFDragNDrop

The import statement correctly adds useWorkFlowFDragNDrop from the specified path.


98-98: Verify safe usage of optional chaining in isExpanded

Ensure that collapsedGroups?.group_by is always defined or consider providing a default value to prevent potential runtime errors when group_by is undefined.


110-111: Correct initialization of useWorkFlowFDragNDrop hook

The useWorkFlowFDragNDrop hook is properly initialized with group_by, and the returned values are correctly destructured.


192-193: Handling workflow state in onDrag event

The call to handleWorkFlowState within the onDrag event appropriately manages the workflow state during drag operations.


Line range hint 210-217: Proper handling of drop disabled state

Including isWorkflowDropDisabled in the drop condition ensures that drops are correctly disabled when workflow constraints apply. The warning toast provides appropriate user feedback.


224-225: Automatically expanding collapsed groups on drop

Expanding collapsed groups when an item is dropped enhances user experience by ensuring the dropped item is visible.


230-238: Updated dependency array in useEffect hook

Adding isWorkflowDropDisabled to the dependency array ensures that the effect responds correctly to changes in this variable.


242-242: Correctly updating overlay visibility logic

Adjusting canOverlayBeVisible to include isWorkflowDropDisabled ensures the overlay behaves appropriately under workflow constraints.


262-262: Passing groupBy prop to HeaderGroupByCard

Including the groupBy prop enhances the component's functionality in relation to the workflow grouping.


279-280: Properly propagating isDropDisabled prop

The GroupDragOverlay component now correctly receives the updated isDropDisabled prop, reflecting both workflow and drop states.

web/core/components/project-states/index.ts (1)

13-13: Approved addition of state-item-title export

The export statement correctly exposes state-item-title, enhancing modularity and access to this component.

web/ce/components/workflow/state-option.tsx (1)

20-35: LGTM! Well-structured component with proper accessibility

The component implementation is clean and follows best practices:

  • Uses Headless UI for accessibility
  • Properly handles active/selected states
  • Clean JSX structure with meaningful class names
web/ce/components/workflow/state-item-child.tsx (1)

19-35: LGTM! Well-structured component with clear responsibilities

The component implementation is clean and follows best practices:

  • Clear separation of concerns
  • Proper props destructuring
  • Meaningful class names for styling
web/core/components/issues/issue-layouts/kanban/headers/sub-group-by-card.tsx (1)

43-44: LGTM! Good integration of workflow grouping

The WorkFlowGroupTree integration is clean and properly typed with the necessary props.

web/core/components/issues/issue-layouts/group-drag-overlay.tsx (1)

13-13: LGTM: New prop enhances workflow state management

The addition of workflowDisabledSource prop aligns with the PR's objective of refactoring project states.

packages/ui/src/tooltip/tooltip.tsx (1)

26-26: LGTM: New prop enhances tooltip flexibility

The addition of jsxContent prop allows for richer tooltip content, which is beneficial for the project state refactoring.

web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx (1)

119-119: Verify WorkFlowGroupTree integration with existing group handling

The addition of WorkFlowGroupTree enhances group visualization, but we should verify its interaction with the existing group collapse functionality.

✅ Verification successful

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

WorkFlowGroupTree integration is safe and non-conflicting

The WorkFlowGroupTree component is a non-intrusive empty component (<></>) that coexists with the existing group collapse functionality. The collapse behavior is handled separately through handleCollapsedGroups and doesn't interfere with the tree visualization.

  • The group collapse functionality remains intact through handleCollapsedGroups(groupID)
  • WorkFlowGroupTree is rendered as a sibling element and doesn't affect the collapse behavior
  • The empty implementation (<></>) ensures no conflicts with existing functionality
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for potential conflicts between WorkFlowGroupTree and group collapse handling
ast-grep --pattern 'handleCollapsedGroups($groupId)'

Length of output: 54


Script:

#!/bin/bash
# Let's search for group collapse related functionality and WorkFlowGroupTree usage
rg -A 5 "WorkFlowGroupTree" 

# Also search for any group collapse related state or handlers
rg -A 5 "collaps.*group" -i

# Check the WorkFlowGroupTree component implementation
fd -e tsx -e ts "WorkFlowGroupTree" --exec cat {}

Length of output: 69499


Script:

#!/bin/bash
# Let's check for any group collapse state management in the component
rg -A 5 "collapsedGroups|handleCollapse" web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx

# Also check for any state management related to groups
rg -A 5 "groupBy|groupID" web/core/components/issues/issue-layouts/list/headers/group-by-card.tsx

# Check the implementation of WorkFlowGroupTree to understand its functionality
rg -A 10 "export const WorkFlowGroupTree" web/ce/components/workflow/workflow-group-tree.tsx

Length of output: 2333

web/core/components/issues/issue-layouts/kanban/headers/group-by-card.tsx (1)

18-19: Maintain import grouping consistency

The new import for WorkFlowGroupTree maintains proper separation in a "Plane-web" section, which is good for organization.

web/core/components/dropdowns/state.tsx (1)

87-89: LGTM! Clean and efficient state list computation.

The conditional computation with null filtering is a good approach for handling potentially invalid state IDs.

web/core/components/issues/issue-layouts/kanban/swimlanes.tsx (1)

173-173: LGTM! Consistent prop passing.

The addition of sub_group_by prop to HeaderSubGroupByCard maintains consistency with the parent component's interface.

Comment on lines +4 to +5
// Plane-web
import { IStateStore } from "@/plane-web/store/state.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

Inconsistent import paths detected for state.store

Multiple files are still using the old import path @/store/state.store while some have been updated to use @/plane-web/store/state.store. This inconsistency needs to be addressed.

Locations requiring attention:

  • space/core/hooks/store/use-state.ts
  • space/core/components/issues/issue-layouts/utils.tsx
  • web/core/components/issues/issue-layouts/utils.tsx
  • web/ee/store/state.store.ts
  • web/ce/store/state.store.ts
🔗 Analysis chain

Verify consistency of @/plane-web imports

The import path has been updated to use @/plane-web/store/state.store. Let's ensure this pattern is consistent across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for inconsistent import patterns
rg "from \"@/store/state.store\""
rg "from \"@/plane-web/store/state.store\""

Length of output: 705

// fetching states
// TODO: check if this function is required
this.rootIssueDetailStore.rootIssueStore.state.fetchProjectStates(workspaceSlug, projectId);
this.rootIssueDetailStore.rootIssueStore.rootStore.state.fetchProjectStates(workspaceSlug, projectId);
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

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

Remove redundant fetchProjectStates call

The fetchProjectStates call appears to be redundant here as:

  1. Project states are already being fetched in multiple UI components when needed (dropdowns, project-states, project-wrapper, hooks)
  2. The TODO comment and the surrounding code context shows this fetch isn't directly related to the issue details being processed
  3. The state_id is only being used as a pass-through property, not requiring immediate state data
🔗 Analysis chain

Review necessity of fetchProjectStates call

There's a TODO comment questioning if this function call is required. Additionally, the store access path has been modified to use rootStore. Consider:

  1. Evaluating if this state fetch is necessary at this point
  2. Documenting why it's needed if it is determined to be required

Let me gather more context about the specific location where this fetch is being called to understand its necessity.


Let me check one more thing to understand if the states are being used immediately after this fetch.


Let me try a different pattern to get the method implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check where else project states are being fetched
# to determine if this fetch is redundant

# Search for fetchProjectStates calls
ast-grep --pattern 'fetchProjectStates($$$)'

Length of output: 545


Script:

#!/bin/bash
# Get context around the fetchProjectStates call in issue.store.ts
rg -B 10 -A 2 "fetchProjectStates" web/core/store/issue/issue-details/issue.store.ts

# Also check for any state-related operations nearby
rg -B 5 -A 5 "state" web/core/store/issue/issue-details/issue.store.ts

Length of output: 1832


Script:

#!/bin/bash
# Get the full method implementation to understand the context
ast-grep --pattern 'fetchIssueDetails($$$) {
  $$$
}'

Length of output: 55


Script:

#!/bin/bash
# Get the full method implementation to understand the context
ast-grep --pattern 'fetchIssueDetails = async ($$$) => {
  $$$
}'

Length of output: 67

Comment on lines +26 to +29
getAvailableProjectStateIdMap: (
projectId: string | null | undefined,
currStateId: string | null | undefined
) => { [key: string]: boolean };
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

Enhance getAvailableProjectStateIdMap implementation

The current implementation has several limitations:

  1. The currStateId parameter is unused but could be valuable for determining valid state transitions
  2. The method returns all states as available without considering transition rules or permissions

Consider enhancing the implementation to:

 getAvailableProjectStateIdMap = computedFn(
   (projectId: string | null | undefined, currStateId: string | null | undefined) => {
     const projectStates = this.getProjectStates(projectId);
+    const currentState = this.getStateById(currStateId);
 
     if (!projectStates) return {};
 
-    return convertStringArrayToBooleanObject(projectStates.map((projectState) => projectState.id));
+    // Filter states based on transition rules and permissions
+    const availableStates = projectStates.filter((state) => {
+      // Add transition rules and permission checks here
+      return true;
+    });
+
+    return convertStringArrayToBooleanObject(availableStates.map((state) => state.id));
   }
 );

Also applies to: 131-143

Comment on lines +286 to +288

// Dummy method
fetchProjectStateTransitions = (workspaceSlug: string, projectId: string) => {};
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

Implement fetchProjectStateTransitions functionality

The method is currently a no-op placeholder. This needs to be implemented to support the state transition management being introduced.

Would you like help implementing this method? I can provide a basic implementation that:

  1. Fetches state transitions from the API
  2. Updates the store with the transition rules
  3. Integrates with the getAvailableProjectStateIdMap method

Comment on lines +1 to +15
import { TIssueGroupByOptions } from "@plane/types";

export const useWorkFlowFDragNDrop = (
groupBy: TIssueGroupByOptions | undefined,
subGroupBy?: TIssueGroupByOptions
) => ({
workflowDisabledSource: undefined,
isWorkflowDropDisabled: false,
handleWorkFlowState: (
sourceGroupId: string,
destinationGroupId: string,
sourceSubGroupId?: string,
destinationSubGroupId?: string
) => {},
});
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

Empty implementation in useWorkFlowFDragNDrop hook

The useWorkFlowFDragNDrop hook currently returns default values, and the handleWorkFlowState function lacks implementation. Ensure that the necessary logic is implemented to manage workflow drag-and-drop states effectively.

Comment on lines +12 to +20
export const AddStateTransition = (props: Props) => (
<div className={cn("flex w-full px-3 h-6 items-center justify-start gap-2 text-sm bg-custom-background-90")}>
<>
<Plus className="h-4 w-4" color="#8591AD" />
<span className="text-custom-text-400 font-medium"> Add Transition</span>
<div className="text-white bg-custom-background-80 font-semibold px-2 rounded-lg">Pro</div>
</>
</div>
);
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

AddStateTransition component lacks interaction handling

The onTransitionAdd prop is defined but not utilized. Consider adding an onClick handler to invoke onTransitionAdd when the component is clicked.

Apply this diff to add the onClick handler:

export const AddStateTransition = (props: Props) => (
  <div
    className={cn("flex w-full px-3 h-6 items-center justify-start gap-2 text-sm bg-custom-background-90")}
+   onClick={props.onTransitionAdd}
  >
    <Plus className="h-4 w-4" color="#8591AD" />
    <span className="text-custom-text-400 font-medium"> Add Transition</span>
    <div className="text-white bg-custom-background-80 font-semibold px-2 rounded-lg">Pro</div>
  </div>
);

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +5 to +15
type Props = {
projectId: string | null | undefined;
option: {
value: string | undefined;
query: string;
content: JSX.Element;
};
filterAvailableStateIds: boolean;
selectedValue: string | null | undefined;
className?: string;
};
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 strengthening prop types and removing unused props

The Props type definition has some potential improvements:

  • projectId and selectedValue being nullable/undefined might lead to runtime issues
  • filterAvailableStateIds is defined but not used in the component

Consider this improvement:

 type Props = {
-  projectId: string | null | undefined;
+  projectId: string;
   option: {
-    value: string | undefined;
+    value: string;
     query: string;
     content: JSX.Element;
   };
-  filterAvailableStateIds: boolean;
-  selectedValue: string | null | undefined;
+  selectedValue: string;
   className?: string;
 };
📝 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
type Props = {
projectId: string | null | undefined;
option: {
value: string | undefined;
query: string;
content: JSX.Element;
};
filterAvailableStateIds: boolean;
selectedValue: string | null | undefined;
className?: string;
};
type Props = {
projectId: string;
option: {
value: string;
query: string;
content: JSX.Element;
};
selectedValue: string;
className?: string;
};

Comment on lines +29 to +33
{!disabled && stateCount != 1 && (
<div className="flex-shrink-0 w-3 h-3 rounded-sm absolute left-0 hidden group-hover:flex justify-center items-center transition-colors bg-custom-background-90 cursor-pointer text-custom-text-200 hover:text-custom-text-100">
<GripVertical className="w-3 h-3" />
</div>
)}
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

Verify drag handle accessibility

The drag handle implementation lacks proper keyboard accessibility and ARIA attributes. It should be enhanced with:

  • role="button" attribute
  • aria-label to describe the drag action
  • tabIndex to make it keyboard focusable
  • Keyboard event handlers for Enter/Space keys

Here are the specific locations that need attention:

  • web/core/components/project-states/state-item-title.tsx: Lines 29-33
    <div className="flex-shrink-0 w-3 h-3 rounded-sm absolute left-0 hidden group-hover:flex justify-center items-center transition-colors bg-custom-background-90 cursor-pointer text-custom-text-200 hover:text-custom-text-100">
      <GripVertical className="w-3 h-3" />
    </div>
🔗 Analysis chain

Verify drag handle accessibility

The drag handle should be keyboard accessible and have proper ARIA attributes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other drag handle implementations in the codebase
rg -A 2 'role="button".*drag' --type tsx

Length of output: 70


Script:

#!/bin/bash
# Check for drag handle implementations and accessibility patterns
rg -t ts -t tsx -A 5 'GripVertical|draggable|drag'

Length of output: 80


Script:

#!/bin/bash
# Look for aria attributes and role assignments in the codebase
ast-grep --pattern 'role="$_"'

Length of output: 32


Script:

#!/bin/bash
# Find keyboard event handlers
rg -t ts -t tsx -A 3 'onKeyDown|onKeyPress|onKeyUp'

Length of output: 81


Script:

#!/bin/bash
# Search for any file content with grip, drag, or keyboard handlers
rg "GripVertical|draggable|drag|onKeyDown|onKeyPress|onKeyUp|role=\"button\""

# Also check the specific file content
cat "web/core/components/project-states/state-item-title.tsx"

Length of output: 52004

Comment on lines +237 to +244
<StateOption
key={option.value}
value={option.value}
className={({ active, selected }) =>
`flex w-full cursor-pointer select-none items-center justify-between gap-2 truncate rounded px-1 py-1.5 ${
active ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
>
{({ selected }) => (
<>
<span className="flex-grow truncate">{option.content}</span>
{selected && <Check className="h-3.5 w-3.5 flex-shrink-0" />}
</>
)}
</Combobox.Option>
option={option}
projectId={projectId}
filterAvailableStateIds={filterAvailableStateIds}
selectedValue={value}
className="flex w-full cursor-pointer select-none items-center justify-between gap-2 truncate rounded px-1 py-1.5"
/>
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

StateOption integration looks correct but props mismatch detected

The StateOption component in web/ce/components/workflow/state-option.tsx only accepts option and className props, but it's being called with additional props (projectId, filterAvailableStateIds, selectedValue) that aren't used in its implementation. This could lead to potential issues:

  • The component ignores projectId, filterAvailableStateIds, and selectedValue props that are being passed to it
  • If these props are meant to affect the component's behavior, the functionality is currently missing
🔗 Analysis chain

LGTM! Verify StateOption component integration.

The integration of the custom StateOption component looks good. However, let's verify its implementation to ensure it handles all edge cases properly.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check StateOption component implementation
ast-grep --pattern 'export const StateOption = ({ option, projectId, filterAvailableStateIds, selectedValue, className }) => {
  $$$
}'

Length of output: 137


Script:

#!/bin/bash
# Let's try a broader search for StateOption component
ast-grep --pattern 'const StateOption = $_'

# Also search for any file containing StateOption
rg "StateOption" -A 10

Length of output: 4245

@pushya22 pushya22 merged commit 66652a5 into preview Dec 5, 2024
@pushya22 pushya22 deleted the chore-refactor-project-state branch December 5, 2024 07:17
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.

2 participants