Skip to content
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

feat: updates for login_app type [LIBS-405] #831

Merged
merged 13 commits into from
Mar 5, 2024
32 changes: 32 additions & 0 deletions adapter/src/components/LoginAppWrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import PropTypes from 'prop-types'
import React from 'react'
import { useSystemDefaultLocale } from '../utils/useLocale.js'
import { Alerts } from './Alerts.js'
import { ErrorBoundary } from './ErrorBoundary.js'
import { LoadingMask } from './LoadingMask.js'
import { styles } from './styles/AppWrapper.style.js'

export const LoginAppWrapper = ({ children }) => {
const { loading: localeLoading } = useSystemDefaultLocale()
// cannot check current user for a loginApp (no api/me)

if (localeLoading) {
return <LoadingMask />
}

return (
<div className="app-shell-adapter">
<style jsx>{styles}</style>
<div className="app-shell-app">
<ErrorBoundary onRetry={() => window.location.reload()}>
{children}
</ErrorBoundary>
</div>
<Alerts />
</div>
)
}

LoginAppWrapper.propTypes = {
children: PropTypes.node,
}
34 changes: 31 additions & 3 deletions adapter/src/components/ServerVersionProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const ServerVersionProvider = ({
plugin,
parentAlertsAdd,
showAlertsInPlugin,
loginApp,
children,
}) => {
const offlineInterface = useOfflineInterface()
Expand Down Expand Up @@ -103,6 +104,27 @@ export const ServerVersionProvider = ({
? state
: { loading: true, error: undefined, systemInfo: undefined }
)

// version is not currently available, minimum for login app
if (loginApp) {
const requestLogin = get(`${baseUrl}/api/loginConfig`)
requestLogin
.then((loginConfig) => {
setSystemInfoState({
loading: false,
error: undefined,
systemInfo: { version: loginConfig.apiVersion },
})
})
.catch((e) => {
setSystemInfoState({
loading: false,
error: e,
systemInfo: undefined,
})
})
return
}
const request = get(`${baseUrl}/api/system/info`)
request
.then((systemInfo) => {
Expand All @@ -125,7 +147,7 @@ export const ServerVersionProvider = ({
return () => {
request.abort()
}
}, [appName, baseUrl])
}, [appName, baseUrl, loginApp])

useEffect(() => {
if (pwaEnabled) {
Expand All @@ -137,7 +159,11 @@ export const ServerVersionProvider = ({

// This needs to come before 'loading' case to show modal at correct times
if (systemInfoState.error || baseUrlState.error) {
return <LoginModal appName={appName} baseUrl={baseUrl} />
return !loginApp ? (
<LoginModal appName={appName} baseUrl={baseUrl} />
) : (
<p>Specify DHIS2_BASE_URL environment variable</p>
)
}

if (
Expand All @@ -162,10 +188,11 @@ export const ServerVersionProvider = ({
systemInfo,
pwaEnabled,
}}
offlineInterface={offlineInterface}
offlineInterface={loginApp ? null : offlineInterface}
plugin={plugin}
parentAlertsAdd={parentAlertsAdd}
showAlertsInPlugin={showAlertsInPlugin}
skipApiVersion={loginApp ? true : false}
>
{children}
</Provider>
Expand All @@ -177,6 +204,7 @@ ServerVersionProvider.propTypes = {
appVersion: PropTypes.string.isRequired,
apiVersion: PropTypes.number,
children: PropTypes.element,
loginApp: PropTypes.bool,
parentAlertsAdd: PropTypes.func,
plugin: PropTypes.bool,
pwaEnabled: PropTypes.bool,
Expand Down
72 changes: 50 additions & 22 deletions adapter/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
import React from 'react'
import { AppWrapper } from './components/AppWrapper.js'
import { ErrorBoundary } from './components/ErrorBoundary.js'
import { LoginAppWrapper } from './components/LoginAppWrapper.js'
import { OfflineInterfaceProvider } from './components/OfflineInterfaceContext.js'
import { PWALoadingBoundary } from './components/PWALoadingBoundary.js'
import { ServerVersionProvider } from './components/ServerVersionProvider.js'
Expand All @@ -19,38 +20,64 @@ const AppAdapter = ({
showAlertsInPlugin,
onPluginError,
clearPluginError,
loginApp,
children,
}) => (
<ErrorBoundary
plugin={plugin}
fullscreen
onRetry={checkForSWUpdateAndReload}
>
<OfflineInterfaceProvider>
<PWALoadingBoundary>
}) => {
if (loginApp) {
return (
<ErrorBoundary
fullscreen
onRetry={() => {
window.location.reload()
}}
plugin={false}
>
<ServerVersionProvider
appName={appName}
appVersion={appVersion}
url={url}
apiVersion={apiVersion}
pwaEnabled={pwaEnabled}
plugin={plugin}
parentAlertsAdd={parentAlertsAdd}
showAlertsInPlugin={showAlertsInPlugin}
loginApp={loginApp}
plugin={false}
>
<AppWrapper
<LoginAppWrapper>{children}</LoginAppWrapper>
</ServerVersionProvider>
</ErrorBoundary>
)
}
return (
<ErrorBoundary
plugin={plugin}
fullscreen
onRetry={checkForSWUpdateAndReload}
>
<OfflineInterfaceProvider>
<PWALoadingBoundary>
<ServerVersionProvider
appName={appName}
appVersion={appVersion}
url={url}
apiVersion={apiVersion}
pwaEnabled={pwaEnabled}
plugin={plugin}
onPluginError={onPluginError}
clearPluginError={clearPluginError}
direction={direction}
parentAlertsAdd={parentAlertsAdd}
showAlertsInPlugin={showAlertsInPlugin}
>
{children}
</AppWrapper>
</ServerVersionProvider>
</PWALoadingBoundary>
</OfflineInterfaceProvider>
</ErrorBoundary>
)
<AppWrapper
plugin={plugin}
onPluginError={onPluginError}
clearPluginError={clearPluginError}
direction={direction}
>
{children}
</AppWrapper>
</ServerVersionProvider>
</PWALoadingBoundary>
</OfflineInterfaceProvider>
</ErrorBoundary>
)
}

AppAdapter.propTypes = {
appName: PropTypes.string.isRequired,
Expand All @@ -59,6 +86,7 @@ AppAdapter.propTypes = {
children: PropTypes.element,
clearPluginError: PropTypes.func,
direction: PropTypes.oneOf(['ltr', 'rtl', 'auto']),
loginApp: PropTypes.bool,
parentAlertsAdd: PropTypes.func,
plugin: PropTypes.bool,
pwaEnabled: PropTypes.bool,
Expand Down
30 changes: 29 additions & 1 deletion adapter/src/utils/useLocale.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useDataQuery } from '@dhis2/app-runtime'
import i18n from '@dhis2/d2-i18n'
import { useState, useEffect } from 'react'
import { useState, useEffect, useMemo } from 'react'
import {
setI18nLocale,
parseLocale,
Expand Down Expand Up @@ -56,3 +56,31 @@ export const useCurrentUserLocale = (configDirection) => {

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

const loginConfigQuery = {
loginConfig: {
resource: 'loginConfig',
},
}

export const useSystemDefaultLocale = () => {
// system language from loginConfiqQuery
const { loading, data, error } = useDataQuery(loginConfigQuery)
// set userSettings to use system locale by default
const localeInformation = useMemo(
() => ({
userSettings: {
keyUiLocale:
data &&
(data?.loginConfig?.uiLocale || window.navigator.language),
},
configDirection: 'auto',
}),
[data]
)
const locale = useLocale(localeInformation)
if (error) {
console.error(error)
}
return { loading: loading || !locale, locale }
}
9 changes: 5 additions & 4 deletions cli/src/commands/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const generateManifests = require('../lib/generateManifests')
const i18n = require('../lib/i18n')
const loadEnvFiles = require('../lib/loadEnvFiles')
const parseConfig = require('../lib/parseConfig')
const { isApp } = require('../lib/parseConfig')
const makePaths = require('../lib/paths')
const makePlugin = require('../lib/plugin')
const { injectPrecacheManifest } = require('../lib/pwa')
Expand Down Expand Up @@ -71,7 +72,7 @@ const handler = async ({
const shell = makeShell({ config, paths })
const plugin = makePlugin({ config, paths })

if (config.type === 'app') {
if (isApp(config.type)) {
setAppParameters(standalone, config)
}

Expand Down Expand Up @@ -106,7 +107,7 @@ const handler = async ({
paths,
})

if (config.type === 'app') {
if (isApp(config.type)) {
reporter.info('Bootstrapping local appShell...')
await shell.bootstrap({ shell: shellSource, force })
}
Expand All @@ -115,7 +116,7 @@ const handler = async ({
`Building ${config.type} ${chalk.bold(config.name)}...`
)

if (config.type === 'app') {
if (isApp(config.type)) {
await compile({
config,
paths,
Expand Down Expand Up @@ -168,7 +169,7 @@ const handler = async ({
}
)

if (config.type === 'app') {
if (isApp(config.type)) {
if (!fs.pathExistsSync(paths.shellBuildOutput)) {
reporter.error('No build output found')
process.exit(1)
Expand Down
3 changes: 2 additions & 1 deletion cli/src/commands/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const generateManifests = require('../lib/generateManifests')
const i18n = require('../lib/i18n')
const loadEnvFiles = require('../lib/loadEnvFiles')
const parseConfig = require('../lib/parseConfig')
const { isApp } = require('../lib/parseConfig')
const makePaths = require('../lib/paths')
const makePlugin = require('../lib/plugin')
const createProxyServer = require('../lib/proxy')
Expand Down Expand Up @@ -33,7 +34,7 @@ const handler = async ({
const shell = makeShell({ config, paths })
const plugin = makePlugin({ config, paths })

if (config.type !== 'app') {
if (!isApp(config.type)) {
reporter.error(
`The command ${chalk.bold(
'd2-app-scripts start'
Expand Down
11 changes: 6 additions & 5 deletions cli/src/lib/compiler/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { reporter, prettyPrint } = require('@dhis2/cli-helpers-engine')
const chokidar = require('chokidar')
const fs = require('fs-extra')
const makeBabelConfig = require('../../../config/makeBabelConfig.js')
const { isApp } = require('../parseConfig')
const {
verifyEntrypoints,
createAppEntrypointWrapper,
Expand Down Expand Up @@ -67,10 +68,10 @@ const compile = async ({
mode = 'development',
watch = false,
}) => {
const isApp = config.type === 'app'
const isAppType = isApp(config.type)

verifyEntrypoints({ config, paths })
if (isApp) {
if (isAppType) {
await createAppEntrypointWrapper({
entrypoint: config.entryPoints.app,
paths,
Expand All @@ -83,13 +84,13 @@ const compile = async ({
}
}

const outDir = isApp
const outDir = isAppType
? paths.shellApp
: path.join(paths.buildOutput, moduleType)
fs.removeSync(outDir)
fs.ensureDirSync(outDir)

if (isApp) {
if (isAppType) {
fs.removeSync(paths.shellPublic)
fs.copySync(paths.shellSourcePublic, paths.shellPublic)
}
Expand Down Expand Up @@ -127,7 +128,7 @@ const compile = async ({
processFileCallback: compileFile,
watch,
}),
isApp &&
isAppType &&
watchFiles({
inputDir: paths.public,
outputDir: paths.shellPublic,
Expand Down
3 changes: 2 additions & 1 deletion cli/src/lib/compiler/entrypoints.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const path = require('path')
const { reporter, chalk } = require('@dhis2/cli-helpers-engine')
const fs = require('fs-extra')
const { isApp } = require('../parseConfig')
const { normalizeExtension } = require('./extensionHelpers.js')

const verifyEntrypoint = ({ entrypoint, basePath, resolveModule }) => {
Expand All @@ -26,7 +27,7 @@ exports.verifyEntrypoints = ({
paths,
resolveModule = require.resolve,
}) => {
if (config.type === 'app') {
if (isApp(config.type)) {
if (
!config.entryPoints ||
(!config.entryPoints.app && !config.entryPoints.plugin)
Expand Down
Loading
Loading