diff --git a/shell/src/PluginLoader.js b/shell/src/PluginLoader.js index 109fe0b2..ee7c900e 100644 --- a/shell/src/PluginLoader.js +++ b/shell/src/PluginLoader.js @@ -2,7 +2,74 @@ import AppAdapter from '@dhis2/app-adapter' import { Layer, layers, CenteredContent, CircularLoader } from '@dhis2/ui' import postRobot from 'post-robot' import PropTypes from 'prop-types' -import React, { useCallback, useEffect, useState } from 'react' +import React, { useCallback, useEffect, useRef, useState } from 'react' + +const PluginInner = ({ + D2App, + config, + propsFromParent, + resizePluginHeight, + resizePluginWidth, +}) => { + const divRef = useRef() + const innerDivRef = useRef() + useEffect(() => { + if (divRef && divRef.current && resizePluginHeight) { + const resizeObserver = new ResizeObserver(() => { + // the additional pixels currently account for possible horizontal scroll bar + if (resizePluginHeight) { + resizePluginHeight(divRef.current.offsetHeight + 20) + } + }) + resizeObserver.observe(divRef.current) + } + }, [resizePluginHeight]) + + const previousWidth = useRef() + + const resetWidth = useCallback(() => { + const currentWidth = innerDivRef.current?.scrollWidth + if (resizePluginWidth && currentWidth) { + if ( + previousWidth.current && + Math.abs(currentWidth - previousWidth.current) > 20 + ) { + resizePluginWidth(currentWidth + 20) + } + previousWidth.current = currentWidth + } + requestAnimationFrame(resetWidth) + }, [resizePluginWidth]) + + useEffect(() => { + if (resizePluginWidth) { + requestAnimationFrame(resetWidth) + } + }, [resetWidth, resizePluginWidth]) + + // inner div disables margin collapsing which would prevent computing correct height + return ( +
+
+
+ +
+
+
+ ) +} + +PluginInner.propTypes = { + D2App: PropTypes.object, + config: PropTypes.object, + propsFromParent: PropTypes.array, + resizePluginHeight: PropTypes.func, + resizePluginWidth: PropTypes.func, +} export const PluginLoader = ({ config, requiredProps, D2App }) => { const [propsFromParent, setPropsFromParent] = useState({}) @@ -11,6 +78,8 @@ export const PluginLoader = ({ config, requiredProps, D2App }) => { const [showAlertsInPlugin, setShowAlertsInPlugin] = useState(false) const [onPluginError, setOnPluginError] = useState(() => () => {}) const [clearPluginError, setClearPluginError] = useState(() => () => {}) + const [resizePluginHeight, setResizePluginHeight] = useState(null) + const [resizePluginWidth, setResizePluginWidth] = useState(null) const receivePropsFromParent = useCallback( (event) => { @@ -20,6 +89,10 @@ export const PluginLoader = ({ config, requiredProps, D2App }) => { setCommunicationReceived, alertsAdd, showAlertsInPlugin, + height, + setPluginHeight, + width, + setPluginWidth, onError, ...explicitlyPassedProps } = receivedProps @@ -61,6 +134,14 @@ export const PluginLoader = ({ config, requiredProps, D2App }) => { if (showAlertsInPlugin) { setShowAlertsInPlugin(Boolean(showAlertsInPlugin)) } + + if (!height && setPluginHeight) { + setResizePluginHeight(() => (height) => setPluginHeight(height)) + } + + if (!width && setPluginWidth) { + setResizePluginWidth(() => (width) => setPluginWidth(width)) + } }, [ requiredProps, @@ -68,6 +149,8 @@ export const PluginLoader = ({ config, requiredProps, D2App }) => { setClearPluginError, setParentAlertsAdd, setShowAlertsInPlugin, + setResizePluginHeight, + setResizePluginWidth, ] ) @@ -120,7 +203,13 @@ export const PluginLoader = ({ config, requiredProps, D2App }) => { } > - + )