Skip to content

Commit

Permalink
fix(app-platform): upgrade platform tools to use vite and react 18
Browse files Browse the repository at this point in the history
  • Loading branch information
kabaros committed Oct 22, 2024
1 parent a162d51 commit e2996af
Show file tree
Hide file tree
Showing 138 changed files with 7,397 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
![React 18](https://img.shields.io/badge/react-18-blue)
# Scheduler

## Cypress env settings
Expand Down
25 changes: 25 additions & 0 deletions src/components/App/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react'
import { CssVariables } from '@dhis2/ui'
import { Routes } from '../Routes'
import { AuthWall } from '../AuthWall'
import { Store } from '../Store'
import { PageWrapper } from '../PageWrapper'
import './App.css'

/* eslint-disable-next-line import/no-unassigned-import -- Necessary for translations to work */
import '../../locales'

const App = () => (
<React.Fragment>
<CssVariables spacers colors theme />
<PageWrapper>
<AuthWall>
<Store>
<Routes />
</Store>
</AuthWall>
</PageWrapper>
</React.Fragment>
)

export default App
9 changes: 9 additions & 0 deletions src/components/App/App.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react'

Check failure on line 1 in src/components/App/App.test.jsx

View workflow job for this annotation

GitHub Actions / lint / lint

No exports found
import { shallow } from 'enzyme'
import App from './App.jsx'

describe('<App>', () => {
it('renders without errors', () => {
shallow(<App />)
})
})
58 changes: 58 additions & 0 deletions src/components/AuthWall/AuthWall.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react'
import PropTypes from 'prop-types'
import { NoticeBox } from '@dhis2/ui'
import i18n from '@dhis2/d2-i18n'
import { useDataQuery } from '@dhis2/app-runtime'
import { Spinner } from '../Spinner'
import { getAuthorized } from './selectors'
import styles from './AuthWall.module.css'

const query = {
me: {
resource: 'me',
},
}

const AuthWall = ({ children }) => {
const { loading, error, data } = useDataQuery(query)

if (loading) {
return <Spinner />
}

if (error) {
return (
<div className={styles.noticeBoxWrapper}>
<NoticeBox error title={i18n.t('Something went wrong')}>
{i18n.t(
'Something went wrong whilst retrieving user permissions.'
)}
</NoticeBox>
</div>
)
}

const isAuthorized = getAuthorized(data.me)

if (!isAuthorized) {
return (
<div className={styles.noticeBoxWrapper}>
<NoticeBox error title={i18n.t('Not authorized')}>
{i18n.t(
"You don't have access to the Job Scheduler. Contact a system administrator to request access."
)}
</NoticeBox>
</div>
)
}

return <React.Fragment>{children}</React.Fragment>
}

const { node } = PropTypes

AuthWall.propTypes = {
children: node.isRequired,
}

export default AuthWall
72 changes: 72 additions & 0 deletions src/components/AuthWall/AuthWall.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react'

Check failure on line 1 in src/components/AuthWall/AuthWall.test.jsx

View workflow job for this annotation

GitHub Actions / lint / lint

No exports found
import { shallow, mount } from 'enzyme'
import { useDataQuery } from '@dhis2/app-runtime'
import { getAuthorized } from './selectors'
import AuthWall from './AuthWall.jsx'

jest.mock('@dhis2/app-runtime', () => ({
useDataQuery: jest.fn(),
}))

jest.mock('./selectors', () => ({
getAuthorized: jest.fn(),
}))

afterEach(() => {
jest.resetAllMocks()
})

describe('<AuthWall>', () => {
it('shows a spinner when loading', () => {
useDataQuery.mockImplementation(() => ({ loading: true }))

const wrapper = mount(<AuthWall>Child</AuthWall>)

Check failure on line 23 in src/components/AuthWall/AuthWall.test.jsx

View workflow job for this annotation

GitHub Actions / lint / lint

disallow literal string
const loadingIndicator = wrapper.find({
'data-test': 'dhis2-uicore-circularloader',
})

expect(loadingIndicator).toHaveLength(1)
})

it('shows a noticebox for fetching errors', () => {
const message = 'Something went wrong'
const error = new Error(message)

useDataQuery.mockImplementation(() => ({
loading: false,
error,
}))

const wrapper = shallow(<AuthWall>Child</AuthWall>)

Check failure on line 40 in src/components/AuthWall/AuthWall.test.jsx

View workflow job for this annotation

GitHub Actions / lint / lint

disallow literal string
const noticebox = wrapper.find('NoticeBox')

expect(noticebox).toHaveLength(1)
})

it('shows a noticebox for unauthorized users', () => {
useDataQuery.mockImplementation(() => ({
loading: false,
error: undefined,
data: {},
}))
getAuthorized.mockImplementation(() => false)

const wrapper = shallow(<AuthWall>Child</AuthWall>)

Check failure on line 54 in src/components/AuthWall/AuthWall.test.jsx

View workflow job for this annotation

GitHub Actions / lint / lint

disallow literal string
const noticebox = wrapper.find('NoticeBox')

expect(noticebox).toHaveLength(1)
})

it('renders the children for users that are authorized', () => {
useDataQuery.mockImplementation(() => ({
loading: false,
error: undefined,
data: {},
}))
getAuthorized.mockImplementation(() => true)

const wrapper = shallow(<AuthWall>Child</AuthWall>)

Check failure on line 68 in src/components/AuthWall/AuthWall.test.jsx

View workflow job for this annotation

GitHub Actions / lint / lint

disallow literal string

expect(wrapper.text()).toEqual(expect.stringContaining('Child'))
})
})
39 changes: 39 additions & 0 deletions src/components/Buttons/CronPresetButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { Button } from '@dhis2/ui'
import i18n from '@dhis2/d2-i18n'
import { CronPresetModal } from '../Modal'

const CronPresetButton = ({ setCron, small }) => {
const [showModal, setShowModal] = useState(false)

return (
<React.Fragment>
<Button onClick={() => setShowModal(true)} small={small}>
{i18n.t('Choose from preset times')}
</Button>
{showModal && (
<CronPresetModal
hideModal={
/* istanbul ignore next */
() => setShowModal(false)
}
setCron={setCron}
/>
)}
</React.Fragment>
)
}

CronPresetButton.defaultProps = {
small: false,
}

const { func, bool } = PropTypes

CronPresetButton.propTypes = {
setCron: func.isRequired,
small: bool,
}

export default CronPresetButton
23 changes: 23 additions & 0 deletions src/components/Buttons/CronPresetButton.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react'

Check failure on line 1 in src/components/Buttons/CronPresetButton.test.jsx

View workflow job for this annotation

GitHub Actions / lint / lint

No exports found
import { shallow, mount } from 'enzyme'
import CronPresetButton from './CronPresetButton.jsx'

describe('<CronPresetButton>', () => {
it('renders without errors', () => {
shallow(<CronPresetButton setCron={() => {}} />)
})

it('renders without errors when small', () => {
shallow(<CronPresetButton setCron={() => {}} small />)
})

it('shows the modal when button is clicked', () => {
const wrapper = mount(<CronPresetButton setCron={() => {}} />)

expect(wrapper.find('CronPresetModal')).toHaveLength(0)

wrapper.find('button').simulate('click')

expect(wrapper.find('CronPresetModal')).toHaveLength(1)
})
})
36 changes: 36 additions & 0 deletions src/components/Buttons/DeleteJobButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { Button } from '@dhis2/ui'
import i18n from '@dhis2/d2-i18n'
import { DeleteJobModal } from '../Modal'

const DeleteJobButton = ({ id, onSuccess }) => {
const [showModal, setShowModal] = useState(false)

return (
<React.Fragment>
<Button destructive onClick={() => setShowModal(true)}>
{i18n.t('Delete job')}
</Button>
{showModal && (
<DeleteJobModal
id={id}
hideModal={
/* istanbul ignore next */
() => setShowModal(false)
}
onSuccess={onSuccess}
/>
)}
</React.Fragment>
)
}

const { string, func } = PropTypes

DeleteJobButton.propTypes = {
id: string.isRequired,
onSuccess: func.isRequired,
}

export default DeleteJobButton
19 changes: 19 additions & 0 deletions src/components/Buttons/DeleteJobButton.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'

Check failure on line 1 in src/components/Buttons/DeleteJobButton.test.jsx

View workflow job for this annotation

GitHub Actions / lint / lint

No exports found
import { shallow, mount } from 'enzyme'
import DeleteJobButton from './DeleteJobButton.jsx'

describe('<DeleteJobButton>', () => {
it('renders without errors', () => {
shallow(<DeleteJobButton id="1" onSuccess={() => {}} />)
})

it('shows the modal when button is clicked', () => {
const wrapper = mount(<DeleteJobButton id="id" onSuccess={() => {}} />)

expect(wrapper.find('DeleteJobModal')).toHaveLength(0)

wrapper.find('button').simulate('click')

expect(wrapper.find('DeleteJobModal')).toHaveLength(1)
})
})
33 changes: 33 additions & 0 deletions src/components/Buttons/DeleteQueueButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { Button } from '@dhis2/ui'
import i18n from '@dhis2/d2-i18n'
import { DeleteQueueModal } from '../Modal'

const DeleteQueueButton = ({ name, onSuccess }) => {
const [showModal, setShowModal] = useState(false)

return (
<React.Fragment>
<Button destructive onClick={() => setShowModal(true)}>
{i18n.t('Delete queue')}
</Button>
{showModal && (
<DeleteQueueModal
name={name}
hideModal={() => setShowModal(false)}
onSuccess={onSuccess}
/>
)}
</React.Fragment>
)
}

const { string, func } = PropTypes

DeleteQueueButton.propTypes = {
name: string.isRequired,
onSuccess: func.isRequired,
}

export default DeleteQueueButton
21 changes: 21 additions & 0 deletions src/components/Buttons/DeleteQueueButton.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'

Check failure on line 1 in src/components/Buttons/DeleteQueueButton.test.jsx

View workflow job for this annotation

GitHub Actions / lint / lint

No exports found
import { shallow, mount } from 'enzyme'
import DeleteQueueButton from './DeleteQueueButton.jsx'

describe('<DeleteQueueButton>', () => {
it('renders without errors', () => {
shallow(<DeleteQueueButton name="name" onSuccess={() => {}} />)
})

it('shows the modal when button is clicked', () => {
const wrapper = mount(
<DeleteQueueButton name="name" onSuccess={() => {}} />
)

expect(wrapper.find('DeleteQueueModal')).toHaveLength(0)

wrapper.find('button').simulate('click')

expect(wrapper.find('DeleteQueueModal')).toHaveLength(1)
})
})
45 changes: 45 additions & 0 deletions src/components/Buttons/DiscardFormButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { Button } from '@dhis2/ui'
import history from '../../services/history'
import { DiscardFormModal } from '../Modal'

const DiscardFormButton = ({ shouldConfirm, children, small, className }) => {
const [showModal, setShowModal] = useState(false)
const onClick = shouldConfirm
? () => setShowModal(true)
: () => history.push('/')

return (
<React.Fragment>
<Button onClick={onClick} small={small} className={className}>
{children}
</Button>
{showModal && (
<DiscardFormModal
hideModal={
/* istanbul ignore next */
() => setShowModal(false)
}
/>
)}
</React.Fragment>
)
}

DiscardFormButton.defaultProps = {
className: '',
shouldConfirm: false,
small: false,
}

const { string, bool } = PropTypes

DiscardFormButton.propTypes = {
children: string.isRequired,
className: string,
shouldConfirm: bool,
small: bool,
}

export default DiscardFormButton
Loading

0 comments on commit e2996af

Please sign in to comment.