@planning-inspectorate/dynamic-forms 1.10.0 → 1.11.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/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Question } from '../../questions/question.js';
|
|
2
|
+
import { nl2br } from '../../lib/utils.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* @typedef {import('../../questions/question.js').QuestionViewModel} QuestionViewModel
|
|
@@ -16,6 +17,7 @@ import { Question } from '../../questions/question.js';
|
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
19
|
export const REDACT_CHARACTER = '█';
|
|
20
|
+
export const TRUNCATED_MAX_LENGTH = 500;
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* @class
|
|
@@ -29,6 +31,7 @@ export default class TextEntryRedactQuestion extends Question {
|
|
|
29
31
|
* @param {boolean} [params.useRedactedFieldNameForSave] whether to use the redacted field name when saving answers
|
|
30
32
|
* @param {boolean} [params.showSuggestionsUi] use the suggestions UI for this question
|
|
31
33
|
* @param {string} [params.summaryText] summaryText to use with the details component
|
|
34
|
+
* @param {boolean} [params.shouldTruncateSummary] determines whether redacted comment is truncated in summary view
|
|
32
35
|
*/
|
|
33
36
|
constructor({
|
|
34
37
|
textEntryCheckbox,
|
|
@@ -37,6 +40,7 @@ export default class TextEntryRedactQuestion extends Question {
|
|
|
37
40
|
useRedactedFieldNameForSave,
|
|
38
41
|
showSuggestionsUi,
|
|
39
42
|
summaryText,
|
|
43
|
+
shouldTruncateSummary,
|
|
40
44
|
...params
|
|
41
45
|
}) {
|
|
42
46
|
super({
|
|
@@ -50,6 +54,7 @@ export default class TextEntryRedactQuestion extends Question {
|
|
|
50
54
|
this.useRedactedFieldNameForSave = useRedactedFieldNameForSave;
|
|
51
55
|
this.showSuggestionsUi = showSuggestionsUi;
|
|
52
56
|
this.summaryText = summaryText;
|
|
57
|
+
this.shouldTruncateSummary = shouldTruncateSummary;
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
async getDataToSave(req, journeyResponse) {
|
|
@@ -83,6 +88,20 @@ export default class TextEntryRedactQuestion extends Question {
|
|
|
83
88
|
} else {
|
|
84
89
|
toShow = redacted || answer;
|
|
85
90
|
}
|
|
91
|
+
|
|
92
|
+
if (this.shouldTruncateSummary && toShow?.length > TRUNCATED_MAX_LENGTH) {
|
|
93
|
+
const action = this.getAction(sectionSegment, journey, answer);
|
|
94
|
+
const truncatedToShow = toShow.substring(0, TRUNCATED_MAX_LENGTH);
|
|
95
|
+
toShow = `${truncatedToShow}... <a class="govuk-link govuk-link--no-visited-state" href="${action?.href}">Read more</a>`;
|
|
96
|
+
return [
|
|
97
|
+
{
|
|
98
|
+
key: this.title ?? this.question,
|
|
99
|
+
value: nl2br(toShow),
|
|
100
|
+
action
|
|
101
|
+
}
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
|
|
86
105
|
return super.formatAnswerForSummary(sectionSegment, journey, toShow, capitals);
|
|
87
106
|
}
|
|
88
107
|
}
|
|
@@ -159,4 +159,113 @@ describe('./src/dynamic-forms/components/text-entry-redact/question.js', () => {
|
|
|
159
159
|
assert.match(view, /Redaction suggestions/);
|
|
160
160
|
assert.match(view, /We have suggested some common redactions/);
|
|
161
161
|
});
|
|
162
|
+
it('should format answer for summary', () => {
|
|
163
|
+
const question = createQuestion();
|
|
164
|
+
const journey = {
|
|
165
|
+
baseUrl: '',
|
|
166
|
+
taskListUrl: 'task',
|
|
167
|
+
journeyTemplate: 'template',
|
|
168
|
+
journeyTitle: 'title',
|
|
169
|
+
journeyId: 'manage-representations',
|
|
170
|
+
getBackLink: () => {
|
|
171
|
+
return 'back';
|
|
172
|
+
},
|
|
173
|
+
getCurrentQuestionUrl: () => {
|
|
174
|
+
return '/redacted-comment';
|
|
175
|
+
},
|
|
176
|
+
response: {
|
|
177
|
+
answers: {}
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
const answer =
|
|
181
|
+
'It began with an ordinary morning. The air smelled faintly of dew, the street empty but for leaves drifting lazily. ████████ ██████ adjusted his collar, noting his watch was three minutes late—a stubborn old thing, loyal only to its own time. Across the street, a bakery opened, the scent of bread spilling into the cool air. A woman in a green scarf carried loaves in quiet balance. The square stirred slowly; ████████ wrote in his notebook, letting the day delay his errands, wholly unhurried and serene.';
|
|
182
|
+
|
|
183
|
+
const viewModel = question.formatAnswerForSummary('section', journey, answer);
|
|
184
|
+
|
|
185
|
+
assert.deepStrictEqual(viewModel, [
|
|
186
|
+
{
|
|
187
|
+
key: 'title',
|
|
188
|
+
value:
|
|
189
|
+
'It began with an ordinary morning. The air smelled faintly of dew, the street empty but for leaves drifting lazily. ████████ ██████ adjusted his collar, noting his watch was three minutes late—a stubborn old thing, loyal only to its own time. Across the street, a bakery opened, the scent of bread spilling into the cool air. A woman in a green scarf carried loaves in quiet balance. The square stirred slowly; ████████ wrote in his notebook, letting the day delay his errands, wholly unhurried and serene.',
|
|
190
|
+
action: {
|
|
191
|
+
href: '/redacted-comment',
|
|
192
|
+
text: 'Change',
|
|
193
|
+
visuallyHiddenText: 'Question?'
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
]);
|
|
197
|
+
});
|
|
198
|
+
it('should truncate when formating answer for summary when shouldTruncateSummary is true', () => {
|
|
199
|
+
const question = createQuestion();
|
|
200
|
+
question.shouldTruncateSummary = true;
|
|
201
|
+
const journey = {
|
|
202
|
+
baseUrl: '',
|
|
203
|
+
taskListUrl: 'task',
|
|
204
|
+
journeyTemplate: 'template',
|
|
205
|
+
journeyTitle: 'title',
|
|
206
|
+
journeyId: 'manage-representations',
|
|
207
|
+
getBackLink: () => {
|
|
208
|
+
return 'back';
|
|
209
|
+
},
|
|
210
|
+
getCurrentQuestionUrl: () => {
|
|
211
|
+
return '/redacted-comment';
|
|
212
|
+
},
|
|
213
|
+
response: {
|
|
214
|
+
answers: {}
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
const answer =
|
|
218
|
+
'It began with an ordinary morning. The air smelled faintly of dew, the street empty but for leaves drifting lazily. ████████ ██████ adjusted his collar, noting his watch was three minutes late—a stubborn old thing, loyal only to its own time. Across the street, a bakery opened, the scent of bread spilling into the cool air. A woman in a green scarf carried loaves in quiet balance. The square stirred slowly; ████████ wrote in his notebook, letting the day delay his errands, wholly unhurried and serene.';
|
|
219
|
+
|
|
220
|
+
const viewModel = question.formatAnswerForSummary('section', journey, answer);
|
|
221
|
+
|
|
222
|
+
assert.deepStrictEqual(viewModel, [
|
|
223
|
+
{
|
|
224
|
+
key: 'title',
|
|
225
|
+
value: `It began with an ordinary morning. The air smelled faintly of dew, the street empty but for leaves drifting lazily. ████████ ██████ adjusted his collar, noting his watch was three minutes late—a stubborn old thing, loyal only to its own time. Across the street, a bakery opened, the scent of bread spilling into the cool air. A woman in a green scarf carried loaves in quiet balance. The square stirred slowly; ████████ wrote in his notebook, letting the day delay his errands, wholly unhurried and s... <a class="govuk-link govuk-link--no-visited-state" href="/redacted-comment">Read more</a>`,
|
|
226
|
+
action: {
|
|
227
|
+
href: '/redacted-comment',
|
|
228
|
+
text: 'Change',
|
|
229
|
+
visuallyHiddenText: 'Question?'
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
]);
|
|
233
|
+
});
|
|
234
|
+
it('should not truncate when formating answer for summary when shouldTruncateSummary is true and length less than 500', () => {
|
|
235
|
+
const question = createQuestion();
|
|
236
|
+
question.shouldTruncateSummary = true;
|
|
237
|
+
const journey = {
|
|
238
|
+
baseUrl: '',
|
|
239
|
+
taskListUrl: 'task',
|
|
240
|
+
journeyTemplate: 'template',
|
|
241
|
+
journeyTitle: 'title',
|
|
242
|
+
journeyId: 'manage-representations',
|
|
243
|
+
getBackLink: () => {
|
|
244
|
+
return 'back';
|
|
245
|
+
},
|
|
246
|
+
getCurrentQuestionUrl: () => {
|
|
247
|
+
return '/redacted-comment';
|
|
248
|
+
},
|
|
249
|
+
response: {
|
|
250
|
+
answers: {}
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
const answer =
|
|
254
|
+
'It began, as many stories do, with an ordinary morning. The air carried the faint smell of dew, and the street was empty save for a few scattered leaves drifting lazily o████████ze too shy to commit to being wind. Jonathan Price adjusted his collar and glanced at his watch, noting with mild irritation tha███████████████████████████ree minutes late.';
|
|
255
|
+
|
|
256
|
+
const viewModel = question.formatAnswerForSummary('section', journey, answer);
|
|
257
|
+
|
|
258
|
+
assert.deepStrictEqual(viewModel, [
|
|
259
|
+
{
|
|
260
|
+
key: 'title',
|
|
261
|
+
value:
|
|
262
|
+
'It began, as many stories do, with an ordinary morning. The air carried the faint smell of dew, and the street was empty save for a few scattered leaves drifting lazily o████████ze too shy to commit to being wind. Jonathan Price adjusted his collar and glanced at his watch, noting with mild irritation tha███████████████████████████ree minutes late.',
|
|
263
|
+
action: {
|
|
264
|
+
href: '/redacted-comment',
|
|
265
|
+
text: 'Change',
|
|
266
|
+
visuallyHiddenText: 'Question?'
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
]);
|
|
270
|
+
});
|
|
162
271
|
});
|