Skip to content

Commit

Permalink
fix: never render HeaderBar without runtime provider (#587)
Browse files Browse the repository at this point in the history
* fix: never render HeaderBar without runtime provider

* style: formatting

* fix: log locale initialization in useEffect, add emoji to log

* fix: short-circuit the system info fetch if no url provided

* style: sort propTypes
  • Loading branch information
amcgee committed Jul 8, 2021
1 parent 3014722 commit 65c7766
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 58 deletions.
29 changes: 29 additions & 0 deletions adapter/src/components/AppWrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { HeaderBar } from '@dhis2/ui'
import PropTypes from 'prop-types'
import React from 'react'
import { useCurrentUserLocale } from '../utils/useLocale.js'
import { Alerts } from './Alerts.js'
import { LoadingMask } from './LoadingMask.js'
import { styles } from './styles/AppWrapper.style.js'

export const AppWrapper = ({ appName, children }) => {
const { loading } = useCurrentUserLocale()

if (loading) {
return <LoadingMask />
}

return (
<div className="app-shell-adapter">
<style jsx>{styles}</style>
<HeaderBar appName={appName} />
<div className="app-shell-app">{children}</div>
<Alerts />
</div>
)
}

AppWrapper.propTypes = {
appName: PropTypes.string.isRequired,
children: PropTypes.node,
}
34 changes: 0 additions & 34 deletions adapter/src/components/AuthBoundary.js

This file was deleted.

4 changes: 3 additions & 1 deletion adapter/src/components/LoginModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ export const LoginModal = () => {
e.preventDefault()
setIsDirty(true)
if (isValid(server) && isValid(username) && isValid(password)) {
window.localStorage.DHIS2_BASE_URL = server
if (!staticUrl) {
window.localStorage.DHIS2_BASE_URL = server
}
try {
await post(
`${server}/dhis-web-commons-security/login.action`,
Expand Down
16 changes: 11 additions & 5 deletions adapter/src/components/ServerVersionProvider.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { Provider } from '@dhis2/app-runtime'
import PropTypes from 'prop-types'
import React, { useEffect, useState } from 'react'
import { get } from '../utils/api'
import { parseServerVersion } from '../utils/parseServerVersion'
import { LoadingMask } from './LoadingMask'
import { get } from '../utils/api.js'
import { parseServerVersion } from '../utils/parseServerVersion.js'
import { LoadingMask } from './LoadingMask.js'
import { LoginModal } from './LoginModal.js'

export const ServerVersionProvider = ({ url, apiVersion, children }) => {
const [{ loading, error, systemInfo }, setState] = useState({
loading: true,
})

useEffect(() => {
if (!url) {
setState({ loading: false, error: new Error('No url specified') })
return
}

setState(state => (state.loading ? state : { loading: true }))
const request = get(`${url}/api/system/info`)
request
Expand All @@ -31,7 +37,7 @@ export const ServerVersionProvider = ({ url, apiVersion, children }) => {
}

if (error) {
return children
return <LoginModal />
}

const serverVersion = parseServerVersion(systemInfo.version)
Expand All @@ -52,7 +58,7 @@ export const ServerVersionProvider = ({ url, apiVersion, children }) => {
}

ServerVersionProvider.propTypes = {
url: PropTypes.string.isRequired,
apiVersion: PropTypes.number,
children: PropTypes.element,
url: PropTypes.string,
}
File renamed without changes.
26 changes: 8 additions & 18 deletions adapter/src/index.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,22 @@
import { HeaderBar } from '@dhis2/ui'
import PropTypes from 'prop-types'
import React from 'react'
import { Alerts } from './components/Alerts'
import { AuthBoundary } from './components/AuthBoundary'
import { FatalErrorBoundary } from './components/FatalErrorBoundary'
import { ServerVersionProvider } from './components/ServerVersionProvider'
import { styles } from './styles.js'
import { AppWrapper } from './components/AppWrapper.js'
import { FatalErrorBoundary } from './components/FatalErrorBoundary.js'
import { ServerVersionProvider } from './components/ServerVersionProvider.js'

const App = ({ url, apiVersion, appName, children }) => (
const AppAdapter = ({ url, apiVersion, appName, children }) => (
<FatalErrorBoundary>
<ServerVersionProvider url={url} apiVersion={apiVersion}>
<div className="app-shell-adapter">
<style jsx>{styles}</style>
<HeaderBar appName={appName} />
<AuthBoundary url={url}>
<div className="app-shell-app">{children}</div>
</AuthBoundary>
<Alerts />
</div>
<AppWrapper appName={appName}>{children}</AppWrapper>
</ServerVersionProvider>
</FatalErrorBoundary>
)

App.propTypes = {
AppAdapter.propTypes = {
appName: PropTypes.string.isRequired,
url: PropTypes.string.isRequired,
apiVersion: PropTypes.number,
children: PropTypes.element,
url: PropTypes.string,
}

export default App
export default AppAdapter
23 changes: 23 additions & 0 deletions adapter/src/utils/useLocale.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useDataQuery } from '@dhis2/app-runtime'
import i18n from '@dhis2/d2-i18n'
import moment from 'moment'
import { useState, useEffect } from 'react'
Expand Down Expand Up @@ -32,8 +33,30 @@ export const useLocale = locale => {
if (!locale) {
return
}

setGlobalLocale(locale)
setResult(locale)

console.log('🗺 Global d2-i18n locale initialized:', locale)
}, [locale])
return result
}

const settingsQuery = {
userSettings: {
resource: 'userSettings',
},
}
export const useCurrentUserLocale = () => {
const { loading, error, data } = useDataQuery(settingsQuery)
const locale = useLocale(
data && (data.userSettings.keyUiLocale || window.navigator.language)
)

if (error) {
// This shouldn't happen, trigger the fatal error boundary
throw new Error('Failed to fetch user locale: ' + error)
}

return { loading: loading || !locale, locale }
}

0 comments on commit 65c7766

Please sign in to comment.