Skip to content

Commit

Permalink
feat: detect server version, use latest available api version (#470)
Browse files Browse the repository at this point in the history
* feat: detect server version, use latest available api version

* docs: update docs for DHIS2_API_VERSION env var

* fix: use functional update instead of implicit loading dep

* chore: rearrange imports

* chore: add tests and run tests in ci

* style: fix lint issues

* ci: add yarn caching logic

* ci: move cache to post-checkout

* ci: DRY in workflow

* ci: move condition back to jobs
  • Loading branch information
amcgee committed Oct 12, 2020
1 parent 93c41a6 commit ef92456
Show file tree
Hide file tree
Showing 25 changed files with 546 additions and 87 deletions.
87 changes: 87 additions & 0 deletions .github/workflows/dhis2-verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: 'DHIS2: Verify'

on: push

env:
CI: true

jobs:
lint:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12.x

- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install
run: yarn install --frozen-lockfile

- name: Run linters
run: |
yarn d2-style js check
yarn d2-style text check
build:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12.x

- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install
run: yarn install --frozen-lockfile

- name: Build
run: yarn build

test:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12.x

- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install
run: yarn install --frozen-lockfile

- name: Test
run: yarn test
23 changes: 0 additions & 23 deletions .github/workflows/node-lint.yml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ jobs:
- name: Build
run: yarn build

- name: Test
run: yarn test

- name: Lint
run: yarn lint

Expand Down
4 changes: 4 additions & 0 deletions adapter/config/setupEnzyme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

configure({ adapter: new Adapter() })
26 changes: 13 additions & 13 deletions adapter/i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,38 @@ 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: 2019-09-26T16:40:43.483Z\n"
"PO-Revision-Date: 2019-09-26T16:40:43.483Z\n"
"POT-Creation-Date: 2020-10-08T15:51:57.880Z\n"
"PO-Revision-Date: 2020-10-08T15:51:57.880Z\n"

msgid "Please sign in"
msgid "An error occurred in the DHIS2 application."
msgstr ""

msgid "Server"
msgid "Something went wrong"
msgstr ""

msgid "Username"
msgid "Refresh to try again"
msgstr ""

msgid "Password"
msgid "Hide technical details"
msgstr ""

msgid "Sign in"
msgid "Show technical details"
msgstr ""

msgid "An error occurred in the DHIS2 application."
msgid "The following information may be requested by technical support."
msgstr ""

msgid "Something went wrong"
msgid "Please sign in"
msgstr ""

msgid "Refresh to try again"
msgid "Server"
msgstr ""

msgid "Hide technical details"
msgid "Username"
msgstr ""

msgid "Show technical details"
msgid "Password"
msgstr ""

msgid "The following information may be requested by technical support."
msgid "Sign in"
msgstr ""
12 changes: 10 additions & 2 deletions adapter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@
"moment": "^2.24.0"
},
"devDependencies": {
"@dhis2/cli-app-scripts": "5.2.2"
"@dhis2/cli-app-scripts": "5.2.2",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5"
},
"scripts": {
"build": "d2-app-scripts build"
"build": "d2-app-scripts build",
"test": "d2-app-scripts test"
},
"peerDependencies": {
"@dhis2/app-runtime": "^2",
Expand All @@ -35,5 +38,10 @@
"react": "^16.8",
"react-dom": "^16.8",
"styled-jsx": "^3"
},
"jest": {
"setupFilesAfterEnv": [
"<rootDir>/config/setupEnzyme.js"
]
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react'
import PropTypes from 'prop-types'
import { useDataQuery } from '@dhis2/app-runtime'

import { Layer, layers, CenteredContent, CircularLoader } from '@dhis2/ui'
import { LoginModal } from './LoginModal'
import { useLocale } from './useLocale'
import { useLocale } from '../utils/useLocale'
import { LoadingMask } from './LoadingMask'

const settingsQuery = {
userSettings: {
Expand All @@ -16,13 +17,7 @@ export const AuthBoundary = ({ url, children }) => {
useLocale(data && data.userSettings.keyUiLocale)

if (loading) {
return (
<Layer translucent level={layers.alert}>
<CenteredContent>
<CircularLoader />
</CenteredContent>
</Layer>
)
return <LoadingMask />
}

if (error) {
Expand All @@ -31,3 +26,8 @@ export const AuthBoundary = ({ url, children }) => {

return children
}

AuthBoundary.propTypes = {
children: PropTypes.element,
url: PropTypes.string,
}
File renamed without changes.
10 changes: 10 additions & 0 deletions adapter/src/components/LoadingMask.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'
import { Layer, CenteredContent, CircularLoader, layers } from '@dhis2/ui'

export const LoadingMask = () => (
<Layer translucent level={layers.alert}>
<CenteredContent>
<CircularLoader />
</CenteredContent>
</Layer>
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Button,
InputField,
} from '@dhis2/ui'
import { post } from '../utils/api'

const staticUrl = process.env.REACT_APP_DHIS2_BASE_URL

Expand All @@ -27,20 +28,11 @@ export const LoginModal = () => {
if (isValid(server) && isValid(username) && isValid(password)) {
window.localStorage.DHIS2_BASE_URL = server
try {
await fetch(
await post(
`${server}/dhis-web-commons-security/login.action`,
{
method: 'POST',
credentials: 'include',
body: `j_username=${encodeURIComponent(
username
)}&j_password=${encodeURIComponent(password)}`,
headers: {
'X-Requested-With': 'XMLHttpRequest',
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
},
}
`j_username=${encodeURIComponent(
username
)}&j_password=${encodeURIComponent(password)}`
)
} catch (e) {
console.log(
Expand Down
58 changes: 58 additions & 0 deletions adapter/src/components/ServerVersionProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import { Provider } from '@dhis2/app-runtime'
import { parseServerVersion } from '../utils/parseServerVersion'
import { LoadingMask } from './LoadingMask'
import { get } from '../utils/api'

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

useEffect(() => {
setState(state => (state.loading ? state : { loading: true }))
const request = get(`${url}/api/system/info`)
request
.then(systemInfo => {
setState({ loading: false, systemInfo })
})
.catch(e => {
setState({ loading: false, error: e })
})

return () => {
request.abort()
}
}, [url])

if (loading) {
return <LoadingMask />
}

if (error) {
return children
}

const serverVersion = parseServerVersion(systemInfo.version)
const realApiVersion = serverVersion.minor

return (
<Provider
config={{
baseUrl: url,
apiVersion: apiVersion || realApiVersion,
serverVersion,
systemInfo,
}}
>
{children}
</Provider>
)
}

ServerVersionProvider.propTypes = {
url: PropTypes.string.isRequired,
apiVersion: PropTypes.number,
children: PropTypes.element,
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { FatalErrorBoundary } from '../'
import { FatalErrorBoundary } from '../FatalErrorBoundary'
import { shallow } from 'enzyme'

const Something = () => {
Expand Down
19 changes: 13 additions & 6 deletions adapter/src/index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
import React from 'react'
import PropTypes from 'prop-types'
import { HeaderBar } from '@dhis2/ui'
import { Provider } from '@dhis2/app-runtime'
import { FatalErrorBoundary } from './FatalErrorBoundary'
import { AuthBoundary } from './AuthBoundary'
import { FatalErrorBoundary } from './components/FatalErrorBoundary'
import { ServerVersionProvider } from './components/ServerVersionProvider'
import { AuthBoundary } from './components/AuthBoundary'

import { styles } from './styles.js'

// eslint-disable-next-line react/prop-types
const App = ({ url, apiVersion, appName, children }) => (
<FatalErrorBoundary>
<Provider config={{ baseUrl: url, apiVersion: apiVersion }}>
<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>
</div>
</Provider>
</ServerVersionProvider>
</FatalErrorBoundary>
)

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

export default App
Loading

0 comments on commit ef92456

Please sign in to comment.