Skip to content

Commit

Permalink
fix(DHIS2-13252): disable install button when no compatible versions …
Browse files Browse the repository at this point in the history
…are available
  • Loading branch information
kabaros committed Dec 13, 2023
1 parent a00f1e8 commit 6a45d21
Show file tree
Hide file tree
Showing 14 changed files with 1,851 additions and 91 deletions.
41 changes: 22 additions & 19 deletions .github/workflows/dhis2-verify-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12.x
node-version: 14.x

- uses: c-hive/gha-yarn-cache@v1
- run: yarn install --frozen-lockfile
Expand All @@ -42,7 +42,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12.x
node-version: 14.x

- uses: c-hive/gha-yarn-cache@v1
- run: yarn install --frozen-lockfile
Expand All @@ -53,22 +53,25 @@ jobs:
- name: Lint
run: yarn lint

# test:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
# - uses: actions/setup-node@v1
# with:
# node-version: 12.x
#
# - uses: c-hive/gha-yarn-cache@v1
# - run: yarn install --frozen-lockfile
#
# - name: Generate translations
# run: yarn d2-app-scripts i18n generate
#
# - name: Test
# run: yarn test
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 14.x

- uses: c-hive/gha-yarn-cache@v1
- run: yarn install --frozen-lockfile

# - name: Generate translations
# run: yarn d2-app-scripts i18n generate

- name: Test
run: yarn test --coverage

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1

release:
runs-on: ubuntu-latest
Expand All @@ -81,7 +84,7 @@ jobs:

- uses: actions/setup-node@v1
with:
node-version: 12.x
node-version: 14.x

- uses: actions/download-artifact@v2
with:
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ npm-debug.log
node_modules
.d2
src/locales
build
build

