Skip to content

Commit

Permalink
fix(alerts-service): add tests and align implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
HendrikThePendric committed Sep 9, 2021
1 parent bd4564c commit dabe477
Show file tree
Hide file tree
Showing 6 changed files with 407 additions and 124 deletions.
8 changes: 8 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,12 @@ module.exports = {
parserOptions: {
allowImportExportEverywhere: true,
},
overrides: [
{
files: ['*.test.js'],
rules: {
'react/prop-types': 'off',
},
},
],
}
1 change: 1 addition & 0 deletions adapter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
"devDependencies": {
"@dhis2/cli-app-scripts": "8.0.0-beta.5",
"@testing-library/react": "^12.0.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"react": "^16.8",
Expand Down
183 changes: 64 additions & 119 deletions adapter/src/components/Alerts.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,6 @@
import { useAlerts } from '@dhis2/app-runtime'
import { AlertBar, AlertStack } from '@dhis2/ui'
import PropTypes from 'prop-types'
import React, { Component } from 'react'

const toIdBasedObjectWithHiddenOption = (arr, hidden) =>
arr.reduce((obj, item) => {
obj[item.id] = {
...item,
options: {
...item.options,
hidden,
},
}
return obj
}, {})
import React, { useState, useEffect } from 'react'

/*
* The alert-manager which populates the `useAlerts` hook from `@dhis2/app-service-alerts`
Expand All @@ -27,117 +14,75 @@ const toIdBasedObjectWithHiddenOption = (arr, hidden) =>
* Alerts are removed from the `alertStackAlerts` state once the `onHidden` callback fires
*/

export class AlertsInternal extends Component {
constructor(props) {
super(props)
this.state = {
alertStackAlerts: props.alertManagerAlerts,
}
}

static getDerivedStateFromProps(props, state) {
const isEqual =
props.alertManagerAlerts.map(({ id }) => id).join() ===
state.alertStackAlerts.map(({ id }) => id).join()

console.log('isEqual: ', isEqual)

if (!isEqual) {
return {
alertStackAlerts: Object.values({
/*
* Assume that all alerts in the alertStackAlerts array are hiding.
* After the object merge only the alerts not in the alertManagerAlerts
* array will have `options.hidden === true`.
*/
...toIdBasedObjectWithHiddenOption(
state.alertStackAlerts,
true
),
/*
* All alertManagerAlerts should be showing. This object merge will
* overwrite any alertStackAlert by the alertManagerAlert with
* the same `id`, thus ensuring the alert is visible.
*/
...toIdBasedObjectWithHiddenOption(
props.alertManagerAlerts,
false
),
}),
}
}

return null
}

removeAlertStackAlert = id => {
// if (
// this.state.alertStackAlerts.find(
// alertStackAlert => alertStackAlert.id === id
// )
// ) {
this.setState({
alertStackAlerts: this.state.alertStackAlerts.filter(
const Alerts = () => {
const alertManagerAlerts = useAlerts()
const [alertStackAlerts, setAlertStackAlerts] = useState(alertManagerAlerts)
const removeAlertStackAlert = id =>
setAlertStackAlerts(
alertStackAlerts.filter(
alertStackAlert => alertStackAlert.id !== id
),
})
// }
}

render() {
console.log(
'+++\n',
'am: ',
this.props.alertManagerAlerts.map(({ id }) => id).join() || 'none',
'\n',
'as: ',
this.state.alertStackAlerts.map(({ id }) => id).join() || 'none',
'\nat:',
performance.now(),
'\n---\n'
)
)

return (
<AlertStack>
{this.state.alertStackAlerts.map(
({
message,
remove,
id,
options: { onHidden, ...props },
}) => (
<AlertBar
{...props}
key={id}
onHidden={() => {
onHidden && onHidden()
this.removeAlertStackAlert(id)
useEffect(() => {
if (alertManagerAlerts.length > 0 || alertStackAlerts.length > 0) {
setAlertStackAlerts(
mergeAlertStackAlerts(alertStackAlerts, alertManagerAlerts)
)
}
}, [alertManagerAlerts])

return (
<AlertStack>
{alertStackAlerts.map(
({ message, remove, id, options: { onHidden, ...props } }) => (
<AlertBar
{...props}
key={id}
onHidden={() => {
onHidden && onHidden()
removeAlertStackAlert(id)
if (alertManagerAlerts.some(a => a.id === id)) {
remove()
}}
>
{message}
</AlertBar>
)
)}
</AlertStack>
)
}
}
}}
>
{message}
</AlertBar>
)
)}
</AlertStack>
)
}

AlertsInternal.propTypes = {
alertManagerAlerts: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number,
message: PropTypes.string,
options: PropTypes.shape({
onHidden: PropTypes.bool,
}),
remove: PropTypes.func,
})
),
function mergeAlertStackAlerts(alertStackAlerts, alertManagerAlerts) {
return Object.values({
/*
* Assume that all alerts in the alertStackAlerts array are hiding.
* After the object merge only the alerts not in the alertManagerAlerts
* array will have `options.hidden === true`.
*/
...toIdBasedObjectWithHiddenOption(alertStackAlerts, true),
/*
* All alertManagerAlerts should be showing. This object merge will
* overwrite any alertStackAlert by the alertManagerAlert with
* the same `id`, thus ensuring the alert is visible.
*/
...toIdBasedObjectWithHiddenOption(alertManagerAlerts, false),
})
}

export const Alerts = () => {
const alertManagerAlerts = useAlerts()
return <AlertsInternal alertManagerAlerts={alertManagerAlerts} />
function toIdBasedObjectWithHiddenOption(arr, hidden) {
return arr.reduce((obj, item) => {
obj[item.id] = {
...item,
options: {
...item.options,
hidden,
},
}
return obj
}, {})
}

export { Alerts, mergeAlertStackAlerts }
Loading

0 comments on commit dabe477

Please sign in to comment.