diff --git a/i18n/en.pot b/i18n/en.pot index fa8cab2e1..b8b8739fb 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,8 +5,8 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2024-12-19T11:30:27.893Z\n" -"PO-Revision-Date: 2024-12-19T11:30:27.893Z\n" +"POT-Creation-Date: 2025-01-16T10:42:35.281Z\n" +"PO-Revision-Date: 2025-01-16T10:42:35.283Z\n" msgid "Untitled dashboard" msgstr "Untitled dashboard" @@ -120,8 +120,17 @@ msgstr "Search for a dashboard" msgid "No dashboards found" msgstr "No dashboards found" -msgid "{{appKey}} app not found" -msgstr "{{appKey}} app not found" +msgid "There was a problem loading this dashboard item" +msgstr "There was a problem loading this dashboard item" + +msgid "Open menu" +msgstr "Open menu" + +msgid "Open in {{appName}}" +msgstr "Open in {{appName}}" + +msgid "View fullscreen" +msgstr "View fullscreen" msgid "Remove this item" msgstr "Remove this item" @@ -129,6 +138,18 @@ msgstr "Remove this item" msgid "This item has been shortened to fit on one page" msgstr "This item has been shortened to fit on one page" +msgid "The plugin needed to display this item is not available" +msgstr "The plugin needed to display this item is not available" + +msgid "Install the {{pluginName}} plugin from the App Hub" +msgstr "Install the {{pluginName}} plugin from the App Hub" + +msgid "There was an error loading data for this item" +msgstr "There was an error loading data for this item" + +msgid "Open this item in {{appName}}" +msgstr "Open this item in {{appName}}" + msgid "Remove" msgstr "Remove" @@ -174,24 +195,15 @@ msgstr "Only Period and Organisation unit filters can be applied to this item" msgid "Some filters not applied" msgstr "Some filters not applied" -msgid "There was a problem loading this dashboard item" -msgstr "There was a problem loading this dashboard item" - msgid "Hide details and interpretations" msgstr "Hide details and interpretations" msgid "Show details and interpretations" msgstr "Show details and interpretations" -msgid "Open menu" -msgstr "Open menu" - msgid "Open in {{appName}} app" msgstr "Open in {{appName}} app" -msgid "View fullscreen" -msgstr "View fullscreen" - msgid "This map can't be displayed as a chart" msgstr "This map can't be displayed as a chart" @@ -216,39 +228,45 @@ msgstr "View as Map" msgid "There was a problem loading interpretations for this item" msgstr "There was a problem loading interpretations for this item" -msgid "The plugin for rendering this item is not available" -msgstr "The plugin for rendering this item is not available" - -msgid "Install the {{appName}} app from the App Hub" -msgstr "Install the {{appName}} app from the App Hub" - msgid "No data to display" msgstr "No data to display" msgid "" -"Install Line Listing app version ${minLLVersion.join(\n" -" '.'\n" -" )} or higher in order to display this item." +"Install Data Visualizer app ${minDVVersion.join(\n" +" '.'\n" +" )} or higher in order to display this item." msgstr "" -"Install Line Listing app version ${minLLVersion.join(\n" -" '.'\n" -" )} or higher in order to display this item." +"Install Data Visualizer app ${minDVVersion.join(\n" +" '.'\n" +" )} or higher in order to display this item." msgid "Show without filters" msgstr "Show without filters" +msgid "" +"Install Line Listing app ${minLLVersion.join(\n" +" '.'\n" +" )} or higher in order to display this item." +msgstr "" +"Install Line Listing app ${minLLVersion.join(\n" +" '.'\n" +" )} or higher in order to display this item." + msgid "Maps with Earth Engine layers cannot be displayed when offline" msgstr "Maps with Earth Engine layers cannot be displayed when offline" +msgid "" +"Install Maps app ${minMapsVersion.join(\n" +" '.'\n" +" )} or higher in order to display this item." +msgstr "" +"Install Maps app ${minMapsVersion.join(\n" +" '.'\n" +" )} or higher in order to display this item." + msgid "Unable to load the plugin for this item" msgstr "Unable to load the plugin for this item" -msgid "There was an error loading data for this item" -msgstr "There was an error loading data for this item" - -msgid "Open this item in {{appName}}" -msgstr "Open this item in {{appName}}" - msgid "Resources" msgstr "Resources" diff --git a/package.json b/package.json index c651ae390..4d11e0901 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,10 @@ "license": "BSD-3-Clause", "dependencies": { "@dhis2/analytics": "^26.9.4", - "@dhis2/app-runtime": "^3.10.6", + "@dhis2/app-runtime": "^3.11.3", "@dhis2/app-runtime-adapter-d2": "^1.1.0", "@dhis2/d2-i18n": "^1.1.3", "@dhis2/ui": "^10.1.4", - "@krakenjs/post-robot": "^11.0.0", "classnames": "^2.3.2", "d2": "^31.10.0", "d2-utilizr": "^0.2.16", @@ -68,7 +67,8 @@ }, "jest": { "moduleNameMapper": { - "^.+\\.(css|sass|scss)$": "identity-obj-proxy" + "^.+\\.(css|sass|scss)$": "identity-obj-proxy", + "@dhis2/app-runtime/experimental": "/node_modules/@dhis2/app-runtime/build/cjs/experimental.js" }, "setupFilesAfterEnv": [ "/config/testSetup.js" diff --git a/src/AppWrapper.js b/src/AppWrapper.js index a0258eeaf..c9f8dc725 100644 --- a/src/AppWrapper.js +++ b/src/AppWrapper.js @@ -43,10 +43,16 @@ const query = { } const providerDataTransformation = ({ rootOrgUnits, apps, currentUser }) => { + const dataVisualizerApp = + apps.find((app) => app.key === 'data-visualizer') || {} const lineListingApp = apps.find((app) => app.key === 'line-listing') || {} + const mapsApp = apps.find((app) => app.key === 'maps') || {} + return { rootOrgUnits: rootOrgUnits.organisationUnits, + dataVisualizerAppVersion: dataVisualizerApp.version || '0.0.0', lineListingAppVersion: lineListingApp.version || '0.0.0', + mapsAppVersion: mapsApp.version || '0.0.0', currentUser, apps, } diff --git a/src/components/DropdownButton/DropdownButton.js b/src/components/DropdownButton/DropdownButton.js index 0e4125570..2f1e8c4a2 100644 --- a/src/components/DropdownButton/DropdownButton.js +++ b/src/components/DropdownButton/DropdownButton.js @@ -25,7 +25,7 @@ const DropdownButton = ({ {open && ( - + {component} diff --git a/src/components/Item/AppItem/Item.js b/src/components/Item/AppItem/Item.js index 57ed1bf9b..f92bec205 100644 --- a/src/components/Item/AppItem/Item.js +++ b/src/components/Item/AppItem/Item.js @@ -1,69 +1,213 @@ +// eslint-disable-next-line import/no-unresolved +import { Plugin } from '@dhis2/app-runtime/experimental' import i18n from '@dhis2/d2-i18n' -import { Divider, colors, spacers, IconQuestion24 } from '@dhis2/ui' import cx from 'classnames' import PropTypes from 'prop-types' -import React from 'react' -import { connect } from 'react-redux' -import { EDIT, isEditMode } from '../../../modules/dashboardModes.js' +import React, { + useCallback, + useMemo, + useReducer, + useRef, + useState, +} from 'react' +import { useSelector, useDispatch } from 'react-redux' +import { acSetSlideshow } from '../../../actions/slideshow.js' +import { + EDIT, + isEditMode, + isViewMode, +} from '../../../modules/dashboardModes.js' +import { APP } from '../../../modules/itemTypes.js' +import { useCacheableSection } from '../../../modules/useCacheableSection.js' import { sGetItemFiltersRoot, DEFAULT_STATE_ITEM_FILTERS, } from '../../../reducers/itemFilters.js' +import { sGetSelectedId } from '../../../reducers/selected.js' +import FatalErrorBoundary from '../FatalErrorBoundary.js' +import { isFullscreenSupported } from '../fullscreenUtil.js' +import { getAvailableDimensions } from '../getAvailableDimensions.js' import ItemHeader from '../ItemHeader/ItemHeader.js' +import itemHeaderClasses from '../ItemHeader/styles/ItemHeader.module.css' +import MissingPluginMessage from '../ItemMessage/MissingPluginMessage.js' import { getIframeSrc } from './getIframeSrc.js' +import { ItemContextMenu } from './ItemContextMenu.js' import styles from './styles/AppItem.module.css' -const AppItem = ({ dashboardMode, item, itemFilters, apps, isFullscreen }) => { - let appDetails - - const appKey = item.appKey +const AppItem = ({ + dashboardMode, + windowDimensions, + item, + apps, + sortIndex, + isFullscreen, +}) => { + const contentRef = useRef(null) + const headerRef = useRef(null) + const [isMounted, setIsMounted] = useState(false) + const dashboardId = useSelector(sGetSelectedId) + const isSlideshowView = useSelector((state) => state.slideshow !== null) + let itemFilters = useSelector(sGetItemFiltersRoot) + const dispatch = useDispatch() - if (appKey) { - appDetails = apps.find((app) => app.key === appKey) + if (isEditMode(dashboardMode)) { + itemFilters = DEFAULT_STATE_ITEM_FILTERS } + const { isCached } = useCacheableSection(dashboardId) + + const [loadItemFailed, setLoadItemFailed] = useState(false) + + const appDetails = + item?.appKey && apps.find((app) => app.key === item.appKey) + + const [{ itemTitle, appUrl, onRemove }, setItemDetails] = useReducer( + (state, newState) => ({ + ...state, + ...newState, + appUrl: `${appDetails?.launchUrl}${newState.appUrl}`, + }), + { + itemTitle: appDetails?.name, + appUrl: appDetails?.launchUrl, + } + ) + + const pluginProps = useMemo( + () => ({ + dashboardItemId: item.id, + dashboardItemFilters: itemFilters, + dashboardMode, + // Edit mode does not have the hamburger menu. + // Don't assume the plugin checks for this function before calling it + setDashboardItemDetails: setItemDetails, + cacheId: `${dashboardId}-${item.id}`, + isParentCached: isCached, + }), + [dashboardId, dashboardMode, item.id, isCached, itemFilters] + ) + + // https://docs.dhis2.org/en/develop/apps/application-manifest.html#apps_creating_apps const hideTitle = appDetails?.settings?.dashboardWidget?.hideTitle && dashboardMode !== EDIT - return appDetails && appDetails.name && appDetails.launchUrl ? ( - <> - {!hideTitle && ( - <> - - - - )} + const onElementMount = useCallback((node) => { + if (node === null || (headerRef.current && contentRef.current)) { + return + } + + if (node.classList.contains(itemHeaderClasses.itemHeaderWrap)) { + headerRef.current = node + } else if (node.classList.contains('content')) { + contentRef.current = node + } + + if (headerRef.current && contentRef.current) { + setIsMounted(true) + } + }, []) + + const renderPlugin = (iframeSrc) => { + // style must be computed at runtime. + // header/content elements need to be rendered first, otherwise the dimensions returned are the previous ones + const style = + headerRef.current && contentRef.current + ? getAvailableDimensions({ + item, + headerRef, + contentRef, + dashboardMode, + windowDimensions, + isFullscreen, + }) + : {} + + // we need width and height in order for resizing to work properly with the platform's plugin components + if (!(style.width && style.height)) { + return null + } + + return appDetails?.appType === APP ? ( + // modern plugins + + ) : ( + // legacy widgets + ) : null} ) @@ -254,7 +173,6 @@ IframePlugin.propTypes = { activeType: PropTypes.string, dashboardId: PropTypes.string, dashboardMode: PropTypes.string, - filterVersion: PropTypes.string, isFirstOfType: PropTypes.bool, itemId: PropTypes.string, itemType: PropTypes.string, diff --git a/src/components/Item/VisualizationItem/Visualization/MissingPluginMessage.js b/src/components/Item/VisualizationItem/Visualization/MissingPluginMessage.js deleted file mode 100644 index f8a2f2da2..000000000 --- a/src/components/Item/VisualizationItem/Visualization/MissingPluginMessage.js +++ /dev/null @@ -1,41 +0,0 @@ -import i18n from '@dhis2/d2-i18n' -import { Center } from '@dhis2/ui' -import PropTypes from 'prop-types' -import React from 'react' -import { isPrintMode } from '../../../../modules/dashboardModes.js' -import { getAppName } from '../../../../modules/itemTypes.js' -import classes from './styles/VisualizationErrorMessage.module.css' - -const MissingPluginMessage = ({ itemType, dashboardMode }) => { - return ( -
-

