Skip to content

Commit 7593695

Browse files
authored
Merge branch 'main' into jorism/fix-spreadsheet-update-on-notifications
2 parents 50ddcfd + 940830b commit 7593695

File tree

6 files changed

+201
-181
lines changed

6 files changed

+201
-181
lines changed

src/components/results/securityanalysis/security-analysis-export-button.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

8-
import { useSnackMessage } from '@gridsuite/commons-ui';
9-
import { ExportButton } from 'components/utils/export-button';
8+
import { ExportCsvButton, useSnackMessage } from '@gridsuite/commons-ui';
109
import { UUID } from 'crypto';
1110
import { FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react';
1211
import { useIntl } from 'react-intl';
@@ -34,12 +33,21 @@ export const SecurityAnalysisExportButton: FunctionComponent<SecurityAnalysisExp
3433
const [isCsvExportLoading, setIsCsvExportLoading] = useState(false);
3534
const [isCsvExportSuccessful, setIsCsvExportSuccessful] = useState(false);
3635
const language = useSelector((state: AppState) => state[PARAM_LANGUAGE]);
36+
const appTabIndex = useSelector((state: AppState) => state.appTabIndex);
3737

3838
const intl = useIntl();
3939

4040
useEffect(() => {
4141
setIsCsvExportSuccessful(false);
42-
}, [nodeUuid, resultType]);
42+
}, [studyUuid, nodeUuid, rootNetworkUuid, resultType, appTabIndex]);
43+
44+
useEffect(() => {
45+
if (disabled) {
46+
// reinit the success state when the button is disabled,
47+
// for example when the calcul status change or results change
48+
setIsCsvExportSuccessful(false);
49+
}
50+
}, [disabled]);
4351

