Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typescript migration of components/diagrams #2273

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
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
14 changes: 12 additions & 2 deletions src/components/diagrams/diagram-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { FEEDER_TYPES, FeederTypes } from 'components/utils/feederType';
import { EQUIPMENT_TYPES } from 'components/utils/equipment-types';
import { Theme } from '@mui/material';
import { AppDispatch } from '../../redux/store';
import { SLDMetadata } from '@powsybl/diagram-viewer';

export const LOADING_WIDTH = 300;
export const LOADING_HEIGHT = 300;
Expand Down Expand Up @@ -137,7 +138,7 @@ export enum DiagramType {
}

// be careful when using this method because there are treatments made on purpose
export function getEquipmentTypeFromFeederType(feederType: FeederTypes) {
export function getEquipmentTypeFromFeederType(feederType: FeederTypes | null): EQUIPMENT_TYPES | null {
switch (feederType) {
case FEEDER_TYPES.LINE:
return EQUIPMENT_TYPES.LINE;
Expand Down Expand Up @@ -259,9 +260,18 @@ export const useDiagram = () => {
};
};

export const NoSvg = {
export interface Svg {
svg: string | null;
metadata: SLDMetadata | null;
additionalMetadata: SLDMetadata | null;
error: string | null;
svgUrl: string | null;
}

export const NoSvg: Svg = {
svg: null,
metadata: null,
additionalMetadata: null,
error: null,
svgUrl: null,
};
2 changes: 1 addition & 1 deletion src/components/diagrams/diagram-header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ DiagramHeader.propTypes = {
showCloseControl: PropTypes.bool,
onClose: PropTypes.func,
diagramId: PropTypes.string,
svgType: PropTypes.string.isRequired,
svgType: PropTypes.string,
};

export default DiagramHeader;
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import React, { useLayoutEffect, useRef, useMemo, useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { RunningStatus } from '../../utils/running-status';
import {
MIN_HEIGHT,
Expand All @@ -16,16 +15,17 @@ import {
MAX_WIDTH_NETWORK_AREA_DIAGRAM,
styles,
} from '../diagram-common';
import { NetworkAreaDiagramViewer, THRESHOLD_STATUS } from '@powsybl/diagram-viewer';
import { CSS_RULE, NetworkAreaDiagramViewer, THRESHOLD_STATUS } from '@powsybl/diagram-viewer';
import LinearProgress from '@mui/material/LinearProgress';
import Box from '@mui/material/Box';
import { mergeSx } from '../../utils/functions';
import ComputingType from 'components/computing-status/computing-type';
import ComputingType from '../../computing-status/computing-type';
import { AppState } from 'redux/reducer';
import { storeNetworkAreaDiagramNodeMovement } from '../../../redux/actions';
import { PARAM_INIT_NAD_WITH_GEO_DATA } from '../../../utils/config-params.js';
import { getNadIdentifier } from '../diagram-utils.js';

const dynamicCssRules = [
const dynamicCssRules: CSS_RULE[] = [
{
cssSelector: '.nad-edge-infos', // data on edges (arrows and values)
belowThresholdCssDeclaration: { display: 'block' },
Expand Down Expand Up @@ -119,24 +119,32 @@ const dynamicCssRules = [
},
];

function NetworkAreaDiagramContent(props) {
type NetworkAreaDiagramContentProps = {
readonly svgType: string;
readonly svg: string;
readonly loadingState: boolean;
readonly diagramSizeSetter: (id: string, type: string, width: number, height: number) => void;
readonly diagramId: string;
};
function NetworkAreaDiagramContent(props: NetworkAreaDiagramContentProps) {
const { diagramSizeSetter } = props;
const dispatch = useDispatch();
const svgRef = useRef();
const diagramViewerRef = useRef();
const currentNode = useSelector((state) => state.currentTreeNode);
const loadFlowStatus = useSelector((state) => state.computingStatus[ComputingType.LOAD_FLOW]);
const nadNodeMovements = useSelector((state) => state.nadNodeMovements);
const diagramStates = useSelector((state) => state.diagramStates);
const networkAreaDiagramDepth = useSelector((state) => state.networkAreaDiagramDepth);
const initNadWithGeoData = useSelector((state) => state[PARAM_INIT_NAD_WITH_GEO_DATA]);

const diagramViewerRef = useRef<NetworkAreaDiagramViewer>();
const currentNode = useSelector((state: AppState) => state.currentTreeNode);
const loadFlowStatus = useSelector((state: AppState) => state.computingStatus[ComputingType.LOAD_FLOW]);
const nadNodeMovements = useSelector((state: AppState) => state.nadNodeMovements);
const diagramStates = useSelector((state: AppState) => state.diagramStates);
const networkAreaDiagramDepth = useSelector((state: AppState) => state.networkAreaDiagramDepth);
const initNadWithGeoData = useSelector((state: AppState) => state[PARAM_INIT_NAD_WITH_GEO_DATA]);

const nadIdentifier = useMemo(() => {
return getNadIdentifier(diagramStates, networkAreaDiagramDepth, initNadWithGeoData);
}, [diagramStates, networkAreaDiagramDepth, initNadWithGeoData]);

const onMoveNodeCallback = useCallback(
(equipmentId, nodeId, x, y, xOrig, yOrig) => {
(equipmentId: string, nodeId: string, x: number, y: number, xOrig: number, yOrig: number) => {
dispatch(storeNetworkAreaDiagramNodeMovement(nadIdentifier, equipmentId, x, y));
},
[dispatch, nadIdentifier]
Expand All @@ -149,7 +157,7 @@ function NetworkAreaDiagramContent(props) {
useLayoutEffect(() => {
if (props.svg) {
const diagramViewer = new NetworkAreaDiagramViewer(
svgRef.current,
svgRef.current!,
props.svg,
MIN_WIDTH,
MIN_HEIGHT,
Expand All @@ -173,7 +181,10 @@ function NetworkAreaDiagramContent(props) {
diagramViewer.getWidth() === diagramViewerRef.current.getWidth() &&
diagramViewer.getHeight() === diagramViewerRef.current.getHeight()
) {
diagramViewer.setViewBox(diagramViewerRef.current.getViewBox());
const viewBox = diagramViewerRef.current.getViewBox();
if (viewBox) {
diagramViewer.setViewBox(viewBox);
}
}

// Repositioning the previously moved nodes
Expand Down Expand Up @@ -221,12 +232,4 @@ function NetworkAreaDiagramContent(props) {
);
}

NetworkAreaDiagramContent.propTypes = {
svgType: PropTypes.string,
svg: PropTypes.string,
loadingState: PropTypes.bool,
diagramSizeSetter: PropTypes.func,
diagramId: PropTypes.string,
};

export default NetworkAreaDiagramContent;
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,31 @@ import PositionDiagram from './position-diagram';
import { SLD_DISPLAY_MODE } from '../../network/constants';
import { DiagramType } from '../diagram-common';
import { getVoltageLevelSingleLineDiagram } from '../../../services/study/network';
import { FC } from 'react';
import { AppState } from 'redux/reducer';

const PositionDiagramPane = ({ open, onClose, voltageLevelId, currentNodeUuid, studyUuid }) => {
const useName = useSelector((state) => state[PARAM_USE_NAME]);
const centerName = useSelector((state) => state[PARAM_CENTER_LABEL]);
const diagonalName = useSelector((state) => state[PARAM_DIAGONAL_LABEL]);
const componentLibrary = useSelector((state) => state[PARAM_COMPONENT_LIBRARY]);
const language = useSelector((state) => state[PARAM_LANGUAGE]);
interface PositionDiagramPaneProps {
open: boolean;
onClose: () => void;
voltageLevelId: any;
currentNodeUuid: string;
studyUuid: string;
}

const [svgUrl, setSvgUrl] = useState(null);
const PositionDiagramPane: FC<PositionDiagramPaneProps> = ({
open,
onClose,
voltageLevelId,
currentNodeUuid,
studyUuid,
}) => {
const useName = useSelector((state: AppState) => state[PARAM_USE_NAME]);
const centerName = useSelector((state: AppState) => state[PARAM_CENTER_LABEL]);
const diagonalName = useSelector((state: AppState) => state[PARAM_DIAGONAL_LABEL]);
const componentLibrary = useSelector((state: AppState) => state[PARAM_COMPONENT_LIBRARY]);
const language = useSelector((state: AppState) => state[PARAM_LANGUAGE]);

const [svgUrl, setSvgUrl] = useState<string | null>(null);
const handleClose = () => {
setSvgUrl(null);
onClose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,55 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import React, { forwardRef, useEffect, useLayoutEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';

import React, { forwardRef, useEffect, useLayoutEffect, useRef, useState, Ref } from 'react';
import { useSelector } from 'react-redux';

import Box from '@mui/material/Box';
import { useTheme } from '@mui/material/styles';
import LinearProgress from '@mui/material/LinearProgress';
import { SingleLineDiagramViewer } from '@powsybl/diagram-viewer';
import { styles, MAX_HEIGHT_VOLTAGE_LEVEL, MAX_WIDTH_VOLTAGE_LEVEL, NoSvg, MIN_WIDTH } from '../diagram-common';
import { styles, MAX_HEIGHT_VOLTAGE_LEVEL, MAX_WIDTH_VOLTAGE_LEVEL, NoSvg, MIN_WIDTH, Svg } from '../diagram-common';
import { useIntlRef, useSnackMessage } from '@gridsuite/commons-ui';
import { Paper } from '@mui/material';
import DiagramHeader from '../diagram-header';
import { fetchSvg } from '../../../services/study';
import { mergeSx } from '../../utils/functions';

const PositionDiagram = forwardRef((props, ref) => {
const [svg, setSvg] = useState(NoSvg);
import { AppState } from 'redux/reducer';

interface PositionDiagramProps {
diagramTitle: string;
svgUrl: string | null;
onClose: () => void;
svgType: string;
disabled?: boolean;
}

const PositionDiagram = forwardRef((props: PositionDiagramProps, ref: Ref<HTMLDivElement>) => {
// fixme : HTMLDivElement is the correct type ?
const [svg, setSvg] = useState<Svg>({
svg: null,
metadata: null,
additionalMetadata: null,
error: null,
svgUrl: null,
});
const svgUrl = useRef('');
const svgDraw = useRef();
const svgDraw = useRef<SingleLineDiagramViewer | null>(null);
const { snackError } = useSnackMessage();
const intlRef = useIntlRef();
const svgRef = useRef();
const svgRef = useRef<HTMLDivElement>();
const { svgType, disabled } = props;

const currentNode = useSelector((state) => state.currentTreeNode);
const currentNode = useSelector((state: AppState) => state.currentTreeNode);

const [loadingState, updateLoadingState] = useState(false);
const [loadingState, updateLoadingState] = useState<boolean>(false);

const theme = useTheme();

// using many useState() calls with literal values only to
// easily avoid recomputing stuff when updating with the same values
const [serverHeight, setServerHeight] = useState(0);
const [serverWidth, setServerWidth] = useState(0);
const [serverHeight, setServerHeight] = useState<number>(0);
const [serverWidth, setServerWidth] = useState<number>(0);

useEffect(() => {
if (props.svgUrl) {
Expand All @@ -50,6 +64,7 @@ const PositionDiagram = forwardRef((props, ref) => {
setSvg({
svg: data.svg,
metadata: data.metadata,
additionalMetadata: data.additionalMetadata,
error: null,
svgUrl: props.svgUrl,
});
Expand All @@ -63,6 +78,7 @@ const PositionDiagram = forwardRef((props, ref) => {
setSvg({
svg: null,
metadata: null,
additionalMetadata: null,
error: errorMessage,
svgUrl: props.svgUrl,
});
Expand All @@ -85,26 +101,39 @@ const PositionDiagram = forwardRef((props, ref) => {
let viewboxMaxWidth = MAX_WIDTH_VOLTAGE_LEVEL;
let viewboxMaxHeight = MAX_HEIGHT_VOLTAGE_LEVEL;
let selectionBackColor = theme.palette.background.paper;
const container = svgRef.current;
if (!container) {
return;
}

const sldViewer = new SingleLineDiagramViewer(
svgRef.current, //container
container, //container
svg.svg, //svgContent
svg.metadata, //svg metadata
svgType,
0,
0,
viewboxMaxWidth,
viewboxMaxHeight,
selectionBackColor //arrows color
null,
null,
null,
null,
selectionBackColor, //arrows color
null
);

setServerHeight(sldViewer.getHeight());
setServerWidth(sldViewer.getWidth());

if (svgDraw.current && svgUrl.current === svg.svgUrl) {
sldViewer.setViewBox(svgDraw.current.getViewBox());
const viewBox = svgDraw.current.getViewBox();
if (viewBox) {
sldViewer.setViewBox(viewBox);
}
}
if (svg.svgUrl) {
svgUrl.current = svg.svgUrl;
}
svgUrl.current = svg.svgUrl;
svgDraw.current = sldViewer;
}
}, [svg, currentNode, svgType, theme, ref, disabled, loadingState]);
Expand All @@ -113,10 +142,10 @@ const PositionDiagram = forwardRef((props, ref) => {
if (serverWidth && serverHeight) {
const divElt = svgRef.current;
if (divElt != null) {
const svgEl = divElt.getElementsByTagName('svg')[0];
const svgEl = divElt.getElementsByTagName('svg')[0] as SVGElement;
if (svgEl != null) {
svgEl.setAttribute('width', serverWidth);
svgEl.setAttribute('height', serverHeight);
svgEl.setAttribute('width', serverWidth.toString());
svgEl.setAttribute('height', serverHeight.toString());
}
}
}
Expand Down Expand Up @@ -160,12 +189,4 @@ const PositionDiagram = forwardRef((props, ref) => {
);
});

PositionDiagram.propTypes = {
diagramTitle: PropTypes.string.isRequired,
svgUrl: PropTypes.string,
onClose: PropTypes.func,
svgType: PropTypes.string.isRequired,
disabled: PropTypes.bool,
};

export default PositionDiagram;
Loading
Loading