Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/components/result-view-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,11 @@ export const ResultViewTab: FunctionComponent<IResultViewTabProps> = ({
studyUuid={studyUuid}
nodeUuid={currentNode?.id}
currentRootNetworkUuid={currentRootNetworkUuid}
openVoltageLevelDiagram={openVoltageLevelDiagram}
/>
</Paper>
);
}, [studyUuid, currentNode, currentRootNetworkUuid]);
}, [studyUuid, currentNode, currentRootNetworkUuid, openVoltageLevelDiagram]);

const renderSecurityAnalysisResult = useMemo(() => {
return (
Expand Down
52 changes: 47 additions & 5 deletions src/components/results/loadflow/load-flow-result-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import Box from '@mui/material/Box';
import { FormattedMessage, useIntl } from 'react-intl/lib';
import { LimitTypes, LoadFlowTabProps } from './load-flow-result.type';
import { LimitTypes, LoadFlowTabProps, OverloadedEquipment } from './load-flow-result.type';
import { LoadFlowResult } from './load-flow-result';
import { fetchLimitViolations, fetchLoadFlowResult } from '../../../services/study/loadflow';
import RunningStatus from 'components/utils/running-status';
Expand Down Expand Up @@ -47,6 +47,10 @@ import { UUID } from 'crypto';
import GlobalFilterSelector from '../common/global-filter/global-filter-selector';
import useGlobalFilters from '../common/global-filter/use-global-filters';
import { useGlobalFilterOptions } from '../common/global-filter/use-global-filter-options';
import { ICellRendererParams } from 'ag-grid-community';
import { Button, Tooltip } from '@mui/material';
import { resultsStyles } from '../common/utils';
import { useLoadFlowResultColumnActions } from './use-load-flow-result-column-actions';

const styles = {
flexWrapper: {
Expand All @@ -70,6 +74,7 @@ export const LoadFlowResultTab: FunctionComponent<LoadFlowTabProps> = ({
studyUuid,
nodeUuid,
currentRootNetworkUuid,
openVoltageLevelDiagram,
}) => {
const intl = useIntl();

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

const { countriesFilter, voltageLevelsFilter, propertiesFilter } = useGlobalFilterOptions();
const { globalFilters, handleGlobalFilterChange, getGlobalFilterParameter } = useGlobalFilters({});

const { onLinkClick } = useLoadFlowResultColumnActions({
studyUuid,
nodeUuid,
currentRootNetworkUuid,
openVoltageLevelDiagram,
});
const { loading: filterEnumsLoading, result: filterEnums } = useFetchFiltersEnums();

const getEnumLabel = useCallback(
Expand Down Expand Up @@ -159,12 +169,44 @@ export const LoadFlowResultTab: FunctionComponent<LoadFlowTabProps> = ({
invalidations: loadflowResultInvalidations,
});

const SubjectIdRenderer = useCallback(
(props: ICellRendererParams) => {
const { value, node, colDef } = props || {};
const onClick = () => {
const row: OverloadedEquipment = { ...node?.data };
onLinkClick(row, colDef);
};
if (value) {
return (
<Tooltip title={value}>
<Button sx={resultsStyles.sldLink} onClick={onClick}>
{value}
</Button>
</Tooltip>
);
}
},
[onLinkClick]
);

const loadFlowLimitViolationsColumns = useMemo(() => {
switch (tabIndex) {
case 0:
return loadFlowCurrentViolationsColumnsDefinition(intl, filterEnums, getEnumLabel, tabIndex);
return loadFlowCurrentViolationsColumnsDefinition(
intl,
filterEnums,
getEnumLabel,
tabIndex,
SubjectIdRenderer
);
case 1:
return loadFlowVoltageViolationsColumnsDefinition(intl, filterEnums, getEnumLabel, tabIndex);
return loadFlowVoltageViolationsColumnsDefinition(
intl,
filterEnums,
getEnumLabel,
tabIndex,
SubjectIdRenderer
);
case 2:
return loadFlowResultColumnsDefinition(
intl,
Expand All @@ -178,7 +220,7 @@ export const LoadFlowResultTab: FunctionComponent<LoadFlowTabProps> = ({
default:
return [];
}
}, [tabIndex, intl, filterEnums, getEnumLabel]);
}, [tabIndex, intl, filterEnums, getEnumLabel, SubjectIdRenderer]);

const resetResultStates = useCallback(() => {
setResult(null);
Expand Down
10 changes: 8 additions & 2 deletions src/components/results/loadflow/load-flow-result-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
FilterEnumsType,
} from '../../custom-aggrid/custom-aggrid-filters/custom-aggrid-filter.type';
import { convertDuration, formatNAValue } from 'components/custom-aggrid/utils/format-values-utils';
import { SubjectIdRendererType } from '../securityanalysis/security-analysis.type';

export const convertSide = (side: string | undefined, intl: IntlShape) => {
return side === BranchSide.ONE
Expand Down Expand Up @@ -237,7 +238,8 @@ export const loadFlowCurrentViolationsColumnsDefinition = (
intl: IntlShape,
filterEnums: FilterEnumsType,
getEnumLabel: (value: string) => string, // Used for translation of enum values in the filter
tabIndex: number
tabIndex: number,
subjectIdRenderer: SubjectIdRendererType
): ColDef[] => {
const sortParams: ColumnContext['sortParams'] = {
table: LOADFLOW_RESULT_SORT_STORE,
Expand All @@ -252,6 +254,8 @@ export const loadFlowCurrentViolationsColumnsDefinition = (
headerName: intl.formatMessage({ id: 'OverloadedEquipment' }),
colId: 'subjectId',
field: 'subjectId',
cellRenderer: subjectIdRenderer,

context: {
sortParams,
filterComponent: CustomAggridComparatorFilter,
Expand Down Expand Up @@ -359,7 +363,8 @@ export const loadFlowVoltageViolationsColumnsDefinition = (
intl: IntlShape,
filterEnums: FilterEnumsType,
getEnumLabel: (value: string) => string, // Used for translation of enum values in the filter
tabIndex: number
tabIndex: number,
subjectIdRenderer: SubjectIdRendererType
): ColDef[] => {
const sortParams: ColumnContext['sortParams'] = {
table: LOADFLOW_RESULT_SORT_STORE,
Expand All @@ -384,6 +389,7 @@ export const loadFlowVoltageViolationsColumnsDefinition = (
headerName: intl.formatMessage({ id: 'OverloadedEquipmentVoltageLevel' }),
colId: 'subjectId',
field: 'subjectId',
cellRenderer: subjectIdRenderer,
context: {
sortParams,
filterComponent: CustomAggridComparatorFilter,
Expand Down
1 change: 1 addition & 0 deletions src/components/results/loadflow/load-flow-result.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface LoadFlowTabProps {
studyUuid: UUID;
nodeUuid: UUID;
currentRootNetworkUuid: UUID;
openVoltageLevelDiagram: (id: string) => void;
}

export interface LoadflowResultTap {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* 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 { useCallback } from 'react';
import { OverloadedEquipment } from './load-flow-result.type';
import { ColDef } from 'ag-grid-community';
import { fetchVoltageLevelIdForLineOrTransformerBySide } from '../../../services/study/network-map';
import { BranchSide } from '../../utils/constants';
import { UUID } from 'crypto';
import { useSnackMessage } from '@gridsuite/commons-ui';
import { useIntl } from 'react-intl';

type UseLoadFlowResultColumnActionsProps = {
studyUuid: UUID;
nodeUuid: UUID;
currentRootNetworkUuid: UUID;
openVoltageLevelDiagram: (id: string) => void;
};

export const useLoadFlowResultColumnActions = ({
studyUuid,
nodeUuid,
currentRootNetworkUuid,
openVoltageLevelDiagram,
}: UseLoadFlowResultColumnActionsProps) => {
const { snackError } = useSnackMessage();
const intl = useIntl();

const getBranchSide = useCallback(
(side: string | undefined) => {
if (side === intl.formatMessage({ id: BranchSide.ONE })) {
return BranchSide.ONE;
} else if (side === intl.formatMessage({ id: BranchSide.TWO })) {
return BranchSide.TWO;
}
return null;
},
[intl]
);

const onLinkClick = useCallback(
(row: OverloadedEquipment, column?: ColDef) => {
if (studyUuid && nodeUuid && currentRootNetworkUuid) {
if (column?.field === 'subjectId') {
let vlId: string | undefined = '';
const { subjectId, side } = row || {};
// ideally we would have the type of the network element, but we don't
fetchVoltageLevelIdForLineOrTransformerBySide(
studyUuid,
nodeUuid,
currentRootNetworkUuid,
subjectId ?? '',
getBranchSide(side) ?? BranchSide.ONE
)
.then((voltageLevelId) => {
if (!voltageLevelId) {
vlId = subjectId;
} else {
vlId = voltageLevelId;
}
})
.finally(() => {
if (!vlId) {
snackError({
messageId: 'NetworkEquipmentNotFound',
messageValues: {
equipmentId: row.subjectId || '',
},
});
} else if (openVoltageLevelDiagram) {
openVoltageLevelDiagram(vlId);
}
});
}
}
},
[studyUuid, nodeUuid, currentRootNetworkUuid, getBranchSide, openVoltageLevelDiagram, snackError]
);

return { onLinkClick };
};
Loading