Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formula screens rework, cascading changes on formula deletion #1682

Merged
merged 2 commits into from
Oct 27, 2024

Conversation

nipunarora-eGov
Copy link
Contributor

@nipunarora-eGov nipunarora-eGov commented Oct 27, 2024

Choose the appropriate template for your PR:

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced formula configuration with improved validation checks for required fields.
    • Dynamic popup for facility assignments introduced, improving user interaction.
    • Updated handling of assumptions and formula deletions for better state management.
  • Bug Fixes

    • Resolved issues with state initialization and data retrieval from session storage.
  • Chores

    • Cleaned up unused code and improved overall code organization for better readability.

@nipunarora-eGov nipunarora-eGov requested a review from a team as a code owner October 27, 2024 15:50
Copy link
Contributor

coderabbitai bot commented Oct 27, 2024

📝 Walkthrough

Walkthrough

The pull request introduces significant modifications across several components, primarily focusing on the FormulaConfigWrapper, FormulaConfiguration, HypothesisWrapper, UICustomizations, and createUpdatePlanProject. Key changes include the source of data retrieval for configurations and assumptions, enhanced validation for user inputs, and improved management of state and component interactions. Context management is introduced, and various functions are updated to streamline logic and enhance clarity. The changes collectively aim to improve the handling of formula configurations, assumptions, and user interactions within the application.

Changes

File Change Summary
.../FormulaConfigWrapper.js - Updated source of formulaConfigValues to use session storage.
- Modified handleNext to include validation checks.
- Removed unused code and updated context provider.
.../FormulaConfiguration.js - Updated context to use assumptionsInPlan.
- Enhanced handleDeleteClick to accept a formula parameter.
- Improved handling of formula deletion logic.
.../HypothesisWrapper.js - Changed initialization of assumptionValues to use session storage.
- Retained existing logic for handling assumption changes.
.../UICustomizations.js - Introduced showPopup for managing popup visibility.
- Updated button logic in FacilityMappingConfig and UserManagementConfig for dynamic behavior.
.../createUpdatePlanProject.js - Restructured function for better handling of campaignObject and planObject.
- Enhanced error handling and expanded switch-case logic for various operations.

Possibly related PRs

  • Mp hypothesis #1501: Changes in the Hypothesis.js component regarding assumptions management may interact with FormulaConfigWrapper.
  • Formula Screen #1599: Modifications in FormulaConfigWrapper.js are directly related to changes in FormulaConfiguration.js, both dealing with formula configurations.
  • Added action bar for pop inbox screen #1622: Updates in PopInbox.js regarding user roles may affect functionalities in FormulaConfigWrapper and FormulaConfiguration.
  • Summary-screen changes and localization #1672: Changes in UICustomizations.js that enhance search configurations could impact interactions in FormulaConfigWrapper and FormulaConfiguration.
  • Adhoc user #1675: Modifications in UICustomizations.js that improve validation may influence behavior in FormulaConfigWrapper and FormulaConfiguration.

🐰 In the land of code where rabbits hop,
New changes sprout, they never stop!
From formulas to popups, all is bright,
With validations in place, we code through the night.
So here’s to the tweaks, both big and small,
In the garden of logic, we celebrate them all! 🌼


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.

coderabbitai[bot]
coderabbitai bot previously requested changes Oct 27, 2024
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: 19

🧹 Outside diff range comments (7)
health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/HypothesisWrapper.js (5)

Line range hint 191-196: Potential memory leak in useEffect cleanup.

The effect hook adds event listeners but the cleanup function doesn't remove them with the same parameters.

 useEffect(() => {
     window.addEventListener("verticalStepper", moveToPreviousStep);
     return () => {
-      window.removeEventListener("verticalStepper", moveToPreviousStep);
+      window.removeEventListener("verticalStepper", moveToPreviousStep, { capture: false });
     };
   }, [internalKey]);

Line range hint 216-223: Remove unbounded execution count effect.

The useEffect without dependencies will run on every render and has a manual counter to limit executions. This is an anti-pattern.

-useEffect(() => {
-    if (executionCount < 5) {
-        onSelect(customProps.name, {assumptionValues})
-        setExecutionCount((prevCount) => prevCount + 1);
-    }
-  }); 
+useEffect(() => {
+    onSelect(customProps.name, {assumptionValues});
+}, [customProps.name, assumptionValues]);

Line range hint 238-255: Optimize assumption initialization logic.