- {i18n.t('The plugin for rendering this item is not available')} -

- {!isPrintMode(dashboardMode) ? ( -

- e.stopPropagation()} - target="_blank" - rel="noopener noreferrer" - href="/dhis-web-app-management/index.html#/app-hub" - > - {i18n.t( - 'Install the {{appName}} app from the App Hub', - { - appName: getAppName(itemType), - } - )} - -

- ) : null} -
- ) -} - -MissingPluginMessage.propTypes = { - dashboardMode: PropTypes.string, - itemType: PropTypes.string, -} - -export default MissingPluginMessage diff --git a/src/components/Item/VisualizationItem/Visualization/PluginWarningMessage.js b/src/components/Item/VisualizationItem/Visualization/PluginWarningMessage.js new file mode 100644 index 000000000..ca0c74e5a --- /dev/null +++ b/src/components/Item/VisualizationItem/Visualization/PluginWarningMessage.js @@ -0,0 +1,20 @@ +import { Cover, IconWarning24, colors } from '@dhis2/ui' +import PropTypes from 'prop-types' +import React from 'react' +import classes from './styles/Visualization.module.css' + +export const PluginWarningMessage = ({ style, message }) => ( +
+ +
+ + {message} +
+
+
+) + +PluginWarningMessage.propTypes = { + message: PropTypes.string, + style: PropTypes.object, +} diff --git a/src/components/Item/VisualizationItem/Visualization/Visualization.js b/src/components/Item/VisualizationItem/Visualization/Visualization.js index dbbff8960..7912599e3 100644 --- a/src/components/Item/VisualizationItem/Visualization/Visualization.js +++ b/src/components/Item/VisualizationItem/Visualization/Visualization.js @@ -1,15 +1,19 @@ import { useCachedDataQuery } from '@dhis2/analytics' import { useDhis2ConnectionStatus } from '@dhis2/app-runtime' import i18n from '@dhis2/d2-i18n' -import { Button, Cover, IconInfo24, IconWarning24, colors } from '@dhis2/ui' +import { Button, Cover, IconInfo24, colors } from '@dhis2/ui' import uniqueId from 'lodash/uniqueId.js' import PropTypes from 'prop-types' -import React, { useMemo } from 'react' +import React, { useCallback, useMemo } from 'react' import { useSelector } from 'react-redux' import { + isDVVersionCompatible, isLLVersionCompatible, + isMapsVersionCompatible, + minDVVersion, minLLVersion, -} from '../../../../modules/isLLVersionCompatible.js' + minMapsVersion, +} from '../../../../modules/isAppVersionCompatible.js' import { VISUALIZATION, EVENT_VISUALIZATION, @@ -23,6 +27,7 @@ import getVisualizationConfig from './getVisualizationConfig.js' import IframePlugin from './IframePlugin.js' import LegacyPlugin from './LegacyPlugin.js' import { pluginIsAvailable } from './plugin.js' +import { PluginWarningMessage } from './PluginWarningMessage.js' import classes from './styles/Visualization.module.css' const mapHasEELayer = (visualization) => @@ -33,8 +38,7 @@ const Visualization = ({ activeType, item, itemFilters, - availableHeight, - availableWidth, + style, gridWidth, dashboardMode, originalType, @@ -44,23 +48,12 @@ const Visualization = ({ }) => { const dashboardId = useSelector(sGetSelectedId) const { isDisconnected: offline } = useDhis2ConnectionStatus() - const { lineListingAppVersion, apps } = useCachedDataQuery() - - // NOTE: - // The following is all memoized because the IframePlugin (and potentially others) - // are wrapped in React.memo() to avoid unnecessary re-renders - // The main problem here was `item` which changes height when the interpretations panel is toggled - // causing all the chain of components to re-render. - // The only dependency using `item` is `item.id` which doesn't change so the memoized plugin props - // should also always be the same regardless of the `item` details. - - const style = useMemo( - () => ({ - height: availableHeight, - width: availableWidth || undefined, - }), - [availableHeight, availableWidth] - ) + const { + dataVisualizerAppVersion, + lineListingAppVersion, + mapsAppVersion, + apps, + } = useCachedDataQuery() const visualizationConfig = useMemo(() => { if (originalType === EVENT_VISUALIZATION) { @@ -73,14 +66,13 @@ const Visualization = ({ ) }, [visualization, activeType, originalType, itemFilters]) - const filterVersion = useMemo(() => uniqueId(), []) + const filterVersion = useCallback(() => uniqueId(), []) const iFramePluginProps = useMemo( () => ({ originalType, activeType, style, - filterVersion, dashboardMode, dashboardId, itemId: item.id, @@ -91,7 +83,6 @@ const Visualization = ({ originalType, activeType, style, - filterVersion, dashboardMode, dashboardId, item.id, @@ -102,34 +93,10 @@ const Visualization = ({ if (!visualization) { return ( -
- -
- - {i18n.t('No data to display')} -
-
-
- ) - } - - if ( - activeType === EVENT_VISUALIZATION && - !isLLVersionCompatible(lineListingAppVersion) - ) { - return ( -
- -
- - {i18n.t( - `Install Line Listing app version ${minLLVersion.join( - '.' - )} or higher in order to display this item.` - )} -
-
-
+ ) } @@ -137,15 +104,24 @@ const Visualization = ({ case CHART: case REPORT_TABLE: case VISUALIZATION: { - return ( + return isDVVersionCompatible(dataVisualizerAppVersion) ? ( + ) : ( + ) } case EVENT_VISUALIZATION: { - return ( + return isLLVersionCompatible(lineListingAppVersion) ? ( <> {showNoFiltersOverlay ? (
@@ -171,49 +147,61 @@ const Visualization = ({ {...iFramePluginProps} /> + ) : ( + ) } case MAP: { - return offline && mapHasEELayer(visualizationConfig) ? ( -
- -
- - - {i18n.t( - 'Maps with Earth Engine layers cannot be displayed when offline' - )} - -
-
-
+ return isMapsVersionCompatible(mapsAppVersion) ? ( + offline && mapHasEELayer(visualizationConfig) ? ( +
+ +
+ + + {i18n.t( + 'Maps with Earth Engine layers cannot be displayed when offline' + )} + +
+
+
+ ) : ( + + ) ) : ( - ) } default: { return !pluginIsAvailable(activeType || item.type, apps) ? ( -
- -
- - - {i18n.t( - 'Unable to load the plugin for this item' - )} - -
-
-
+ ) : ( ( - - - - - - - -) - -const VisualizationErrorMessage = ({ - itemType, - dashboardMode, - visualizationId, -}) => { - const { baseUrl } = useConfig() - - const visHref = `${baseUrl}/${itemTypeMap[itemType].appUrl( - visualizationId - )}` - - return ( -
- {getErrorIcon()} -

- {i18n.t('There was an error loading data for this item')} -

- {!isPrintMode(dashboardMode) ? ( -

- e.stopPropagation()} - target="_blank" - rel="noopener noreferrer" - href={visHref} - > - {i18n.t('Open this item in {{appName}}', { - appName: getAppName(itemType), - })} - -

- ) : null} -
- ) -} - -VisualizationErrorMessage.propTypes = { - dashboardMode: PropTypes.string, - itemType: PropTypes.string, - visualizationId: PropTypes.string, -} - -export default VisualizationErrorMessage diff --git a/src/components/Item/VisualizationItem/Visualization/__tests__/Visualization.spec.js b/src/components/Item/VisualizationItem/Visualization/__tests__/Visualization.spec.js index 9bf07295a..a9fb6cd2a 100644 --- a/src/components/Item/VisualizationItem/Visualization/__tests__/Visualization.spec.js +++ b/src/components/Item/VisualizationItem/Visualization/__tests__/Visualization.spec.js @@ -49,7 +49,7 @@ test('renders a VisualizationPlugin when activeType is MAP', () => { }} activeType="MAP" itemFilters={{}} - availableHeight={500} + style={{ height: '500px' }} /> ) @@ -67,7 +67,7 @@ test('renders a VisualizationPlugin for CHART', () => { }} activeType="CHART" itemFilters={{}} - availableHeight={500} + style={{ height: '500px' }} /> ) @@ -85,7 +85,7 @@ test('renders a VisualizationPlugin for REPORT_TABLE', () => { }} activeType="REPORT_TABLE" itemFilters={{}} - availableHeight={500} + style={{ height: '500px' }} /> ) @@ -103,7 +103,7 @@ test('renders a DefaultPlugin when activeType is EVENT_CHART', () => { }} activeType="EVENT_CHART" itemFilters={{}} - availableHeight={500} + style={{ height: '500px' }} /> ) @@ -121,7 +121,7 @@ test('renders a DefaultPlugin when activeType is EVENT_REPORT', () => { }} activeType="EVENT_REPORT" itemFilters={{}} - availableHeight={500} + style={{ height: '500px' }} /> ) @@ -146,7 +146,7 @@ test('renders NoVisMessage when no visualization', () => { }} activeType="CHART" itemFilters={{}} - availableHeight={500} + style={{ height: '500px' }} /> ) diff --git a/src/components/Item/VisualizationItem/__tests__/Item.spec.js b/src/components/Item/VisualizationItem/__tests__/Item.spec.js index d151fd193..b6180d72a 100644 --- a/src/components/Item/VisualizationItem/__tests__/Item.spec.js +++ b/src/components/Item/VisualizationItem/__tests__/Item.spec.js @@ -5,7 +5,7 @@ import configureMockStore from 'redux-mock-store' import { apiFetchVisualization } from '../../../../api/fetchVisualization.js' import SystemSettingsProvider from '../../../SystemSettingsProvider.js' import WindowDimensionsProvider from '../../../WindowDimensionsProvider.js' -import Item from '../Item.js' +import { Item } from '../../Item.js' jest.mock('../../../../api/fetchVisualization') jest.mock('../../../SystemSettingsProvider') diff --git a/src/components/Item/VisualizationItem/assets/icons.js b/src/components/Item/VisualizationItem/assets/icons.js deleted file mode 100644 index 5ade2c42f..000000000 --- a/src/components/Item/VisualizationItem/assets/icons.js +++ /dev/null @@ -1,15 +0,0 @@ -import { colors } from '@dhis2/ui' -import React from 'react' - -export const Warning = () => ( - - - - -) diff --git a/src/components/Item/VisualizationItem/__tests__/memoizeOne.spec.js b/src/components/Item/__tests__/memoizeOne.spec.js similarity index 100% rename from src/components/Item/VisualizationItem/__tests__/memoizeOne.spec.js rename to src/components/Item/__tests__/memoizeOne.spec.js diff --git a/src/components/Item/fullscreenUtil.js b/src/components/Item/fullscreenUtil.js new file mode 100644 index 000000000..4c2de7978 --- /dev/null +++ b/src/components/Item/fullscreenUtil.js @@ -0,0 +1,6 @@ +import { getGridItemElement } from './getGridItemElement.js' + +export const isFullscreenSupported = (itemId) => { + const el = getGridItemElement(itemId) + return !!(el?.requestFullscreen || el?.webkitRequestFullscreen) +} diff --git a/src/components/Item/getAvailableDimensions.js b/src/components/Item/getAvailableDimensions.js new file mode 100644 index 000000000..5fdd2364d --- /dev/null +++ b/src/components/Item/getAvailableDimensions.js @@ -0,0 +1,81 @@ +import { isEditMode, isPrintMode } from '../../modules/dashboardModes.js' +import { getItemHeightPx } from '../../modules/gridUtil.js' +import { getGridItemElement } from './getGridItemElement.js' +import memoizeOne from './memoizeOne.js' + +const MIN_CLIENT_HEIGHT = 16 +const FS_CONTROLS_BUFFER = 40 // space for the fullscreen controls at bottom of screen + +export const getAvailableDimensions = ({ + item, + headerRef, + contentRef, + dashboardMode, + windowDimensions, + isFullscreen, +}) => { + const style = window.getComputedStyle(document.documentElement) + + const itemContentPadding = parseInt( + style.getPropertyValue('--item-content-padding').replace('px', '') + ) + + const itemHeaderTotalMargin = + parseInt( + style.getPropertyValue('--item-header-margin-top').replace('px', '') + ) + + parseInt( + style + .getPropertyValue('--item-header-margin-bottom') + .replace('px', '') + ) + + const memoizedGetContentHeight = memoizeOne( + (calculatedHeight, measuredHeight, preferMeasured) => + preferMeasured + ? measuredHeight || calculatedHeight + : calculatedHeight + ) + + const getAvailableHeight = ({ width }) => { + if (isFullscreen) { + const totalNonVisHeight = + (headerRef.current.clientHeight || MIN_CLIENT_HEIGHT) + + itemHeaderTotalMargin + + (isFullscreen ? 0 : itemContentPadding) + + FS_CONTROLS_BUFFER + + return `calc(100vh - ${totalNonVisHeight}px)` + } + + const calculatedHeight = + getItemHeightPx(item, width) - + headerRef.current.clientHeight - + itemHeaderTotalMargin - + itemContentPadding + + const height = memoizedGetContentHeight( + calculatedHeight, + contentRef.current ? contentRef.current.offsetHeight : null, + isEditMode(dashboardMode) || isPrintMode(dashboardMode) + ) + + return `${height}px` + } + + const getAvailableWidth = () => { + if (isFullscreen) { + return '100%' + } + const rect = getGridItemElement(item.id)?.getBoundingClientRect() + + return rect && rect.width - itemContentPadding * 2 + } + + const res = { + height: getAvailableHeight(windowDimensions), + width: getAvailableWidth() || undefined, + } + + return res +} diff --git a/src/components/Item/VisualizationItem/getGridItemElement.js b/src/components/Item/getGridItemElement.js similarity index 54% rename from src/components/Item/VisualizationItem/getGridItemElement.js rename to src/components/Item/getGridItemElement.js index 43653423b..230bfb95a 100644 --- a/src/components/Item/VisualizationItem/getGridItemElement.js +++ b/src/components/Item/getGridItemElement.js @@ -1,4 +1,4 @@ -import { getGridItemDomElementClassName } from '../../../modules/getGridItemDomElementClassName.js' +import { getGridItemDomElementClassName } from '../../modules/getGridItemDomElementClassName.js' export const getGridItemElement = (itemId) => document.querySelector(`.${getGridItemDomElementClassName(itemId)}`) diff --git a/src/components/Item/VisualizationItem/memoizeOne.js b/src/components/Item/memoizeOne.js similarity index 91% rename from src/components/Item/VisualizationItem/memoizeOne.js rename to src/components/Item/memoizeOne.js index 70a38e45e..839c10f3b 100644 --- a/src/components/Item/VisualizationItem/memoizeOne.js +++ b/src/components/Item/memoizeOne.js @@ -3,8 +3,8 @@ // Inspiration: https://github.com/alexreardon/memoize-one const memoizeOne = (fn) => { - let lastArgs = undefined - let lastValue = undefined + let lastArgs + let lastValue return (...args) => { if ( diff --git a/src/components/Item/VisualizationItem/styles/FatalErrorBoundary.module.css b/src/components/Item/styles/FatalErrorBoundary.module.css similarity index 63% rename from src/components/Item/VisualizationItem/styles/FatalErrorBoundary.module.css rename to src/components/Item/styles/FatalErrorBoundary.module.css index 270ca682a..88e9911de 100644 --- a/src/components/Item/VisualizationItem/styles/FatalErrorBoundary.module.css +++ b/src/components/Item/styles/FatalErrorBoundary.module.css @@ -6,12 +6,3 @@ inset-inline-start: 50%; transform: translate(-50%, -50%); } - -.icon { - vertical-align: middle; - margin-inline-end: 3px; -} - -.message { - font-size: 13px; -} diff --git a/src/modules/__tests__/isLLVersionCompatible.spec.js b/src/modules/__tests__/isAppVersionCompatible.spec.js similarity index 67% rename from src/modules/__tests__/isLLVersionCompatible.spec.js rename to src/modules/__tests__/isAppVersionCompatible.spec.js index bc8201e3c..fb197c55a 100644 --- a/src/modules/__tests__/isLLVersionCompatible.spec.js +++ b/src/modules/__tests__/isAppVersionCompatible.spec.js @@ -1,12 +1,11 @@ -import { isLLVersionCompatible } from '../isLLVersionCompatible.js' +import { isLLVersionCompatible } from '../isAppVersionCompatible.js' const testcases = [ - ['100.6.1', true], + ['101.1.9', true], ['100.5.9', false], - ['100.6.0', true], - ['101.0.0', true], + ['101.2.0', true], ['100.0.9', false], - ['100.6.0-alpha', true], + ['101.2.0-alpha', true], ['100.5.9-beta', false], ] diff --git a/src/modules/isAppVersionCompatible.js b/src/modules/isAppVersionCompatible.js new file mode 100644 index 000000000..364b3a8b8 --- /dev/null +++ b/src/modules/isAppVersionCompatible.js @@ -0,0 +1,28 @@ +// TODO handle plugin version matrix in a better way +export const minDVVersion = [100, 8, 1] +export const minLLVersion = [101, 1, 9] +export const minMapsVersion = [100, 7, 1] + +const isAppVersionCompatible = (version, minVersion) => { + const [major, minor, patch] = version + .split('.') + .map((el) => parseInt(el, 10)) + + const [minMajor, minMinor, minPatch] = minVersion + + const isCompatible = + major > minMajor || + (major === minMajor && minor > minMinor) || + (major === minMajor && minor === minMinor && patch >= minPatch) + + return isCompatible +} + +export const isDVVersionCompatible = (version) => + isAppVersionCompatible(version, minDVVersion) + +export const isLLVersionCompatible = (version) => + isAppVersionCompatible(version, minLLVersion) + +export const isMapsVersionCompatible = (version) => + isAppVersionCompatible(version, minMapsVersion) diff --git a/src/modules/isLLVersionCompatible.js b/src/modules/isLLVersionCompatible.js deleted file mode 100644 index ef80d18f0..000000000 --- a/src/modules/isLLVersionCompatible.js +++ /dev/null @@ -1,16 +0,0 @@ -// TODO handle plugin version matrix in a better way -export const minLLVersion = [100, 6, 0] - -export const isLLVersionCompatible = (version) => { - const versionArray = version.split('.').map((el) => parseInt(el, 10)) - - const [minMajor, minMinor, minPatch] = minLLVersion - const [major, minor, patch] = versionArray - - const isCompatible = - major > minMajor || - (major === minMajor && minor > minMinor) || - (major === minMajor && minor === minMinor && patch >= minPatch) - - return isCompatible -} diff --git a/src/pages/edit/ItemSelector/ItemSelector.js b/src/pages/edit/ItemSelector/ItemSelector.js index 5b104b887..bfe3ffbbc 100644 --- a/src/pages/edit/ItemSelector/ItemSelector.js +++ b/src/pages/edit/ItemSelector/ItemSelector.js @@ -107,7 +107,7 @@ const ItemSelector = () => { /> {isOpen && ( - +
{ } }, [recordingState]) - const onToggleItemExpanded = (clickedId) => { - const isExpanded = - typeof expandedItems[clickedId] === 'boolean' - ? expandedItems[clickedId] - : false - - const newExpandedItems = { ...expandedItems } - newExpandedItems[clickedId] = !isExpanded - setExpandedItems(newExpandedItems) - } + const onToggleItemExpanded = useCallback( + (clickedId) => { + const isExpanded = + typeof expandedItems[clickedId] === 'boolean' + ? expandedItems[clickedId] + : false + + const newExpandedItems = { ...expandedItems } + newExpandedItems[clickedId] = !isExpanded + setExpandedItems(newExpandedItems) + }, + [expandedItems] + ) const getItemComponent = (item) => { if (!layoutSm.length) { diff --git a/yarn.lock b/yarn.lock index 1e4996ba6..04463935d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1168,7 +1168,7 @@ core-js-pure "^3.30.2" regenerator-runtime "^0.13.11" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.24.8" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.8.tgz#5d958c3827b13cc6d05e038c07fb2e5e3420d82e" integrity sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA== @@ -2340,45 +2340,45 @@ dependencies: prop-types "^15.7.2" -"@dhis2/app-runtime@^3.10.6": - version "3.10.6" - resolved "https://registry.yarnpkg.com/@dhis2/app-runtime/-/app-runtime-3.10.6.tgz#10add0b8a2e1de06777e6e78c681a3a8f15ba058" - integrity sha512-WfC+AHkw0V3V3/wyLPHoTyAf8i4btLl/R2nMBVs3NEXLwA9mekG/gXs7AEPnK2/p6FVoqXMDwJHEH2b8Iw4UFw== +"@dhis2/app-runtime@^3.10.6", "@dhis2/app-runtime@^3.11.3": + version "3.12.0" + resolved "https://registry.yarnpkg.com/@dhis2/app-runtime/-/app-runtime-3.12.0.tgz#7cdcc33e9dd74194583a4e22ecb8ce5e04c6a1b6" + integrity sha512-qAR6y2V+KERtylLWHXpld39QBbYCBubQ5G79Hhqta/wcNbKrkHCCfurGWL29CGcPD/MVDnkAE5K68v+iBAQigA== dependencies: - "@dhis2/app-service-alerts" "3.10.6" - "@dhis2/app-service-config" "3.10.6" - "@dhis2/app-service-data" "3.10.6" - "@dhis2/app-service-offline" "3.10.6" - "@dhis2/app-service-plugin" "3.10.6" + "@dhis2/app-service-alerts" "3.12.0" + "@dhis2/app-service-config" "3.12.0" + "@dhis2/app-service-data" "3.12.0" + "@dhis2/app-service-offline" "3.12.0" + "@dhis2/app-service-plugin" "3.12.0" -"@dhis2/app-service-alerts@3.10.6": - version "3.10.6" - resolved "https://registry.yarnpkg.com/@dhis2/app-service-alerts/-/app-service-alerts-3.10.6.tgz#47e65d7ed57a4bd801a513b0f71d0ed2839ea363" - integrity sha512-2r9IUBp5Z5zuSqjTEWpt+rx7tP5AqrtkPJ8ZVOKW5YBn1DB4bQ5ti9GOevHM4othr7Mrmt22UADPgfEkfc7XzQ== +"@dhis2/app-service-alerts@3.12.0": + version "3.12.0" + resolved "https://registry.yarnpkg.com/@dhis2/app-service-alerts/-/app-service-alerts-3.12.0.tgz#528feecc52da568961591dd3a1753d175ae6dd64" + integrity sha512-Ucyx8pOuwJ2MfVt7JFl0LWb9kkZV867joS+LVNKBLnEtZP+xpTofQvSJb5C/1UAVKFd/Fv+yrvpysygmQmgCCg== -"@dhis2/app-service-config@3.10.6": - version "3.10.6" - resolved "https://registry.yarnpkg.com/@dhis2/app-service-config/-/app-service-config-3.10.6.tgz#bf952156329ab48d6da407522c6e06072fdf896a" - integrity sha512-Z/rSBjCc8kP78QYhKNyGoCafGfwpqMDg8mV2x/H6CavgEicOa+qHX3bkKV6+fC9Sw2FnsWHRemxYRkgbW/BD3g== +"@dhis2/app-service-config@3.12.0": + version "3.12.0" + resolved "https://registry.yarnpkg.com/@dhis2/app-service-config/-/app-service-config-3.12.0.tgz#b90ee526f6b933c65b99ec3199e18060b9b37091" + integrity sha512-FzoiBkpJbebeFPEZcyzu4b5W7xh8zlKJIY/qNXM+ylYxv3yGh08GhBDxhexNanluoq9ch8Wxrfit2pHgnAom2A== -"@dhis2/app-service-data@3.10.6": - version "3.10.6" - resolved "https://registry.yarnpkg.com/@dhis2/app-service-data/-/app-service-data-3.10.6.tgz#2f3f522b4a5a8c8d531f8901cca502323e566042" - integrity sha512-9RH3Dn0shcVdF7itgKy9cK3yMEcyP5xXjNzYPGzWf+3q9aGlzjh22pHE4p+C9OV+SeVO2q+5GcNOk7rdZvS+Cg== +"@dhis2/app-service-data@3.12.0": + version "3.12.0" + resolved "https://registry.yarnpkg.com/@dhis2/app-service-data/-/app-service-data-3.12.0.tgz#ab1fac7a2b4edf03fc15135e7b5ff55d2f8d7329" + integrity sha512-uSGyiQx1DAAQc0gIIpH6EIVpkpV+bMHN9p26qNpPDYIwbQDGy6/gLi7eiig18mLJ2k11//kNtg3fGcFk3M3uVg== dependencies: - react-query "^3.13.11" + "@tanstack/react-query" "^4.36.1" -"@dhis2/app-service-offline@3.10.6": - version "3.10.6" - resolved "https://registry.yarnpkg.com/@dhis2/app-service-offline/-/app-service-offline-3.10.6.tgz#e1d83520bb292fc51b24eab65d05e1c9fa1e2ad6" - integrity sha512-179QXdUOFgPPIOhY5HD+C6GzzJDvhR8GW7jXT4LtjCeO/4EbA3r9sycyrYpLZL66GtpGHkeV5g4slxM1t+63cw== +"@dhis2/app-service-offline@3.12.0": + version "3.12.0" + resolved "https://registry.yarnpkg.com/@dhis2/app-service-offline/-/app-service-offline-3.12.0.tgz#0919ebf52aa2f325e631ffd5158f3546aa65d72f" + integrity sha512-GUEBymqTAGdyIPOw+ZRZ1YQdCzczagytZh2e+goG/phiUqslUUOjB1cVjBVLjf7XZ17KCTCJnfOHBVdcPz8q7Q== dependencies: lodash "^4.17.21" -"@dhis2/app-service-plugin@3.10.6": - version "3.10.6" - resolved "https://registry.yarnpkg.com/@dhis2/app-service-plugin/-/app-service-plugin-3.10.6.tgz#1c6792b6d051c4b3301d76d083c3364424140a83" - integrity sha512-um4ONieW+xpWfagt+QNF4ZtzzFpm8KeA9tlBomamOfhGIpi9mkCWtaY0Mw2IUWO+d0Uh4cfmeQV6w6jOX6xJzw== +"@dhis2/app-service-plugin@3.12.0": + version "3.12.0" + resolved "https://registry.yarnpkg.com/@dhis2/app-service-plugin/-/app-service-plugin-3.12.0.tgz#5be4d5f14b4725f4fc40578b36c046e6ad67efbd" + integrity sha512-tzIpQFExFWi5rU2PrwauF0Cp3eP7DzRFem4lnke+qdU3T+x94pCxY8eaMrrr4trq0B6pO4/TikNDjXvw4O+RHQ== dependencies: post-robot "^10.0.46" @@ -3290,48 +3290,6 @@ resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== -"@krakenjs/belter@^2.0.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@krakenjs/belter/-/belter-2.1.2.tgz#b51c5a2d0652279262eb2fa79a6e26b12a868867" - integrity sha512-9qg3xsfcMtljHyxYuin8/KDeqG80ecHCAbuqbHd8Cz0CszK4JvYS3tsmCzYnp6zfnR9uSRCuoj/dKWhZcJtqbg== - dependencies: - "@krakenjs/cross-domain-safe-weakmap" "^2.0.2" - "@krakenjs/cross-domain-utils" "^3.0.2" - "@krakenjs/zalgo-promise" "^2.0.0" - -"@krakenjs/cross-domain-safe-weakmap@^2.0.0", "@krakenjs/cross-domain-safe-weakmap@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@krakenjs/cross-domain-safe-weakmap/-/cross-domain-safe-weakmap-2.0.3.tgz#eb607534c14bd8bc2f3456d993618361fb38489f" - integrity sha512-WsGi6347ddZ9Y0HoBuTYCX2QTAHxYVaUs2T/0n8XJKXZOEJPnLWlW6eYAOgyyuUsYusWMAkYv00fvfxAlTU8/w== - dependencies: - "@krakenjs/cross-domain-utils" "^3.0.2" - -"@krakenjs/cross-domain-utils@^3.0.0", "@krakenjs/cross-domain-utils@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@krakenjs/cross-domain-utils/-/cross-domain-utils-3.0.2.tgz#cbbd3323e65e831debc351549c0b8972df0382d5" - integrity sha512-uNTQrAevzKtOu13UZzamCR6rKX2vpdb6g/gVXMJVSMvAlYhxBN6mOD6U56DmSdBJDKvLSYZbIYUkBh2inDyIXQ== - -"@krakenjs/post-robot@^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@krakenjs/post-robot/-/post-robot-11.0.0.tgz#98a285b70db2bac2c58f297cd8403a4cc2518a6a" - integrity sha512-t+IlQCrwzLa1IWxEvdfr9r/xgOmQoykVQ1rtEukw1LYVHPU3p3eDDC5djODE7ErWYDbkYncrHcbDEh6Gc/G9wQ== - dependencies: - "@krakenjs/belter" "^2.0.0" - "@krakenjs/cross-domain-safe-weakmap" "^2.0.0" - "@krakenjs/cross-domain-utils" "^3.0.0" - "@krakenjs/universal-serialize" "^2.0.0" - "@krakenjs/zalgo-promise" "^2.0.0" - -"@krakenjs/universal-serialize@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@krakenjs/universal-serialize/-/universal-serialize-2.0.0.tgz#c4a508ec53f6b412b1032e78c570b87f4f2c7763" - integrity sha512-Qd9W2iaP5lMTzXPETomBDAaqbgHYkEjJKcQ+3eNC8EwWGCHFk3/+uQ41B+QYfSZqRoz8AEjdNHOps7nDEypAyw== - -"@krakenjs/zalgo-promise@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@krakenjs/zalgo-promise/-/zalgo-promise-2.0.1.tgz#36b4225a566f0a0903a8d771a11a9efc131c6987" - integrity sha512-n30eknZjD7z8/joFqjI8FIDZ0yJPZHcQBce1B3tAumwNZL0C42Ta/w37MfthxHV61JHEFGfy7b727h/kzagJDA== - "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -4028,6 +3986,19 @@ dependencies: defer-to-connect "^1.0.1" +"@tanstack/query-core@4.36.1": + version "4.36.1" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.36.1.tgz#79f8c1a539d47c83104210be2388813a7af2e524" + integrity sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA== + +"@tanstack/react-query@^4.36.1": + version "4.36.1" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.36.1.tgz#acb589fab4085060e2e78013164868c9c785e5d2" + integrity sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw== + dependencies: + "@tanstack/query-core" "4.36.1" + use-sync-external-store "^1.2.0" + "@teppeis/multimaps@3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@teppeis/multimaps/-/multimaps-3.0.0.tgz#bb9c3f8d569f589e548586fa0bbf423010ddfdc5" @@ -5500,11 +5471,6 @@ bfj@^7.0.2: hoopy "^0.1.4" tryer "^1.0.1" -big-integer@^1.6.16: - version "1.6.51" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" - integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== - big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -5641,20 +5607,6 @@ braces@^3.0.3, braces@~3.0.2: dependencies: fill-range "^7.1.1" -broadcast-channel@^3.4.1: - version "3.7.0" - resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.7.0.tgz#2dfa5c7b4289547ac3f6705f9c00af8723889937" - integrity sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg== - dependencies: - "@babel/runtime" "^7.7.2" - detect-node "^2.1.0" - js-sha3 "0.8.0" - microseconds "0.2.0" - nano-time "1.0.0" - oblivious-set "1.0.0" - rimraf "3.0.2" - unload "2.2.0" - browser-process-hrtime@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" @@ -7225,7 +7177,7 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -detect-node@^2.0.4, detect-node@^2.1.0: +detect-node@^2.0.4: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== @@ -11025,11 +10977,6 @@ joi@^17.7.0: "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" -js-sha3@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -11951,14 +11898,6 @@ marked@^4.1.0: resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== -match-sorter@^6.0.2: - version "6.3.1" - resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda" - integrity sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw== - dependencies: - "@babel/runtime" "^7.12.5" - remove-accents "0.4.2" - mathjs@^9.4.2: version "9.5.2" resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-9.5.2.tgz#e0f3279320dc6f49e45d99c4fcdd8b52231f0462" @@ -12085,11 +12024,6 @@ micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5, micr braces "^3.0.3" picomatch "^2.3.1" -microseconds@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" - integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== - mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -12388,13 +12322,6 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nano-time@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef" - integrity sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA== - dependencies: - big-integer "^1.6.16" - nanoid@^3.3.7: version "3.3.8" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" @@ -12930,11 +12857,6 @@ object.values@^1.1.0, object.values@^1.1.5, object.values@^1.1.6: define-properties "^1.1.4" es-abstract "^1.20.4" -oblivious-set@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566" - integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw== - obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -14506,15 +14428,6 @@ react-popper@^2.2.5: react-fast-compare "^3.0.1" warning "^4.0.2" -react-query@^3.13.11: - version "3.39.2" - resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.39.2.tgz#9224140f0296f01e9664b78ed6e4f69a0cc9216f" - integrity sha512-F6hYDKyNgDQfQOuR1Rsp3VRzJnWHx6aRnnIZHMNGGgbL3SBgpZTDg8MQwmxOgpCAoqZJA+JSNCydF1xGJqKOCA== - dependencies: - "@babel/runtime" "^7.5.5" - broadcast-channel "^3.4.1" - match-sorter "^6.0.2" - react-redux@^5.0.7: version "5.1.2" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.2.tgz#b19cf9e21d694422727bf798e934a916c4080f57" @@ -14946,11 +14859,6 @@ relateurl@^0.2.7: resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= -remove-accents@0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" - integrity sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA== - remove-bom-buffer@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" @@ -15184,13 +15092,6 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== -rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -15198,6 +15099,13 @@ rimraf@^2.6.3: dependencies: glob "^7.1.3" +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -17077,14 +16985,6 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== -unload@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7" - integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA== - dependencies: - "@babel/runtime" "^7.6.2" - detect-node "^2.0.4" - unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -17178,6 +17078,11 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" +use-sync-external-store@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" + integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -17835,7 +17740,7 @@ workerpool@^6.5.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==