Skip to content

Commit

Permalink
feat: add recording props to plugin (#2125)
Browse files Browse the repository at this point in the history
* fix(pwa): make cache filters more specifc

* feat(plugins): add `record` prop to iframe plugins when caching dashboard

* feat: remove cached plugin data with dashboard
  • Loading branch information
KaiVandivier authored and edoardo committed Mar 2, 2023
1 parent 2f00bbe commit 8cb24db
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 13 deletions.
11 changes: 7 additions & 4 deletions d2.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ const config = {
enabled: true,
caching: {
patternsToOmit: [
'dashboards/[a-zA-Z0-9]*',
'visualizations',
'analytics',
'geoFeatures',
// Make these specific as possible --
// unspecific ones have caused errors on instances with
// 'analytics' in the name, for example
/\/api\/(\d+\/)?dashboards\/[a-zA-Z0-9]*/,
/\/api\/(\d+\/)?visualizations/,
/\/api\/(\d+\/)?analytics/,
/\/api\/(\d+\/)?geoFeatures/,
'cartodb-basemaps-a.global.ssl.fastly.net',
],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import React, {
} from 'react'
import { itemTypeMap } from '../../../../modules/itemTypes.js'
import { getPluginOverrides } from '../../../../modules/localStorage.js'
import { useCacheableSection } from '../../../../modules/useCacheableSection.js'
import { useUserSettings } from '../../../UserSettingsProvider.js'
import classes from './styles/DataVisualizerPlugin.module.css'
import VisualizationErrorMessage from './VisualizationErrorMessage.js'
Expand All @@ -19,6 +20,7 @@ const IframePlugin = ({
style,
visualization,
dashboardMode,
dashboardId,
}) => {
const { d2 } = useD2()
// TODO replace d2 with useCachedDataQuery
Expand All @@ -27,25 +29,73 @@ const IframePlugin = ({
const iframeRef = useRef()
const [error, setError] = useState(false)

// When this mounts, check if the dashboard is recording
const { isCached, recordingState } = useCacheableSection(dashboardId)
const [recordOnNextLoad, setRecordOnNextLoad] = useState(
recordingState === 'recording'
)

const onError = () => setError(true)

useEffect(() => {
// Tell plugin to remove cached data if this dashboard has been removed
// from offline storage
if (!isCached) {
postRobot
.send(iframeRef.current.contentWindow, 'removeCachedData')
.catch((err) => {
// catch error if iframe hasn't loaded yet
const msg = 'No handler found for post message:'
if (err.message.startsWith(msg)) {
return
}
console.error(err)
})
}
}, [isCached])

useEffect(() => {
const listener = postRobot.on(
'getProps',
// listen for messages coming only from the iframe rendered by this component
{ window: iframeRef.current.contentWindow },
() => ({
isVisualizationLoaded: true,
forDashboard: true,
userSettings,
nameProp: userSettings.displayProperty,
visualization,
onError,
})
() => {
const pluginProps = {
isVisualizationLoaded: true,
forDashboard: true,
userSettings,
nameProp: userSettings.displayProperty,
visualization,
onError,

// For caching: ---
// Add user & dashboard IDs to cache ID to avoid removing a cached
// plugin that might be used in another dashboard also
// TODO: May also want user ID too for multi-user situations
cacheId: `${dashboardId}-${item.id}`,
isParentCached: isCached,
recordOnNextLoad: recordOnNextLoad,
}

if (recordOnNextLoad) {
// Avoid recording unnecessarily,
// e.g. if plugin re-requests props for some reason
setRecordOnNextLoad(false)
}

return pluginProps
}
)

return () => listener.cancel()
}, [visualization, userSettings])
}, [
visualization,
userSettings,
dashboardId,
item.id,
isCached,
recordOnNextLoad,
])

useEffect(() => {
setError(false)
Expand Down Expand Up @@ -100,6 +150,7 @@ const IframePlugin = ({
}

IframePlugin.propTypes = {
dashboardId: PropTypes.string,
dashboardMode: PropTypes.string,
filterVersion: PropTypes.string,
item: PropTypes.object,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
sGetItemFiltersRoot,
DEFAULT_STATE_ITEM_FILTERS,
} from '../../../../reducers/itemFilters.js'
import { sGetSelected } from '../../../../reducers/selected.js'
import { sGetVisualization } from '../../../../reducers/visualizations.js'
import memoizeOne from '../memoizeOne.js'
import DataVisualizerPlugin from './DataVisualizerPlugin.js'
Expand All @@ -36,6 +37,7 @@ const Visualization = ({
availableHeight,
availableWidth,
dashboardMode,
dashboardId,
...rest
}) => {
const memoizedGetFilteredVisualization = memoizeOne(
Expand Down Expand Up @@ -96,6 +98,7 @@ const Visualization = ({
filterVersion={filterVersion}
item={item}
dashboardMode={dashboardMode}
dashboardId={dashboardId}
/>
)
}
Expand Down Expand Up @@ -139,6 +142,7 @@ Visualization.propTypes = {
activeType: PropTypes.string,
availableHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
availableWidth: PropTypes.number,
dashboardId: PropTypes.string,
dashboardMode: PropTypes.string,
item: PropTypes.object,
itemFilters: PropTypes.object,
Expand All @@ -151,6 +155,7 @@ const mapStateToProps = (state, ownProps) => {
: DEFAULT_STATE_ITEM_FILTERS

return {
dashboardId: sGetSelected(state).id,
itemFilters,
visualization: sGetVisualization(
state,
Expand Down

0 comments on commit 8cb24db

Please sign in to comment.