Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/pic 3744 on hold tab #939

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion integration-tests/cypress/support/step_definitions/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ Then('I click the {string} link in the pagination links', ($link) => {

Then('the page {int} should be loaded', ($pageNo) => {
cy.location().should(location => {
const urlParams = new URLSearchParams(location.href)
const url = new URL(location.href)
const urlParams = new URLSearchParams(url.search)
expect(urlParams.get('page')).eq(`${$pageNo}`)
})
})
Expand Down
3 changes: 2 additions & 1 deletion server/routes/handlers/outcomes/getCasesInProgressHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ const getCasesInProgressHandler = caseService => async (req, res) => {
filters: flaggedFilters,
filtersApplied,
casesInProgressCount: response?.totalElements || 0,
casesToResultCount: response?.countsByState?.toResultCount || 0
casesToResultCount: response?.countsByState?.toResultCount || 0,
casesOnHoldCount: response?.countsByState?.onHoldCount || 0
},
title,
currentUserUuid: res.locals.user.uuid,
Expand Down
3 changes: 2 additions & 1 deletion server/routes/handlers/outcomes/getCasesToResultHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ const getCasesToResultHandler = caseService => async (req, res) => {
filters,
filtersApplied,
casesInProgressCount: response?.countsByState?.inProgressCount || 0,
casesToResultCount: response.totalElements
casesToResultCount: response.totalElements,
casesOnHoldCount: response?.countsByState?.onHoldCount || 0
},
title,
data: response.cases || [],
Expand Down
27 changes: 27 additions & 0 deletions server/routes/handlers/outcomes/getMoveToOnHoldHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const trackEvent = require('../../../utils/analytics')
const getMoveToResultedHandler = (caseService, utils) => async (req, res) => {
const { params: { courtCode, hearingId, defendantId } } = req
const templateValues = await utils.getCaseAndTemplateValues(req)
const { apostropheInName, properCase, removeTitle } = utils.nunjucksFilters
const formattedName = removeTitle(properCase(apostropheInName(templateValues.data.defendantName)))

const bannerText = `You have moved ${formattedName}'s case to on hold.`

req.flash('move-to-on-hold', bannerText)

await caseService.updateHearingOutcomeToOnHold(hearingId, defendantId)

trackEvent(
'PiCPrepareACaseHearingOutcomes',
{
operation: 'updateHearingOutcomeToOnHold',
hearingId,
courtCode,
userId: res.locals.user.userId
}
)

res.redirect(`/${courtCode}/outcomes/on-hold`)
}

module.exports = getMoveToResultedHandler
13 changes: 9 additions & 4 deletions server/routes/handlers/outcomes/getMoveToResultedHandler.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const trackEvent = require('../../../utils/analytics')
const getMoveToResultedHandler = caseService => async (req, res) => {
const { params: { courtCode, hearingId, defendantId }, session } = req
const getMoveToResultedHandler = (caseService, utils) => async (req, res) => {
const { params: { courtCode, hearingId, defendantId } } = req
const { defendantName, redirectPage } = req.query
const { apostropheInName, properCase, removeTitle } = utils.nunjucksFilters
const formattedName = removeTitle(properCase(apostropheInName(defendantName)))

await caseService.updateHearingOutcomeToResulted(hearingId, defendantId)

Expand All @@ -14,9 +17,11 @@ const getMoveToResultedHandler = caseService => async (req, res) => {
}
)

session.moveToResultedSuccess = req.query.defendantName
const redirectUrl = redirectPage ?? 'in-progress'

res.redirect(`/${courtCode}/outcomes/in-progress`)
req.flash('moved-to-resulted', `You have moved ${formattedName}'s case to resulted cases.`)

res.redirect(`/${courtCode}/outcomes/${redirectUrl}`)
}

module.exports = getMoveToResultedHandler
66 changes: 66 additions & 0 deletions server/routes/handlers/outcomes/getOnHoldCasesHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const getOutcomeTypesListFilters = require('../../../utils/getOutcomeTypesListFilters')
const getHearingOutcomeAssignedToFilters = require('../../../utils/getHearingOutcomeAssignedToFilters')
const flagFilters = require('../../../utils/flagFilters')
const { prepareCourtRoomFilters } = require('../../helpers')

const getOnHoldCasesHandler = caseService => async (req, res) => {
const {
params: { courtCode, title, sorts, state },
params
} = req

const response = await caseService.getOutcomesList(
courtCode,
req.query,
sorts,
state
)

const flashMessage = req.flash('move-to-on-hold') ?? req.flash('moved-to-resulted')

const cases = response.cases

const courtRoomFilter = {
id: 'courtRoom',
label: 'Courtroom',
items: prepareCourtRoomFilters(response.courtRoomFilters)
}

const outcomeTypesListFilters = await getOutcomeTypesListFilters()

const filters = [outcomeTypesListFilters, courtRoomFilter]

const assignedToFilter = getHearingOutcomeAssignedToFilters(cases, req.query)

if (assignedToFilter) {
filters.push(assignedToFilter)
}

const flaggedFilters = flagFilters(req.query, filters)

const filtersApplied = flaggedFilters
.map(filterObj => filterObj.items.filter(item => item.checked).length)
.some(length => length > 0)

const templateValues = {
params: {
...params,
filters: flaggedFilters,
filtersApplied,
casesInProgressCount: response?.countsByState?.inProgressCount || 0,
casesToResultCount: response?.countsByState?.toResultCount || 0,
casesOnHoldCount: response?.countsByState?.onHoldCount || 0
},
title,
currentUserUuid: res.locals.user.uuid,
data: cases || [],
displayFilters: response.cases?.length || filtersApplied,
totalPages: response.totalPages,
totalElements: response.totalElements,
flashMessage
}

res.render('outcomes/casesOnHold', templateValues)
}

module.exports = getOnHoldCasesHandler
3 changes: 2 additions & 1 deletion server/routes/handlers/outcomes/getResultedCasesHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ const getResultedCasesHandler = caseService => async (req, res) => {
filters: flaggedFilters,
filtersApplied,
casesInProgressCount: response?.countsByState?.inProgressCount || 0,
casesToResultCount: response?.countsByState?.toResultCount || 0
casesToResultCount: response?.countsByState?.toResultCount || 0,
casesOnHoldCount: response?.countsByState?.onHoldCount || 0
},
title,
currentUserUuid: res.locals.user.uuid,
Expand Down
11 changes: 9 additions & 2 deletions server/routes/handlers/outcomes/outcomesRouter.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
const express = require('express')

const { getOutcomesList, assignHearingOutcome, updateHearingOutcomeToResulted } = require('../../../services/case-service')
const { getOutcomesList, assignHearingOutcome, updateHearingOutcomeToResulted, updateHearingOutcomeToOnHold, getCase } = require('../../../services/case-service')
const getCaseAndTemplateValues = require('../getCaseTemplateValuesHelper')({ getCase })
const nunjucksFilters = require('../../../utils/nunjucksFilters')

const casesToResultHandler = require('./getCasesToResultHandler')({ getOutcomesList })
const casesInProgressHandler = require('./getCasesInProgressHandler')({ getOutcomesList })
const getResultedCasesHandler = require('./getResultedCasesHandler')({ getOutcomesList })
const getOnHoldCasesHandler = require('./getOnHoldCasesHandler')({ getOutcomesList })
const assignHearingOutcomeRouteHandler = require('./getAssignUserToOutcomeRequestHandler')({ assignHearingOutcome })
const getMoveToResultedHandler = require('./getMoveToResultedHandler')({ updateHearingOutcomeToResulted })
const getMoveToResultedHandler = require('./getMoveToResultedHandler')({ updateHearingOutcomeToResulted }, { nunjucksFilters })
const getMoveToOnHoldHandler = require('./getMoveToOnHoldHandler')({ updateHearingOutcomeToOnHold }, { getCaseAndTemplateValues, nunjucksFilters })
const postActionsHandler = require('./postActionsHandler')({ assignHearingOutcome })

const { defaults } = require('../../middleware/defaults')
Expand All @@ -17,8 +22,10 @@ const outcomesRouter = express.Router({ mergeParams: true })
outcomesRouter.get('/', defaults, outcomesMiddleware('NEW'), catchErrors(casesToResultHandler))
outcomesRouter.post('/', defaults, outcomesMiddleware('NEW'), catchErrors(postActionsHandler))
outcomesRouter.get('/in-progress', defaults, outcomesMiddleware('IN_PROGRESS'), catchErrors(casesInProgressHandler))
outcomesRouter.get('/on-hold', defaults, outcomesMiddleware('ON_HOLD'), catchErrors(getOnHoldCasesHandler))
outcomesRouter.get('/resulted-cases', defaults, outcomesMiddleware('RESULTED'), catchErrors(getResultedCasesHandler))
outcomesRouter.get('/hearing/:hearingId/defendant/:defendantId/move-to-resulted', defaults, catchErrors(getMoveToResultedHandler))
outcomesRouter.get('/hearing/:hearingId/defendant/:defendantId/move-to-on-hold', defaults, catchErrors(getMoveToOnHoldHandler))
outcomesRouter.post('/hearing/:hearingId/assign', defaults, catchErrors(assignHearingOutcomeRouteHandler))

module.exports = outcomesRouter
18 changes: 17 additions & 1 deletion server/routes/middleware/outcomesMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@ const getOutcomeListSorts = require('../../utils/getOutcomesSorts')
const features = require('../../utils/features')
const log = require('../../log')
const { settings } = require('../../config')

const getBaseUrl = (state) => {
switch (state) {
case 'NEW':
return ''
case 'IN_PROGRESS':
return 'in-progress'
case 'RESULTED':
return 'resulted-cases'
case 'ON_HOLD':
return 'on-hold'
default:
return ''
}
}

const outcomesMiddleware = state => async (req, res, next) => {
const context = { court: req.params.courtCode, username: res.locals.user.username }

Expand Down Expand Up @@ -43,7 +59,7 @@ const outcomesMiddleware = state => async (req, res, next) => {
}
})

const pagingBaseUrl = `${state === 'NEW' ? '' : (state === 'IN_PROGRESS' ? 'in-progress' : 'resulted-cases')}?${paramMap.toString()}`
const pagingBaseUrl = getBaseUrl(state)

req.params = {
...params,
Expand Down
7 changes: 6 additions & 1 deletion server/services/case-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const defaultFilterMatcher = (courtCase, filterObj, item) =>
: false

const allowedSortValues = ['ASC', 'DESC']
const allowedStates = ['NEW', 'IN_PROGRESS', 'RESULTED']
const allowedStates = ['NEW', 'IN_PROGRESS', 'RESULTED', 'ON_HOLD']

const createCaseService = apiUrl => {
return {
Expand Down Expand Up @@ -381,6 +381,11 @@ const createCaseService = apiUrl => {
await create(urlString)
},

updateHearingOutcomeToOnHold: async (hearingId, defendantId) => {
const urlString = `${apiUrl}/hearing/${hearingId}/defendant/${defendantId}/outcome/on-hold`
await create(urlString)
},

searchCases: async (term, type, page, pageSize) => {
try {
return await request(`${apiUrl}/search`, {
Expand Down
33 changes: 26 additions & 7 deletions server/views/outcomes/casesInProgress.njk
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,36 @@
{{ offences.push('</ol>') }}
{% endif %}

{% set actionButtonHtml %}
{% set assignedToCurrentUser = currentUserUuid === item.assignedToUuid %}
<div class="govuk-button-group">
{{ govukButton({
text: 'Move to resulted',
classes: ('govuk-!-width-three-quarters' if assignedToCurrentUser else "govuk-button--secondary govuk-!-width-three-quarters"),
href: ('hearing/' + item.hearingId + '/defendant/' + item.defendantId + '/move-to-resulted?defendantName=' + item.defendantName) if assignedToCurrentUser else '',
disabled: not assignedToCurrentUser
}) }}

{{ govukButton({
text: 'Put on hold',
classes: "govuk-button--secondary govuk-!-width-three-quarters",
href: ('hearing/' + item.hearingId + '/defendant/' + item.defendantId + '/move-to-on-hold?defendantName=' + item.defendantName) if assignedToCurrentUser else '',
disabled: not assignedToCurrentUser
}) }}
</div>
{% endset %}


{% set defendantFullName = (item.name.forename1 + ' ' + item.name.surname) if (item.name.forename1 and item.name.surname) else item.defendantName %}
{% set a11yTitle = 'View case for defendant ' + defendantFullName | escape | apostropheInName | properCase | removeTitle %}
{% set crnDisplay = '<div class="pac-secondary-text govuk-body-s govuk-!-margin-top-1">' + item.crn if item.crn else '' + '</div>' %}
{% set assignedToCurrentUser = currentUserUuid === item.assignedToUuid %}
{%- set tableRow = [
{ text: ('<a href="/' + params.courtCode + '/hearing/' + item.hearingId + '/defendant/' + item.defendantId + '/summary" class="pac-defendant-link govuk-!-font-weight-bold govuk-link govuk-link--no-visited-state' + (' pac-reassign' | safe if not assignedToCurrentUser ) + '" aria-label="' + a11yTitle + '"' + ('data-hearingid="' + item.hearingId + '" data-defendantid="' + item.defendantId + '" data-courtcode="' + params.courtCode + '" data-bs-toggle="modal" data-bs-target="#reassign-outcome-modal"' | safe if not assignedToCurrentUser) + '>' + defendantFullName | escape | apostropheInName | properCase | removeTitle + '</a>' + crnDisplay ) | safe },
{ text: item.hearingOutcomeDescription | safe },
{ text: ('<div>' + ('<span class="moj-badge moj-badge--red pac-badge">Possible NDelius Record</span>' | safe if notMatched ) + '</div>'+ (item.probationStatus | string | capitalize if not notMatched)) | safe },
{ text: offences | join('') | safe },
{ text: moment(item.hearingDate, 'YYYY-MM-DD').format("D MMM YYYY"), format: 'numeric' },
{ text: govukButton({
text: 'Move to resulted',
classes: ('' if assignedToCurrentUser else "govuk-button--secondary"),
href: ('hearing/' + item.hearingId + '/defendant/' + item.defendantId + '/move-to-resulted?defendantName=' + item.defendantName) if assignedToCurrentUser else '',
disabled: not assignedToCurrentUser
}) }
{ text: actionButtonHtml | safe}
] -%}
{{ tableData.rows.push(tableRow) }}

Expand All @@ -88,6 +101,12 @@
current: true,
count: params.casesInProgressCount
},
{
title: 'On hold',
a11yTitle: 'View case outcomes on hold',
link: '/' + params.courtCode + '/outcomes/on-hold',
count: params.casesOnHoldCount
},
{
title: 'Resulted cases',
a11yTitle: 'View resulted cases',
Expand Down
Loading