-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WEB-2380] chore: cycle sidebar refactor #5759
Conversation
WalkthroughThe pull request introduces updates to several components related to cycle analytics. The Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (9)
web/core/components/cycles/analytics-sidebar/sidebar-chart.tsx (2)
14-17
: Consider adding a fallback forcompletionChartDistributionData
.The current implementation might cause issues if
chartDistributionData
is undefined. Consider using optional chaining and providing a default value to ensure type safety and prevent potential runtime errors.Here's a suggested improvement:
- const completionChartDistributionData = chartDistributionData?.completion_chart || undefined; + const completionChartDistributionData = chartDistributionData?.completion_chart ?? [];This change ensures that
completionChartDistributionData
is always an array, even ifchartDistributionData
or itscompletion_chart
property is undefined.
30-57
: LGTM: Chart rendering logic is well-implemented. Consider a minor refactor for readability.The conditional rendering logic is sound, handling potential missing data and providing appropriate user feedback with a loader. The use of a Fragment for wrapping multiple elements is correct.
To improve readability, consider extracting the
ProgressChart
rendering into a separate function.Here's a suggested refactor:
const renderProgressChart = () => { const commonProps = { distribution: completionChartDistributionData, startDate: cycleStartDate, endDate: cycleEndDate, }; return plotType === "points" ? ( <ProgressChart {...commonProps} totalIssues={totalEstimatePoints} plotTitle="points" /> ) : ( <ProgressChart {...commonProps} totalIssues={totalIssues} plotTitle="issues" /> ); }; // In the return statement: {cycleStartDate && cycleEndDate && completionChartDistributionData ? ( renderProgressChart() ) : ( <Loader className="w-full h-[160px] mt-4"> <Loader.Item width="100%" height="100%" /> </Loader> )}This refactor improves readability by separating the chart rendering logic and reducing duplication.
web/core/components/cycles/analytics-sidebar/sidebar-details.tsx (4)
6-9
: Improved import organization and consistency.The changes to the import statements enhance code organization and maintainability. Grouping related imports and using a centralized UI component library (@plane/ui) are good practices.
Consider adding a comment for the @plane/ui import similar to the one for @plane/types:
// types import { ICycle } from "@plane/types"; // ui components import { Avatar, AvatarGroup, TextArea } from "@plane/ui";This would further improve code readability and organization.
Line range hint
32-39
: Improved robustness in issueCount calculation.The updated logic for calculating
issueCount
is more comprehensive and handles different scenarios effectively. It correctly differentiates between completed and ongoing cycles, and accounts for the presence ofprogress_snapshot
.To improve readability, consider refactoring the nested ternary operators into a more explicit if-else structure or a switch statement. For example:
let issueCount: string; if (isCompleted && !isEmpty(cycleDetails?.progress_snapshot)) { issueCount = cycleDetails?.progress_snapshot?.total_issues === 0 ? "0 Issue" : `${cycleDetails?.progress_snapshot?.completed_issues}/${cycleDetails?.progress_snapshot?.total_issues}`; } else { issueCount = cycleDetails?.total_issues === 0 ? "0 Issue" : `${cycleDetails?.completed_issues}/${cycleDetails?.total_issues}`; }This approach would make the logic easier to read and maintain.
Line range hint
43-47
: Enhanced logic for isEstimatePointValid calculation.The updated calculation for
isEstimatePointValid
is more comprehensive and handles different scenarios effectively. It correctly checks for the presence ofprogress_snapshot
and considers the estimate system type.To improve readability and maintainability, consider refactoring this logic into a separate function with explicit conditions. For example:
const isEstimatePointValid = () => { if (!isEmpty(cycleDetails?.progress_snapshot)) { return !isEmpty(cycleDetails?.progress_snapshot?.estimate_distribution); } return estimateType && estimateType?.type === EEstimateSystem.POINTS; };This approach would make the logic easier to understand and modify in the future.
Line range hint
49-56
: Improved robustness in issueEstimatePointCount calculation.The updated logic for calculating
issueEstimatePointCount
is more comprehensive and handles different scenarios effectively. It correctly differentiates between completed and ongoing cycles, and accounts for the presence ofprogress_snapshot
.
To improve readability, consider refactoring the nested ternary operators into a more explicit if-else structure, similar to the suggestion for
issueCount
.There's a significant similarity between the
issueCount
andissueEstimatePointCount
calculations. Consider creating a reusable function to handle both cases:const calculateCount = ( isCompleted: boolean, snapshot: any, totalKey: string, completedKey: string ) => { if (isCompleted && !isEmpty(snapshot)) { return snapshot[totalKey] === 0 ? "0 Issue" : `${snapshot[completedKey]}/${snapshot[totalKey]}`; } return cycleDetails?.[totalKey] === 0 ? "0 Issue" : `${cycleDetails?.[completedKey]}/${cycleDetails?.[totalKey]}`; }; const issueCount = calculateCount( isCompleted, cycleDetails?.progress_snapshot, 'total_issues', 'completed_issues' ); const issueEstimatePointCount = calculateCount( isCompleted, cycleDetails?.progress_snapshot, 'total_estimate_points', 'completed_estimate_points' );This refactoring would reduce code duplication and improve maintainability.
web/core/components/cycles/analytics-sidebar/issue-progress.tsx (1)
220-225
: LGTM: New progress percentage displayThe addition of the progress percentage display enhances the UI by providing immediate feedback to the user. The implementation correctly uses the existing
progressHeaderPercentage
calculation.Consider adding an aria-label to the outer div for improved accessibility:
- <div className="flex items-center justify-center gap-2"> + <div className="flex items-center justify-center gap-2" aria-label="Cycle progress">web/core/components/cycles/analytics-sidebar/sidebar-header.tsx (2)
159-159
: Approve the additional safety check and suggest optional chaining.The additional check for
cycleDetails
improves the robustness of the code by preventing potential runtime errors. This is a good practice for defensive programming.Consider using optional chaining for a more concise and equally safe approach:
if (cycleDetails?.start_date && cycleDetails?.end_date)This achieves the same safety while reducing code verbosity.
🧰 Tools
🪛 Biome
[error] 159-159: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
Line range hint
1-300
: Consider enhancing error handling and user feedback.While the component is well-structured and the recent change improves safety, there are opportunities to enhance the overall user experience:
Error Handling: Consider implementing a more robust error handling mechanism, especially for asynchronous operations like
dateChecker
andupdateCycleDetails
.Loading States: Add loading indicators during asynchronous operations to provide visual feedback to users.
Confirmation Dialogs: For critical actions like archiving or deleting a cycle, consider adding confirmation dialogs to prevent accidental operations.
Would you like assistance in implementing any of these suggestions?
🧰 Tools
🪛 Biome
[error] 159-159: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
- web/core/components/cycles/analytics-sidebar/issue-progress.tsx (2 hunks)
- web/core/components/cycles/analytics-sidebar/sidebar-chart.tsx (1 hunks)
- web/core/components/cycles/analytics-sidebar/sidebar-details.tsx (1 hunks)
- web/core/components/cycles/analytics-sidebar/sidebar-header.tsx (1 hunks)
🧰 Additional context used
🪛 Biome
web/core/components/cycles/analytics-sidebar/sidebar-header.tsx
[error] 159-159: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (6)
web/core/components/cycles/analytics-sidebar/sidebar-chart.tsx (2)
1-13
: LGTM: Imports and type definition are well-structured.The imports are appropriate for the component's functionality, and the
ProgressChartProps
type is well-defined, including all necessary props for theSidebarChart
component.
1-58
: Overall, theSidebarChart
component is well-implemented.The component effectively visualizes cycle analytics progress, following React best practices and providing good user feedback. The suggested improvements, if implemented, will enhance maintainability and readability without changing the core functionality.
Great job on this new component!
web/core/components/cycles/analytics-sidebar/issue-progress.tsx (3)
21-21
: LGTM: Import change for SidebarChartThe import change from
SidebarBaseChart
toSidebarChart
aligns with the refactoring mentioned in the PR objectives. This change appears to be intentional and consistent with the overall refactoring effort.
Line range hint
1-265
: Summary: Successful refactoring of CycleAnalyticsProgress componentThe changes in this file successfully refactor the CycleAnalyticsProgress component, aligning with the PR objectives. Key improvements include:
- Replacing the old chart component with a new SidebarChart component.
- Adding a progress percentage display for immediate user feedback.
- Maintaining consistency with the existing code structure and logic.
These changes enhance the UI and potentially improve the component's maintainability. The refactoring appears to be well-executed, with no major issues identified.
Line range hint
228-235
: LGTM: SidebarChart implementationThe replacement of the previous chart component with the new SidebarChart aligns with the refactoring objectives. The implementation appears correct, with all necessary data being passed as props.
To ensure the SidebarChart component is implemented correctly, please verify that the prop types in the SidebarChart component match the data being passed here. Run the following script to check the SidebarChart component definition:
web/core/components/cycles/analytics-sidebar/sidebar-header.tsx (1)
Line range hint
1-300
: Overall assessment: Good improvement with minor suggestions.The changes in this file enhance the code's robustness. The component is well-structured and follows React best practices. The suggestions provided aim to further improve code quality and user experience. Great job on the refactoring!
🧰 Tools
🪛 Biome
[error] 159-159: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
<div> | ||
<div className="relative flex items-center gap-2"> | ||
<div className="flex items-center justify-center gap-1 text-xs"> | ||
<span className="h-2.5 w-2.5 rounded-full bg-[#A9BBD0]" /> | ||
<span>Ideal</span> | ||
</div> | ||
<div className="flex items-center justify-center gap-1 text-xs"> | ||
<span className="h-2.5 w-2.5 rounded-full bg-[#4C8FFF]" /> | ||
<span>Current</span> | ||
</div> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider using CSS variables for color values.
While the legend provides clear visual cues, using hardcoded color values might make future theme changes difficult. Consider using CSS variables for better maintainability and easier theming.
Here's a suggested improvement:
- <span className="h-2.5 w-2.5 rounded-full bg-[#A9BBD0]" />
+ <span className="h-2.5 w-2.5 rounded-full bg-[var(--color-ideal)]" />
- <span className="h-2.5 w-2.5 rounded-full bg-[#4C8FFF]" />
+ <span className="h-2.5 w-2.5 rounded-full bg-[var(--color-current)]" />
Then, define these variables in your global CSS file:
:root {
--color-ideal: #A9BBD0;
--color-current: #4C8FFF;
}
This approach allows for easier theme management and consistency across the application.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anmolsinghbhatia also look at this comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
web/core/components/cycles/analytics-sidebar/issue-progress.tsx
Outdated
Show resolved
Hide resolved
web/core/components/cycles/analytics-sidebar/sidebar-header.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this 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 (4)
web/ce/components/cycles/analytics-sidebar/root.tsx (3)
1-4
: LGTM! Consider removing unnecessary comment.The imports and "use client" directive are correctly implemented. However, the comment "// components" on line 3 doesn't add significant value and could be removed for cleaner code.
"use client"; import React, { FC } from "react"; -// components import { SidebarChart } from "./base";
6-10
: LGTM! Consider adding JSDoc comments.The Props type is well-defined with appropriate types for all properties. To improve documentation, consider adding JSDoc comments to describe the purpose of each prop.
Here's an example of how you could add JSDoc comments:
/** * Props for the SidebarChartRoot component */ type Props = { /** The slug of the workspace */ workspaceSlug: string; /** The ID of the project */ projectId: string; /** The ID of the cycle */ cycleId: string; };
12-12
: LGTM! Consider adding JSDoc comments.The SidebarChartRoot component is well-implemented as a functional component with proper typing. It effectively serves as a pass-through for the SidebarChart component. To improve documentation, consider adding JSDoc comments to describe the component's purpose and usage.
Here's an example of how you could add JSDoc comments:
/** * Root component for the Sidebar Chart in the Cycle Analytics * This component serves as a wrapper for the SidebarChart component * * @param props - The props of type Props * @returns A React functional component */ export const SidebarChartRoot: FC<Props> = (props) => <SidebarChart {...props} />;web/ce/components/cycles/analytics-sidebar/base.tsx (1)
38-38
: Unnecessary check forcycleId
Since
cycleId
is a required prop, the check for its existence might be redundant.You might remove
!cycleId
from the condition:- if (!workspaceSlug || !projectId || !cycleId) return null; + if (!workspaceSlug || !projectId) return null;However, if there is a possibility that
cycleId
could be undefined, it's acceptable to keep the check.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
- web/ce/components/cycles/analytics-sidebar/base.tsx (1 hunks)
- web/ce/components/cycles/analytics-sidebar/index.ts (1 hunks)
- web/ce/components/cycles/analytics-sidebar/root.tsx (1 hunks)
- web/core/components/cycles/analytics-sidebar/issue-progress.tsx (4 hunks)
✅ Files skipped from review due to trivial changes (1)
- web/ce/components/cycles/analytics-sidebar/index.ts
🧰 Additional context used
🔇 Additional comments (9)
web/ce/components/cycles/analytics-sidebar/root.tsx (1)
1-12
: Well-implemented component. Clarification needed on wrapper purpose.The SidebarChartRoot component is well-implemented, following React and TypeScript best practices. It serves as a wrapper for the SidebarChart component, which is a good practice for code organization and potential future extensibility.
However, it would be helpful to understand the specific purpose of this wrapper component. Is it intended for future enhancements, context provision, or some other architectural reason?
To better understand the context and purpose of this wrapper, let's check for any related components or usage:
✅ Verification successful
Verified: SidebarChartRoot Usage Confirmed
The SidebarChartRoot component is utilized in
issue-progress.tsx
, confirming its role as a wrapper for the SidebarChart component. This aligns with best practices for code organization and supports potential future extensibility.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for imports or uses of SidebarChartRoot rg --type typescript --type tsx "SidebarChartRoot" # Search for other similar wrapper components rg --type typescript --type tsx "export const \w+Root: FC<Props> = \(props\) =>"Length of output: 203
Script:
#!/bin/bash # Search for imports or uses of SidebarChartRoot rg --type ts --type tsx "SidebarChartRoot" # Search for other similar wrapper components rg --type ts --type tsx "export const \w+Root: FC<Props> = \(props\) =>"Length of output: 173
Script:
#!/bin/bash # Search for imports or uses of SidebarChartRoot in .ts and .tsx files rg "SidebarChartRoot" --glob "*.ts" --glob "*.tsx" # Search for other similar wrapper components in .ts and .tsx files rg "export const \\w+Root: FC<Props> = \\(props\\) =>" --glob "*.ts" --glob "*.tsx"Length of output: 706
web/core/components/cycles/analytics-sidebar/issue-progress.tsx (6)
209-214
: Approve UI enhancement with a suggestion for accessibility.The addition of the progress percentage display is a good UI improvement. It provides users with a clear, quantitative representation of the cycle's progress.
To further enhance this feature, consider the following accessibility improvement:
- Add an
aria-label
to the progress display for screen readers. This will provide context for the percentage value.Example:
<div className="flex items-center justify-center gap-2"> <div className="flex items-center gap-1 text-xs" aria-label={`Cycle progress: ${progressHeaderPercentage}% complete`} > <span className="text-custom-text-300">Done</span> <span className="font-semibold text-custom-text-400">{progressHeaderPercentage}%</span> </div> </div>This change will improve the experience for users relying on screen readers or other assistive technologies.
Line range hint
29-43
: Consider using immutable operations invalidateCycleSnapshot
.The
validateCycleSnapshot
function is now exported, which is good for reusability. However, consider the following improvements:
Use immutable operations to avoid modifying the input object directly. This can prevent unexpected side effects.
Consider using TypeScript's built-in
Partial<T>
type for theupdatedCycleDetails
variable to better represent its potential incompleteness.Here's a suggested refactor:
export const validateCycleSnapshot = (cycleDetails: ICycle | null): ICycle | null => { if (!cycleDetails) return null; if (isEmpty(cycleDetails.progress_snapshot)) return cycleDetails; const updatedCycleDetails: Partial<ICycle> = { ...cycleDetails }; (Object.keys(cycleDetails.progress_snapshot) as Array<keyof TProgressSnapshot>).forEach((key) => { if (cycleDetails.progress_snapshot?.[key] !== undefined) { updatedCycleDetails[key] = cycleDetails.progress_snapshot[key]; } }); return updatedCycleDetails as ICycle; };To verify the usage of
validateCycleSnapshot
across the codebase, run the following script:#!/bin/bash # Check for validateCycleSnapshot usage echo "Checking for validateCycleSnapshot usage:" rg --type typescript "validateCycleSnapshot"
217-217
: Verify props and functionality ofSidebarChartRoot
.The chart component has been replaced with
SidebarChartRoot
. This change likely introduces more specialized functionality for cycle analytics. To ensure a smooth transition:
- Verify that all necessary props are being passed correctly to
SidebarChartRoot
.- Confirm that
SidebarChartRoot
provides all the functionality that was available in the previous chart component.- Check if any additional props or configurations are required for optimal performance and functionality.
To verify the props and usage of
SidebarChartRoot
, run the following script:#!/bin/bash # Check for SidebarChartRoot usage and props echo "Checking for SidebarChartRoot usage and props:" rg --type typescript "SidebarChartRoot" web/core/components/cycles/analytics-sidebar/issue-progress.tsx -C 5 # Check the implementation of SidebarChartRoot echo "Checking SidebarChartRoot implementation:" rg --type typescript "const SidebarChartRoot" web/plane-web/components/cyclesThis will help ensure that the new component is being used correctly and consistently throughout the codebase.
130-133
: Enhance error handling inCycleAnalyticsProgress
.The error handling has been simplified to only log errors to the console. While this is a good start, consider the following improvements:
Implement more robust error handling, such as displaying an error message to the user or triggering a fallback UI.
Use a centralized error logging service instead of
console.error
for better tracking and debugging in production.Consider adding error boundaries to prevent the entire component from crashing due to errors in child components.
Example improvement:
try { if (isArchived) { await fetchArchivedCycleDetails(workspaceSlug, projectId, cycleId); } else { await fetchCycleDetails(workspaceSlug, projectId, cycleId); } } catch (err) { console.error(err); // Log to a centralized error tracking service errorTrackingService.logError(err); // Display an error message to the user setErrorState("Failed to fetch cycle details. Please try again."); // Revert the estimate type change setEstimateType(cycleId, estimateType); }To check for existing error handling patterns in the codebase, run:
#!/bin/bash # Check for error handling patterns echo "Checking for error handling patterns:" rg --type typescript "catch \(.*\) \{"
21-21
: Verify impact of import change on Enterprise Edition.Addressing the previous review comment:
The import of
SidebarChartRoot
from "@/plane-web/components/cycles" raises a concern about potential issues in the Enterprise Edition (EE). To ensure this change doesn't cause any problems:
- Confirm that this import path is compatible with both the open-source and EE versions of the application.
- Verify that the
SidebarChartRoot
component is available and functions correctly in the EE environment.- If necessary, consider implementing a strategy to handle different import paths for different editions (e.g., using environment variables or build-time configuration).
To verify the compatibility and availability of the
SidebarChartRoot
component, run the following script:#!/bin/bash # Check for SidebarChartRoot in different potential locations echo "Checking for SidebarChartRoot in plane-web:" rg --type typescript "export.*SidebarChartRoot" web/plane-web/components/cycles echo "Checking for SidebarChartRoot in potential EE-specific locations:" rg --type typescript "export.*SidebarChartRoot" web/ee/components/cycles # Check for any conditional imports or EE-specific logic echo "Checking for EE-specific import logic:" rg --type typescript "import.*from.*ee.*cycles" web/core/components/cycles/analytics-sidebar/issue-progress.tsxThis script will help identify if there are separate implementations for different editions and if any EE-specific import logic is in place.
3-3
: Verify import changes and their impact.
The
Fragment
import has been added, but its usage is not visible in the provided code. Please ensure it's being used or remove it if unnecessary.The
useProjectEstimates
hook has been removed from the imports. Confirm that this removal is intentional and doesn't affect any functionality.The import of
SidebarChartRoot
from "@/plane-web/components/cycles" is new. Ensure that this component is compatible with the existing code and provides the necessary functionality.To verify the usage of
Fragment
and the removal ofuseProjectEstimates
, run the following script:Also applies to: 19-21
✅ Verification successful
Re-run the verification with corrected search patterns.
Re-run the verification with corrected search patterns.
Re-run the verification without specifying file types.
Remove unused
Fragment
import and confirm hook removal.
The
Fragment
import is present but not used in the component. Please remove it to clean up the code:import { FC, useCallback, useMemo } from "react";The
useProjectEstimates
hook has been successfully removed and no references are found, ensuring no unintended side effects.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check for Fragment usage echo "Checking for Fragment usage:" rg --type typescript "Fragment" web/core/components/cycles/analytics-sidebar/issue-progress.tsx # Check for any remaining useProjectEstimates references echo "Checking for useProjectEstimates references:" rg --type typescript "useProjectEstimates" web/core/components/cycles/analytics-sidebar/issue-progress.tsxLength of output: 700
Script:
#!/bin/bash # Check for Fragment usage echo "Checking for Fragment usage:" rg --type ts --type tsx "Fragment" web/core/components/cycles/analytics-sidebar/issue-progress.tsx # Check for any remaining useProjectEstimates references echo "Checking for useProjectEstimates references:" rg --type ts --type tsx "useProjectEstimates" web/core/components/cycles/analytics-sidebar/issue-progress.tsxLength of output: 430
Script:
#!/bin/bash # Check for Fragment usage echo "Checking for Fragment usage:" rg --type typescript --type tsx "Fragment" web/core/components/cycles/analytics-sidebar/issue-progress.tsx # Check for any remaining useProjectEstimates references echo "Checking for useProjectEstimates references:" rg --type typescript --type tsx "useProjectEstimates" web/core/components/cycles/analytics-sidebar/issue-progress.tsxLength of output: 460
Script:
#!/bin/bash # Check for Fragment usage echo "Checking for Fragment usage:" rg "Fragment" web/core/components/cycles/analytics-sidebar/issue-progress.tsx # Check for any remaining useProjectEstimates references echo "Checking for useProjectEstimates references:" rg "useProjectEstimates" web/core/components/cycles/analytics-sidebar/issue-progress.tsxLength of output: 392
web/ce/components/cycles/analytics-sidebar/base.tsx (2)
26-31
: EnsurecycleDetails
is valid before accessing its propertiesIf
validateCycleSnapshot
returnsundefined
, accessing properties likecycleDetails?.start_date
will result inundefined
. While this may not cause errors due to optional chaining, passingundefined
togetDate()
might not yield the expected results.Confirm that
getDate()
can handleundefined
inputs gracefully. Alternatively, add a check to ensurecycleDetails
is defined:+ if (!cycleDetails) return null; const cycleStartDate = getDate(cycleDetails?.start_date); const cycleEndDate = getDate(cycleDetails?.end_date);
1-69
: Overall code assessmentThe component is well-structured and follows best practices. The use of hooks and MobX observables ensures that the component reacts to state changes efficiently. The code is clean and readable.
{cycleStartDate && cycleEndDate && completionChartDistributionData ? ( | ||
<Fragment> | ||
<ProgressChart | ||
distribution={completionChartDistributionData} | ||
startDate={cycleStartDate} | ||
endDate={cycleEndDate} | ||
totalIssues={estimateType === "points" ? totalEstimatePoints : totalIssues} | ||
plotTitle={estimateType === "points" ? "points" : "issues"} | ||
/> | ||
</Fragment> | ||
) : ( | ||
<Loader className="w-full h-[160px] mt-4"> | ||
<Loader.Item width="100%" height="100%" /> | ||
</Loader> | ||
)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enhance error handling for missing data
If cycleStartDate
, cycleEndDate
, or completionChartDistributionData
are missing, the loader is displayed. However, there may be situations where data fetching fails, and the user is left waiting indefinitely.
Consider adding error handling to inform the user if data cannot be loaded:
{cycleStartDate && cycleEndDate && completionChartDistributionData ? (
// existing code
) : hasError ? (
<div className="text-center text-sm text-red-500">Failed to load data.</div>
) : (
<Loader className="w-full h-[160px] mt-4">
<Loader.Item width="100%" height="100%" />
</Loader>
)}
You'll need to implement hasError
based on your data fetching logic.
const chartDistributionData = | ||
estimateType === "points" ? cycleDetails?.estimate_distribution : cycleDetails?.distribution || undefined; | ||
|
||
const completionChartDistributionData = chartDistributionData?.completion_chart || undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove unnecessary || undefined
Similarly, the || undefined
in completionChartDistributionData
is unnecessary because if chartDistributionData?.completion_chart
doesn't exist, it will already be undefined
.
Simplify the code as:
- const completionChartDistributionData = chartDistributionData?.completion_chart || undefined;
+ const completionChartDistributionData = chartDistributionData?.completion_chart;
📝 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.
const completionChartDistributionData = chartDistributionData?.completion_chart || undefined; | |
const completionChartDistributionData = chartDistributionData?.completion_chart; |
distribution={completionChartDistributionData} | ||
startDate={cycleStartDate} | ||
endDate={cycleEndDate} | ||
totalIssues={estimateType === "points" ? totalEstimatePoints : totalIssues} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider renaming totalIssues
prop for clarity
When estimateType
is "points"
, you're passing totalEstimatePoints
to a prop named totalIssues
, which might be confusing.
Consider renaming the prop to better reflect its purpose, such as totalCount
:
- totalIssues={estimateType === "points" ? totalEstimatePoints : totalIssues}
+ totalCount={estimateType === "points" ? totalEstimatePoints : totalIssues}
You'll also need to update the ProgressChart
component to accept totalCount
instead of totalIssues
.
Committable suggestion was skipped due to low confidence.
const chartDistributionData = | ||
estimateType === "points" ? cycleDetails?.estimate_distribution : cycleDetails?.distribution || undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Simplify 'chartDistributionData' assignment
The use of || undefined
is redundant since cycleDetails?.distribution
will return undefined
if it doesn't exist.
Consider simplifying the code as follows:
- const chartDistributionData =
- estimateType === "points" ? cycleDetails?.estimate_distribution : cycleDetails?.distribution || undefined;
+ const chartDistributionData =
+ estimateType === "points" ? cycleDetails?.estimate_distribution : cycleDetails?.distribution;
📝 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.
const chartDistributionData = | |
estimateType === "points" ? cycleDetails?.estimate_distribution : cycleDetails?.distribution || undefined; | |
const chartDistributionData = | |
estimateType === "points" ? cycleDetails?.estimate_distribution : cycleDetails?.distribution; |
Summary
Cycle sidebar code refactoring
[WEB-2380]
Summary by CodeRabbit
New Features
SidebarChart
component for visualizing progress data.SidebarChartRoot
component to wrap the chart functionality.CycleAnalyticsProgress
component.Improvements
CycleSidebarHeader
component to prevent potential errors.These updates enhance user experience by providing clearer visualizations and more robust functionality.