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 479076: Advanced Search #686

Merged
merged 11 commits into from
Jan 29, 2025
14 changes: 14 additions & 0 deletions designer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,17 @@ The following attribution statement MUST be cited in your products and applicati
The Open Government Licence (OGL) was developed by the Controller of Her Majesty's Stationery Office (HMSO) to enable information providers in the public sector to license the use and re-use of their information under a common open licence.

It is designed to encourage use and re-use of information freely and flexibly, with only a few conditions.

# Forms Model Changes

If you make changes to the `@defra/forms-model` package (in the `model/` dir), or pull in model changes after rebasing with main, you'll need to:

```sh
npm run build --workspace=model
```

2. Restart your terminal/command prompt

3. In VS Code, press `Cmd + Shift + P` (Mac) or `Ctrl + Shift + P` (Windows/Linux) and search for "Developer: Reload Window"

This might be needed as the model package needs to be rebuilt to generate new TypeScript type definitions and compiled JavaScript files. Without these steps, you may see TS errors about missing types, especially after rebasing with main.
2 changes: 2 additions & 0 deletions designer/client/src/javascripts/application.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ServiceHeader } from '@defra/forms-designer/server/src/common/components/service-header/service-header.js'
import {
Accordion,
Button,
CharacterCount,
ErrorSummary,
Expand All @@ -8,6 +9,7 @@ import {
createAll
} from 'govuk-frontend'

createAll(Accordion)
createAll(Button)
createAll(CharacterCount)
createAll(ErrorSummary)
Expand Down
21 changes: 17 additions & 4 deletions designer/server/src/common/components/pagination/template.njk
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
{% from "govuk/components/pagination/macro.njk" import govukPagination %}

{% if params.pagination and params.pagination.totalPages > 1 %}
{% set titleQuery = "" %}
{% set queryParams = "" %}
{% if params.search.title %}
{% set titleQuery = "&title=" ~ (params.search.title | urlencode) %}
{% set queryParams = queryParams ~ "&title=" ~ (params.search.title | urlencode) %}
{% endif %}
{% if params.search.author is defined and params.search.author != "" %}
{% set queryParams = queryParams ~ "&author=" ~ (params.search.author | urlencode) %}
{% endif %}
{% if params.search.organisations and params.search.organisations | length %}
{% for org in params.search.organisations %}
{% set queryParams = queryParams ~ "&organisations=" ~ (org | urlencode) %}
{% endfor %}
{% endif %}
{% if params.search.status and params.search.status | length %}
{% for state in params.search.status %}
{% set queryParams = queryParams ~ "&status=" ~ (state | urlencode) %}
{% endfor %}
{% endif %}

{% set previous = null %}
{% if params.pagination.page > 1 %}
{% set previousHref = (params.baseUrl | default('')) ~ "?page=" ~ (params.pagination.page - 1) ~ "&perPage=" ~ params.pagination.perPage ~ titleQuery %}
{% set previousHref = (params.baseUrl | default('')) ~ "?page=" ~ (params.pagination.page - 1) ~ "&perPage=" ~ params.pagination.perPage ~ queryParams %}
{% set previous = {
href: previousHref,
labelText: "Previous page",
Expand All @@ -18,7 +31,7 @@

{% set next = null %}
{% if params.pagination.page < params.pagination.totalPages %}
{% set nextHref = (params.baseUrl | default('')) ~ "?page=" ~ (params.pagination.page + 1) ~ "&perPage=" ~ params.pagination.perPage ~ titleQuery %}
{% set nextHref = (params.baseUrl | default('')) ~ "?page=" ~ (params.pagination.page + 1) ~ "&perPage=" ~ params.pagination.perPage ~ queryParams %}
{% set next = {
href: nextHref,
labelText: "Next page",
Expand Down
302 changes: 302 additions & 0 deletions designer/server/src/common/components/pagination/template.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,308 @@ describe('Pagination Component', () => {
})
})

describe('With search author parameter', () => {
beforeEach(() => {
const { container } = renderMacro(
'appPagination',
'pagination/macro.njk',
{
params: {
baseUrl: '/library',
search: {
author: 'Enrique Chase'
},
pagination: {
page: 2,
perPage: 10,
totalPages: 3,
totalItems: 25,
pages: [
{
number: '1',
href: '/library?page=1&perPage=10&author=Enrique%20Chase',
current: false
},
{
number: '2',
href: '/library?page=2&perPage=10&author=Enrique%20Chase',
current: true
},
{
number: '3',
href: '/library?page=3&perPage=10&author=Enrique%20Chase',
current: false
}
]
}
}
}
)

$pagination = container.getByRole('navigation', { name: 'Pagination' })
})

it('should include encoded author parameter in navigation links', () => {
const $previousLink = within($pagination).getByRole('link', {
name: 'Previous'
})
const $nextLink = within($pagination).getByRole('link', {
name: 'Next'
})

expect($previousLink).toHaveAttribute(
'href',
'/library?page=1&perPage=10&author=Enrique%20Chase'
)
expect($nextLink).toHaveAttribute(
'href',
'/library?page=3&perPage=10&author=Enrique%20Chase'
)
})

it('should include encoded author parameter in page number links', () => {
const $pageLinks = within($pagination).getAllByRole('link', {
name: /Page \d+/
})

expect($pageLinks[0]).toHaveAttribute(
'href',
'/library?page=1&perPage=10&author=Enrique%20Chase'
)
expect($pageLinks[1]).toHaveAttribute(
'href',
'/library?page=2&perPage=10&author=Enrique%20Chase'
)
expect($pageLinks[2]).toHaveAttribute(
'href',
'/library?page=3&perPage=10&author=Enrique%20Chase'
)
})
})

describe('With search organisations parameter', () => {
beforeEach(() => {
const { container } = renderMacro(
'appPagination',
'pagination/macro.njk',
{
params: {
baseUrl: '/library',
search: {
organisations: [
'Defra',
'Environment Agency',
'Natural England'
]
},
pagination: {
page: 2,
perPage: 10,
totalPages: 3,
totalItems: 25,
pages: [
{
number: '1',
href: '/library?page=1&perPage=10&organisations=Defra&organisations=Environment%20Agency&organisations=Natural%20England',
current: false
},
{
number: '2',
href: '/library?page=2&perPage=10&organisations=Defra&organisations=Environment%20Agency&organisations=Natural%20England',
current: true
},
{
number: '3',
href: '/library?page=3&perPage=10&organisations=Defra&organisations=Environment%20Agency&organisations=Natural%20England',
current: false
}
]
}
}
}
)

$pagination = container.getByRole('navigation', { name: 'Pagination' })
})

it('should include encoded organisations parameter in navigation links', () => {
const $previousLink = within($pagination).getByRole('link', {
name: 'Previous'
})
const $nextLink = within($pagination).getByRole('link', {
name: 'Next'
})

const expectedParams =
'organisations=Defra&organisations=Environment%20Agency&organisations=Natural%20England'

expect($previousLink).toHaveAttribute(
'href',
`/library?page=1&perPage=10&${expectedParams}`
)
expect($nextLink).toHaveAttribute(
'href',
`/library?page=3&perPage=10&${expectedParams}`
)
})

it('should include encoded organisations parameter in page number links', () => {
const $pageLinks = within($pagination).getAllByRole('link', {
name: /Page \d+/
})

const expectedParams =
'organisations=Defra&organisations=Environment%20Agency&organisations=Natural%20England'

expect($pageLinks[0]).toHaveAttribute(
'href',
`/library?page=1&perPage=10&${expectedParams}`
)
expect($pageLinks[1]).toHaveAttribute(
'href',
`/library?page=2&perPage=10&${expectedParams}`
)
expect($pageLinks[2]).toHaveAttribute(
'href',
`/library?page=3&perPage=10&${expectedParams}`
)
})
})

describe('With search status parameter', () => {
beforeEach(() => {
const { container } = renderMacro(
'appPagination',
'pagination/macro.njk',
{
params: {
baseUrl: '/library',
search: {
status: ['draft', 'live']
},
pagination: {
page: 2,
perPage: 10,
totalPages: 3,
totalItems: 25,
pages: [
{
number: '1',
href: '/library?page=1&perPage=10&status=draft&status=live',
current: false
},
{
number: '2',
href: '/library?page=2&perPage=10&status=draft&status=live',
current: true
},
{
number: '3',
href: '/library?page=3&perPage=10&status=draft&status=live',
current: false
}
]
}
}
}
)

$pagination = container.getByRole('navigation', { name: 'Pagination' })
})

it('should include encoded status parameter in navigation links', () => {
const $previousLink = within($pagination).getByRole('link', {
name: 'Previous'
})
const $nextLink = within($pagination).getByRole('link', {
name: 'Next'
})

expect($previousLink).toHaveAttribute(
'href',
'/library?page=1&perPage=10&status=draft&status=live'
)
expect($nextLink).toHaveAttribute(
'href',
'/library?page=3&perPage=10&status=draft&status=live'
)
})

it('should include encoded status parameter in page number links', () => {
const $pageLinks = within($pagination).getAllByRole('link', {
name: /Page \d+/
})

expect($pageLinks[0]).toHaveAttribute(
'href',
'/library?page=1&perPage=10&status=draft&status=live'
)
expect($pageLinks[1]).toHaveAttribute(
'href',
'/library?page=2&perPage=10&status=draft&status=live'
)
expect($pageLinks[2]).toHaveAttribute(
'href',
'/library?page=3&perPage=10&status=draft&status=live'
)
})
})

describe('With special characters in organisation names', () => {
beforeEach(() => {
const { container } = renderMacro(
'appPagination',
'pagination/macro.njk',
{
params: {
baseUrl: '/library',
search: {
organisations: [
'Animal and Plant Health Agency – APHA',
'Centre for Environment, Fisheries and Aquaculture Science – Cefas',
'Marine Management Organisation – MMO'
]
},
pagination: {
page: 1,
perPage: 10,
totalPages: 2,
totalItems: 15,
pages: [
{
number: '1',
href: '/library?page=1&perPage=10',
current: true
},
{
number: '2',
href: '/library?page=2&perPage=10',
current: false
}
]
}
}
}
)

$pagination = container.getByRole('navigation', { name: 'Pagination' })
})

it('should properly encode special characters in organisation names', () => {
const $nextLink = within($pagination).getByRole('link', {
name: 'Next'
})

const expectedParams =
'organisations=Animal%20and%20Plant%20Health%20Agency%20%E2%80%93%20APHA&organisations=Centre%20for%20Environment%2C%20Fisheries%20and%20Aquaculture%20Science%20%E2%80%93%20Cefas&organisations=Marine%20Management%20Organisation%20%E2%80%93%20MMO'

expect($nextLink).toHaveAttribute(
'href',
`/library?page=2&perPage=10&${expectedParams}`
)
})
})

describe('With special characters in search title', () => {
beforeEach(() => {
const { container } = renderMacro(
Expand Down
4 changes: 4 additions & 0 deletions designer/server/src/common/components/search/_search.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
margin-top: govuk-spacing(4);
}

.govuk-accordion {
margin-bottom: govuk-spacing(4);
}

@include govuk-media-query($from: tablet) {
margin-bottom: govuk-spacing(0);

Expand Down
Loading
Loading