-
Notifications
You must be signed in to change notification settings - Fork 12
feat: implement shared dashboard plugin wrapper #1672
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
Closed
Closed
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
4bfe16f
feat: implement dashboard plugin wrapper component
edoardo b15a1ab
chore: bump app-runtime and cli-app-scripts dev dependencies
edoardo f0ec2ad
chore: bump cli-app-scripts
edoardo 3327723
chore: deduplicate yarn.lock
edoardo 5672b60
fix: only use cache if plugin has PWA enabled
edoardo f1fdd5f
chore: remove postbuild temporarily
edoardo e9252d3
fix: remove required props and add defaults
edoardo 29a2c6f
chore: tweak ESLint config so that jsx property is allowed
HendrikThePendric b7e4c16
chore: fix import order ESLint errors
HendrikThePendric af456a2
chore: use named functions for default exports too
HendrikThePendric 1e9dda2
refactor: import ui components from the root package
edoardo cd99b54
fix: remove eslint disable and fix useEffect dep list
edoardo 292f88f
chore: bump app-runtime to latest
edoardo e55b82f
Merge remote-tracking branch 'origin/master' into feat/dashboard-plug…
edoardo 6b3e34a
Merge branch 'master' into feat/dashboard-plugin-wrapper
edoardo cfa7893
Merge branch 'master' into feat/dashboard-plugin-wrapper
edoardo bb4b556
chore: regenerate yarn.lock
edoardo d24d959
Merge remote-tracking branch 'origin/master' into feat/dashboard-plug…
edoardo 47c1be0
fix: use correct function arguments
edoardo 6cbd380
Merge remote-tracking branch 'origin/master' into feat/dashboard-plug…
edoardo 8bf4ac6
refactor: import ui components from the root package
edoardo 1b6dda6
Merge remote-tracking branch 'origin/master' into feat/dashboard-plug…
edoardo b6fbb11
Merge branch 'master' into feat/dashboard-plugin-wrapper
edoardo 7d9993d
Merge remote-tracking branch 'origin/master' into feat/dashboard-plug…
edoardo 34a15ec
Merge remote-tracking branch 'origin/master' into feat/dashboard-plug…
edoardo 1e915a5
chore: update ui dependency
edoardo babe3c4
Merge branch 'master' into feat/dashboard-plugin-wrapper
jenniferarnesen a7d9d69
chore: platform with latest plugin code
jenniferarnesen b02cddc
chore: yarn dedupe
jenniferarnesen 413455e
chore: regenerate yarn.lock
jenniferarnesen cb5fbde
Revert "chore: regenerate yarn.lock"
jenniferarnesen 84cc5f8
chore: yarn dedupe
jenniferarnesen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
src/components/DashboardPluginWrapper/DashboardPluginWrapper.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { | ||
useCacheableSection, | ||
CacheableSection, | ||
useConfig, | ||
} from '@dhis2/app-runtime' | ||
import { CenteredContent, CircularLoader, CssVariables, Layer } from '@dhis2/ui' | ||
import PropTypes from 'prop-types' | ||
import React, { useEffect } from 'react' | ||
import { getPWAInstallationStatus } from '../../modules/getPWAInstallationStatus.js' | ||
|
||
const LoadingMask = () => { | ||
return ( | ||
<Layer> | ||
<CenteredContent> | ||
<CircularLoader /> | ||
</CenteredContent> | ||
</Layer> | ||
) | ||
} | ||
|
||
const CacheableSectionWrapper = ({ id, children, isParentCached }) => { | ||
const { startRecording, isCached, remove } = useCacheableSection(id) | ||
|
||
useEffect(() => { | ||
if (isParentCached && !isCached) { | ||
startRecording({ onError: console.error }) | ||
} else if (!isParentCached && isCached) { | ||
// Synchronize cache state on load or prop update | ||
// -- a back-up to imperative `removeCachedData` | ||
remove() | ||
} | ||
}, [isCached, isParentCached, remove, startRecording]) | ||
|
||
return ( | ||
<CacheableSection id={id} loadingMask={<LoadingMask />}> | ||
{children} | ||
</CacheableSection> | ||
) | ||
} | ||
|
||
CacheableSectionWrapper.propTypes = { | ||
children: PropTypes.node, | ||
id: PropTypes.string, | ||
isParentCached: PropTypes.bool, | ||
} | ||
|
||
export const DashboardPluginWrapper = ({ | ||
onInstallationStatusChange, | ||
children, | ||
cacheId, | ||
isParentCached, | ||
...props | ||
}) => { | ||
const { pwaEnabled } = useConfig() | ||
|
||
useEffect(() => { | ||
// Get & send PWA installation status now | ||
getPWAInstallationStatus({ | ||
onStateChange: onInstallationStatusChange, | ||
}).then(onInstallationStatusChange) | ||
}, [onInstallationStatusChange]) | ||
|
||
return props ? ( | ||
<div | ||
style={{ | ||
display: 'flex', | ||
height: '100%', | ||
overflow: 'hidden', | ||
}} | ||
> | ||
{pwaEnabled ? ( | ||
<CacheableSectionWrapper | ||
id={cacheId} | ||
isParentCached={isParentCached} | ||
> | ||
{children(props)} | ||
</CacheableSectionWrapper> | ||
) : ( | ||
children(props) | ||
)} | ||
<CssVariables colors spacers elevations /> | ||
</div> | ||
) : null | ||
} | ||
|
||
DashboardPluginWrapper.defaultProps = { | ||
isParentCached: false, | ||
onInstallationStatusChange: Function.prototype, | ||
} | ||
|
||
DashboardPluginWrapper.propTypes = { | ||
cacheId: PropTypes.string, | ||
children: PropTypes.func, | ||
isParentCached: PropTypes.bool, | ||
onInstallationStatusChange: PropTypes.func, | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
src/components/Toolbar/HoverMenuBar/HoverMenuListItem.styles.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
export const INSTALLATION_STATES = { | ||
READY: 'READY', | ||
INSTALLING: 'INSTALLING', | ||
} | ||
|
||
function handleInstallingWorker({ installingWorker, onStateChange }) { | ||
installingWorker.onstatechange = () => { | ||
if (installingWorker.state === 'activated') { | ||
// ... and update state to 'ready' | ||
onStateChange(INSTALLATION_STATES.READY) | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Gets the current installation state of the PWA features, which is intended | ||
* to be reported from this plugin to the parent app to indicate that the | ||
* static assets are cached and ready to be accessed locally instead of over | ||
* the network. | ||
* | ||
* Returns either READY, INSTALLING, or `null` for not installed/won't install | ||
*/ | ||
export async function getPWAInstallationStatus({ onStateChange }) { | ||
if (!navigator.serviceWorker) { | ||
// Nothing to do here | ||
return null | ||
} | ||
|
||
const registration = await navigator.serviceWorker.getRegistration() | ||
if (!registration) { | ||
// This shouldn't happen since this is a PWA app, but return null | ||
return null | ||
} | ||
|
||
if (registration.active) { | ||
return INSTALLATION_STATES.READY | ||
} | ||
// note that 'registration.waiting' is skipped - it implies there's an active one | ||
if (registration.installing) { | ||
handleInstallingWorker({ | ||
installingWorker: registration.installing, | ||
onStateChange, | ||
}) | ||
return INSTALLATION_STATES.INSTALLING | ||
} | ||
HendrikThePendric marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// It shouldn't normally be possible to get here, but just in case, | ||
// listen for installations | ||
registration.onupdatefound = () => { | ||
// update state for this plugin to 'installing' | ||
onStateChange(INSTALLATION_STATES.INSTALLING) | ||
|
||
// also listen for the installing worker to become active | ||
const installingWorker = registration.installing | ||
if (!installingWorker) { | ||
return | ||
} | ||
handleInstallingWorker({ installingWorker, onStateChange }) | ||
} | ||
|
||
// and in the mean time, return null to show 'not installed' | ||
return null | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.