coverage
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[![codecov](https://codecov.io/gh/dhis2/app-management-app/graph/badge.svg?token=Z62Z57XE21)](https://codecov.io/gh/dhis2/maintenance-app-beta)

This project was bootstrapped with [DHIS2 Application Platform](https://github.com/dhis2/app-platform).

## Available Scripts
Expand Down
6 changes: 6 additions & 0 deletions jest-setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { configure } from '@testing-library/react'
import '@testing-library/jest-dom'

beforeEach(() => {
configure({ testIdAttribute: 'data-test' })
})
20 changes: 20 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const config = {
setupFilesAfterEnv: ['<rootDir>/jest-setup.js'],
collectCoverageFrom: [
'src/**/*.{js,jsx,ts,tsx}',
'!<rootDir>/node_modules/',
],
coverageThreshold: {
global: {
// TODO: The following should be 50
branches: 0,

// TODO: The following should be 75
functions: 0,
lines: 0,
statements: 0,
},
},
}

module.exports = config
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@
"homepage": "https://github.com/dhis2/app-management-app#readme",
"devDependencies": {
"@dhis2/cli-app-scripts": "^8.0.1",
"@dhis2/cli-style": "^10.4.1"
"@dhis2/cli-style": "^10.4.1",
"@testing-library/jest-dom": "^6.1.5",
"@testing-library/react": "^12",
"@types/jest": "^29.5.11",
"jest": "^29.7.0",
"react-dom": "^16"
},
"dependencies": {
"@dhis2/app-runtime": "^3.2.0",
Expand Down
24 changes: 21 additions & 3 deletions src/components/AppDetails/ManageInstalledVersion.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useAlert } from '@dhis2/app-runtime'
import { useAlert, useConfig } from '@dhis2/app-runtime'
import i18n from '@dhis2/d2-i18n'
import { PropTypes } from '@dhis2/prop-types'
import { Button } from '@dhis2/ui'
import React from 'react'
import semver from 'semver'
import { useApi } from '../../api.js'
import { getLatestVersion } from '../../get-latest-version.js'
import { semverGt } from '../../semver-gt.js'
import { getCompatibleVersions, semverGt } from '../../semver-helpers.js'
import styles from './AppDetails.module.css'
import { channelToDisplayName } from './channel-to-display-name.js'

Expand All @@ -22,6 +23,16 @@ export const ManageInstalledVersion = ({
const latestVersion = getLatestVersion(versions)
const canInstall =
latestVersion && latestVersion.version !== installedApp?.version

const { serverVersion } = useConfig()

const dhisVersion = semver.coerce(
`${serverVersion.major}.${serverVersion.minor}`
)

const compatibleVersions = getCompatibleVersions(versions, dhisVersion)
const hasCompatibleVersions = compatibleVersions.length > 0

const canUninstall = installedApp && !isBundled
const canUpdate =
installedApp &&
Expand Down Expand Up @@ -72,7 +83,14 @@ export const ManageInstalledVersion = ({

return (
<div className={styles.manageInstalledVersion}>
{canInstall && (
{!hasCompatibleVersions && (
<>
<em>
{i18n.t('There are no compatible versions available.')}
</em>
</>
)}
{hasCompatibleVersions && canInstall && (
<>
<Button primary onClick={handleInstall}>
{canUpdate
Expand Down
105 changes: 54 additions & 51 deletions src/components/AppDetails/Versions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import i18n from '@dhis2/d2-i18n'
import { PropTypes } from '@dhis2/prop-types'
import {
Checkbox,
CircularLoader,
Button,
Table,
TableHead,
Expand All @@ -16,6 +17,7 @@ import moment from 'moment'
import React, { useState } from 'react'
import semver from 'semver'
import { useApi } from '../../api.js'
import { getCompatibleVersions } from '../../semver-helpers.js'
import styles from './AppDetails.module.css'
import { channelToDisplayName } from './channel-to-display-name.js'

Expand Down Expand Up @@ -86,7 +88,12 @@ ChannelsFilter.propTypes = {
versions: PropTypes.array.isRequired,
}

const VersionsTable = ({ installedVersion, versions, onVersionInstall }) => (
const VersionsTable = ({
installedVersion,
versions,
onVersionInstall,
versionBeingInstalled,
}) => (
<Table>
<TableHead>
<TableRowHead>
Expand All @@ -101,39 +108,44 @@ const VersionsTable = ({ installedVersion, versions, onVersionInstall }) => (
</TableRowHead>
</TableHead>
<TableBody>
{versions.map((version) => (
<TableRow key={version.id}>
<TableCell>{version.version}</TableCell>
<TableCell>
{channelToDisplayName[version.channel]}
</TableCell>
<TableCell>
{moment(version.created).format('ll')}
</TableCell>
<TableCell>
<Button
small
secondary
className={styles.installBtn}
disabled={version.version === installedVersion}
onClick={() => onVersionInstall(version)}
>
{version.version === installedVersion
? i18n.t('Installed')
: i18n.t('Install')}
</Button>
<a
download
href={version.downloadUrl}
className={styles.downloadLink}
>
<Button small secondary>
{i18n.t('Download')}
{versions.map((version) => {
const isVersionInstalling = versionBeingInstalled === version.id
return (
<TableRow key={version.id} dataTest="versions-table-row">
<TableCell>{version.version}</TableCell>
<TableCell>
{channelToDisplayName[version.channel]}
</TableCell>
<TableCell>
{moment(version.created).format('ll')}
</TableCell>
<TableCell>
<Button
small
secondary
className={styles.installBtn}
disabled={
version.version === installedVersion ||
versionBeingInstalled
}
onClick={() => onVersionInstall(version)}
>
{isVersionInstalling && (
<>
{i18n.t('Installing...')}
<CircularLoader small />
</>
)}
{!isVersionInstalling
? version.version === installedVersion
? i18n.t('Installed')
: i18n.t('Install')
: ''}
</Button>
</a>
</TableCell>
</TableRow>
))}
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
)
Expand All @@ -142,6 +154,7 @@ VersionsTable.propTypes = {
versions: PropTypes.array.isRequired,
onVersionInstall: PropTypes.func.isRequired,
installedVersion: PropTypes.string,
versionBeingInstalled: PropTypes.string,
}

export const Versions = ({ installedVersion, versions, onVersionInstall }) => {
Expand All @@ -158,28 +171,18 @@ export const Versions = ({ installedVersion, versions, onVersionInstall }) => {
{ critical: true }
)
const { serverVersion } = useConfig()

const { installVersion } = useApi()
const dhisVersion = semver.coerce(
`${serverVersion.major}.${serverVersion.minor}`
)
const satisfiesDhisVersion = (version) => {
const { minDhisVersion: min, maxDhisVersion: max } = version
if (!min && !max) {
return true
} else if (min && max) {
const range = new semver.Range(`${min} - ${max}`)
return semver.satisfies(dhisVersion, range)
} else if (!min && max) {
const range = new semver.Range(`<=${max}`)
return semver.satisfies(dhisVersion, range)
} else if (min && !max) {
const range = new semver.Range(`>=${min}`)
return semver.satisfies(dhisVersion, range)
}
}
const filteredVersions = versions
.filter((version) => channelsFilter.has(version.channel))
.filter(satisfiesDhisVersion)

const filteredVersions = getCompatibleVersions(
versions,
dhisVersion,
channelsFilter
)

const handleVersionInstall = async (version) => {
try {
await installVersion(version.id)
Expand Down
Loading

0 comments on commit 6a45d21

Please sign in to comment.