Skip to content
Draft
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
4 changes: 4 additions & 0 deletions src/client/stylesheets/_prose.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
@extend %govuk-body-m;
}

> :last-child {
margin-bottom: 0;
}

strong,
b {
@include govuk-typography-weight-bold;
Expand Down
19 changes: 19 additions & 0 deletions src/server/forms/simple-form.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,25 @@ pages:
id: '00738799-3489-4ab2-a57b-542eecb31bfa'
next: []
id: da0fbdb4-a2de-4650-be16-9ba552af135f
- title: ''
path: '/notification-demo'
components:
- type: NotificationBanner
title: Important
name: notificationImportant
content: 'Contact us if you need [help with your application](https://www.defra.gov.uk).'
options:
heading: There may be a delay in processing your application.
id: ca6b6590-1608-49f4-82f9-9d92e38e66ea
- type: NotificationBanner
title: Success
name: notificationSuccess
content: 'Your application has been submitted.'
options:
type: success
id: b6960f4b-d771-4956-9c9b-17da5c603062
next: []
id: be4b4b86-514c-43bb-8cdc-f9aed6155924
- id: 449a45f6-4541-4a46-91bd-8b8931b07b50
title: ''
path: '/summary'
Expand Down
83 changes: 83 additions & 0 deletions src/server/plugins/engine/components/NotificationBanner.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {
ComponentType,
type NotificationBannerComponent
} from '@defra/forms-model'

import { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'
import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
import definition from '~/test/form/definitions/basic.js'

describe('NotificationBanner', () => {
let model: FormModel

beforeEach(() => {
model = new FormModel(definition, {
basePath: 'test'
})
})

it('sets Nunjucks component defaults', () => {
const def = {
title: 'Important',
name: 'myComponent',
type: ComponentType.NotificationBanner,
content: 'You have 30 days to [appeal this decision](/appeal).',
options: {}
} satisfies NotificationBannerComponent

const collection = new ComponentCollection([def], { model })
const viewModel = collection.guidance[0].getViewModel()

expect(viewModel).toEqual(
expect.objectContaining({
attributes: {},
titleHtml: def.title,
content: def.content
})
)
})

it('includes heading in view model', () => {
const def = {
title: 'Important',
name: 'myComponent',
type: ComponentType.NotificationBanner,
content: 'Contact us if you need help.',
options: {
heading: 'There may be a **delay** in processing your application.'
}
} satisfies NotificationBannerComponent

const collection = new ComponentCollection([def], { model })
const viewModel = collection.guidance[0].getViewModel()

expect(viewModel).toEqual(
expect.objectContaining({
titleHtml: def.title,
content: def.content,
heading: def.options.heading
})
)
})

it('sets type: success for success variant', () => {
const def = {
title: 'Success',
name: 'myComponent',
type: ComponentType.NotificationBanner,
content: 'Your application has been submitted.',
options: { type: 'success' }
} satisfies NotificationBannerComponent

const collection = new ComponentCollection([def], { model })
const viewModel = collection.guidance[0].getViewModel()

expect(viewModel).toEqual(
expect.objectContaining({
titleHtml: def.title,
content: def.content,
type: 'success'
})
)
})
})
32 changes: 32 additions & 0 deletions src/server/plugins/engine/components/NotificationBanner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { type NotificationBannerComponent } from '@defra/forms-model'

Check failure on line 1 in src/server/plugins/engine/components/NotificationBanner.ts

View workflow job for this annotation

GitHub Actions / Build (Node 24)

Module '"@defra/forms-model"' has no exported member 'NotificationBannerComponent'.

Check failure on line 1 in src/server/plugins/engine/components/NotificationBanner.ts

View workflow job for this annotation

GitHub Actions / Build (Node 23)

Module '"@defra/forms-model"' has no exported member 'NotificationBannerComponent'.

Check failure on line 1 in src/server/plugins/engine/components/NotificationBanner.ts

View workflow job for this annotation

GitHub Actions / Build (Node 22)

Module '"@defra/forms-model"' has no exported member 'NotificationBannerComponent'.

import { ComponentBase } from '~/src/server/plugins/engine/components/ComponentBase.js'

export class NotificationBanner extends ComponentBase {
declare options: NotificationBannerComponent['options']
content: NotificationBannerComponent['content']

constructor(
def: NotificationBannerComponent,
props: ConstructorParameters<typeof ComponentBase>[1]
) {
super(def, props)

const { content, options } = def

this.content = content
this.options = options
}

getViewModel() {
const { content, title, viewModel } = this

return {
...viewModel,
titleHtml: title,
content,
heading: this.options.heading,
type: this.options.type
}
}
}
5 changes: 5 additions & 0 deletions src/server/plugins/engine/components/helpers/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
| InstanceType<typeof Components.Markdown>
| InstanceType<typeof Components.InsetText>
| InstanceType<typeof Components.List>
| InstanceType<typeof Components.NotificationBanner>

// List component instances only
export type ListField = InstanceType<
Expand Down Expand Up @@ -134,6 +135,10 @@
component = new Components.Markdown(def, options)
break

case ComponentType.NotificationBanner:

Check failure on line 138 in src/server/plugins/engine/components/helpers/components.ts

View workflow job for this annotation

GitHub Actions / Build (Node 24)

Property 'NotificationBanner' does not exist on type 'typeof ComponentType'.

Check failure on line 138 in src/server/plugins/engine/components/helpers/components.ts

View workflow job for this annotation

GitHub Actions / Build (Node 23)

Property 'NotificationBanner' does not exist on type 'typeof ComponentType'.

Check failure on line 138 in src/server/plugins/engine/components/helpers/components.ts

View workflow job for this annotation

GitHub Actions / Build (Node 22)

Property 'NotificationBanner' does not exist on type 'typeof ComponentType'.
component = new Components.NotificationBanner(def, options)
break

case ComponentType.MultilineTextField:
component = new Components.MultilineTextField(def, options)
break
Expand Down
1 change: 1 addition & 0 deletions src/server/plugins/engine/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export { Html } from '~/src/server/plugins/engine/components/Html.js'
export { InsetText } from '~/src/server/plugins/engine/components/InsetText.js'
export { List } from '~/src/server/plugins/engine/components/List.js'
export { Markdown } from '~/src/server/plugins/engine/components/Markdown.js'
export { NotificationBanner } from '~/src/server/plugins/engine/components/NotificationBanner.js'
export { MonthYearField } from '~/src/server/plugins/engine/components/MonthYearField.js'
export { MultilineTextField } from '~/src/server/plugins/engine/components/MultilineTextField.js'
export { NumberField } from '~/src/server/plugins/engine/components/NumberField.js'
Expand Down
15 changes: 15 additions & 0 deletions src/server/plugins/engine/views/components/notificationbanner.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{% from "govuk/components/notification-banner/macro.njk" import govukNotificationBanner %}

{% macro NotificationBanner(component) %}
{%- set bannerHtml -%}
<div class="app-prose-scope">
{%- if component.model.heading %}{{ component.model.heading | markdown | safe }}{% endif -%}
{{ component.model.content | markdown | safe }}
</div>
{%- endset -%}
{{ govukNotificationBanner({
titleHtml: component.model.titleHtml,
html: bannerHtml,
type: component.model.type
}) }}
{% endmacro %}
Loading