@ministryofjustice/hmpps-connect-dps-components 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -16
- package/package.json +27 -23
- package/scripts/patch.diff +170 -0
package/README.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# hmpps-connect-dps-components
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://operations-engineering-reports.cloud-platform.service.justice.gov.uk/public-report/hmpps-connect-dps-components "Link to report")
|
|
4
|
+
[](https://github.com/ministryofjustice/hmpps-connect-dps-components/actions/workflows/pipeline.yml)
|
|
5
|
+
|
|
6
|
+
`hmpps-connect-dps-components` is a Node.js client library to simplify the process of incorporating global components
|
|
4
7
|
within DPS applications. We welcome feedback on this README [here](https://moj.enterprise.slack.com/archives/C04JFG3QJE6)
|
|
5
8
|
in order to improve it.
|
|
6
9
|
|
|
@@ -84,7 +87,7 @@ It may be sufficient for you app to only request components for GET requests for
|
|
|
84
87
|
may be more appropriate, especially if you use the [PRG pattern](https://en.wikipedia.org/wiki/Post/Redirect/Get) to
|
|
85
88
|
handle form submission. This will help us to reduce the load on the micro frontend components API. You may wish to
|
|
86
89
|
go even further, for example avoiding routes that don't need components - the Prisoner Profile does
|
|
87
|
-
something like this to avoid the component API call for the following routes: `/api` (provides prisoner images) and `/`
|
|
90
|
+
something like this to avoid the component API call for the following routes: `/api` (provides prisoner images) and `/`
|
|
88
91
|
(a redirect only route).
|
|
89
92
|
|
|
90
93
|
```javascript
|
|
@@ -152,7 +155,7 @@ Include reference to the components in your layout.njk file:
|
|
|
152
155
|
|
|
153
156
|
### Extra calls
|
|
154
157
|
|
|
155
|
-
It may be that you need to add some extra requests for the page components for pages that do not fit the normal flow
|
|
158
|
+
It may be that you need to add some extra requests for the page components for pages that do not fit the normal flow
|
|
156
159
|
of routes. e.g. in `setUpAuthentication.ts` on the `/autherror` path:
|
|
157
160
|
|
|
158
161
|
```javascript
|
|
@@ -175,13 +178,13 @@ This will provide a stripped down header for if there is no user object on `res.
|
|
|
175
178
|
|
|
176
179
|
### CSP
|
|
177
180
|
|
|
178
|
-
The package updates the content-security-middleware to include references to the fe-components API. This package should
|
|
181
|
+
The package updates the content-security-middleware to include references to the fe-components API. This package should
|
|
179
182
|
be run after Helmet to prevent this being overwritten.
|
|
180
183
|
|
|
181
|
-
### Shared Data
|
|
184
|
+
### Shared Data
|
|
182
185
|
|
|
183
|
-
An optional parameter `includeSharedData: true` can be passed into the `get` methods request options. Setting this will result in a
|
|
184
|
-
`sharedData` object being added to `res.locals.feComponents` containing data the components have collected to render.
|
|
186
|
+
An optional parameter `includeSharedData: true` can be passed into the `get` methods request options. Setting this will result in a
|
|
187
|
+
`sharedData` object being added to `res.locals.feComponents` containing data the components have collected to render.
|
|
185
188
|
This includes:
|
|
186
189
|
|
|
187
190
|
- activeCaseLoad (the active caseload of the user)
|
|
@@ -189,19 +192,19 @@ This includes:
|
|
|
189
192
|
- services (information on services the user has access to used for global navigation)
|
|
190
193
|
- allocationJobResponsibilities (the allocation policy codes the user has the associated job responsibility for. Allocation policy codes are: `KEY_WORKER`, meaning the user is a key worker and `PERSONAL_OFFICER`, meaning the user is a personal officer.)
|
|
191
194
|
|
|
192
|
-
This can be useful e.g. for when your service needs access to activeCaseLoad information to prevent extra calls to the
|
|
195
|
+
This can be useful e.g. for when your service needs access to activeCaseLoad information to prevent extra calls to the
|
|
193
196
|
api and takes advantage of the caching that the micro frontend api does.
|
|
194
197
|
|
|
195
198
|
### Populating res.locals.user with the shared case load data
|
|
196
199
|
|
|
197
|
-
Many services typically add case load information to the user object on `res.locals`. This library provides some
|
|
200
|
+
Many services typically add case load information to the user object on `res.locals`. This library provides some
|
|
198
201
|
optional middleware which populates:
|
|
199
202
|
- `res.locals.user.caseLoads` with all case loads the user has access to
|
|
200
203
|
- `res.locals.user.activeCaseLoad` with the active case load of the user
|
|
201
204
|
- `res.locals.user.activeCaseLoadId` with the id of the active case load
|
|
202
205
|
|
|
203
|
-
It uses the `sharedData` object if it is present and caches in `req.session` so that any subsequent routes that do not
|
|
204
|
-
use the component middleware can still use the data. If there is no data in the cache, it will fall back to making a
|
|
206
|
+
It uses the `sharedData` object if it is present and caches in `req.session` so that any subsequent routes that do not
|
|
207
|
+
use the component middleware can still use the data. If there is no data in the cache, it will fall back to making a
|
|
205
208
|
call to Prison API to retrieve the data using the user token.
|
|
206
209
|
|
|
207
210
|
To enable this, add the middleware after the component middleware as follows:
|
|
@@ -216,7 +219,7 @@ app.use(retrieveCaseLoadData({
|
|
|
216
219
|
)
|
|
217
220
|
```
|
|
218
221
|
|
|
219
|
-
This middleware checks the `res.locals.user.authSource` so ensure that any mock auth data used in tests includes
|
|
222
|
+
This middleware checks the `res.locals.user.authSource` so ensure that any mock auth data used in tests includes
|
|
220
223
|
`auth_source: 'nomis'` in the response.
|
|
221
224
|
|
|
222
225
|
### Populating res.locals.user with the shared allocation job responsibilities
|
|
@@ -232,7 +235,7 @@ To enable this, add the middleware after the component middleware as follows:
|
|
|
232
235
|
|
|
233
236
|
```javascript
|
|
234
237
|
import { retrieveAllocationJobResponsibilities } from '@ministryofjustice/hmpps-connect-dps-components'
|
|
235
|
-
app.use(retrieveAllocationJobResponsibilities({
|
|
238
|
+
app.use(retrieveAllocationJobResponsibilities({
|
|
236
239
|
logger,
|
|
237
240
|
authenticationClient: new AuthenticationClient(config.apis.hmppsAuth, logger, services.dataAccess.tokenStore),
|
|
238
241
|
allocationsApiConfig: config.apis.allocationsApi,
|
|
@@ -244,14 +247,14 @@ This should go after `retrieveCaseLoadData` so that `res.locals.user.activeCaseL
|
|
|
244
247
|
This middleware checks the `res.locals.user.authSource` so ensure that any mock auth data used in tests includes
|
|
245
248
|
`auth_source: 'nomis'` in the response. It also checks the `res.locals.user.activeCaseLoadId`, which is required for retrieving allocation job responsibilities.
|
|
246
249
|
|
|
247
|
-
Your service will need to be set up with client credentials in order to use this middleware, although it currently
|
|
250
|
+
Your service will need to be set up with client credentials in order to use this middleware, although it currently
|
|
248
251
|
does not need any specific role.
|
|
249
252
|
|
|
250
253
|
### Note
|
|
251
254
|
|
|
252
255
|
In the event of a failure to retrieve the components, the package will populate the html fields with fallback components.
|
|
253
|
-
The `feComponents.sharedData` will not be populated, but if you use the retrieveCaseLoadData middleware (see above) it
|
|
254
|
-
will either take case load data from the cache or make a call to the Prison API to retrieve it.
|
|
256
|
+
The `feComponents.sharedData` will not be populated, but if you use the retrieveCaseLoadData middleware (see above) it
|
|
257
|
+
will either take case load data from the cache or make a call to the Prison API to retrieve it.
|
|
255
258
|
|
|
256
259
|
|
|
257
260
|
## For library developers:
|
package/package.json
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ministryofjustice/hmpps-connect-dps-components",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "A package to allow the inclusion of connect DPS micro frontend components within DPS applications",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.esm.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"files": [
|
|
9
|
-
"dist/**/*"
|
|
9
|
+
"dist/**/*",
|
|
10
|
+
"scripts/**/*"
|
|
10
11
|
],
|
|
11
12
|
"bin": "./scripts/install.ts",
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": "20 || 22 || 24"
|
|
15
|
+
},
|
|
12
16
|
"scripts": {
|
|
13
17
|
"prepare": "hmpps-precommit-hooks-prepare",
|
|
14
18
|
"build": "rollup -c rollup.config.ts --bundleConfigAsCjs && npm run copy:assets",
|
|
@@ -44,36 +48,36 @@
|
|
|
44
48
|
},
|
|
45
49
|
"homepage": "https://github.com/ministryofjustice/hmpps-connect-dps-components#readme",
|
|
46
50
|
"devDependencies": {
|
|
47
|
-
"@ministryofjustice/eslint-config-hmpps": "^0.0
|
|
48
|
-
"@ministryofjustice/hmpps-auth-clients": "^0.0
|
|
49
|
-
"@ministryofjustice/hmpps-precommit-hooks": "^
|
|
50
|
-
"@rollup/plugin-commonjs": "^
|
|
51
|
-
"@rollup/plugin-multi-entry": "^
|
|
52
|
-
"@rollup/plugin-node-resolve": "^16.0.
|
|
53
|
-
"@rollup/plugin-typescript": "^12.
|
|
54
|
-
"@tsconfig/
|
|
51
|
+
"@ministryofjustice/eslint-config-hmpps": "^1.0.0",
|
|
52
|
+
"@ministryofjustice/hmpps-auth-clients": "^1.0.0",
|
|
53
|
+
"@ministryofjustice/hmpps-precommit-hooks": "^1.0.2",
|
|
54
|
+
"@rollup/plugin-commonjs": "^29.0.0",
|
|
55
|
+
"@rollup/plugin-multi-entry": "^7.1.0",
|
|
56
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
57
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
58
|
+
"@tsconfig/node24": "^24.0.1",
|
|
55
59
|
"@types/bunyan": "^1.8.11",
|
|
56
|
-
"@types/express": "^
|
|
57
|
-
"@types/jest": "^
|
|
60
|
+
"@types/express": "^5.0.5",
|
|
61
|
+
"@types/jest": "^30.0.0",
|
|
58
62
|
"@types/superagent": "^8.1.9",
|
|
59
63
|
"@types/supertest": "^6.0.3",
|
|
60
64
|
"cheerio": "^1.0.0",
|
|
61
|
-
"express": "^
|
|
62
|
-
"govuk-frontend": "^5.
|
|
63
|
-
"jest": "^
|
|
64
|
-
"jest-html-reporter": "^3.
|
|
65
|
+
"express": "^5.1.0",
|
|
66
|
+
"govuk-frontend": "^5.13.0",
|
|
67
|
+
"jest": "^30.2.0",
|
|
68
|
+
"jest-html-reporter": "^4.3.0",
|
|
65
69
|
"jest-junit": "^16.0.0",
|
|
66
|
-
"lint-staged": "^16.
|
|
67
|
-
"nock": "^
|
|
68
|
-
"rollup": "^4.
|
|
69
|
-
"rollup-plugin-dts": "^6.2.
|
|
70
|
+
"lint-staged": "^16.2.6",
|
|
71
|
+
"nock": "^14.0.10",
|
|
72
|
+
"rollup": "^4.53.2",
|
|
73
|
+
"rollup-plugin-dts": "^6.2.3",
|
|
70
74
|
"supertest": "^7.1.1",
|
|
71
|
-
"ts-jest": "^29.
|
|
75
|
+
"ts-jest": "^29.4.5",
|
|
72
76
|
"tslib": "^2.8.1"
|
|
73
77
|
},
|
|
74
78
|
"dependencies": {
|
|
75
|
-
"@ministryofjustice/hmpps-rest-client": "^0.0
|
|
76
|
-
"@types/node": "
|
|
79
|
+
"@ministryofjustice/hmpps-rest-client": "^1.0.0",
|
|
80
|
+
"@types/node": "^24.10.0",
|
|
77
81
|
"@types/nunjucks": "^3.2.6",
|
|
78
82
|
"nunjucks": "^3.2.4",
|
|
79
83
|
"superagent": "^10.2.3"
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
diff --git a/assets/scss/index.scss b/assets/scss/index.scss
|
|
2
|
+
index 70feedd..a7cd9fd 100644
|
|
3
|
+
--- a/assets/scss/index.scss
|
|
4
|
+
+++ b/assets/scss/index.scss
|
|
5
|
+
@@ -6,6 +6,8 @@ $govuk-page-width: $moj-page-width;
|
|
6
|
+
|
|
7
|
+
@import "govuk-frontend/dist/govuk/index";
|
|
8
|
+
@import "@ministryofjustice/frontend/moj/all";
|
|
9
|
+
+@import "@ministryofjustice/hmpps-connect-dps-components/dist/assets/footer";
|
|
10
|
+
+@import "@ministryofjustice/hmpps-connect-dps-components/dist/assets/header-bar";
|
|
11
|
+
|
|
12
|
+
@import './components/header-bar';
|
|
13
|
+
@import './overrides/local';
|
|
14
|
+
diff --git a/feature.env b/feature.env
|
|
15
|
+
index 9a3f344..11b4654 100644
|
|
16
|
+
--- a/feature.env
|
|
17
|
+
+++ b/feature.env
|
|
18
|
+
@@ -1,6 +1,8 @@
|
|
19
|
+
PORT=3007
|
|
20
|
+
HMPPS_AUTH_URL=http://localhost:9091/auth
|
|
21
|
+
TOKEN_VERIFICATION_API_URL=http://localhost:9091/verification
|
|
22
|
+
+COMPONENT_API_URL=http://localhost:9091/frontend-components
|
|
23
|
+
+DPS_HOME_PAGE_URL=http://localhost:9091/dpshomepage
|
|
24
|
+
EXAMPLE_API_URL=http://localhost:9091/example-api
|
|
25
|
+
TOKEN_VERIFICATION_ENABLED=true
|
|
26
|
+
REDIS_ENABLED=false
|
|
27
|
+
diff --git a/helm_deploy/values-dev.yaml b/helm_deploy/values-dev.yaml
|
|
28
|
+
index f40e7d3..52b7431 100644
|
|
29
|
+
--- a/helm_deploy/values-dev.yaml
|
|
30
|
+
+++ b/helm_deploy/values-dev.yaml
|
|
31
|
+
@@ -11,6 +11,8 @@ generic-service:
|
|
32
|
+
INGRESS_URL: "https://template-typescript-dev.hmpps.service.justice.gov.uk"
|
|
33
|
+
HMPPS_AUTH_URL: "https://sign-in-dev.hmpps.service.justice.gov.uk/auth"
|
|
34
|
+
TOKEN_VERIFICATION_API_URL: "https://token-verification-api-dev.prison.service.justice.gov.uk"
|
|
35
|
+
+ COMPONENT_API_URL: "https://frontend-components-dev.hmpps.service.justice.gov.uk"
|
|
36
|
+
+ DPS_HOME_PAGE_URL: "https://digital-dev.prison.service.justice.gov.uk"
|
|
37
|
+
EXAMPLE_API_URL: 'https://template-kotlin-dev.hmpps.service.justice.gov.uk'
|
|
38
|
+
ENVIRONMENT_NAME: DEV
|
|
39
|
+
AUDIT_ENABLED: "false"
|
|
40
|
+
diff --git a/helm_deploy/values-preprod.yaml b/helm_deploy/values-preprod.yaml
|
|
41
|
+
index 554e19a..0d577b2 100644
|
|
42
|
+
--- a/helm_deploy/values-preprod.yaml
|
|
43
|
+
+++ b/helm_deploy/values-preprod.yaml
|
|
44
|
+
@@ -11,6 +11,8 @@ generic-service:
|
|
45
|
+
INGRESS_URL: "https://template-typescript-preprod.hmpps.service.justice.gov.uk"
|
|
46
|
+
HMPPS_AUTH_URL: "https://sign-in-preprod.hmpps.service.justice.gov.uk/auth"
|
|
47
|
+
TOKEN_VERIFICATION_API_URL: "https://token-verification-api-preprod.prison.service.justice.gov.uk"
|
|
48
|
+
+ COMPONENT_API_URL: "https://frontend-components-preprod.hmpps.service.justice.gov.uk"
|
|
49
|
+
+ DPS_HOME_PAGE_URL: "https://digital-preprod.prison.service.justice.gov.uk"
|
|
50
|
+
EXAMPLE_API_URL: 'https://template-kotlin-preprod.hmpps.service.justice.gov.uk'
|
|
51
|
+
ENVIRONMENT_NAME: PRE-PRODUCTION
|
|
52
|
+
AUDIT_ENABLED: "false"
|
|
53
|
+
diff --git a/helm_deploy/values-prod.yaml b/helm_deploy/values-prod.yaml
|
|
54
|
+
index 6bb4e41..3a2ae46 100644
|
|
55
|
+
--- a/helm_deploy/values-prod.yaml
|
|
56
|
+
+++ b/helm_deploy/values-prod.yaml
|
|
57
|
+
@@ -9,6 +9,8 @@ generic-service:
|
|
58
|
+
INGRESS_URL: "https://template-typescript.hmpps.service.justice.gov.uk"
|
|
59
|
+
HMPPS_AUTH_URL: "https://sign-in.hmpps.service.justice.gov.uk/auth"
|
|
60
|
+
TOKEN_VERIFICATION_API_URL: "https://token-verification-api.prison.service.justice.gov.uk"
|
|
61
|
+
+ COMPONENT_API_URL: "https://frontend-components.hmpps.service.justice.gov.uk"
|
|
62
|
+
+ DPS_HOME_PAGE_URL: "https://digital.prison.service.justice.gov.uk"
|
|
63
|
+
EXAMPLE_API_URL: 'https://template-kotlin.hmpps.service.justice.gov.uk'
|
|
64
|
+
AUDIT_ENABLED: "false"
|
|
65
|
+
|
|
66
|
+
diff --git a/server/app.ts b/server/app.ts
|
|
67
|
+
index eddaa67..0dfb1fe 100644
|
|
68
|
+
--- a/server/app.ts
|
|
69
|
+
+++ b/server/app.ts
|
|
70
|
+
@@ -1,7 +1,10 @@
|
|
71
|
+
import express from 'express'
|
|
72
|
+
+import { getFrontendComponents } from '@ministryofjustice/hmpps-connect-dps-components'
|
|
73
|
+
|
|
74
|
+
import createError from 'http-errors'
|
|
75
|
+
|
|
76
|
+
+import logger from '../logger'
|
|
77
|
+
+import config from './config'
|
|
78
|
+
import nunjucksSetup from './utils/nunjucksSetup'
|
|
79
|
+
import errorHandler from './errorHandler'
|
|
80
|
+
import { appInsightsMiddleware } from './utils/azureAppInsights'
|
|
81
|
+
@@ -38,6 +41,15 @@ export default function createApp(services: Services): express.Application {
|
|
82
|
+
app.use(setUpCsrf())
|
|
83
|
+
app.use(setUpCurrentUser())
|
|
84
|
+
|
|
85
|
+
+ app.use(
|
|
86
|
+
+ getFrontendComponents({
|
|
87
|
+
+ logger,
|
|
88
|
+
+ componentApiConfig: config.apis.componentApi,
|
|
89
|
+
+ dpsUrl: config.serviceUrls.digitalPrison,
|
|
90
|
+
+ requestOptions: { includeSharedData: true },
|
|
91
|
+
+ }),
|
|
92
|
+
+ )
|
|
93
|
+
+
|
|
94
|
+
app.use(routes(services))
|
|
95
|
+
|
|
96
|
+
app.use((req, res, next) => next(createError(404, 'Not found')))
|
|
97
|
+
diff --git a/server/config.ts b/server/config.ts
|
|
98
|
+
index e49a07b..9bbba57 100644
|
|
99
|
+
--- a/server/config.ts
|
|
100
|
+
+++ b/server/config.ts
|
|
101
|
+
@@ -72,6 +72,15 @@ export default {
|
|
102
|
+
agent: new AgentConfig(Number(get('TOKEN_VERIFICATION_API_TIMEOUT_RESPONSE', 5000))),
|
|
103
|
+
enabled: get('TOKEN_VERIFICATION_ENABLED', 'false') === 'true',
|
|
104
|
+
},
|
|
105
|
+
+ componentApi: {
|
|
106
|
+
+ url: get('COMPONENT_API_URL', 'http://localhost:8082', requiredInProduction),
|
|
107
|
+
+ healthPath: '/ping',
|
|
108
|
+
+ timeout: {
|
|
109
|
+
+ response: Number(get('COMPONENT_API_TIMEOUT_RESPONSE', 2500)),
|
|
110
|
+
+ deadline: Number(get('COMPONENT_API_TIMEOUT_DEADLINE', 2500)),
|
|
111
|
+
+ },
|
|
112
|
+
+ agent: new AgentConfig(Number(get('COMPONENT_TIMEOUT_DEADLINE', 10000))),
|
|
113
|
+
+ },
|
|
114
|
+
exampleApi: {
|
|
115
|
+
url: get('EXAMPLE_API_URL', 'http://localhost:8080', requiredInProduction),
|
|
116
|
+
healthPath: '/health/ping',
|
|
117
|
+
@@ -82,6 +91,7 @@ export default {
|
|
118
|
+
agent: new AgentConfig(Number(get('EXAMPLE_API_TIMEOUT_RESPONSE', 5000))),
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
+ serviceUrls: { digitalPrison: get('DPS_HOME_PAGE_URL', 'http://localhost:3001', requiredInProduction) },
|
|
122
|
+
sqs: {
|
|
123
|
+
audit: auditConfig(),
|
|
124
|
+
},
|
|
125
|
+
diff --git a/server/utils/nunjucksSetup.ts b/server/utils/nunjucksSetup.ts
|
|
126
|
+
index 1d00293..69a787c 100644
|
|
127
|
+
--- a/server/utils/nunjucksSetup.ts
|
|
128
|
+
+++ b/server/utils/nunjucksSetup.ts
|
|
129
|
+
@@ -30,6 +30,7 @@ export default function nunjucksSetup(app: express.Express): void {
|
|
130
|
+
path.join(__dirname, '../../server/views'),
|
|
131
|
+
'node_modules/govuk-frontend/dist/',
|
|
132
|
+
'node_modules/@ministryofjustice/frontend/',
|
|
133
|
+
+ 'node_modules/@ministryofjustice/hmpps-connect-dps-components/dist/assets/',
|
|
134
|
+
],
|
|
135
|
+
{
|
|
136
|
+
autoescape: true,
|
|
137
|
+
diff --git a/server/views/partials/layout.njk b/server/views/partials/layout.njk
|
|
138
|
+
index 63653a0..d87b07a 100644
|
|
139
|
+
--- a/server/views/partials/layout.njk
|
|
140
|
+
+++ b/server/views/partials/layout.njk
|
|
141
|
+
@@ -2,17 +2,28 @@
|
|
142
|
+
|
|
143
|
+
{% block head %}
|
|
144
|
+
<link href="{{ '/assets/css/index.css' | assetMap }}" rel="stylesheet"/>
|
|
145
|
+
+
|
|
146
|
+
+ {% for js in feComponents.jsIncludes %}
|
|
147
|
+
+ <script src="{{ js }}" nonce="{{ cspNonce }}"></script>
|
|
148
|
+
+ {% endfor %}
|
|
149
|
+
+ {% for css in feComponents.cssIncludes %}
|
|
150
|
+
+ <link href="{{ css }}" nonce="{{ cspNonce }}" rel="stylesheet" />
|
|
151
|
+
+ {% endfor %}
|
|
152
|
+
{% endblock %}
|
|
153
|
+
|
|
154
|
+
{% block pageTitle %}{{pageTitle | default(applicationName)}}{% endblock %}
|
|
155
|
+
|
|
156
|
+
{% block header %}
|
|
157
|
+
- {% include "./header.njk" %}
|
|
158
|
+
+ {{ feComponents.header | safe }}
|
|
159
|
+
{% endblock %}
|
|
160
|
+
|
|
161
|
+
{% block bodyStart %}
|
|
162
|
+
{% endblock %}
|
|
163
|
+
|
|
164
|
+
+{% block footer %}
|
|
165
|
+
+ {{ feComponents.footer | safe }}
|
|
166
|
+
+{% endblock %}
|
|
167
|
+
+
|
|
168
|
+
{% block bodyEnd %}
|
|
169
|
+
<script type="module" src="{{ '/assets/js/index.js' | assetMap }}"></script>
|
|
170
|
+
{% endblock %}
|