Skip to content

Commit

Permalink
[bugfix 5573] Error handling when sorting (#2779)
Browse files Browse the repository at this point in the history
* Showing chevron after answer from backend has returned

- Chevron is now shown in column that has either a successful return from the backend, or in the column that was previous ordered.
- create selector makeSelectErrorMessage
- made prop errorMessage in IncidentOverviewPageContainerComponent
- set globalNotification when errorMessage changes and is not undefined.

* fixed definition of Type_Global and Variant_Notice. Now it is all in one place again.
  • Loading branch information
SireeKoolenWijkstra authored Dec 8, 2023
1 parent 2ed33b3 commit 728307d
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 16 deletions.
10 changes: 5 additions & 5 deletions src/signals/incident-management/__tests__/saga.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ describe('signals/incident-management/saga', () => {
const filter = { name: 'filter', refresh: false }
const page = 2
const ordering = '-created_at'
const incidents = [{}, {}]
const incidents = { 0: {}, 1: {}, orderedAs: '-created_at' }
const params = { test: 'test' }
const filterParams = {
page,
Expand Down Expand Up @@ -182,7 +182,7 @@ describe('signals/incident-management/saga', () => {
[select(makeSelectActiveFilter), {}],
[matchers.call.fn(authCall), []],
])
.put(requestIncidentsSuccess([]))
.put(requestIncidentsSuccess({ orderedAs: '' }))
.dispatch({ type: CLEAR_FILTERS })
.silentRun())

Expand All @@ -192,7 +192,7 @@ describe('signals/incident-management/saga', () => {
[select(makeSelectActiveFilter), {}],
[matchers.call.fn(authCall), []],
])
.put(requestIncidentsSuccess([]))
.put(requestIncidentsSuccess({ orderedAs: '' }))
.dispatch({ type: PAGE_CHANGED, payload: 4 })
.silentRun())

Expand All @@ -202,7 +202,7 @@ describe('signals/incident-management/saga', () => {
[select(makeSelectActiveFilter), {}],
[matchers.call.fn(authCall), []],
])
.put(requestIncidentsSuccess([]))
.put(requestIncidentsSuccess({ orderedAs: '' }))
.dispatch({
type: ORDERING_CHANGED,
payload: 'incident-id-in-asc-order',
Expand All @@ -225,7 +225,7 @@ describe('signals/incident-management/saga', () => {
.select(makeSelectFilterParams)
.call.like(authCall, CONFIGURATION.SEARCH_ENDPOINT, { q })
.not.put(push('/manage/incidents'))
.put(searchIncidentsSuccess(incidentsJSON))
.put(searchIncidentsSuccess({ ...incidentsJSON, orderedAs: '' }))
.run()
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import LoadingIndicator from 'components/LoadingIndicator'
import Modal from 'components/Modal'
import OverviewMap from 'components/OverviewMap'
import { showGlobalNotification } from 'containers/App/actions'
import { VARIANT_NOTICE, TYPE_GLOBAL } from 'containers/App/constants'
import { makeSelectSearchQuery } from 'containers/App/selectors'
import MapContext from 'containers/MapContext'
import useEventEmitter from 'hooks/useEventEmitter'
Expand All @@ -32,6 +31,7 @@ import MyFilters from 'signals/incident-management/containers/MyFilters'
import dataLists from 'signals/incident-management/definitions'
import {
makeSelectActiveFilter,
makeSelectErrorMessage,
makeSelectFiltersOnOverview,
makeSelectIncidents,
makeSelectOrdering,
Expand All @@ -53,6 +53,12 @@ import {
StyledButton,
StyledPagination,
} from './styled'
import {
TYPE_GLOBAL,
TYPE_LOCAL,
VARIANT_ERROR,
VARIANT_NOTICE,
} from '../../../../containers/Notification/constants'
import { MAP_URL } from '../../routes'
import FilterTagList from '../FilterTagList/FilterTagList'

Expand All @@ -68,6 +74,7 @@ export const IncidentOverviewPageContainerComponent = ({
orderingChangedAction,
page,
pageChangedAction,
errorMessage,
}) => {
const location = useLocation()
const dispatch = useDispatch()
Expand Down Expand Up @@ -98,6 +105,19 @@ export const IncidentOverviewPageContainerComponent = ({
const disableFilters = hasActiveOrdering || searchQueryIncidents
const disableSorting = hasActiveFilters || searchQueryIncidents

useEffect(() => {
if (errorMessage) {
dispatch(
showGlobalNotification({
title: 'Let op, het sorteren is niet gelukt',
message: errorMessage,
variant: VARIANT_ERROR,
type: TYPE_LOCAL,
})
)
}
}, [errorMessage, dispatch])

const showNotification = useCallback(() => {
dispatch(
showGlobalNotification({
Expand Down Expand Up @@ -278,7 +298,7 @@ export const IncidentOverviewPageContainerComponent = ({

{canRenderList && (
<List
ordering={ordering}
ordering={incidents.orderedAs}
orderingChangedAction={orderingChangedAction}
incidents={incidents.results}
incidentsCount={count}
Expand Down Expand Up @@ -318,6 +338,7 @@ IncidentOverviewPageContainerComponent.propTypes = {
pageChangedAction: PropTypes.func.isRequired,
ordering: PropTypes.string.isRequired,
page: PropTypes.number,
errorMessage: PropTypes.string,
}

const mapStateToProps = createStructuredSelector({
Expand All @@ -326,6 +347,7 @@ const mapStateToProps = createStructuredSelector({
incidents: makeSelectIncidents,
ordering: makeSelectOrdering,
page: makeSelectPage,
errorMessage: makeSelectErrorMessage,
})

export const mapDispatchToProps = (dispatch) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import Adapter from '@wojtekmaj/enzyme-adapter-react-17'
import Enzyme, { mount } from 'enzyme'
import fetchMock from 'jest-fetch-mock'
import { mocked } from 'jest-mock'
import * as reactRedux from 'react-redux'
import { disablePageScroll, enablePageScroll } from 'scroll-lock'
Expand All @@ -17,12 +18,6 @@ import IncidentOverviewPage, { IncidentOverviewPageContainerComponent } from '.'

Enzyme.configure({ adapter: new Adapter() })

const mockedGlobalNotification = mocked(
actions.showGlobalNotification,
true
).mockReturnValue({
type: 'sia/App/SHOW_GLOBAL_NOTIFICATION',
})
jest.mock('containers/App/actions')

jest.mock('scroll-lock')
Expand Down Expand Up @@ -87,6 +82,10 @@ describe('signals/incident-management/containers/IncidentOverviewPage', () => {
clearFiltersAction: jest.fn(),
}
})
afterEach(() => {
jest.resetAllMocks()
fetchMock.resetMocks()
})

it('should render modal buttons', () => {
render(
Expand Down Expand Up @@ -219,6 +218,39 @@ describe('signals/incident-management/containers/IncidentOverviewPage', () => {
expect(screen.getByText('Geen meldingen')).toBeInTheDocument()
})

it('should show notification when sorting is not working', async () => {
const mockedGlobalNotification = mocked(
actions.showGlobalNotification,
true
).mockReturnValue({
type: 'sia/App/SHOW_GLOBAL_NOTIFICATION',
})

const incidents = generateIncidents()

render(
withAppContext(
<IncidentOverviewPageContainerComponent
{...props}
incidents={{
count: incidents.length,
results: incidents,
loadingIncidents: false,
}}
errorMessage="testing"
/>
)
)
await waitFor(() => {
expect(mockedGlobalNotification).toHaveBeenCalledWith(
expect.objectContaining({
title: 'Let op, het sorteren is niet gelukt',
message: 'testing',
})
)
})
})

it('should have props from structured selector', () => {
const tree = mount(withAppContext(<IncidentOverviewPage />))

Expand Down Expand Up @@ -440,6 +472,13 @@ describe('signals/incident-management/containers/IncidentOverviewPage', () => {
})

it('should disable filter buttons when ordering is active and show notification when clicked', async () => {
const mockedGlobalNotification = mocked(
actions.showGlobalNotification,
true
).mockReturnValue({
type: 'sia/App/SHOW_GLOBAL_NOTIFICATION',
})

render(
withAppContext(
<IncidentOverviewPageContainerComponent
Expand All @@ -465,6 +504,12 @@ describe('signals/incident-management/containers/IncidentOverviewPage', () => {
})

it('should disable filter buttons when search is active and show notification when clicked', async () => {
const mockedGlobalNotification = mocked(
actions.showGlobalNotification,
true
).mockReturnValue({
type: 'sia/App/SHOW_GLOBAL_NOTIFICATION',
})
jest.spyOn(reactRedux, 'useSelector').mockReturnValue('mock-search-query')

render(
Expand Down
4 changes: 3 additions & 1 deletion src/signals/incident-management/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ export const initialState = fromJS({
incidents: {
count: undefined,
results: [],
orderedAs: '', //ordering of results
},
loading: false,
loadingDistricts: false,
loadingFilters: false,
loadingIncidents: false,
ordering: '',
ordering: '', //ordering as user wants, may have failed. Old ordering still available in incidients.orderedAs

page: 1,
})

Expand Down
6 changes: 4 additions & 2 deletions src/signals/incident-management/saga.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ export function* fetchIncidents() {
params
)

yield put(requestIncidentsSuccess(incidents))
yield put(
requestIncidentsSuccess({ ...incidents, orderedAs: params.ordering })
)

if (filter && filter.refresh) {
yield put(applyFilterRefresh())
Expand All @@ -113,7 +115,7 @@ export function* searchIncidents() {
ordering,
})

yield put(searchIncidentsSuccess(incidents))
yield put(searchIncidentsSuccess({ ...incidents, orderedAs: ordering }))
} catch (error) {
if (error.response && error.response.status === 500) {
// Getting an error response with status code 500 from the search endpoint
Expand Down
9 changes: 9 additions & 0 deletions src/signals/incident-management/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,15 @@ export const makeSelectIncidents = createSelector(
}
)

export const makeSelectErrorMessage = createSelector(
selectIncidentManagementDomain,
(state) => {
const obj = state.toJS()

return obj.errorMessage
}
)

export const makeSelectIncidentsCount = createSelector(
selectIncidentManagementDomain,
(state) => {
Expand Down

0 comments on commit 728307d

Please sign in to comment.