4452
const enumValueTranslations = useMemo(() => {
4553
const returnedValue: Record<string, string> = {
@@ -109,7 +117,7 @@ export const SecurityAnalysisExportButton: FunctionComponent<SecurityAnalysisExp
109117
]);
110118

111119
return (
112-
<ExportButton
120+
<ExportCsvButton
113121
onClick={exportResultCsv}
114122
disabled={disabled}
115123
isDownloadLoading={isCsvExportLoading}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
import { FunctionComponent, useCallback, useEffect, useState } from 'react';
9+
import { ExportCsvButton, PARAM_LANGUAGE, useSnackMessage } from '@gridsuite/commons-ui';
10+
import { downloadZipFile } from '../../../services/utils';
11+
import { UUID } from 'crypto';
12+
import { AppState } from 'redux/reducer';
13+
import { useSelector } from 'react-redux';
14+
import { useFilterSelector } from 'hooks/use-filter-selector';
15+
import {
16+
DATA_KEY_TO_FILTER_KEY_N,
17+
DATA_KEY_TO_FILTER_KEY_NK,
18+
DATA_KEY_TO_SORT_KEY,
19+
FUNCTION_TYPES,
20+
isSensiKind,
21+
mappingTabs,
22+
SensitivityResultTabs,
23+
} from './sensitivity-analysis-result-utils';
24+
import { exportSensitivityResultsAsCsv } from 'services/study/sensitivity-analysis';
25+
import { SensiKind } from './sensitivity-analysis-result.type';
26+
import { FilterType as AgGridFilterType, SortWay } from '../../../types/custom-aggrid-types';
27+
import { SENSITIVITY_ANALYSIS_RESULT_SORT_STORE } from 'utils/store-sort-filter-fields';
28+
import { GlobalFilters } from '../common/global-filter/global-filter-types';
29+
30+
interface SensitivityExportButtonProps {
31+
studyUuid: UUID;
32+
nodeUuid: UUID;
33+
currentRootNetworkUuid: UUID;
34+
csvHeaders: string[];
35+
nOrNkIndex: number;
36+
sensiKind: SensiKind;
37+
globalFilters?: GlobalFilters;
38+
disabled?: boolean;
39+
}
40+
41+
export const SensitivityExportButton: FunctionComponent<SensitivityExportButtonProps> = (props) => {
42+
const {
43+
studyUuid,
44+
nodeUuid,
45+
currentRootNetworkUuid,
46+
csvHeaders,
47+
disabled = false,
48+
nOrNkIndex,
49+
sensiKind,
50+
globalFilters,
51+
} = props;
52+
const { snackError } = useSnackMessage();
53+
54+
const [isCsvExportLoading, setIsCsvExportLoading] = useState(false);
55+
const [isCsvExportSuccessful, setIsCsvExportSuccessful] = useState(false);
56+
57+
const language = useSelector((state: AppState) => state[PARAM_LANGUAGE]);
58+
const appTabIndex = useSelector((state: AppState) => state.appTabIndex);
59+
const { filters } = useFilterSelector(AgGridFilterType.SensitivityAnalysis, mappingTabs(sensiKind, nOrNkIndex));
60+
const sortConfig = useSelector(
61+
(state: AppState) => state.tableSort[SENSITIVITY_ANALYSIS_RESULT_SORT_STORE][mappingTabs(sensiKind, nOrNkIndex)]
62+
);
63+
64+
useEffect(() => {
65+
setIsCsvExportSuccessful(false);
66+
}, [studyUuid, currentRootNetworkUuid, nodeUuid, nOrNkIndex, sensiKind, globalFilters, sortConfig, appTabIndex]);
67+
68+
useEffect(() => {
69+
if (disabled) {
70+
// reinit the success state when the button is disabled,
71+
// for example when the calcul status change or results change
72+
setIsCsvExportSuccessful(false);
73+
}
74+
}, [disabled]);
75+
76+
const exportCsv = useCallback(() => {
77+
setIsCsvExportLoading(true);
78+
setIsCsvExportSuccessful(false);
79+
const mappedFilters = filters?.map((elem) => {
80+
const keyMap = nOrNkIndex === 0 ? DATA_KEY_TO_FILTER_KEY_N : DATA_KEY_TO_FILTER_KEY_NK;
81+
const newColumn = keyMap[elem.column as keyof typeof keyMap];
82+
return { ...elem, column: newColumn };
83+
});
84+
const sortSelector = sortConfig?.length
85+
? {
86+
sortKeysWithWeightAndDirection: Object.fromEntries(
87+
sortConfig.map((value) => [
88+
DATA_KEY_TO_SORT_KEY[value.colId as keyof typeof DATA_KEY_TO_SORT_KEY],
89+
value.sort === SortWay.DESC ? -1 : 1,
90+
])
91+
),
92+
}
93+
: {};
94+
const selector = {
95+
tabSelection: SensitivityResultTabs[nOrNkIndex].id,
96+
functionType: FUNCTION_TYPES[sensiKind],
97+
offset: 0,
98+
pageNumber: 0,
99+
pageSize: -1, // meaning 'All'
100+
...sortSelector,
101+
};
102+
103+
exportSensitivityResultsAsCsv(
104+
studyUuid,
105+
nodeUuid,
106+
currentRootNetworkUuid,
107+
{
108+
csvHeaders: csvHeaders,
109+
resultTab: SensitivityResultTabs[nOrNkIndex].id,
110+
sensitivityFunctionType: isSensiKind(sensiKind) ? FUNCTION_TYPES[sensiKind] : undefined,
111+
language: language,
112+
},
113+
selector,
114+
mappedFilters,
115+
globalFilters
116+
)
117+
.then((response) => {
118+
response.blob().then((blob: Blob) => {
119+
downloadZipFile(blob, 'sensitivity_analyse_results.zip');
120+
setIsCsvExportSuccessful(true);
121+
});
122+
})
123+
.catch((error) => {
124+
snackError({
125+
messageTxt: error.message,
126+
headerId: 'csvExportSensitivityResultError',
127+
});
128+
setIsCsvExportSuccessful(false);
129+
})
130+
.finally(() => setIsCsvExportLoading(false));
131+
}, [
132+
filters,
133+
sortConfig,
134+
nOrNkIndex,
135+
sensiKind,
136+
studyUuid,
137+
nodeUuid,
138+
currentRootNetworkUuid,
139+
csvHeaders,
140+
language,
141+
globalFilters,
142+
snackError,
143+
]);
144+
145+
return (
146+
<ExportCsvButton
147+
onClick={exportCsv}
148+
disabled={disabled}
149+
isDownloadLoading={isCsvExportLoading}
150+
isDownloadSuccessful={isCsvExportSuccessful}
151+
/>
152+
);
153+
};

src/components/results/sensitivity-analysis/sensitivity-analysis-result-tab.tsx

Lines changed: 13 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,20 @@
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

8-
import { SyntheticEvent, useCallback, useMemo, useState } from 'react';
8+
import { SyntheticEvent, useMemo, useState } from 'react';
99
import { Box, LinearProgress, Tab, Tabs } from '@mui/material';
1010
import SensitivityAnalysisTabs from './sensitivity-analysis-tabs.js';
1111
import PagedSensitivityAnalysisResult from './paged-sensitivity-analysis-result';
12-
import {
13-
DATA_KEY_TO_FILTER_KEY_N,
14-
DATA_KEY_TO_FILTER_KEY_NK,
15-
DATA_KEY_TO_SORT_KEY,
16-
FUNCTION_TYPES,
17-
isSensiKind,
18-
mappingTabs,
19-
SensitivityResultTabs,
20-
} from './sensitivity-analysis-result-utils';
2112
import { useSelector } from 'react-redux';
2213
import { ComputationReportViewer } from '../common/computation-report-viewer';
2314
import { RunningStatus } from '../../utils/running-status';
2415
import { useOpenLoaderShortWait } from '../../dialogs/commons/handle-loader';
2516
import { RESULTS_LOADING_DELAY } from '../../network/constants';
26-
import { exportSensitivityResultsAsCsv } from '../../../services/study/sensitivity-analysis';
27-
import { downloadZipFile } from '../../../services/utils';
28-
import { ComputingType, PARAM_LANGUAGE, useSnackMessage } from '@gridsuite/commons-ui';
29-
import { ExportButton } from '../../utils/export-button';
17+
import { ComputingType } from '@gridsuite/commons-ui';
3018
import { AppState } from '../../../redux/reducer';
3119
import { UUID } from 'crypto';
3220
import {
3321
COMPUTATION_RESULTS_LOGS,
34-
SensiKind,
3522
SensiTab,
3623
SENSITIVITY_AT_NODE,
3724
SENSITIVITY_IN_DELTA_MW,
@@ -40,9 +27,8 @@ import useGlobalFilters from '../common/global-filter/use-global-filters';
4027
import GlobalFilterSelector from '../common/global-filter/global-filter-selector';
4128
import { EQUIPMENT_TYPES } from '../../utils/equipment-types';
4229
import { useGlobalFilterOptions } from '../common/global-filter/use-global-filter-options';
43-
import { useFilterSelector } from '../../../hooks/use-filter-selector';
44-
import { FilterType as AgGridFilterType, SortWay } from '../../../types/custom-aggrid-types';
45-
import { SENSITIVITY_ANALYSIS_RESULT_SORT_STORE } from '../../../utils/store-sort-filter-fields';
30+
import { SensitivityExportButton } from './sensitivity-analysis-export-button.js';
31+
import { isSensiKind, SensitivityResultTabs } from './sensitivity-analysis-result-utils.js';
4632

4733
export type SensitivityAnalysisResultTabProps = {
4834
studyUuid: UUID;
@@ -55,38 +41,16 @@ function SensitivityAnalysisResultTab({
5541
nodeUuid,
5642
currentRootNetworkUuid,
5743
}: Readonly<SensitivityAnalysisResultTabProps>) {
58-
const { snackError } = useSnackMessage();
5944
const [nOrNkIndex, setNOrNkIndex] = useState<number>(0);
6045
const [sensiTab, setSensiTab] = useState<SensiTab>(SENSITIVITY_IN_DELTA_MW);
61-
const [isCsvExportSuccessful, setIsCsvExportSuccessful] = useState<boolean>(false);
62-
const [isCsvExportLoading, setIsCsvExportLoading] = useState<boolean>(false);
6346
const sensitivityAnalysisStatus = useSelector(
6447
(state: AppState) => state.computingStatus[ComputingType.SENSITIVITY_ANALYSIS]
6548
);
66-
const language = useSelector((state: AppState) => state[PARAM_LANGUAGE]);
6749

6850
const { globalFilters, handleGlobalFilterChange, getGlobalFilterParameter } = useGlobalFilters({});
6951
const { countriesFilter, voltageLevelsFilter, propertiesFilter } = useGlobalFilterOptions();
70-
const { filters } = useFilterSelector(
71-
AgGridFilterType.SensitivityAnalysis,
72-
mappingTabs(sensiTab as SensiKind, nOrNkIndex)
73-
);
74-
const sortConfig = useSelector(
75-
(state: AppState) =>
76-
state.tableSort[SENSITIVITY_ANALYSIS_RESULT_SORT_STORE][mappingTabs(sensiTab as SensiKind, nOrNkIndex)]
77-
);
78-
79-
const initTable = () => {
80-
setIsCsvExportSuccessful(false);
81-
};
82-
83-
const handleSensiTabChange = (newSensiTab: SensiTab) => {
84-
initTable();
85-
setSensiTab(newSensiTab);
86-
};
8752

8853
const handleSensiNOrNkIndexChange = (event: SyntheticEvent, newNOrNKIndex: number) => {
89-
initTable();
9054
setNOrNkIndex(newNOrNKIndex);
9155
};
9256

@@ -98,76 +62,6 @@ function SensitivityAnalysisResultTab({
9862
const [csvHeaders, setCsvHeaders] = useState<string[]>([]);
9963
const [isCsvButtonDisabled, setIsCsvButtonDisabled] = useState(true);
10064

101-
const handleExportResultAsCsv = useCallback(() => {
102-
setIsCsvExportLoading(true);
103-
setIsCsvExportSuccessful(false);
104-
const mappedFilters = filters?.map((elem) => {
105-
const keyMap = nOrNkIndex === 0 ? DATA_KEY_TO_FILTER_KEY_N : DATA_KEY_TO_FILTER_KEY_NK;
106-
const newColumn = keyMap[elem.column as keyof typeof keyMap];
107-
return { ...elem, column: newColumn };
108-
});
109-
const sortSelector = sortConfig?.length
110-
? {
111-
sortKeysWithWeightAndDirection: Object.fromEntries(
112-
sortConfig.map((value) => [
113-
DATA_KEY_TO_SORT_KEY[value.colId as keyof typeof DATA_KEY_TO_SORT_KEY],
114-
value.sort === SortWay.DESC ? -1 : 1,
115-
])
116-
),
117-
}
118-
: {};
119-
const selector = {
120-
tabSelection: SensitivityResultTabs[nOrNkIndex].id,
121-
functionType: FUNCTION_TYPES[sensiTab as SensiKind],
122-
offset: 0,
123-
pageNumber: 0,
124-
pageSize: -1, // meaning 'All'
125-
...sortSelector,
126-
};
127-
128-
exportSensitivityResultsAsCsv(
129-
studyUuid,
130-
nodeUuid,
131-
currentRootNetworkUuid,
132-
{
133-
csvHeaders: csvHeaders,
134-
resultTab: SensitivityResultTabs[nOrNkIndex].id,
135-
sensitivityFunctionType: isSensiKind(sensiTab) ? FUNCTION_TYPES[sensiTab] : undefined,
136-
language: language,
137-
},
138-
selector,
139-
mappedFilters,
140-
getGlobalFilterParameter(globalFilters)
141-
)
142-
.then((response) => {
143-
response.blob().then((blob: Blob) => {
144-
downloadZipFile(blob, 'sensitivity_analyse_results.zip');
145-
setIsCsvExportSuccessful(true);
146-
});
147-
})
148-
.catch((error) => {
149-
snackError({
150-
messageTxt: error.message,
151-
headerId: 'csvExportSensitivityResultError',
152-
});
153-
setIsCsvExportSuccessful(false);
154-
})
155-
.finally(() => setIsCsvExportLoading(false));
156-
}, [
157-
filters,
158-
sortConfig,
159-
nOrNkIndex,
160-
sensiTab,
161-
studyUuid,
162-
nodeUuid,
163-
currentRootNetworkUuid,
164-
csvHeaders,
165-
language,
166-
getGlobalFilterParameter,
167-
globalFilters,
168-
snackError,
169-
]);
170-
17165
const filterableEquipmentTypes: EQUIPMENT_TYPES[] = useMemo(() => {
17266
return sensiTab === SENSITIVITY_AT_NODE ? [] : [EQUIPMENT_TYPES.TWO_WINDINGS_TRANSFORMER, EQUIPMENT_TYPES.LINE];
17367
}, [sensiTab]);
@@ -179,7 +73,7 @@ function SensitivityAnalysisResultTab({
17973

18074
return (
18175
<>
182-
<SensitivityAnalysisTabs sensiTab={sensiTab} setSensiTab={handleSensiTabChange} />
76+
<SensitivityAnalysisTabs sensiTab={sensiTab} setSensiTab={setSensiTab} />
18377
{isSensiKind(sensiTab) && (
18478
<>
18579
<Box
@@ -203,11 +97,15 @@ function SensitivityAnalysisResultTab({
20397
disableGenericFilters={sensiTab === SENSITIVITY_AT_NODE}
20498
/>
20599
</Box>
206-
<ExportButton
100+
<SensitivityExportButton
101+
studyUuid={studyUuid}
102+
nodeUuid={nodeUuid}
103+
currentRootNetworkUuid={currentRootNetworkUuid}
104+
csvHeaders={csvHeaders}
105+
nOrNkIndex={nOrNkIndex}
106+
sensiKind={sensiTab}
107+
globalFilters={getGlobalFilterParameter(globalFilters)}
207108
disabled={isCsvButtonDisabled}
208-
onClick={handleExportResultAsCsv}
209-
isDownloadLoading={isCsvExportLoading}
210-
isDownloadSuccessful={isCsvExportSuccessful}
211109
/>
212110
</Box>
213111
<PagedSensitivityAnalysisResult

0 commit comments

Comments
 (0)