@benwatsonuk/govuk-pages-plugin 1.0.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/CHANGELOG.md +7 -0
- package/LICENCE.txt +21 -0
- package/README.md +192 -0
- package/dist/assets/images/arrow.svg +27 -0
- package/dist/assets/images/page-types/arrow-base.svg +13 -0
- package/dist/assets/images/page-types/arrow-head.svg +13 -0
- package/dist/assets/images/page-types/check-answers.svg +142 -0
- package/dist/assets/images/page-types/checkbox-input.svg +85 -0
- package/dist/assets/images/page-types/confirmation.svg +73 -0
- package/dist/assets/images/page-types/content-page.svg +84 -0
- package/dist/assets/images/page-types/email.svg +56 -0
- package/dist/assets/images/page-types/radio-input.svg +115 -0
- package/dist/assets/images/page-types/start-page.svg +101 -0
- package/dist/assets/images/page-types/task-list.svg +179 -0
- package/dist/assets/images/page-types/text-input.svg +65 -0
- package/dist/assets/javascripts/all.js +1 -0
- package/dist/assets/styles/all.scss +2 -0
- package/dist/assets/styles/scss/_pages.scss +169 -0
- package/dist/assets/styles/scss/_variables.scss +19 -0
- package/dist/functions/pages/getPages.js +9 -0
- package/dist/functions/stages/getStages.js +65 -0
- package/dist/index.js +39 -0
- package/dist/schema.json +89 -0
- package/dist/types.js +2 -0
- package/dist/validate.js +27 -0
- package/dist/views/page-index.html +34 -0
- package/dist/views/stage-index.html +41 -0
- package/govuk-prototype-kit.config.json +12 -0
- package/index.js +22 -0
- package/package.json +43 -0
- package/src/assets/images/arrow.svg +27 -0
- package/src/assets/images/page-types/arrow-base.svg +13 -0
- package/src/assets/images/page-types/arrow-head.svg +13 -0
- package/src/assets/images/page-types/check-answers.svg +142 -0
- package/src/assets/images/page-types/checkbox-input.svg +85 -0
- package/src/assets/images/page-types/confirmation.svg +73 -0
- package/src/assets/images/page-types/content-page.svg +84 -0
- package/src/assets/images/page-types/email.svg +56 -0
- package/src/assets/images/page-types/radio-input.svg +115 -0
- package/src/assets/images/page-types/start-page.svg +101 -0
- package/src/assets/images/page-types/task-list.svg +179 -0
- package/src/assets/images/page-types/text-input.svg +65 -0
- package/src/assets/javascripts/all.js +1 -0
- package/src/assets/styles/all.scss +2 -0
- package/src/assets/styles/scss/_pages.scss +169 -0
- package/src/assets/styles/scss/_variables.scss +19 -0
- package/src/functions/pages/getPages.ts +7 -0
- package/src/functions/stages/getStages.ts +78 -0
- package/src/index.ts +40 -0
- package/src/schema.json +89 -0
- package/src/types.ts +40 -0
- package/src/validate.ts +35 -0
- package/src/views/page-index.html +34 -0
- package/src/views/stage-index.html +41 -0
- package/test/data/outputs.ts +197 -0
- package/test/data/pages.ts +61 -0
- package/test/data/stages.ts +87 -0
- package/test/getPages.test.js +19 -0
- package/test/getStages.test.js +46 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
.govuk-pages-plugin {
|
|
2
|
+
|
|
3
|
+
.screenPreviewContainer {
|
|
4
|
+
height: 400px;
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
border: 1px solid #000;
|
|
7
|
+
.screenPreview {
|
|
8
|
+
width: 200%;
|
|
9
|
+
height: 800px;
|
|
10
|
+
transform: scale(0.5);
|
|
11
|
+
transform-origin: 0 0;
|
|
12
|
+
background: none;
|
|
13
|
+
border: 0;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.page-flow-feedback {
|
|
18
|
+
&--positive {
|
|
19
|
+
color: #00a33b;
|
|
20
|
+
}
|
|
21
|
+
&--negative {
|
|
22
|
+
color: #a33038;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.page-flow--stages, .user-flow--stages {
|
|
27
|
+
@extend .govuk-body;
|
|
28
|
+
padding: 0;
|
|
29
|
+
}
|
|
30
|
+
.user-flow-item--stage {
|
|
31
|
+
display: inline-block;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.user-flow-page-item {
|
|
35
|
+
border-top: 1px solid #333;
|
|
36
|
+
padding-top:1em;
|
|
37
|
+
//margin-bottom: 2em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.page-flow-item--stage, .user-flow-item--stage {
|
|
41
|
+
border-top: 10px solid;
|
|
42
|
+
.page-flow-stage-descriptor {
|
|
43
|
+
padding: 2px 10px;
|
|
44
|
+
display: block;
|
|
45
|
+
//padding: 5px;
|
|
46
|
+
}
|
|
47
|
+
&--1 {
|
|
48
|
+
border-color: $stage-color--1;
|
|
49
|
+
}
|
|
50
|
+
&--2 {
|
|
51
|
+
border-color: $stage-color--2;
|
|
52
|
+
}
|
|
53
|
+
&--3 {
|
|
54
|
+
border-color: $stage-color--3;
|
|
55
|
+
}
|
|
56
|
+
&--4 {
|
|
57
|
+
border-color: $stage-color--4;
|
|
58
|
+
}
|
|
59
|
+
&--authentication {
|
|
60
|
+
border-color: $stage-color--authentication;
|
|
61
|
+
}
|
|
62
|
+
&--documents {
|
|
63
|
+
border-color: $stage-color--documents;
|
|
64
|
+
}
|
|
65
|
+
&--notifications, &--notifications {
|
|
66
|
+
border-color: $stage-color--notifications;
|
|
67
|
+
}
|
|
68
|
+
&:last-of-type {
|
|
69
|
+
.page-flow-item--page{
|
|
70
|
+
&:last-of-type {
|
|
71
|
+
&:before {
|
|
72
|
+
display: none;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.page-flow--pages, .user-flow--pages {
|
|
80
|
+
@extend .govuk-body;
|
|
81
|
+
padding: 0;
|
|
82
|
+
.page-flow-item--page {
|
|
83
|
+
display: inline-block;
|
|
84
|
+
font-size: 14px;
|
|
85
|
+
width: 130px;
|
|
86
|
+
//min-height: 200px;
|
|
87
|
+
vertical-align: top;
|
|
88
|
+
position: relative;
|
|
89
|
+
.page-flow-item-screen-icon {
|
|
90
|
+
width: 100px;
|
|
91
|
+
height: 100px;
|
|
92
|
+
display: block;
|
|
93
|
+
background-repeat: no-repeat;
|
|
94
|
+
&--email {
|
|
95
|
+
background-image: url($icons + '/email.svg');
|
|
96
|
+
-webkit-background-size: contain;
|
|
97
|
+
background-size: contain;
|
|
98
|
+
}
|
|
99
|
+
&--text-input {
|
|
100
|
+
background-image: url($icons + '/text-input.svg');
|
|
101
|
+
-webkit-background-size: contain;
|
|
102
|
+
background-size: contain;
|
|
103
|
+
}
|
|
104
|
+
&--dashboard, &--content-page {
|
|
105
|
+
background-image: url($icons + '/content-page.svg');
|
|
106
|
+
-webkit-background-size: contain;
|
|
107
|
+
background-size: contain;
|
|
108
|
+
}
|
|
109
|
+
&--radio-input {
|
|
110
|
+
background-image: url($icons + '/radio-input.svg');
|
|
111
|
+
-webkit-background-size: contain;
|
|
112
|
+
background-size: contain;
|
|
113
|
+
}
|
|
114
|
+
&--checkbox-input {
|
|
115
|
+
background-image: url($icons + '/checkbox-input.svg');
|
|
116
|
+
-webkit-background-size: contain;
|
|
117
|
+
background-size: contain;
|
|
118
|
+
}
|
|
119
|
+
&--check-answers {
|
|
120
|
+
background-image: url($icons + '/check-answers.svg');
|
|
121
|
+
-webkit-background-size: contain;
|
|
122
|
+
background-size: contain;
|
|
123
|
+
}
|
|
124
|
+
&--confirmation {
|
|
125
|
+
background-image: url($icons + '/confirmation.svg');
|
|
126
|
+
-webkit-background-size: contain;
|
|
127
|
+
background-size: contain;
|
|
128
|
+
}
|
|
129
|
+
&--task-list {
|
|
130
|
+
background-image: url($icons + '/task-list.svg');
|
|
131
|
+
-webkit-background-size: contain;
|
|
132
|
+
background-size: contain;
|
|
133
|
+
}
|
|
134
|
+
&--start-page {
|
|
135
|
+
background-image: url($icons + '/start-page.svg');
|
|
136
|
+
-webkit-background-size: contain;
|
|
137
|
+
background-size: contain;
|
|
138
|
+
}
|
|
139
|
+
&--checkbox-page {
|
|
140
|
+
background-image: url($icons + '/checkbox-page.svg');
|
|
141
|
+
-webkit-background-size: contain;
|
|
142
|
+
background-size: contain;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
.user-flow--pages {
|
|
148
|
+
@extend .page-flow--pages;
|
|
149
|
+
.page-flow-item--page {
|
|
150
|
+
display: inline-block;
|
|
151
|
+
font-size: 14px;
|
|
152
|
+
width: 170px;
|
|
153
|
+
//min-height: 200px;
|
|
154
|
+
vertical-align: top;
|
|
155
|
+
position: relative;
|
|
156
|
+
|
|
157
|
+
&:before {
|
|
158
|
+
content: "";
|
|
159
|
+
position: absolute;
|
|
160
|
+
background: url($page-flow-images + '/arrow.svg') no-repeat;
|
|
161
|
+
background-size: contain;
|
|
162
|
+
width: 78px;
|
|
163
|
+
left: 92px;
|
|
164
|
+
height: 20px;
|
|
165
|
+
top: 35px;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Assets - these can all be overridden
|
|
2
|
+
$page-flow-assets: '/extension-assets/govuk-page-flow-plugin/app/assets/';
|
|
3
|
+
$page-flow-images: $page-flow-assets + 'images/';
|
|
4
|
+
$icons: $page-flow-images + 'page-types';
|
|
5
|
+
|
|
6
|
+
// Stock colours for stages
|
|
7
|
+
$stage-color--1: #006c56;
|
|
8
|
+
$stage-color--2: #00beb7;
|
|
9
|
+
$stage-color--3: pink;
|
|
10
|
+
$stage-color--4: #f47738;
|
|
11
|
+
$stage-color--5: #ccc;
|
|
12
|
+
$stage-color--6: #005ea5;
|
|
13
|
+
$stage-color--7: #004432;
|
|
14
|
+
$stage-color--8: #f47738;
|
|
15
|
+
$stage-color--9: #3b1f5f;
|
|
16
|
+
$stage-color--10: #ffdd00;
|
|
17
|
+
$stage-color--documents: purple;
|
|
18
|
+
$stage-color--notifications: teal;
|
|
19
|
+
$stage-color--authentication: crimson;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { PagesArray, StagesArray, StagesWithPagesArray } from "../../types"
|
|
2
|
+
import { validatePagesArray, validateStagesArray } from "../../validate"
|
|
3
|
+
|
|
4
|
+
// Get and validate stages from the provided input
|
|
5
|
+
export const getStages = (stages: StagesArray) => {
|
|
6
|
+
const validatedStages = validateStagesArray(stages)
|
|
7
|
+
return validatedStages
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Get and validate stages and relevant pages from the provided input. Return an array of Stage objects containing relevant pages.
|
|
11
|
+
export const getStagesWithPages = (stages: StagesArray, pages: PagesArray): StagesWithPagesArray => {
|
|
12
|
+
const validatedStages = validateStagesArray(stages)
|
|
13
|
+
const validatedPages = validatePagesArray(pages)
|
|
14
|
+
return mapPagesToStages(validatedStages, validatedPages)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Below this point is just the helper function used internally for the above functions
|
|
18
|
+
|
|
19
|
+
// This function does the heavy lifting of mapping pages to their relevant stages
|
|
20
|
+
export const mapPagesToStages = (
|
|
21
|
+
stages: StagesArray,
|
|
22
|
+
pages: PagesArray
|
|
23
|
+
): StagesWithPagesArray => {
|
|
24
|
+
let allPages = [...pages]; // Create a copy to avoid mutating the original
|
|
25
|
+
|
|
26
|
+
const stagesWithPages: StagesWithPagesArray = stages.map((stage) => {
|
|
27
|
+
// Filter pages that belong to this stage
|
|
28
|
+
const pagesForStage = pages.filter(
|
|
29
|
+
(page) => page.stage && page.stage.main === stage.id
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
// Only add the stage if it has pages (after all, why return empty stages?)
|
|
33
|
+
if (pagesForStage.length > 0) {
|
|
34
|
+
|
|
35
|
+
// Remove the filtered pages from allPages to get unused pages
|
|
36
|
+
allPages = allPages.filter(page => !pagesForStage.some(p => p.id === page.id));
|
|
37
|
+
|
|
38
|
+
// Map sub-stages with their relevant pages
|
|
39
|
+
let subStagesWithPages
|
|
40
|
+
if (stage.subStages) {
|
|
41
|
+
subStagesWithPages = stage.subStages.map((subStage) => {
|
|
42
|
+
// Filter pages that belong to this sub-stage
|
|
43
|
+
const pagesForSubStage = pagesForStage.filter(
|
|
44
|
+
(page) => page.stage && page.stage.subStage === subStage.id
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
if (pagesForSubStage.length > 0) {
|
|
48
|
+
return {
|
|
49
|
+
id: subStage.id,
|
|
50
|
+
title: subStage.title,
|
|
51
|
+
description: subStage.description,
|
|
52
|
+
pages: pagesForSubStage
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}).filter(subStage => subStage !== undefined)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
id: stage.id,
|
|
60
|
+
title: stage.title,
|
|
61
|
+
description: stage.description,
|
|
62
|
+
subStages: subStagesWithPages,
|
|
63
|
+
pages: pagesForStage
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}).filter(stage => stage !== undefined);
|
|
67
|
+
|
|
68
|
+
// add allPages to a misc category and bolt on to stagesWithPages
|
|
69
|
+
if (allPages.length > 0) {
|
|
70
|
+
stagesWithPages.push({
|
|
71
|
+
id: "unassigned",
|
|
72
|
+
title: "Unassigned",
|
|
73
|
+
description: "Pages not assigned to any stage or sub-stage",
|
|
74
|
+
pages: allPages
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
return stagesWithPages
|
|
78
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {Router} from "express"
|
|
2
|
+
import { getPages } from "./functions/pages/getPages"
|
|
3
|
+
import { getStagesWithPages } from "./functions/stages/getStages"
|
|
4
|
+
import { PagesArray, StagesArray } from "./types"
|
|
5
|
+
|
|
6
|
+
/*--- UTILITIES (used by supplied routes AND made available to plugin users) ---*/
|
|
7
|
+
|
|
8
|
+
export const pageIndexData = (pages: PagesArray) => {
|
|
9
|
+
return getPages(pages)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const pageIndex = (pages: PagesArray, pageType: string) => {
|
|
13
|
+
pageType = pageType || "page-index"
|
|
14
|
+
return (req: any, res: any) => {
|
|
15
|
+
res.render(pageType, { pages: pages })
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const stageIndexData = (stages: StagesArray, pages: PagesArray) => {
|
|
20
|
+
return getStagesWithPages(stages, pages)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const stageIndex = (stages: StagesArray, pages: PagesArray, pageType?: string) => {
|
|
24
|
+
pageType = pageType || "stage-index"
|
|
25
|
+
return (req: any, res: any) => {
|
|
26
|
+
res.render(pageType, { stages: stageIndexData(stages, pages) })
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Add user flows, etc here later
|
|
31
|
+
|
|
32
|
+
/*--- THE MAIN USER ROUTES ---*/
|
|
33
|
+
|
|
34
|
+
export const govukPagesPlugin = (pages: PagesArray, stages?: StagesArray, pageType?: string) => {
|
|
35
|
+
pageType = pageType || "page-index" // Options can be 'all', 'page-index', 'stage-index' - in future could be 'user-flow-index', etc
|
|
36
|
+
const router = Router()
|
|
37
|
+
// This is the default offering from the plugin - it is expected that must users will use this. It should be robust
|
|
38
|
+
router.get("/", pageIndex(pageIndexData(pages), pageType))
|
|
39
|
+
return router
|
|
40
|
+
}
|
package/src/schema.json
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"required": ["mode"],
|
|
5
|
+
"properties": {
|
|
6
|
+
"mode": {
|
|
7
|
+
"type": "string",
|
|
8
|
+
"enum": ["pages", "stages"]
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"allOf": [
|
|
12
|
+
{
|
|
13
|
+
"if": {
|
|
14
|
+
"properties": { "mode": { "const": "pages" } }
|
|
15
|
+
},
|
|
16
|
+
"then": { "$ref": "#/definitions/pages" },
|
|
17
|
+
"else": { "$ref": "#/definitions/stages" }
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"definitions": {
|
|
21
|
+
"pages": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"required": ["mode", "pages"],
|
|
24
|
+
"properties": {
|
|
25
|
+
"mode": { "const": "pages" },
|
|
26
|
+
"pages": {
|
|
27
|
+
"type": "array",
|
|
28
|
+
"items": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"required": ["id", "title", "route"],
|
|
31
|
+
"properties": {
|
|
32
|
+
"id": { "type": "integer" },
|
|
33
|
+
"title": { "type": "string" },
|
|
34
|
+
"route": { "type": "string" },
|
|
35
|
+
"type": { "type": ["string", "null"] },
|
|
36
|
+
"stage": {
|
|
37
|
+
"type": ["object"],
|
|
38
|
+
"properties": {
|
|
39
|
+
"main": { "type": ["string"] },
|
|
40
|
+
"subStage": { "type": ["integer", "string"] }
|
|
41
|
+
},
|
|
42
|
+
"additionalProperties": false
|
|
43
|
+
},
|
|
44
|
+
"description": { "type": ["string", "null"] }
|
|
45
|
+
},
|
|
46
|
+
"additionalProperties": true
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"additionalProperties": false
|
|
51
|
+
},
|
|
52
|
+
"stages": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"required": ["mode", "stages"],
|
|
55
|
+
"properties": {
|
|
56
|
+
"mode": { "const": "stages" },
|
|
57
|
+
"stages": {
|
|
58
|
+
"type": "array",
|
|
59
|
+
"items": {
|
|
60
|
+
"type": "object",
|
|
61
|
+
"required": ["id", "title", "route"],
|
|
62
|
+
"properties": {
|
|
63
|
+
"id": { "type": "string" },
|
|
64
|
+
"title": { "type": "string" },
|
|
65
|
+
"route": { "type": "string" },
|
|
66
|
+
"description": { "type": ["string", "null"] },
|
|
67
|
+
"subStages": {
|
|
68
|
+
"type": "array",
|
|
69
|
+
"items": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"required": ["id", "title"],
|
|
72
|
+
"properties": {
|
|
73
|
+
"id": { "type": ["string", "integer"] },
|
|
74
|
+
"title": { "type": "string" },
|
|
75
|
+
"route": { "type": "string" },
|
|
76
|
+
"description": { "type": ["string", "null"] }
|
|
77
|
+
},
|
|
78
|
+
"additionalProperties": true
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"additionalProperties": true
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"additionalProperties": false
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface Page {
|
|
2
|
+
id: number
|
|
3
|
+
title: string
|
|
4
|
+
type: string
|
|
5
|
+
route: string
|
|
6
|
+
description?: string
|
|
7
|
+
stage?: {
|
|
8
|
+
main: string,
|
|
9
|
+
subStage?: number | string
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type SubStage = Omit<Stage, 'id' | 'subStages'> & {
|
|
14
|
+
id: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type SubStageWithPages = Omit<StageWithPages, 'id' | 'subStages'> & {
|
|
18
|
+
id: number | string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface Stage {
|
|
22
|
+
id: string
|
|
23
|
+
title: string
|
|
24
|
+
route?: string
|
|
25
|
+
description: string | null
|
|
26
|
+
subStages?: SubStage[]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface StageWithPages {
|
|
30
|
+
id: string
|
|
31
|
+
title: string
|
|
32
|
+
description: string | null
|
|
33
|
+
subStages?: SubStageWithPages[]
|
|
34
|
+
pages: Page[]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
export type StagesArray = Stage[];
|
|
39
|
+
export type PagesArray = Page[];
|
|
40
|
+
export type StagesWithPagesArray = StageWithPages[] | [];
|
package/src/validate.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import Ajv from "ajv"
|
|
2
|
+
import schema from "./schema.json"
|
|
3
|
+
import { PagesArray, StagesArray } from "./types"
|
|
4
|
+
|
|
5
|
+
const ajv = new Ajv({ allErrors: true, strict: false })
|
|
6
|
+
|
|
7
|
+
const validate = ajv.compile(schema)
|
|
8
|
+
|
|
9
|
+
export function validatePagesArray(pages: unknown): PagesArray {
|
|
10
|
+
if (!validate({ mode: "pages", pages: pages })) {
|
|
11
|
+
const message = validate.errors
|
|
12
|
+
?.map(err => `${err.instancePath || "Pages"} ${err.message}`)
|
|
13
|
+
.join("\n")
|
|
14
|
+
|
|
15
|
+
throw new Error(
|
|
16
|
+
`Invalid array of PAGES passed to govuk-pages-plugin - please check the documentation to ensure the JSON schema you are passing matches what is expected:\n${message}`
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return pages as PagesArray
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function validateStagesArray(stages: unknown): StagesArray {
|
|
24
|
+
if (!validate({ mode: "stages", stages: stages })) {
|
|
25
|
+
const message = validate.errors
|
|
26
|
+
?.map(err => `${err.instancePath || "Stages"} ${err.message}`)
|
|
27
|
+
.join("\n")
|
|
28
|
+
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Invalid array of STAGES passed to govuk-pages-plugin - please check the documentation to ensure the JSON schema you are passing matches what is expected:\n${message}`
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return stages as StagesArray
|
|
35
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{% extends "layouts/main.html" %}
|
|
2
|
+
|
|
3
|
+
{% block pageTitle %}
|
|
4
|
+
Page Index
|
|
5
|
+
{% endblock %}
|
|
6
|
+
|
|
7
|
+
{% block beforeContent %}
|
|
8
|
+
{% from "govuk/components/back-link/macro.njk" import govukBackLink %}
|
|
9
|
+
|
|
10
|
+
{{ govukBackLink({
|
|
11
|
+
text: "Back",
|
|
12
|
+
href: "javascript:history.back(-1);"
|
|
13
|
+
}) }}
|
|
14
|
+
{% endblock %}
|
|
15
|
+
|
|
16
|
+
{% block content %}
|
|
17
|
+
|
|
18
|
+
<div class="page-index ">
|
|
19
|
+
<h1 class="govuk-heading-l">Page Index</h1>
|
|
20
|
+
{% from "govuk/components/details/macro.njk" import govukDetails %}
|
|
21
|
+
|
|
22
|
+
{{ govukDetails({
|
|
23
|
+
summaryText: "What is the 'Page Index'?",
|
|
24
|
+
html: "<p>This page contains links to tracked pages in this prototype. It is useful for navigating the prototype without having to go through flows.</p><p class='govuk-body-s'> Note, the prototype might contain more pages than are listed here.</p>"
|
|
25
|
+
}) }}
|
|
26
|
+
|
|
27
|
+
<ul class="govuk-list govuk-list--number">
|
|
28
|
+
{% for page in pages %}
|
|
29
|
+
<li><a href="{{ page.route }}">{{ page.title }}</a></li>
|
|
30
|
+
{% endfor %}
|
|
31
|
+
</ul>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
{% endblock %}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{% extends "layouts/main.html" %}
|
|
2
|
+
|
|
3
|
+
{% block pageTitle %}
|
|
4
|
+
Stage Index
|
|
5
|
+
{% endblock %}
|
|
6
|
+
|
|
7
|
+
{% block beforeContent %}
|
|
8
|
+
{% from "govuk/components/back-link/macro.njk" import govukBackLink %}
|
|
9
|
+
|
|
10
|
+
{{ govukBackLink({
|
|
11
|
+
text: "Back",
|
|
12
|
+
href: "javascript:history.back(-1);"
|
|
13
|
+
}) }}
|
|
14
|
+
{% endblock %}
|
|
15
|
+
|
|
16
|
+
{% block content %}
|
|
17
|
+
|
|
18
|
+
<div class="page-index ">
|
|
19
|
+
<h1 class="govuk-heading-l">Stage Index</h1>
|
|
20
|
+
{% from "govuk/components/details/macro.njk" import govukDetails %}
|
|
21
|
+
|
|
22
|
+
{{ govukDetails({
|
|
23
|
+
summaryText: "What is the 'Stage Index'?",
|
|
24
|
+
html: "<p>This page contains links to tracked pages in this prototype, these pages are grouped by the 'stages' that they are assigned to. It is useful for navigating the prototype without having to go through flows.</p><p>'Stages' are defined by the plugin user but can be throught about as logical groups of pages that work to achieve a common goal, such as 'authenticating' or 'registering'.</p><p class='govuk-body-s'> Note, the prototype might contain more pages than are listed here.</p>"
|
|
25
|
+
}) }}
|
|
26
|
+
<!-- {{ stages | dump }} -->
|
|
27
|
+
{% for stage in stages %}
|
|
28
|
+
<h2>{{ stage.title }}</h2>
|
|
29
|
+
{% if stage.description %}
|
|
30
|
+
<p class="govuk-body-s">{{ stage.description }}</p>
|
|
31
|
+
{% endif %}
|
|
32
|
+
<ol>
|
|
33
|
+
{% for page in stage.pages %}
|
|
34
|
+
<li><a href="{{ page.route }}">{{ page.title }}</a>{% if page.description %} - <span class="govuk-body-s">{{ page.description }}</span> {% endif %}</li>
|
|
35
|
+
{% endfor %}
|
|
36
|
+
</ol>
|
|
37
|
+
<hr/>
|
|
38
|
+
{% endfor %}
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
{% endblock %}
|