The current implementation may cause unnecessary re-renders due to state updates in useEffect.

 useEffect(() => {
-    const initialAssumptions = filteredAssumptions.map(item => ({
-        source: "MDMS",
-        category: null,
-        key: item,
-        value: null
-    }));
-
-    // Create a set of existing keys for quick lookup
-    const existingKeys = new Set(assumptionValues.map(assumption => assumption.key));
-
-    // Filter out initialAssumptions to avoid duplicates and deleted assumptions
-    const newAssumptions = initialAssumptions.filter(assumption => 
-        !existingKeys.has(assumption.key) &&
-        !deletedAssumptions.includes(assumption.key)
-    );
-
-    // Update state only with non-duplicate assumptions
-    setAssumptionValues(prev => [...prev, ...newAssumptions]);
+    const existingKeys = new Set(assumptionValues.map(assumption => assumption.key));
+    const deletedKeys = new Set(deletedAssumptions);
+    
+    const newAssumptions = filteredAssumptions.reduce((acc, item) => {
+        if (!existingKeys.has(item) && !deletedKeys.has(item)) {
+            acc.push({
+                source: "MDMS",
+                category: null,
+                key: item,
+                value: null
+            });
+        }
+        return acc;
+    }, []);
+    
+    if (newAssumptions.length > 0) {
+        setAssumptionValues(prev => [...prev, ...newAssumptions]);
+    }
 }, [filteredAssumptions]);

Line range hint 84-117: Improve error handling in API call.

The error handling in the updateResources API call is incomplete. Errors are only logged to console without proper user feedback.

 updateResources({
     config:{
         name:"SUB_HYPOTHESIS"
     },
     assumptionsToUpdate
 },{
     onSuccess: (data) => {
         if (internalKey < assumptionCategories.length) {
             setInternalKey((prevKey) => prevKey + 1);
         }
         refetchPlan();
+        setShowToast({
+            key: "success",
+            label: t("ASSUMPTIONS_UPDATED_SUCCESSFULLY"),
+            transitionTime: 3000
+        });
     },
     onError: (error, variables) => {
         console.error(error)
-        //   setShowToast(({ key: "error", label: error?.message ? error.message : t("FAILED_TO_UPDATE_RESOURCE") }))
+        setShowToast({
+            key: "error",
+            label: error?.message || t("FAILED_TO_UPDATE_RESOURCE"),
+            transitionTime: 3000
+        });
     },
 })

Line range hint 269-307: Improve accessibility in component structure.

The component's UI structure needs accessibility improvements:

  1. Missing ARIA labels
  2. No keyboard navigation support for stepper
 <div style={{ display: "flex",gap:"2rem" }}>
-    <div className="card-container">
+    <div className="card-container" role="complementary" aria-label={t("ASSUMPTIONS_NAVIGATION")}>
         <Card className="card-header-timeline">
-            <TextBlock subHeader={t("ESTIMATION_ASSUMPTIONS")} subHeaderClassName={"stepper-subheader"} wrapperClassName={"stepper-wrapper"} />
+            <TextBlock 
+                subHeader={t("ESTIMATION_ASSUMPTIONS")} 
+                subHeaderClassName={"stepper-subheader"} 
+                wrapperClassName={"stepper-wrapper"}
+                role="heading"
+                aria-level="2"
+            />
         </Card>
         <Card className="stepper-card">
             <Stepper
                 customSteps={assumptionCategories.map(category => category.category)}
                 currentStep={internalKey}
-                onStepClick={() => null}
+                onStepClick={handleStepClick}
                 direction={"vertical"}
+                aria-label={t("ASSUMPTIONS_STEPPER")}
             />
         </Card>
     </div>
health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/configs/UICustomizations.js (2)

Line range hint 503-524: Enhance popup handling for better UX and memory management.

While the popup implementation is good, consider these improvements:

  1. Add cleanup for any async operations when the popup closes
  2. Add loading state during async operations
  3. Consider using a portal for better modal rendering

Here's a suggested implementation:

 return (
   <>
     <ButtonNew
       className=""
       icon="ArrowForward"
       iconFill=""
       isSuffix
       label={t("MICROPLAN_ASSIGN")}
       onClick={() => setShowPopup(true)}
       options={[]}
       optionsKey=""
       size="medium"
       style={{}}
       title=""
       variation="secondary"
     />
     {showPopup && (
+      <Portal>
         <FacilityPopUp
           details={row}
+          isLoading={false} // Add loading state
           onClose={() => {
+            // Cleanup any subscriptions/async operations here
             setShowPopup(false);
           }}
         />
+      </Portal>
     )}
   </>
 );

Line range hint 1-524: Refactor common patterns into reusable utilities.

There's duplicate code for handling NA values and text wrapping styles across different configurations. Consider extracting these into reusable utilities.

Create utility functions:

// utils.js
export const renderWithWordWrap = (value, t) => {
  if (value && value !== "NA") {
    return (
      <div
        style={{
          maxWidth: "15rem",
          wordWrap: "break-word",
          whiteSpace: "normal",
          overflowWrap: "break-word",
        }}
      >
        <p>{t(value)}</p>
      </div>
    );
  }
  return (
    <div>
      <p>{t("ES_COMMON_NA")}</p>
    </div>
  );
};

Then use it in configurations:

- if (value && value !== "NA") {
-   return (
-     <div
-       style={{
-         maxWidth: "15rem",
-         wordWrap: "break-word",
-         whiteSpace: "normal",
-         overflowWrap: "break-word",
-       }}
-     >
-       <p>{t(value)}</p>
-     </div>
-   );
- } else {
-   return (
-     <div>
-       <p>{t("ES_COMMON_NA")}</p>
-     </div>
-   );
- }
+ return renderWithWordWrap(value, t);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 3953563 and 31f7af8.

📒 Files selected for processing (5)
  • health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/FormulaConfigWrapper.js (6 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/FormulaConfiguration.js (9 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/HypothesisWrapper.js (1 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/configs/UICustomizations.js (2 hunks)
  • health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/hooks/services/createUpdatePlanProject.js (9 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/FormulaConfigWrapper.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/FormulaConfiguration.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/HypothesisWrapper.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/configs/UICustomizations.js (1)

Pattern **/*.js: check

health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/hooks/services/createUpdatePlanProject.js (1)

Pattern **/*.js: check

🪛 Biome
health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/hooks/services/createUpdatePlanProject.js

[error] 230-235: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 237-237: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 257-262: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 264-275: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 277-277: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 400-409: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 432-437: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 440-446: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 447-457: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 454-454: Avoid the delete operator which can impact performance.

(lint/performance/noDelete)


[error] 459-462: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 464-464: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 584-584: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (4)
health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/HypothesisWrapper.js (1)

20-20: 🧹 Nitpick (assertive)

Verify data persistence across page reloads.

The change from customProps?.sessionData to Digit.SessionStorage.get("MICROPLAN_DATA") could lead to data loss if session storage is cleared or expires. Consider implementing a fallback mechanism.

Consider implementing a more robust state management solution:

  1. Use Redux/Context for global state management
  2. Implement data persistence strategy (localStorage backup)
  3. Add error boundaries for handling storage-related failures
health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/components/FormulaConfigWrapper.js (1)

18-20: 🧹 Nitpick (assertive)

Consider adding a fallback mechanism for session storage

While using SessionStorage centralizes data management, consider adding a fallback mechanism in case the session storage is cleared or corrupted.

 const [formulaConfigValues, setFormulaConfigValues] = useState(
-    Digit.SessionStorage.get("MICROPLAN_DATA")?.FORMULA_CONFIGURATION?.formulaConfiguration?.formulaConfigValues || []
+    Digit.SessionStorage.get("MICROPLAN_DATA")?.FORMULA_CONFIGURATION?.formulaConfiguration?.formulaConfigValues || customProps?.formulaConfigValues || []
 );
health/micro-ui/web/micro-ui-internals/packages/modules/microplan/src/hooks/services/createUpdatePlanProject.js (2)

423-430: ⚠️ Potential issue

Wrap 'case' clause in a block to prevent variable leakage

Variables such as fetchedPlanForFormula declared within this case clause can be accessed by other clauses. Enclosing this case in braces {} ensures variables are scoped correctly.

Apply this diff:

        case "FORMULA_CONFIGURATION": {
          if (
            !totalFormData?.FORMULA_CONFIGURATION?.formulaConfiguration?.formulaConfigValues.every(
              (row) => row.category && row.output && row.input && row.operatorName && row.assumptionValue
            )
          ) {
            setShowToast({ key: "error", label: "ERR_FORMULA_MANDATORY" });
            return;
          }
          // rest of the code...
        }

Likely invalid or redundant comment.


165-186: 🛠️ Refactor suggestion

Simplify conditional assignment of planObject and campaignObject

Instead of initializing planObject and campaignObject as empty objects and then reassigning them, consider declaring them within the conditional blocks where they are assigned. This improves readability and prevents unintended side effects.

Apply this diff:

-       let planObject = {};
-       let campaignObject = {};
        if (microplanId) {
+         const planObject = await searchPlanConfig({
            PlanConfigurationSearchCriteria: {
              tenantId,
              id: microplanId,
            },
          });
        }
        if (campaignId) {
+         const campaignObject = await searchCampaignConfig({
            CampaignDetails: {
              tenantId: tenantId,
              ids: [campaignId],
            },
          });
        }

Likely invalid or redundant comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants