Skip to content

Use the new Managed Export CSV Button#4075

Open
khouadrired wants to merge 4 commits into
mainfrom
refactor-exportcsv-button
Open

Use the new Managed Export CSV Button#4075
khouadrired wants to merge 4 commits into
mainfrom
refactor-exportcsv-button

Conversation

@khouadrired

Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a resetKey mechanism to CSV export components across the app, threading an exportCsvResetKey (typed Key) through Voltage Init, Load Flow, and State Estimation result views into a shared RenderTableAndExportCsv/CsvExport utility. Separately, it replaces bespoke export button components (PCC-Min, Security Analysis, Sensitivity Analysis, Short Circuit) with a shared ManagedExportCsvButton, each wired to feature-specific exportCsv callbacks and snackbar-based error handling.

Changes

CSV Export Reset Key and Managed Export Button

Layer / File(s) Summary
Shared CSV export utility and type contracts
src/components/utils/renderTable-ExportCsv.tsx, src/components/results/loadflow/load-flow-result.type.ts, src/components/results/stateestimation/state-estimation-result.type.ts, src/components/voltage-init-result.type.ts
RenderTableAndExportCsv gains an optional exportCsvResetKey prop forwarded to CsvExport's resetKey, inverts its disabled condition, and related type interfaces add a Key-typed exportCsvResetKey field.
Voltage Init result reset key wiring
src/components/dialogs/network-modifications/voltage-init-modification/voltage-init-modification-dialog.tsx, src/components/graph/menus/network-modifications/network-modification-node-editor.tsx, src/components/voltage-init-result.tsx, src/components/voltage-init-result-tab.tsx
exportCsvResetKey (derived from studyUuid/nodeId/currentRootNetworkUuid) is threaded through the modification dialog and result tables.
Load Flow result reset key wiring
src/components/results/loadflow/limit-violation-result.tsx, src/components/results/loadflow/load-flow-result.tsx, src/components/results/loadflow/load-flow-result-tab.tsx
exportCsvResetKey is computed per tab and forwarded into limit-violation and load-flow table export calls.
State Estimation result reset key wiring
src/components/results/stateestimation/state-estimation-quality-result.tsx, src/components/results/stateestimation/state-estimation-result-tab.tsx
exportCsvResetKey is passed into StateEstimationQualityResult for Quality Criterion and Quality Per Region tabs.
PCC-Min export refactor
src/components/results/pccmin/pcc-min-result.tsx, src/components/results/pccmin/pcc-min-export-button.tsx (removed)
PccMinExportButton is removed and replaced by ManagedExportCsvButton with a resetKey, an exportCsv callback calling exportPccMinResultsAsCsv, and error handling via snackWithFallback.
Security Analysis export refactor
src/components/results/securityanalysis/security-analysis-result-tab.tsx, src/components/results/securityanalysis/security-analysis-export-button.tsx (removed)
SecurityAnalysisExportButton is removed; ManagedExportCsvButton is wired with localized enum translations, a resetKey, exportResultCsv, and handleExportError.
Sensitivity Analysis export refactor
src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.tsx, src/components/results/sensitivity-analysis/sensitivity-analysis-export-button.tsx (removed)
SensitivityExportButton is removed; ManagedExportCsvButton is wired with a resetKey, an exportCsv callback remapping filters/sort for N vs NK, and error handling.
Short Circuit export refactor
src/components/results/shortcircuit/shortcircuit-analysis-result-tab.tsx, src/components/results/shortcircuit/shortcircuit-analysis-export-button.tsx (removed)
ShortCircuitExportButton is removed; ManagedExportCsvButton is wired with localized enum translations, a resetKey, an exportCsv callback calling downloadShortCircuitResultZippedCsv, and error handling.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ResultTab as Feature Result Tab
    participant ManagedButton as ManagedExportCsvButton
    participant ExportCallback as exportCsv Callback
    participant Service as Export Service (e.g. exportSensitivityResultsAsCsv)
    participant Snackbar as Snackbar (snackWithFallback)

    User->>ManagedButton: click export
    ManagedButton->>ExportCallback: invoke exportCsv()
    ExportCallback->>Service: request CSV/ZIP with filters, sort, language
    alt success
        Service-->>ExportCallback: return blob
        ExportCallback->>User: download ZIP file
    else failure
        Service-->>ExportCallback: throw error
        ExportCallback->>Snackbar: handleExportError(error)
        Snackbar-->>User: show error message
    end
