@asd20/ui-next 2.26.0 → 2.27.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
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
# [2.27.0](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.26.1...ui-next-v2.27.0) (2026-09-30)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* support inline public form introduction links ([bea4683](https://github.com/academydistrict20/asd20-ui-next/commit/bea4683f849623abe527ad9b70f6d85db145aa25))
|
|
9
|
+
|
|
10
|
+
## [2.26.1](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.26.0...ui-next-v2.26.1) (2026-09-30)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* show public form fallback only after submission failure ([7f17021](https://github.com/academydistrict20/asd20-ui-next/commit/7f17021d2e1f4e04fd193fb0e16d80125efe3ae7))
|
|
16
|
+
|
|
3
17
|
# [2.26.0](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.25.3...ui-next-v2.26.0) (2026-09-30)
|
|
4
18
|
|
|
5
19
|
|
package/package.json
CHANGED
|
@@ -53,9 +53,14 @@
|
|
|
53
53
|
v-if="formDefinition.introduction"
|
|
54
54
|
class="asd20-public-form-modal__introduction"
|
|
55
55
|
>
|
|
56
|
-
|
|
56
|
+
<template v-if="inlineIntroductionParts">
|
|
57
|
+
{{ inlineIntroductionParts.before }}<a :href="formDefinition.introductionLink.href">{{ formDefinition.introductionLink.label }}</a>{{ inlineIntroductionParts.after }}
|
|
58
|
+
</template>
|
|
59
|
+
<template v-else>
|
|
60
|
+
{{ formDefinition.introduction }}
|
|
61
|
+
</template>
|
|
57
62
|
</p>
|
|
58
|
-
<p v-if="formDefinition.introductionLink">
|
|
63
|
+
<p v-if="formDefinition.introductionLink && !formDefinition.introductionLink.inline">
|
|
59
64
|
<a :href="formDefinition.introductionLink.href">
|
|
60
65
|
{{ formDefinition.introductionLink.label }}
|
|
61
66
|
</a>
|
|
@@ -114,26 +119,6 @@
|
|
|
114
119
|
/>
|
|
115
120
|
</div>
|
|
116
121
|
|
|
117
|
-
<div
|
|
118
|
-
v-if="hasFallbackContact"
|
|
119
|
-
class="asd20-public-form-modal__fallback"
|
|
120
|
-
>
|
|
121
|
-
<p>
|
|
122
|
-
{{
|
|
123
|
-
formDefinition.fallbackContact.instructions ||
|
|
124
|
-
'If you cannot submit this form, use one of these contact options:'
|
|
125
|
-
}}
|
|
126
|
-
</p>
|
|
127
|
-
<a
|
|
128
|
-
v-if="formDefinition.fallbackContact.email"
|
|
129
|
-
:href="`mailto:${formDefinition.fallbackContact.email}`"
|
|
130
|
-
>{{ formDefinition.fallbackContact.email }}</a>
|
|
131
|
-
<a
|
|
132
|
-
v-if="formDefinition.fallbackContact.phone"
|
|
133
|
-
:href="fallbackPhoneHref"
|
|
134
|
-
>{{ formDefinition.fallbackContact.phone }}</a>
|
|
135
|
-
</div>
|
|
136
|
-
|
|
137
122
|
<div
|
|
138
123
|
class="asd20-public-form-modal__submit"
|
|
139
124
|
aria-live="polite"
|
|
@@ -180,6 +165,26 @@
|
|
|
180
165
|
>
|
|
181
166
|
{{ feedbackMessage }}
|
|
182
167
|
</div>
|
|
168
|
+
|
|
169
|
+
<div
|
|
170
|
+
v-if="showFallbackContact"
|
|
171
|
+
class="asd20-public-form-modal__fallback"
|
|
172
|
+
>
|
|
173
|
+
<p>
|
|
174
|
+
{{
|
|
175
|
+
formDefinition.fallbackContact.instructions ||
|
|
176
|
+
'If you cannot submit this form, use one of these contact options:'
|
|
177
|
+
}}
|
|
178
|
+
</p>
|
|
179
|
+
<a
|
|
180
|
+
v-if="formDefinition.fallbackContact.email"
|
|
181
|
+
:href="`mailto:${formDefinition.fallbackContact.email}`"
|
|
182
|
+
>{{ formDefinition.fallbackContact.email }}</a>
|
|
183
|
+
<a
|
|
184
|
+
v-if="formDefinition.fallbackContact.phone"
|
|
185
|
+
:href="fallbackPhoneHref"
|
|
186
|
+
>{{ formDefinition.fallbackContact.phone }}</a>
|
|
187
|
+
</div>
|
|
183
188
|
</form>
|
|
184
189
|
</asd20-viewport>
|
|
185
190
|
</asd20-modal>
|
|
@@ -245,6 +250,7 @@ export default {
|
|
|
245
250
|
feedbackRole: 'alert',
|
|
246
251
|
sending: false,
|
|
247
252
|
submissionSuccess: false,
|
|
253
|
+
submissionFailed: false,
|
|
248
254
|
loadSequence: 0,
|
|
249
255
|
}
|
|
250
256
|
},
|
|
@@ -252,6 +258,16 @@ export default {
|
|
|
252
258
|
modalTitle() {
|
|
253
259
|
return this.formDefinition?.title || 'Public Form'
|
|
254
260
|
},
|
|
261
|
+
inlineIntroductionParts() {
|
|
262
|
+
const introduction = this.formDefinition?.introduction || ''
|
|
263
|
+
const link = this.formDefinition?.introductionLink
|
|
264
|
+
if (!link?.inline) return null
|
|
265
|
+
const index = introduction.indexOf(link.label)
|
|
266
|
+
return {
|
|
267
|
+
before: introduction.slice(0, index),
|
|
268
|
+
after: introduction.slice(index + link.label.length),
|
|
269
|
+
}
|
|
270
|
+
},
|
|
255
271
|
usesRecordsFormSpacing() {
|
|
256
272
|
return [
|
|
257
273
|
'student-records-request',
|
|
@@ -272,7 +288,10 @@ export default {
|
|
|
272
288
|
},
|
|
273
289
|
hasFallbackContact() {
|
|
274
290
|
const fallback = this.formDefinition?.fallbackContact
|
|
275
|
-
return Boolean(fallback?.email || fallback?.phone)
|
|
291
|
+
return Boolean(fallback?.instructions || fallback?.email || fallback?.phone)
|
|
292
|
+
},
|
|
293
|
+
showFallbackContact() {
|
|
294
|
+
return this.submissionFailed && this.hasFallbackContact
|
|
276
295
|
},
|
|
277
296
|
fallbackPhoneHref() {
|
|
278
297
|
const phone = this.formDefinition?.fallbackContact?.phone || ''
|
|
@@ -318,6 +337,7 @@ export default {
|
|
|
318
337
|
this.definitionError = ''
|
|
319
338
|
this.feedbackMessage = ''
|
|
320
339
|
this.submissionSuccess = false
|
|
340
|
+
this.submissionFailed = false
|
|
321
341
|
this.validationErrors = {}
|
|
322
342
|
this.validationAttempted = false
|
|
323
343
|
this.honeypot = ''
|
|
@@ -386,7 +406,7 @@ export default {
|
|
|
386
406
|
},
|
|
387
407
|
captchaFailed() {
|
|
388
408
|
this.showFeedback(
|
|
389
|
-
'The verification service could not start. Please try again or use
|
|
409
|
+
'The verification service could not start. Please try again or use another contact option on this page.'
|
|
390
410
|
)
|
|
391
411
|
},
|
|
392
412
|
captchaExpired() {
|
|
@@ -426,6 +446,7 @@ export default {
|
|
|
426
446
|
|
|
427
447
|
this.sending = true
|
|
428
448
|
this.feedbackMessage = ''
|
|
449
|
+
this.submissionFailed = false
|
|
429
450
|
try {
|
|
430
451
|
const payload = {
|
|
431
452
|
...this.values,
|
|
@@ -443,6 +464,7 @@ export default {
|
|
|
443
464
|
definitionVersion: this.formDefinition.version,
|
|
444
465
|
})
|
|
445
466
|
} catch (error) {
|
|
467
|
+
this.submissionFailed = true
|
|
446
468
|
this.showFeedback(this.failureMessage(error))
|
|
447
469
|
} finally {
|
|
448
470
|
this.sending = false
|
|
@@ -171,6 +171,12 @@ export function normalizePublicFormDefinition(definition) {
|
|
|
171
171
|
const id = boundedText(definition.id, 'Form ID', 100, true)
|
|
172
172
|
if (!FORM_ID_PATTERN.test(id)) throw new Error('The public form ID is invalid.')
|
|
173
173
|
|
|
174
|
+
const introduction = boundedText(
|
|
175
|
+
definition.introduction,
|
|
176
|
+
'Form introduction',
|
|
177
|
+
2000
|
|
178
|
+
)
|
|
179
|
+
|
|
174
180
|
let introductionLink
|
|
175
181
|
if (definition.introductionLink != null) {
|
|
176
182
|
const label = boundedText(
|
|
@@ -187,18 +193,25 @@ export function normalizePublicFormDefinition(definition) {
|
|
|
187
193
|
)
|
|
188
194
|
if (!/^\/[a-z0-9/-]+\/?$/.test(href) || href.startsWith('//'))
|
|
189
195
|
throw new Error('The introduction link must be a local page path.')
|
|
190
|
-
|
|
196
|
+
const inline = optionalBoolean(
|
|
197
|
+
definition.introductionLink.inline,
|
|
198
|
+
'Inline introduction link'
|
|
199
|
+
)
|
|
200
|
+
if (
|
|
201
|
+
inline &&
|
|
202
|
+
(!introduction.includes(label) ||
|
|
203
|
+
introduction.indexOf(label) !== introduction.lastIndexOf(label))
|
|
204
|
+
) {
|
|
205
|
+
throw new Error('The inline introduction link label must appear once in the introduction.')
|
|
206
|
+
}
|
|
207
|
+
introductionLink = inline ? { label, href, inline: true } : { label, href }
|
|
191
208
|
}
|
|
192
209
|
|
|
193
210
|
return {
|
|
194
211
|
id,
|
|
195
212
|
version,
|
|
196
213
|
title: boundedText(definition.title, 'Form title', 200, true),
|
|
197
|
-
introduction
|
|
198
|
-
definition.introduction,
|
|
199
|
-
'Form introduction',
|
|
200
|
-
2000
|
|
201
|
-
),
|
|
214
|
+
introduction,
|
|
202
215
|
introductionLink,
|
|
203
216
|
submitLabel: boundedText(definition.submitLabel, 'Submit label', 100, true),
|
|
204
217
|
successMessage: boundedText(
|