diff --git a/src/components/results/securityanalysis/security-analysis-export-button.tsx b/src/components/results/securityanalysis/security-analysis-export-button.tsx index 85b73fb7f6..c75a2284b1 100644 --- a/src/components/results/securityanalysis/security-analysis-export-button.tsx +++ b/src/components/results/securityanalysis/security-analysis-export-button.tsx @@ -34,12 +34,13 @@ export const SecurityAnalysisExportButton: FunctionComponent state[PARAM_LANGUAGE]); + const appTabIndex = useSelector((state: AppState) => state.appTabIndex); const intl = useIntl(); useEffect(() => { setIsCsvExportSuccessful(false); - }, [nodeUuid, resultType]); + }, [studyUuid, nodeUuid, rootNetworkUuid, resultType, appTabIndex]); useEffect(() => { if (disabled) { diff --git a/src/components/results/sensitivity-analysis/sensitivity-analysis-export-button.tsx b/src/components/results/sensitivity-analysis/sensitivity-analysis-export-button.tsx new file mode 100644 index 0000000000..931b5aa5b3 --- /dev/null +++ b/src/components/results/sensitivity-analysis/sensitivity-analysis-export-button.tsx @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +import { FunctionComponent, useCallback, useEffect, useState } from 'react'; +import { ExportButton } from '../../utils/export-button'; +import { PARAM_LANGUAGE, useSnackMessage } from '@gridsuite/commons-ui'; +import { downloadZipFile } from '../../../services/utils'; +import { UUID } from 'crypto'; +import { AppState } from 'redux/reducer'; +import { useSelector } from 'react-redux'; +import { useFilterSelector } from 'hooks/use-filter-selector'; +import { + DATA_KEY_TO_FILTER_KEY_N, + DATA_KEY_TO_FILTER_KEY_NK, + DATA_KEY_TO_SORT_KEY, + FUNCTION_TYPES, + isSensiKind, + mappingTabs, + SensitivityResultTabs, +} from './sensitivity-analysis-result-utils'; +import { exportSensitivityResultsAsCsv } from 'services/study/sensitivity-analysis'; +import { SensiKind } from './sensitivity-analysis-result.type'; +import { FilterType as AgGridFilterType, SortWay } from '../../../types/custom-aggrid-types'; +import { SENSITIVITY_ANALYSIS_RESULT_SORT_STORE } from 'utils/store-sort-filter-fields'; +import { GlobalFilters } from '../common/global-filter/global-filter-types'; + +interface SensitivityExportButtonProps { + studyUuid: UUID; + nodeUuid: UUID; + currentRootNetworkUuid: UUID; + csvHeaders: string[]; + nOrNkIndex: number; + sensiKind: SensiKind; + globalFilters?: GlobalFilters; + disabled?: boolean; +} + +export const SensitivityExportButton: FunctionComponent = (props) => { + const { + studyUuid, + nodeUuid, + currentRootNetworkUuid, + csvHeaders, + disabled = false, + nOrNkIndex, + sensiKind, + globalFilters, + } = props; + const { snackError } = useSnackMessage(); + + const [isCsvExportLoading, setIsCsvExportLoading] = useState(false); + const [isCsvExportSuccessful, setIsCsvExportSuccessful] = useState(false); + + const language = useSelector((state: AppState) => state[PARAM_LANGUAGE]); + const appTabIndex = useSelector((state: AppState) => state.appTabIndex); + const { filters } = useFilterSelector(AgGridFilterType.SensitivityAnalysis, mappingTabs(sensiKind, nOrNkIndex)); + const sortConfig = useSelector( + (state: AppState) => state.tableSort[SENSITIVITY_ANALYSIS_RESULT_SORT_STORE][mappingTabs(sensiKind, nOrNkIndex)] + ); + + useEffect(() => { + setIsCsvExportSuccessful(false); + }, [studyUuid, currentRootNetworkUuid, nodeUuid, nOrNkIndex, sensiKind, globalFilters, sortConfig, appTabIndex]); + + useEffect(() => { + if (disabled) { + // reinit the success state when the button is disabled, + // for example when the calcul status change or results change + setIsCsvExportSuccessful(false); + } + }, [disabled]); + + const exportCsv = useCallback(() => { + setIsCsvExportLoading(true); + setIsCsvExportSuccessful(false); + const mappedFilters = filters?.map((elem) => { + const keyMap = nOrNkIndex === 0 ? DATA_KEY_TO_FILTER_KEY_N : DATA_KEY_TO_FILTER_KEY_NK; + const newColumn = keyMap[elem.column as keyof typeof keyMap]; + return { ...elem, column: newColumn }; + }); + const sortSelector = sortConfig?.length + ? { + sortKeysWithWeightAndDirection: Object.fromEntries( + sortConfig.map((value) => [ + DATA_KEY_TO_SORT_KEY[value.colId as keyof typeof DATA_KEY_TO_SORT_KEY], + value.sort === SortWay.DESC ? -1 : 1, + ]) + ), + } + : {}; + const selector = { + tabSelection: SensitivityResultTabs[nOrNkIndex].id, + functionType: FUNCTION_TYPES[sensiKind], + offset: 0, + pageNumber: 0, + pageSize: -1, // meaning 'All' + ...sortSelector, + }; + + exportSensitivityResultsAsCsv( + studyUuid, + nodeUuid, + currentRootNetworkUuid, + { + csvHeaders: csvHeaders, + resultTab: SensitivityResultTabs[nOrNkIndex].id, + sensitivityFunctionType: isSensiKind(sensiKind) ? FUNCTION_TYPES[sensiKind] : undefined, + language: language, + }, + selector, + mappedFilters, + globalFilters + ) + .then((response) => { + response.blob().then((blob: Blob) => { + downloadZipFile(blob, 'sensitivity_analyse_results.zip'); + setIsCsvExportSuccessful(true); + }); + }) + .catch((error) => { + snackError({ + messageTxt: error.message, + headerId: 'csvExportSensitivityResultError', + }); + setIsCsvExportSuccessful(false); + }) + .finally(() => setIsCsvExportLoading(false)); + }, [ + filters, + sortConfig, + nOrNkIndex, + sensiKind, + studyUuid, + nodeUuid, + currentRootNetworkUuid, + csvHeaders, + language, + globalFilters, + snackError, + ]); + + return ( + + ); +}; diff --git a/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.tsx b/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.tsx index fe1ccd296b..8109ffc92b 100644 --- a/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.tsx +++ b/src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.tsx @@ -5,33 +5,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { SyntheticEvent, useCallback, useEffect, useMemo, useState } from 'react'; +import { SyntheticEvent, useMemo, useState } from 'react'; import { Box, LinearProgress, Tab, Tabs } from '@mui/material'; import SensitivityAnalysisTabs from './sensitivity-analysis-tabs.js'; import PagedSensitivityAnalysisResult from './paged-sensitivity-analysis-result'; -import { - DATA_KEY_TO_FILTER_KEY_N, - DATA_KEY_TO_FILTER_KEY_NK, - DATA_KEY_TO_SORT_KEY, - FUNCTION_TYPES, - isSensiKind, - mappingTabs, - SensitivityResultTabs, -} from './sensitivity-analysis-result-utils'; import { useSelector } from 'react-redux'; import { ComputationReportViewer } from '../common/computation-report-viewer'; import { RunningStatus } from '../../utils/running-status'; import { useOpenLoaderShortWait } from '../../dialogs/commons/handle-loader'; import { RESULTS_LOADING_DELAY } from '../../network/constants'; -import { exportSensitivityResultsAsCsv } from '../../../services/study/sensitivity-analysis'; -import { downloadZipFile } from '../../../services/utils'; -import { ComputingType, PARAM_LANGUAGE, useSnackMessage } from '@gridsuite/commons-ui'; -import { ExportButton } from '../../utils/export-button'; +import { ComputingType } from '@gridsuite/commons-ui'; import { AppState } from '../../../redux/reducer'; import { UUID } from 'crypto'; import { COMPUTATION_RESULTS_LOGS, - SensiKind, SensiTab, SENSITIVITY_AT_NODE, SENSITIVITY_IN_DELTA_MW, @@ -40,9 +27,8 @@ import useGlobalFilters from '../common/global-filter/use-global-filters'; import GlobalFilterSelector from '../common/global-filter/global-filter-selector'; import { EQUIPMENT_TYPES } from '../../utils/equipment-types'; import { useGlobalFilterOptions } from '../common/global-filter/use-global-filter-options'; -import { useFilterSelector } from '../../../hooks/use-filter-selector'; -import { FilterType as AgGridFilterType, SortWay } from '../../../types/custom-aggrid-types'; -import { SENSITIVITY_ANALYSIS_RESULT_SORT_STORE } from '../../../utils/store-sort-filter-fields'; +import { SensitivityExportButton } from './sensitivity-analysis-export-button.js'; +import { isSensiKind, SensitivityResultTabs } from './sensitivity-analysis-result-utils.js'; export type SensitivityAnalysisResultTabProps = { studyUuid: UUID; @@ -55,38 +41,16 @@ function SensitivityAnalysisResultTab({ nodeUuid, currentRootNetworkUuid, }: Readonly) { - const { snackError } = useSnackMessage(); const [nOrNkIndex, setNOrNkIndex] = useState(0); const [sensiTab, setSensiTab] = useState(SENSITIVITY_IN_DELTA_MW); - const [isCsvExportSuccessful, setIsCsvExportSuccessful] = useState(false); - const [isCsvExportLoading, setIsCsvExportLoading] = useState(false); const sensitivityAnalysisStatus = useSelector( (state: AppState) => state.computingStatus[ComputingType.SENSITIVITY_ANALYSIS] ); - const language = useSelector((state: AppState) => state[PARAM_LANGUAGE]); const { globalFilters, handleGlobalFilterChange, getGlobalFilterParameter } = useGlobalFilters({}); const { countriesFilter, voltageLevelsFilter, propertiesFilter } = useGlobalFilterOptions(); - const { filters } = useFilterSelector( - AgGridFilterType.SensitivityAnalysis, - mappingTabs(sensiTab as SensiKind, nOrNkIndex) - ); - const sortConfig = useSelector( - (state: AppState) => - state.tableSort[SENSITIVITY_ANALYSIS_RESULT_SORT_STORE][mappingTabs(sensiTab as SensiKind, nOrNkIndex)] - ); - - const initTable = () => { - setIsCsvExportSuccessful(false); - }; - - const handleSensiTabChange = (newSensiTab: SensiTab) => { - initTable(); - setSensiTab(newSensiTab); - }; const handleSensiNOrNkIndexChange = (event: SyntheticEvent, newNOrNKIndex: number) => { - initTable(); setNOrNkIndex(newNOrNKIndex); }; @@ -98,76 +62,6 @@ function SensitivityAnalysisResultTab({ const [csvHeaders, setCsvHeaders] = useState([]); const [isCsvButtonDisabled, setIsCsvButtonDisabled] = useState(true); - const handleExportResultAsCsv = useCallback(() => { - setIsCsvExportLoading(true); - setIsCsvExportSuccessful(false); - const mappedFilters = filters?.map((elem) => { - const keyMap = nOrNkIndex === 0 ? DATA_KEY_TO_FILTER_KEY_N : DATA_KEY_TO_FILTER_KEY_NK; - const newColumn = keyMap[elem.column as keyof typeof keyMap]; - return { ...elem, column: newColumn }; - }); - const sortSelector = sortConfig?.length - ? { - sortKeysWithWeightAndDirection: Object.fromEntries( - sortConfig.map((value) => [ - DATA_KEY_TO_SORT_KEY[value.colId as keyof typeof DATA_KEY_TO_SORT_KEY], - value.sort === SortWay.DESC ? -1 : 1, - ]) - ), - } - : {}; - const selector = { - tabSelection: SensitivityResultTabs[nOrNkIndex].id, - functionType: FUNCTION_TYPES[sensiTab as SensiKind], - offset: 0, - pageNumber: 0, - pageSize: -1, // meaning 'All' - ...sortSelector, - }; - - exportSensitivityResultsAsCsv( - studyUuid, - nodeUuid, - currentRootNetworkUuid, - { - csvHeaders: csvHeaders, - resultTab: SensitivityResultTabs[nOrNkIndex].id, - sensitivityFunctionType: isSensiKind(sensiTab) ? FUNCTION_TYPES[sensiTab] : undefined, - language: language, - }, - selector, - mappedFilters, - getGlobalFilterParameter(globalFilters) - ) - .then((response) => { - response.blob().then((blob: Blob) => { - downloadZipFile(blob, 'sensitivity_analyse_results.zip'); - setIsCsvExportSuccessful(true); - }); - }) - .catch((error) => { - snackError({ - messageTxt: error.message, - headerId: 'csvExportSensitivityResultError', - }); - setIsCsvExportSuccessful(false); - }) - .finally(() => setIsCsvExportLoading(false)); - }, [ - filters, - sortConfig, - nOrNkIndex, - sensiTab, - studyUuid, - nodeUuid, - currentRootNetworkUuid, - csvHeaders, - language, - getGlobalFilterParameter, - globalFilters, - snackError, - ]); - const filterableEquipmentTypes: EQUIPMENT_TYPES[] = useMemo(() => { return sensiTab === SENSITIVITY_AT_NODE ? [] : [EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER, EQUIPMENT_TYPES.LINE]; }, [sensiTab]); @@ -177,17 +71,9 @@ function SensitivityAnalysisResultTab({ [voltageLevelsFilter, countriesFilter, propertiesFilter] ); - useEffect(() => { - if (isCsvButtonDisabled) { - // reinit the success state when the button is disabled, - // for example when the calcul status change or results change - setIsCsvExportSuccessful(false); - } - }, [isCsvButtonDisabled]); - return ( <> - + {isSensiKind(sensiTab) && ( <> - state[PARAM_LANGUAGE]); + const appTabIndex = useSelector((state: AppState) => state.appTabIndex); useEffect(() => { setIsCsvExportSuccessful(false); - }, [nodeUuid, analysisType]); + }, [studyUuid, currentRootNetworkUuid, nodeUuid, analysisType, appTabIndex]); useEffect(() => { if (disabled) {