Loading

Suggested reviewers: dbraquart, klesaulnier

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive No pull request description was provided, so there is nothing to assess beyond the code changes. Add a short description summarizing the export-button refactor and the affected result tabs/components.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: replacing export flows with the new Managed Export CSV Button.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@khouadrired khouadrired force-pushed the refactor-exportcsv-button branch from ca75d9b to 763051a Compare July 2, 2026 15:57

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/components/dialogs/network-modifications/voltage-init-modification/voltage-init-modification-dialog.tsx (1)

546-554: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Build fails: CsvExport doesn't accept resetKey.

CI reports a TS error at Line 553: resetKey: Key isn't assignable to CsvDownloadProps & { disabled: boolean }. CsvExport's prop type needs to be updated to accept resetKey before this compiles.

🐛 Likely fix (in CsvExport's own definition file, not included in this batch)
 interface CsvDownloadProps {
   columns: any[];
   tableName: string;
+  resetKey?: Key;
   ...
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/components/dialogs/network-modifications/voltage-init-modification/voltage-init-modification-dialog.tsx`
around lines 546 - 554, The build error comes from passing resetKey to CsvExport
even though its prop type does not include it. Update CsvExport’s definition and
props type (the component’s own declaration, likely CsvDownloadProps /
CsvExport) to accept a resetKey prop, and ensure the implementation forwards or
uses it consistently so the voltage-init-modification-dialog.tsx usage compiles
without a TS mismatch.

Source: Pipeline failures

src/components/voltage-init-result.tsx (1)

281-297: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Flip the CSV disable condition In src/components/utils/renderTable-ExportCsv.tsx, disabled={!isRowsEmpty} disables export when rows are present and enables it when the table is empty. That blocks CSV export for the Indicators, ReactiveSlacks, and BusVoltages tables; use disabled={isRowsEmpty} instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/voltage-init-result.tsx` around lines 281 - 297, The CSV
export disable logic in RenderTableAndExportCsv is inverted, which prevents
exporting the Indicators, ReactiveSlacks, and BusVoltages tables when data
exists. Update the disabled condition in the RenderTableAndExportCsv component
so it uses the empty-state check directly, and verify the callers in
voltage-init-result.tsx still pass rows correctly for the affected tables.
🧹 Nitpick comments (2)
src/components/results/shortcircuit/shortcircuit-analysis-result-tab.tsx (1)

186-210: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid (window as any).intl; use the useIntl hook and correct memo deps.

Reading intl off window is fragile (relies on a global set elsewhere and defeats type safety), and the useMemo([]) captures the formatter once, so translations won't recompute if the locale/language changes. The component already uses react-intl, so prefer the hook.

♻️ Proposed refactor using useIntl
+    const intl = useIntl();
+
     const enumValueTranslations = useMemo(() => {
         const returnedValue: Record<string, string> = {};
         const enumValuesToTranslate = [
             'THREE_PHASE',
             ...
             'OTHER',
         ];

         enumValuesToTranslate.forEach((value) => {
-            returnedValue[value] = (window as any).intl?.formatMessage
-                ? (window as any).intl.formatMessage({ id: value })
-                : value;
+            returnedValue[value] = intl.formatMessage({ id: value });
         });

         return returnedValue;
-    }, []);
+    }, [intl]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/results/shortcircuit/shortcircuit-analysis-result-tab.tsx`
around lines 186 - 210, The enumValueTranslations memo in
shortcircuit-analysis-result-tab.tsx should stop reading from window and instead
use the useIntl hook already supported by react-intl. Replace the (window as
any).intl formatting logic with the intl formatter from the hook, and update the
useMemo dependency list so translations recompute when the formatter or locale
changes. Keep the mapping in enumValueTranslations and the enumValuesToTranslate
list, but ensure the memo is tied to intl rather than initialized once with an
empty dependency array.
src/components/graph/menus/network-modifications/network-modification-node-editor.tsx (1)

232-246: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor: exportCsvResetKey passed to all withDefaultParams dialogs, not just Voltage Init.

withDefaultParams fans this prop out to every generic modification dialog even though only VoltageInitModificationDialog uses it. Harmless today given the React.FC<any> typing, but consider scoping it to just that dialog invocation for clarity.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/components/graph/menus/network-modifications/network-modification-node-editor.tsx`
around lines 232 - 246, `withDefaultParams` is forwarding `exportCsvResetKey` to
every generic modification dialog even though only
`VoltageInitModificationDialog` needs it. Update the helper in
`network-modification-node-editor` so it only passes shared props, and move
`exportCsvResetKey` to the specific `VoltageInitModificationDialog` invocation
(or conditionally add it there) to keep the prop scoped to the one dialog that
uses it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/results/pccmin/pcc-min-result.tsx`:
- Line 14: The import in pcc-min-result.tsx is using ManagedExportCsvButton, but
that symbol is not exported by the current `@gridsuite/commons-ui` version. Update
the results component to use the CSV button symbol that is actually exported
from the package, or adjust the package version if this component must keep
ManagedExportCsvButton; locate the fix in the import list for the pcc-min result
component.

In `@src/components/utils/renderTable-ExportCsv.tsx`:
- Line 86: The CSV export button in renderTable-ExportCsv.tsx has its disabled
logic inverted, causing the shared export control to be disabled when rows exist
and enabled when the table is empty. Update the button’s disabled prop in the
export component to match the intended empty-state check by using the existing
isRowsEmpty condition directly, and verify the shared component behavior still
enables export for populated tables like Voltage Init, Load Flow, and State
Estimation.

---

Outside diff comments:
In
`@src/components/dialogs/network-modifications/voltage-init-modification/voltage-init-modification-dialog.tsx`:
- Around line 546-554: The build error comes from passing resetKey to CsvExport
even though its prop type does not include it. Update CsvExport’s definition and
props type (the component’s own declaration, likely CsvDownloadProps /
CsvExport) to accept a resetKey prop, and ensure the implementation forwards or
uses it consistently so the voltage-init-modification-dialog.tsx usage compiles
without a TS mismatch.

In `@src/components/voltage-init-result.tsx`:
- Around line 281-297: The CSV export disable logic in RenderTableAndExportCsv
is inverted, which prevents exporting the Indicators, ReactiveSlacks, and
BusVoltages tables when data exists. Update the disabled condition in the
RenderTableAndExportCsv component so it uses the empty-state check directly, and
verify the callers in voltage-init-result.tsx still pass rows correctly for the
affected tables.

---

Nitpick comments:
In
`@src/components/graph/menus/network-modifications/network-modification-node-editor.tsx`:
- Around line 232-246: `withDefaultParams` is forwarding `exportCsvResetKey` to
every generic modification dialog even though only
`VoltageInitModificationDialog` needs it. Update the helper in
`network-modification-node-editor` so it only passes shared props, and move
`exportCsvResetKey` to the specific `VoltageInitModificationDialog` invocation
(or conditionally add it there) to keep the prop scoped to the one dialog that
uses it.

In `@src/components/results/shortcircuit/shortcircuit-analysis-result-tab.tsx`:
- Around line 186-210: The enumValueTranslations memo in
shortcircuit-analysis-result-tab.tsx should stop reading from window and instead
use the useIntl hook already supported by react-intl. Replace the (window as
any).intl formatting logic with the intl formatter from the hook, and update the
useMemo dependency list so translations recompute when the formatter or locale
changes. Keep the mapping in enumValueTranslations and the enumValuesToTranslate
list, but ensure the memo is tied to intl rather than initialized once with an
empty dependency array.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7a7763e1-9b38-4004-93ba-8206f1432b82

📥 Commits

Reviewing files that changed from the base of the PR and between 766bafa and 000acda.

📒 Files selected for processing (21)
  • src/components/dialogs/network-modifications/voltage-init-modification/voltage-init-modification-dialog.tsx
  • src/components/graph/menus/network-modifications/network-modification-node-editor.tsx
  • src/components/results/loadflow/limit-violation-result.tsx
  • src/components/results/loadflow/load-flow-result-tab.tsx
  • src/components/results/loadflow/load-flow-result.tsx
  • src/components/results/loadflow/load-flow-result.type.ts
  • src/components/results/pccmin/pcc-min-export-button.tsx
  • src/components/results/pccmin/pcc-min-result.tsx
  • src/components/results/securityanalysis/security-analysis-export-button.tsx
  • src/components/results/securityanalysis/security-analysis-result-tab.tsx
  • src/components/results/sensitivity-analysis/sensitivity-analysis-export-button.tsx
  • src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.tsx
  • src/components/results/shortcircuit/shortcircuit-analysis-export-button.tsx
  • src/components/results/shortcircuit/shortcircuit-analysis-result-tab.tsx
  • src/components/results/stateestimation/state-estimation-quality-result.tsx
  • src/components/results/stateestimation/state-estimation-result-tab.tsx
  • src/components/results/stateestimation/state-estimation-result.type.ts
  • src/components/utils/renderTable-ExportCsv.tsx
  • src/components/voltage-init-result-tab.tsx
  • src/components/voltage-init-result.tsx
  • src/components/voltage-init-result.type.ts
💤 Files with no reviewable changes (4)
  • src/components/results/pccmin/pcc-min-export-button.tsx
  • src/components/results/shortcircuit/shortcircuit-analysis-export-button.tsx
  • src/components/results/securityanalysis/security-analysis-export-button.tsx
  • src/components/results/sensitivity-analysis/sensitivity-analysis-export-button.tsx

import {
ComputingType,
CustomTablePagination,
ManagedExportCsvButton,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm declared commons-ui version and whether ManagedExportCsvButton is exported.
fd -H -t f 'package.json' -d 2 --exec sh -c 'echo "== {} =="; jq -r ".dependencies[\"`@gridsuite/commons-ui`\"] // .devDependencies[\"`@gridsuite/commons-ui`\"] // empty" "{}"'

# If a lockfile is present, show the resolved version.
fd -H -t f 'package-lock.json|yarn.lock|pnpm-lock.yaml' -d 2

# Look for the export anywhere the package types are declared (best-effort, node_modules may be absent in sandbox).
rg -n 'ManagedExportCsvButton' -g '!**/node_modules/**' || echo "no local references found outside node_modules"

Repository: gridsuite/gridstudy-app

Length of output: 255


🌐 Web query:

@gridsuite/commons-ui 0.240.0 ManagedExportCsvButton exported

💡 Result:

There is no public evidence or documentation confirming that a component named ManagedExportCsvButton exists or is exported within the @gridsuite/commons-ui library [1][2][3]. The @gridsuite/commons-ui library is a private or internal component library used by GridSuite applications [1]. While developers have occasionally encountered issues with missing exports in this package (such as CsvPicker or getCsvDelimiter) [4], there are no references to a ManagedExportCsvButton in the library's public repository or related development logs [1][4][5]. If you are encountering a build error related to this component, it is likely that the import path is incorrect, the component does not exist in your specific version of the library, or it is a custom component internal to a different project [4]. You may wish to verify your import statements against the actual exports of the package installed in your node_modules directory [2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file excerpt =="
cat -n src/components/results/pccmin/pcc-min-result.tsx | sed -n '1,40p'

echo
echo "== package.json dependency =="
jq -r '.dependencies["`@gridsuite/commons-ui`"] // .devDependencies["`@gridsuite/commons-ui`"] // empty' package.json

echo
echo "== lockfile references =="
if [ -f package-lock.json ]; then
  rg -n '"`@gridsuite/commons-ui`"|ManagedExportCsvButton' package-lock.json
fi

Repository: gridsuite/gridstudy-app

Length of output: 2554


Replace ManagedExportCsvButton
@gridsuite/commons-ui@0.240.0 does not expose this symbol, so the import will fail type-checking. Use the exported CSV button name or bump @gridsuite/commons-ui to a version that includes ManagedExportCsvButton.

🧰 Tools
🪛 GitHub Check: build / build

[failure] 14-14:
'"@gridsuite/commons-ui"' has no exported member named 'ManagedExportCsvButton'. Did you mean 'ExportCsvButton'?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/results/pccmin/pcc-min-result.tsx` at line 14, The import in
pcc-min-result.tsx is using ManagedExportCsvButton, but that symbol is not
exported by the current `@gridsuite/commons-ui` version. Update the results
component to use the CSV button symbol that is actually exported from the
package, or adjust the package version if this component must keep
ManagedExportCsvButton; locate the fix in the import list for the pcc-min result
component.

Sources: Linters/SAST tools, Pipeline failures

columns={columns}
tableName={tableName}
disabled={isRowsEmpty}
disabled={!isRowsEmpty}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

disabled condition appears inverted — button disables when data exists.

isRowsEmpty is true only when there are no rows. disabled={!isRowsEmpty} therefore disables the export button when rows ARE present, and enables it when the table is empty — the opposite of the intended behavior (and of the prior disabled={isRowsEmpty}). This would break CSV export for every table using this shared component (Voltage Init, Load Flow, State Estimation).

🐛 Proposed fix
-                    disabled={!isRowsEmpty}
+                    disabled={isRowsEmpty}
📝 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
disabled={!isRowsEmpty}
disabled={isRowsEmpty}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/utils/renderTable-ExportCsv.tsx` at line 86, The CSV export
button in renderTable-ExportCsv.tsx has its disabled logic inverted, causing the
shared export control to be disabled when rows exist and enabled when the table
is empty. Update the button’s disabled prop in the export component to match the
intended empty-state check by using the existing isRowsEmpty condition directly,
and verify the shared component behavior still enables export for populated
tables like Voltage Init, Load Flow, and State Estimation.

columns={columns}
tableName={tableName}
disabled={isRowsEmpty}
disabled={!isRowsEmpty}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why this change ?
Export button is now disabled if there are results available in loadflow, voltage init and state estimation

const fileBlob = await downloadZipResult(
studyUuid as UUID,
nodeUuid as UUID,
currentRootNetworkUuid as UUID,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These casts are useless ...

const csvHeaders = useMemo(() => columnDefs.map((cDef) => cDef.headerName ?? ''), [columnDefs]);

const language = useSelector((state: AppState) => state[PARAM_COMPUTED_LANGUAGE]);
const appTabIndex = useSelector((state: AppState) => state.appTabIndex);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Don't see when this redux value appTabIndex is set ...

}, []);

const language = useSelector((state: AppState) => state[PARAM_COMPUTED_LANGUAGE]);
const appTabIndex = useSelector((state: AppState) => state.appTabIndex);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Don't see when this redux value appTabIndex is set ...

}, [sensiTab]);

const language = useSelector((state: AppState) => state[PARAM_COMPUTED_LANGUAGE]);
const appTabIndex = useSelector((state: AppState) => state.appTabIndex);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Don't see when this redux value appTabIndex is set ...

csvHeaders={csvHeaders}
nOrNkIndex={nOrNkIndex}
sensiKind={sensiTab}
<ManagedExportCsvButton

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

csv headers are not properly translated anymore (sometimes in english when it should be french, and sometimes in french when it should be in english)

But fields separators are ok in the exported csv

nodeUuid={nodeUuid}
currentRootNetworkUuid={currentRootNetworkUuid}
csvHeaders={csvHeaders}
<ManagedExportCsvButton

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

csv headers are not properly translated anymore (sometimes in english when it should be french, and sometimes in french when it should be in english)

But fields separators are ok in the exported csv

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.

2 participants