Skip to content

Commit dc01130

Browse files
authored
Handle the link redirection to the tree view. (#3298)
Signed-off-by: AAJELLAL <[email protected]>
1 parent 65852d0 commit dc01130

File tree

5 files changed

+143
-8
lines changed

5 files changed

+143
-8
lines changed

src/components/result-view-tab.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,11 @@ export const ResultViewTab: FunctionComponent<IResultViewTabProps> = ({
9595
studyUuid={studyUuid}
9696
nodeUuid={currentNode?.id}
9797
currentRootNetworkUuid={currentRootNetworkUuid}
98+
openVoltageLevelDiagram={openVoltageLevelDiagram}
9899
/>
99100
</Paper>
100101
);
101-
}, [studyUuid, currentNode, currentRootNetworkUuid]);
102+
}, [studyUuid, currentNode, currentRootNetworkUuid, openVoltageLevelDiagram]);
102103

103104
const renderSecurityAnalysisResult = useMemo(() => {
104105
return (

src/components/results/loadflow/load-flow-result-tab.tsx

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Tabs from '@mui/material/Tabs';
1010
import Tab from '@mui/material/Tab';
1111
import Box from '@mui/material/Box';
1212
import { FormattedMessage, useIntl } from 'react-intl/lib';
13-
import { LimitTypes, LoadFlowTabProps } from './load-flow-result.type';
13+
import { LimitTypes, LoadFlowTabProps, OverloadedEquipment } from './load-flow-result.type';
1414
import { LoadFlowResult } from './load-flow-result';
1515
import { fetchLimitViolations, fetchLoadFlowResult } from '../../../services/study/loadflow';
1616
import RunningStatus from 'components/utils/running-status';
@@ -47,6 +47,10 @@ import { UUID } from 'crypto';
4747
import GlobalFilterSelector from '../common/global-filter/global-filter-selector';
4848
import useGlobalFilters from '../common/global-filter/use-global-filters';
4949
import { useGlobalFilterOptions } from '../common/global-filter/use-global-filter-options';
50+
import { ICellRendererParams } from 'ag-grid-community';
51+
import { Button, Tooltip } from '@mui/material';
52+
import { resultsStyles } from '../common/utils';
53+
import { useLoadFlowResultColumnActions } from './use-load-flow-result-column-actions';
5054

5155
const styles = {
5256
flexWrapper: {
@@ -70,6 +74,7 @@ export const LoadFlowResultTab: FunctionComponent<LoadFlowTabProps> = ({
7074
studyUuid,
7175
nodeUuid,
7276
currentRootNetworkUuid,
77+
openVoltageLevelDiagram,
7378
}) => {
7479
const intl = useIntl();
7580

@@ -84,7 +89,12 @@ export const LoadFlowResultTab: FunctionComponent<LoadFlowTabProps> = ({
8489

8590
const { countriesFilter, voltageLevelsFilter, propertiesFilter } = useGlobalFilterOptions();
8691
const { globalFilters, handleGlobalFilterChange, getGlobalFilterParameter } = useGlobalFilters({});
87-
92+
const { onLinkClick } = useLoadFlowResultColumnActions({
93+
studyUuid,
94+
nodeUuid,
95+
currentRootNetworkUuid,
96+
openVoltageLevelDiagram,
97+
});
8898
const { loading: filterEnumsLoading, result: filterEnums } = useFetchFiltersEnums();
8999

90100
const getEnumLabel = useCallback(
@@ -159,12 +169,44 @@ export const LoadFlowResultTab: FunctionComponent<LoadFlowTabProps> = ({
159169
invalidations: loadflowResultInvalidations,
160170
});
161171

172+
const SubjectIdRenderer = useCallback(
173+
(props: ICellRendererParams) => {
174+
const { value, node, colDef } = props || {};
175+
const onClick = () => {
176+
const row: OverloadedEquipment = { ...node?.data };
177+
onLinkClick(row, colDef);
178+
};
179+
if (value) {
180+
return (
181+
<Tooltip title={value}>
182+
<Button sx={resultsStyles.sldLink} onClick={onClick}>
183+
{value}
184+
</Button>
185+
</Tooltip>
186+
);
187+
}
188+
},
189+
[onLinkClick]
190+
);
191+
162192
const loadFlowLimitViolationsColumns = useMemo(() => {
163193
switch (tabIndex) {
164194
case 0:
165-
return loadFlowCurrentViolationsColumnsDefinition(intl, filterEnums, getEnumLabel, tabIndex);
195+
return loadFlowCurrentViolationsColumnsDefinition(
196+
intl,
197+
filterEnums,
198+
getEnumLabel,
199+
tabIndex,
200+
SubjectIdRenderer
201+
);
166202
case 1:
167-
return loadFlowVoltageViolationsColumnsDefinition(intl, filterEnums, getEnumLabel, tabIndex);
203+
return loadFlowVoltageViolationsColumnsDefinition(
204+
intl,
205+
filterEnums,
206+
getEnumLabel,
207+
tabIndex,
208+
SubjectIdRenderer
209+
);
168210
case 2:
169211
return loadFlowResultColumnsDefinition(
170212
intl,
@@ -178,7 +220,7 @@ export const LoadFlowResultTab: FunctionComponent<LoadFlowTabProps> = ({
178220
default:
179221
return [];
180222
}
181-
}, [tabIndex, intl, filterEnums, getEnumLabel]);
223+
}, [tabIndex, intl, filterEnums, getEnumLabel, SubjectIdRenderer]);
182224

183225
const resetResultStates = useCallback(() => {
184226
setResult(null);

src/components/results/loadflow/load-flow-result-utils.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
FilterEnumsType,
3737
} from '../../custom-aggrid/custom-aggrid-filters/custom-aggrid-filter.type';
3838
import { convertDuration, formatNAValue } from 'components/custom-aggrid/utils/format-values-utils';
39+
import { SubjectIdRendererType } from '../securityanalysis/security-analysis.type';
3940

4041
export const convertSide = (side: string | undefined, intl: IntlShape) => {
4142
return side === BranchSide.ONE
@@ -237,7 +238,8 @@ export const loadFlowCurrentViolationsColumnsDefinition = (
237238
intl: IntlShape,
238239
filterEnums: FilterEnumsType,
239240
getEnumLabel: (value: string) => string, // Used for translation of enum values in the filter
240-
tabIndex: number
241+
tabIndex: number,
242+
subjectIdRenderer: SubjectIdRendererType
241243
): ColDef[] => {
242244
const sortParams: ColumnContext['sortParams'] = {
243245
table: LOADFLOW_RESULT_SORT_STORE,
@@ -252,6 +254,8 @@ export const loadFlowCurrentViolationsColumnsDefinition = (
252254
headerName: intl.formatMessage({ id: 'OverloadedEquipment' }),
253255
colId: 'subjectId',
254256
field: 'subjectId',
257+
cellRenderer: subjectIdRenderer,
258+
255259
context: {
256260
sortParams,
257261
filterComponent: CustomAggridComparatorFilter,
@@ -359,7 +363,8 @@ export const loadFlowVoltageViolationsColumnsDefinition = (
359363
intl: IntlShape,
360364
filterEnums: FilterEnumsType,
361365
getEnumLabel: (value: string) => string, // Used for translation of enum values in the filter
362-
tabIndex: number
366+
tabIndex: number,
367+
subjectIdRenderer: SubjectIdRendererType
363368
): ColDef[] => {
364369
const sortParams: ColumnContext['sortParams'] = {
365370
table: LOADFLOW_RESULT_SORT_STORE,
@@ -384,6 +389,7 @@ export const loadFlowVoltageViolationsColumnsDefinition = (
384389
headerName: intl.formatMessage({ id: 'OverloadedEquipmentVoltageLevel' }),
385390
colId: 'subjectId',
386391
field: 'subjectId',
392+
cellRenderer: subjectIdRenderer,
387393
context: {
388394
sortParams,
389395
filterComponent: CustomAggridComparatorFilter,

src/components/results/loadflow/load-flow-result.type.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export interface LoadFlowTabProps {
4040
studyUuid: UUID;
4141
nodeUuid: UUID;
4242
currentRootNetworkUuid: UUID;
43+
openVoltageLevelDiagram: (id: string) => void;
4344
}
4445

4546
export interface LoadflowResultTap {
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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 { useCallback } from 'react';
9+
import { OverloadedEquipment } from './load-flow-result.type';
10+
import { ColDef } from 'ag-grid-community';
11+
import { fetchVoltageLevelIdForLineOrTransformerBySide } from '../../../services/study/network-map';
12+
import { BranchSide } from '../../utils/constants';
13+
import { UUID } from 'crypto';
14+
import { useSnackMessage } from '@gridsuite/commons-ui';
15+
import { useIntl } from 'react-intl';
16+
17+
type UseLoadFlowResultColumnActionsProps = {
18+
studyUuid: UUID;
19+
nodeUuid: UUID;
20+
currentRootNetworkUuid: UUID;
21+
openVoltageLevelDiagram: (id: string) => void;
22+
};
23+
24+
export const useLoadFlowResultColumnActions = ({
25+
studyUuid,
26+
nodeUuid,
27+
currentRootNetworkUuid,
28+
openVoltageLevelDiagram,
29+
}: UseLoadFlowResultColumnActionsProps) => {
30+
const { snackError } = useSnackMessage();
31+
const intl = useIntl();
32+
33+
const getBranchSide = useCallback(
34+
(side: string | undefined) => {
35+
if (side === intl.formatMessage({ id: BranchSide.ONE })) {
36+
return BranchSide.ONE;
37+
} else if (side === intl.formatMessage({ id: BranchSide.TWO })) {
38+
return BranchSide.TWO;
39+
}
40+
return null;
41+
},
42+
[intl]
43+
);
44+
45+
const onLinkClick = useCallback(
46+
(row: OverloadedEquipment, column?: ColDef) => {
47+
if (studyUuid && nodeUuid && currentRootNetworkUuid) {
48+
if (column?.field === 'subjectId') {
49+
let vlId: string | undefined = '';
50+
const { subjectId, side } = row || {};
51+
// ideally we would have the type of the network element, but we don't
52+
fetchVoltageLevelIdForLineOrTransformerBySide(
53+
studyUuid,
54+
nodeUuid,
55+
currentRootNetworkUuid,
56+
subjectId ?? '',
57+
getBranchSide(side) ?? BranchSide.ONE
58+
)
59+
.then((voltageLevelId) => {
60+
if (!voltageLevelId) {
61+
vlId = subjectId;
62+
} else {
63+
vlId = voltageLevelId;
64+
}
65+
})
66+
.finally(() => {
67+
if (!vlId) {
68+
snackError({
69+
messageId: 'NetworkEquipmentNotFound',
70+
messageValues: {
71+
equipmentId: row.subjectId || '',
72+
},
73+
});
74+
} else if (openVoltageLevelDiagram) {
75+
openVoltageLevelDiagram(vlId);
76+
}
77+
});
78+
}
79+
}
80+
},
81+
[studyUuid, nodeUuid, currentRootNetworkUuid, getBranchSide, openVoltageLevelDiagram, snackError]
82+
);
83+
84+
return { onLinkClick };
85+
};

0 commit comments

Comments
 (0)