@wral/report-it 0.1.1 → 0.1.3
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 +40 -1
- package/dist/define.mjs +1 -1
- package/dist/define.standalone.js +1243 -1049
- package/dist/index.mjs +94 -80
- package/dist/{wral-code-input-6ckbynNg.js → wral-code-input-DM3AfzRM.js} +643 -449
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { css as
|
|
2
|
-
import { getAuthContext as
|
|
3
|
-
const
|
|
1
|
+
import { css as f, html as a, nothing as c, LitElement as A } from "lit";
|
|
2
|
+
import { getAuthContext as H, createStorage as K, verifyCode as Q, extractTokens as R, saveTokens as T, decodeJwtPayload as D, refreshTokenSimple as G, sendCode as J, createUserPool as X, signUpIfNeeded as Z, createCognitoUser as ee, getAuthHeaders as te, STORAGE_KEYS as F, isAuthenticatedSimple as re } from "@wral/sdk-auth-audience";
|
|
3
|
+
const se = f`
|
|
4
4
|
:host {
|
|
5
5
|
display: block;
|
|
6
6
|
box-sizing: border-box;
|
|
@@ -24,7 +24,7 @@ const X = p`
|
|
|
24
24
|
position: absolute; width: 1px; height: 1px; overflow: hidden;
|
|
25
25
|
clip: rect(0 0 0 0); white-space: nowrap;
|
|
26
26
|
}
|
|
27
|
-
`,
|
|
27
|
+
`, ie = f`
|
|
28
28
|
@keyframes pop-in {
|
|
29
29
|
0% { opacity: 0; transform: translateY(16px) scale(0.95); }
|
|
30
30
|
100% { opacity: 1; transform: translateY(0) scale(1); }
|
|
@@ -55,7 +55,7 @@ const X = p`
|
|
|
55
55
|
animation: none !important;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
`,
|
|
58
|
+
`, ne = f`
|
|
59
59
|
.msg { max-width: 85%; padding: 12px 16px; border-radius: 14px; font-size: 15px; }
|
|
60
60
|
.msg.bot {
|
|
61
61
|
background: var(--wral-semantic-surface-default, #FFFFFF);
|
|
@@ -77,7 +77,7 @@ const X = p`
|
|
|
77
77
|
.msg .sub { display: block; font-size: 13px; color: var(--wral-semantic-fg-muted, #64748B); margin-top: 4px; }
|
|
78
78
|
.msg.user .sub { color: rgba(255, 255, 255, 0.75); }
|
|
79
79
|
.msg.error { border-left: 3px solid var(--wral-base-red-on-light, #D1232A); }
|
|
80
|
-
`,
|
|
80
|
+
`, ae = f`
|
|
81
81
|
.options { display: flex; flex-wrap: wrap; gap: 8px; align-self: flex-start; max-width: 92%; padding: 2px 0 6px; }
|
|
82
82
|
.chip {
|
|
83
83
|
font-family: var(--wral-base-font-ui, 'IBM Plex Sans Condensed', sans-serif);
|
|
@@ -91,7 +91,7 @@ const X = p`
|
|
|
91
91
|
.chip:hover { background: var(--wral-base-secondary-1, #2594E3); color: #FFFFFF; }
|
|
92
92
|
.chip:focus-visible { outline: 2px solid var(--wral-base-secondary-1, #2594E3); outline-offset: 2px; }
|
|
93
93
|
.chip:active { transform: scale(0.97); }
|
|
94
|
-
`,
|
|
94
|
+
`, oe = f`
|
|
95
95
|
.form-card {
|
|
96
96
|
align-self: stretch;
|
|
97
97
|
background: var(--wral-semantic-surface-default, #FFFFFF);
|
|
@@ -156,7 +156,7 @@ const X = p`
|
|
|
156
156
|
.btn-ghost:hover { border-color: var(--wral-base-secondary-1, #2594E3); }
|
|
157
157
|
.btn-ghost:active { transform: scale(0.97); }
|
|
158
158
|
.btn-ghost:focus-visible { outline: 2px solid var(--wral-base-secondary-1, #2594E3); outline-offset: 2px; }
|
|
159
|
-
`,
|
|
159
|
+
`, le = f`
|
|
160
160
|
.login-card { padding: 28px 26px; }
|
|
161
161
|
.login-card h2 {
|
|
162
162
|
font-family: var(--wral-base-font-display, 'IBM Plex Sans Condensed', sans-serif);
|
|
@@ -201,7 +201,49 @@ const X = p`
|
|
|
201
201
|
}
|
|
202
202
|
.login-why ul { margin: 0; padding-left: 20px; font-size: 14px; color: var(--color-gray-6, #565454); }
|
|
203
203
|
.login-why li { margin-bottom: 4px; line-height: 1.5; }
|
|
204
|
-
|
|
204
|
+
.login-why a { color: var(--color-secondary, #2594E3); font-weight: 600; text-decoration: underline; }
|
|
205
|
+
.login-alt {
|
|
206
|
+
border-top: 1px solid var(--color-gray-2, #E7E5E4); margin-top: 16px; padding-top: 12px;
|
|
207
|
+
}
|
|
208
|
+
.login-alt > summary {
|
|
209
|
+
display: flex; align-items: center; gap: 7px;
|
|
210
|
+
font-size: 14px; font-weight: 600;
|
|
211
|
+
color: var(--color-gray-5, #6C6C6C);
|
|
212
|
+
padding: 3px 0; cursor: pointer; list-style: none;
|
|
213
|
+
}
|
|
214
|
+
.login-alt > summary::-webkit-details-marker { display: none; }
|
|
215
|
+
.login-alt > summary::before {
|
|
216
|
+
content: ''; flex-shrink: 0; padding: 2.5px;
|
|
217
|
+
border: solid currentColor; border-width: 0 1.5px 1.5px 0;
|
|
218
|
+
transform: rotate(-45deg); transition: transform 150ms;
|
|
219
|
+
}
|
|
220
|
+
.login-alt[open] > summary::before { transform: rotate(45deg); }
|
|
221
|
+
.login-alt > summary:hover { color: var(--color-gray-8, #263238); }
|
|
222
|
+
.login-alt > summary:focus-visible { outline: 2px solid var(--color-secondary, #2594E3); outline-offset: 2px; }
|
|
223
|
+
.login-alt .alt-body {
|
|
224
|
+
font-size: 13.5px; color: var(--color-gray-6, #565454);
|
|
225
|
+
line-height: 1.55; padding: 6px 0 2px;
|
|
226
|
+
}
|
|
227
|
+
.login-alt .alt-row { margin: 0 0 10px; }
|
|
228
|
+
.login-alt .alt-row:last-child { margin-bottom: 0; }
|
|
229
|
+
.login-alt a, .login-alt .alt-link {
|
|
230
|
+
color: var(--color-primary-dark, #00144A); font-weight: 600;
|
|
231
|
+
text-decoration: underline;
|
|
232
|
+
}
|
|
233
|
+
.login-alt a { text-decoration: none; white-space: nowrap; }
|
|
234
|
+
.login-alt a:hover { text-decoration: underline; }
|
|
235
|
+
.login-alt .alt-link {
|
|
236
|
+
background: none; border: none; padding: 0; cursor: pointer;
|
|
237
|
+
font-family: inherit; font-size: inherit;
|
|
238
|
+
}
|
|
239
|
+
.login-alt .alt-link:focus-visible { outline: 2px solid var(--color-secondary, #2594E3); outline-offset: 2px; }
|
|
240
|
+
.anon-costs { margin: 0 0 18px; padding: 0; list-style: none; font-size: 14px; color: var(--color-gray-6, #565454); }
|
|
241
|
+
.anon-costs li { display: flex; gap: 9px; align-items: flex-start; margin-bottom: 9px; line-height: 1.5; }
|
|
242
|
+
.anon-costs li:last-child { margin-bottom: 0; }
|
|
243
|
+
.anon-costs .x { flex-shrink: 0; font-weight: 700; color: var(--wral-base-red-on-light, #D1232A); }
|
|
244
|
+
.anon-actions { display: flex; flex-direction: column; gap: 10px; }
|
|
245
|
+
.anon-actions .btn-ghost { width: 100%; }
|
|
246
|
+
`, de = f`
|
|
205
247
|
.review-list { margin: 0; padding: 0; list-style: none; font-size: 14px; }
|
|
206
248
|
.review-list li {
|
|
207
249
|
display: grid; grid-template-columns: 130px 1fr; gap: 10px;
|
|
@@ -233,7 +275,7 @@ const X = p`
|
|
|
233
275
|
color: var(--wral-base-primary-1, #001D68);
|
|
234
276
|
}
|
|
235
277
|
@media (max-width: 540px) { .review-list li { grid-template-columns: 1fr; gap: 2px; } }
|
|
236
|
-
`,
|
|
278
|
+
`, ce = f`
|
|
237
279
|
.upload-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; font-size: 13.5px; }
|
|
238
280
|
.upload-row .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
239
281
|
.upload-row .state { font-size: 12px; color: var(--wral-semantic-fg-subtle, #64748B); }
|
|
@@ -249,7 +291,7 @@ const X = p`
|
|
|
249
291
|
border-radius: 999px; padding: 3px 12px; cursor: pointer;
|
|
250
292
|
}
|
|
251
293
|
.retry-chip:focus-visible { outline: 2px solid var(--wral-base-secondary-1, #2594E3); outline-offset: 2px; }
|
|
252
|
-
`,
|
|
294
|
+
`, ue = f`
|
|
253
295
|
.confirm-card {
|
|
254
296
|
align-self: stretch;
|
|
255
297
|
background: var(--wral-base-primary-1, #001D68);
|
|
@@ -299,7 +341,7 @@ const X = p`
|
|
|
299
341
|
.c-again:hover { background: rgba(255, 255, 255, 0.12); }
|
|
300
342
|
.c-again:focus-visible { outline: 2px solid var(--wral-base-secondary-2, #50A9E8); outline-offset: 2px; }
|
|
301
343
|
.c-again:active { transform: scale(0.97); }
|
|
302
|
-
`,
|
|
344
|
+
`, pe = f`
|
|
303
345
|
.journey {
|
|
304
346
|
align-self: stretch;
|
|
305
347
|
background: var(--wral-semantic-surface-default, #FFFFFF);
|
|
@@ -340,7 +382,7 @@ const X = p`
|
|
|
340
382
|
color: var(--wral-base-primary-1, #001D68); margin-bottom: 2px;
|
|
341
383
|
}
|
|
342
384
|
.j-body .j-d { font-size: 13.5px; color: var(--wral-semantic-fg-muted, #475569); line-height: 1.55; }
|
|
343
|
-
`,
|
|
385
|
+
`, he = f`
|
|
344
386
|
.bottom-bar {
|
|
345
387
|
position: sticky; bottom: 0; z-index: 20;
|
|
346
388
|
background: var(--wral-semantic-surface-default, #FFFFFF);
|
|
@@ -353,118 +395,143 @@ const X = p`
|
|
|
353
395
|
}
|
|
354
396
|
.bottom-bar .note { margin-left: auto; font-size: 12px; color: var(--wral-semantic-fg-subtle, #64748B); }
|
|
355
397
|
@media (max-width: 540px) { .bottom-bar .note { display: none; } }
|
|
356
|
-
`,
|
|
398
|
+
`, fe = [se, ie, ne, ae, oe, le, de, ce, ue, pe, he];
|
|
357
399
|
function h(r, e, { noAnim: t = !1, error: s = !1 } = {}) {
|
|
358
|
-
return
|
|
400
|
+
return a`
|
|
359
401
|
<div class="msg bot ${t ? "no-anim" : ""} ${s ? "error" : ""}">
|
|
360
402
|
<span class="lead">${r}</span>
|
|
361
|
-
${e ?
|
|
403
|
+
${e ? a`<span class="sub">${e}</span>` : c}
|
|
362
404
|
</div>
|
|
363
405
|
`;
|
|
364
406
|
}
|
|
365
|
-
function
|
|
366
|
-
return
|
|
407
|
+
function _(r, { noAnim: e = !1 } = {}) {
|
|
408
|
+
return a`<div class="msg user ${e ? "no-anim" : ""}">${r}</div>`;
|
|
367
409
|
}
|
|
368
|
-
function
|
|
369
|
-
return
|
|
410
|
+
function I() {
|
|
411
|
+
return a`<div class="msg bot typing"><span></span><span></span><span></span></div>`;
|
|
370
412
|
}
|
|
371
|
-
function
|
|
372
|
-
return r ?
|
|
413
|
+
function ge(r) {
|
|
414
|
+
return r ? a`<span class="flag-pill ${r}">${r === "urgent" ? "Urgent" : "Moderate"}</span>` : c;
|
|
373
415
|
}
|
|
374
|
-
function
|
|
375
|
-
return
|
|
416
|
+
function me() {
|
|
417
|
+
return a`
|
|
376
418
|
<svg viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="3"
|
|
377
419
|
stroke-linecap="round" stroke-linejoin="round" width="20" height="20"
|
|
378
420
|
aria-hidden="true"><path d="M20 6L9 17l-5-5"/></svg>
|
|
379
421
|
`;
|
|
380
422
|
}
|
|
381
|
-
class
|
|
423
|
+
class y extends Error {
|
|
382
424
|
constructor(e, t) {
|
|
383
425
|
super(`api-forms request failed with status ${e}`), this.status = e, this.body = t;
|
|
384
426
|
}
|
|
385
427
|
}
|
|
386
|
-
|
|
428
|
+
const z = Object.freeze({ enabled: !1, humanCheck: null });
|
|
429
|
+
function be({
|
|
387
430
|
baseUrl: r,
|
|
388
431
|
fetchFn: e = (...i) => fetch(...i),
|
|
389
432
|
xhrFactory: t = () => new XMLHttpRequest(),
|
|
390
433
|
getAuthHeaders: s
|
|
391
434
|
}) {
|
|
392
435
|
const i = String(r || "").replace(/\/+$/, "");
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
436
|
+
let n = z, o = null;
|
|
437
|
+
async function l(d, { method: u = "GET", body: g, auth: b = !1 } = {}) {
|
|
438
|
+
const p = { Accept: "application/json" };
|
|
439
|
+
b && Object.assign(p, o ? { Authorization: `Bearer ${o}` } : await s()), g !== void 0 && (p["Content-Type"] = "application/json");
|
|
440
|
+
let w;
|
|
397
441
|
try {
|
|
398
|
-
|
|
399
|
-
method:
|
|
400
|
-
headers:
|
|
401
|
-
...
|
|
442
|
+
w = await e(`${i}${d}`, {
|
|
443
|
+
method: u,
|
|
444
|
+
headers: p,
|
|
445
|
+
...g !== void 0 ? { body: JSON.stringify(g) } : {}
|
|
402
446
|
});
|
|
403
|
-
} catch (
|
|
404
|
-
throw Object.assign(new
|
|
447
|
+
} catch (v) {
|
|
448
|
+
throw Object.assign(new y(0, null), { cause: v });
|
|
405
449
|
}
|
|
406
|
-
let
|
|
450
|
+
let x = null;
|
|
407
451
|
try {
|
|
408
|
-
|
|
452
|
+
x = await w.json();
|
|
409
453
|
} catch {
|
|
410
454
|
}
|
|
411
|
-
if (!
|
|
412
|
-
throw new w
|
|
413
|
-
return
|
|
455
|
+
if (!w.ok)
|
|
456
|
+
throw new y(w.status, x);
|
|
457
|
+
return x;
|
|
414
458
|
}
|
|
415
459
|
return {
|
|
416
460
|
/** @returns {Promise<Array>} published form documents */
|
|
417
461
|
listForms: async () => {
|
|
418
|
-
const
|
|
419
|
-
return
|
|
462
|
+
const d = await l("/v1/forms");
|
|
463
|
+
return n = d?.anonymous?.enabled === !0 ? { enabled: !0, humanCheck: d.anonymous.humanCheck || null } : z, (d?.forms || []).filter((u) => u?.formId && u?.start && Array.isArray(u?.nodes));
|
|
464
|
+
},
|
|
465
|
+
/**
|
|
466
|
+
* What the server advertised on the last listForms.
|
|
467
|
+
* @returns {{enabled: boolean, humanCheck: {provider, siteKey}|null}}
|
|
468
|
+
*/
|
|
469
|
+
anonymousCapability: () => n,
|
|
470
|
+
/**
|
|
471
|
+
* Mint a submission-scoped anonymous session; subsequent auth-bearing
|
|
472
|
+
* calls present it until endAnonSession(). Unauthenticated by design.
|
|
473
|
+
* @returns {Promise<{expiresIn: number}>}
|
|
474
|
+
*/
|
|
475
|
+
createAnonSession: async ({ formId: d, requestId: u, humanToken: g }) => {
|
|
476
|
+
const b = await l("/v1/anon/sessions", {
|
|
477
|
+
method: "POST",
|
|
478
|
+
body: { formId: d, requestId: u, ...g ? { humanToken: g } : {} }
|
|
479
|
+
});
|
|
480
|
+
if (o = b?.token || null, !o)
|
|
481
|
+
throw new y(502, { message: "The anonymous session had no token" });
|
|
482
|
+
return { expiresIn: b.expiresIn };
|
|
483
|
+
},
|
|
484
|
+
/** Drop the anonymous session so identity headers apply again. */
|
|
485
|
+
endAnonSession: () => {
|
|
486
|
+
o = null;
|
|
420
487
|
},
|
|
421
488
|
/** @returns {Promise<Array<{assetId,url,method,expires,assetUrl}>>} */
|
|
422
|
-
createUploads: async (
|
|
423
|
-
const { uploads:
|
|
424
|
-
return
|
|
489
|
+
createUploads: async (d) => {
|
|
490
|
+
const { uploads: u } = await l("/v1/uploads", { method: "POST", body: d, auth: !0 });
|
|
491
|
+
return u || [];
|
|
425
492
|
},
|
|
426
493
|
/**
|
|
427
494
|
* PUT one file to its presigned URL. XHR (not fetch) so upload
|
|
428
495
|
* progress is observable. Resolves on 2xx; rejects with
|
|
429
496
|
* ApiError(status) otherwise. Returns { promise, abort }.
|
|
430
497
|
*/
|
|
431
|
-
uploadFile: ({ url:
|
|
498
|
+
uploadFile: ({ url: d, file: u, contentType: g, onProgress: b = () => {
|
|
432
499
|
} }) => {
|
|
433
|
-
const
|
|
434
|
-
return { promise: new Promise((
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
}),
|
|
438
|
-
|
|
439
|
-
},
|
|
440
|
-
}), abort: () =>
|
|
500
|
+
const p = t();
|
|
501
|
+
return { promise: new Promise((x, v) => {
|
|
502
|
+
p.open("PUT", d), p.setRequestHeader("Content-Type", g || u.type), p.upload && (p.upload.onprogress = (S) => {
|
|
503
|
+
b({ loaded: S.loaded, total: S.total || u.size });
|
|
504
|
+
}), p.onload = () => {
|
|
505
|
+
p.status >= 200 && p.status < 300 ? x({ status: p.status }) : v(new y(p.status, null));
|
|
506
|
+
}, p.onerror = () => v(new y(0, null)), p.onabort = () => v(new y(0, { aborted: !0 })), p.send(u);
|
|
507
|
+
}), abort: () => p.abort() };
|
|
441
508
|
},
|
|
442
509
|
/** @returns {Promise<{requestId,reference,confirmation,routing}>} */
|
|
443
|
-
putRequest: async (
|
|
510
|
+
putRequest: async (d, u) => await l(`/v1/requests/${d}`, { method: "PUT", body: u, auth: !0 })
|
|
444
511
|
};
|
|
445
512
|
}
|
|
446
|
-
function
|
|
447
|
-
const { config: r, storage: e } =
|
|
513
|
+
function ye() {
|
|
514
|
+
const { config: r, storage: e } = H();
|
|
448
515
|
let t = null;
|
|
449
516
|
return {
|
|
450
|
-
isAuthenticated: () =>
|
|
451
|
-
signedInEmail: () => e.get(
|
|
452
|
-
getAuthHeaders: () =>
|
|
517
|
+
isAuthenticated: () => re(),
|
|
518
|
+
signedInEmail: () => e.get(F.userEmail) || null,
|
|
519
|
+
getAuthHeaders: () => te(r, e),
|
|
453
520
|
/**
|
|
454
521
|
* Email step. Keeps the challenge user in memory for verifyCode.
|
|
455
522
|
* @returns {{challengeRequired?: boolean, authenticated?: boolean}}
|
|
456
523
|
*/
|
|
457
524
|
sendCode: async (s) => {
|
|
458
|
-
const i = await
|
|
525
|
+
const i = await J(
|
|
459
526
|
r,
|
|
460
527
|
s,
|
|
461
528
|
e,
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
529
|
+
X,
|
|
530
|
+
Z,
|
|
531
|
+
ee,
|
|
532
|
+
R,
|
|
533
|
+
T,
|
|
534
|
+
D
|
|
468
535
|
);
|
|
469
536
|
return t = i.cognitoUser || null, {
|
|
470
537
|
challengeRequired: !!i.challengeRequired,
|
|
@@ -479,114 +546,114 @@ function he() {
|
|
|
479
546
|
if (!t)
|
|
480
547
|
throw new Error("Please enter your email again to get a new code.");
|
|
481
548
|
try {
|
|
482
|
-
await
|
|
549
|
+
await Q(
|
|
483
550
|
t,
|
|
484
551
|
s,
|
|
485
552
|
e,
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
553
|
+
R,
|
|
554
|
+
T,
|
|
555
|
+
D
|
|
489
556
|
);
|
|
490
557
|
} catch {
|
|
491
558
|
throw new Error("Invalid or expired code. Please request a new one and try again.");
|
|
492
559
|
}
|
|
493
|
-
return await
|
|
560
|
+
return await G(), { success: !0 };
|
|
494
561
|
},
|
|
495
562
|
/** Local sign-out only ("use a different email"). */
|
|
496
563
|
signOut: () => {
|
|
497
|
-
t = null,
|
|
564
|
+
t = null, K().clear();
|
|
498
565
|
},
|
|
499
566
|
/**
|
|
500
567
|
* Detect a login completed in ANOTHER tab (the storage event
|
|
501
568
|
* never fires in the tab that wrote). Returns an unsubscribe.
|
|
502
569
|
*/
|
|
503
570
|
onCrossTabLogin: (s) => {
|
|
504
|
-
const i = (
|
|
505
|
-
(
|
|
571
|
+
const i = (n) => {
|
|
572
|
+
(n.key === F.accessToken || n.key === F.idToken) && s();
|
|
506
573
|
};
|
|
507
574
|
return window.addEventListener("storage", i), () => window.removeEventListener("storage", i);
|
|
508
575
|
}
|
|
509
576
|
};
|
|
510
577
|
}
|
|
511
|
-
function
|
|
512
|
-
const e =
|
|
513
|
-
return { ...
|
|
578
|
+
function we({ baseUrl: r }) {
|
|
579
|
+
const e = ye();
|
|
580
|
+
return { ...be({ baseUrl: r, getAuthHeaders: e.getAuthHeaders }), ...e };
|
|
514
581
|
}
|
|
515
|
-
function
|
|
582
|
+
function m(r, e) {
|
|
516
583
|
return (r?.nodes || []).find((t) => t.id === e);
|
|
517
584
|
}
|
|
518
|
-
function
|
|
585
|
+
function N(r, e = []) {
|
|
519
586
|
const t = [];
|
|
520
587
|
let s = r?.start;
|
|
521
|
-
for (const
|
|
522
|
-
const
|
|
523
|
-
if (!
|
|
524
|
-
return { nodeId: null, node: null, flags: t, error: { step:
|
|
525
|
-
if (
|
|
526
|
-
return { nodeId: null, node: null, flags: t, error: { step:
|
|
527
|
-
if (
|
|
528
|
-
return { nodeId: null, node: null, flags: t, error: { step:
|
|
529
|
-
if (
|
|
530
|
-
const
|
|
531
|
-
if (!
|
|
532
|
-
return { nodeId: null, node: null, flags: t, error: { step:
|
|
533
|
-
t.push(...
|
|
588
|
+
for (const n of e) {
|
|
589
|
+
const o = m(r, s);
|
|
590
|
+
if (!o)
|
|
591
|
+
return { nodeId: null, node: null, flags: t, error: { step: n, reason: `unknown node: ${s}` } };
|
|
592
|
+
if (o.type === "terminal" || o.type === "redirect")
|
|
593
|
+
return { nodeId: null, node: null, flags: t, error: { step: n, reason: `steps continue past ${o.type}` } };
|
|
594
|
+
if (n.nodeId !== s || n.kind !== o.type)
|
|
595
|
+
return { nodeId: null, node: null, flags: t, error: { step: n, reason: `step does not match node ${s}` } };
|
|
596
|
+
if (o.type === "choice") {
|
|
597
|
+
const l = (o.options || []).find((d) => d.id === n.optionId);
|
|
598
|
+
if (!l)
|
|
599
|
+
return { nodeId: null, node: null, flags: t, error: { step: n, reason: `unknown option: ${n.optionId}` } };
|
|
600
|
+
t.push(...l.flags || []), s = l.next;
|
|
534
601
|
continue;
|
|
535
602
|
}
|
|
536
|
-
s =
|
|
603
|
+
s = o.next;
|
|
537
604
|
}
|
|
538
|
-
const i =
|
|
539
|
-
return i ? { nodeId: s, node: i, flags:
|
|
605
|
+
const i = m(r, s);
|
|
606
|
+
return i ? { nodeId: s, node: i, flags: V(t), error: null } : { nodeId: null, node: null, flags: t, error: { step: null, reason: `unknown node: ${s}` } };
|
|
540
607
|
}
|
|
541
|
-
function
|
|
608
|
+
function xe(r, e = []) {
|
|
542
609
|
const t = [];
|
|
543
610
|
for (const s of e) {
|
|
544
611
|
if (s.kind !== "collect") continue;
|
|
545
|
-
const i =
|
|
612
|
+
const i = m(r, s.nodeId);
|
|
546
613
|
t.push(...i?.fields || []);
|
|
547
614
|
}
|
|
548
615
|
return t;
|
|
549
616
|
}
|
|
550
|
-
function
|
|
617
|
+
function ve(r = []) {
|
|
551
618
|
const e = {};
|
|
552
619
|
for (const t of r)
|
|
553
620
|
t.kind === "collect" && Object.assign(e, t.values || {});
|
|
554
621
|
return e;
|
|
555
622
|
}
|
|
556
|
-
function
|
|
623
|
+
function ke(r = []) {
|
|
557
624
|
return r.filter((e) => e.kind === "choice").map((e) => `${e.nodeId}:${e.optionId}`);
|
|
558
625
|
}
|
|
559
|
-
function
|
|
626
|
+
function W(r, e = []) {
|
|
560
627
|
const t = [];
|
|
561
628
|
for (const s of e) {
|
|
562
629
|
if (s.kind !== "choice") continue;
|
|
563
|
-
const
|
|
564
|
-
t.push(...
|
|
630
|
+
const n = (m(r, s.nodeId)?.options || []).find((o) => o.id === s.optionId);
|
|
631
|
+
t.push(...n?.flags || []);
|
|
565
632
|
}
|
|
566
|
-
return
|
|
633
|
+
return V(t);
|
|
567
634
|
}
|
|
568
|
-
function
|
|
635
|
+
function _e(r = []) {
|
|
569
636
|
return r.includes("urgent") ? "urgent" : r.includes("moderate") ? "moderate" : null;
|
|
570
637
|
}
|
|
571
|
-
function
|
|
638
|
+
function V(r) {
|
|
572
639
|
return [...new Set(r)];
|
|
573
640
|
}
|
|
574
|
-
const
|
|
641
|
+
const $e = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/, P = {
|
|
575
642
|
text: 500,
|
|
576
643
|
textarea: 5e3,
|
|
577
644
|
url: 2048
|
|
578
645
|
};
|
|
579
|
-
function
|
|
580
|
-
if (e == null || e === "" || r.kind === "location" &&
|
|
646
|
+
function Fe(r, e) {
|
|
647
|
+
if (e == null || e === "" || r.kind === "location" && Ie(e))
|
|
581
648
|
return r.required ? `Please fill in: ${r.label.toLowerCase()}.` : null;
|
|
582
649
|
switch (r.kind) {
|
|
583
650
|
case "text":
|
|
584
651
|
case "textarea": {
|
|
585
|
-
const s = r.maxLength ||
|
|
652
|
+
const s = r.maxLength || P[r.kind];
|
|
586
653
|
return typeof e != "string" ? `Please enter text for ${r.label.toLowerCase()}.` : e.length > s ? `Please keep ${r.label.toLowerCase()} under ${s} characters.` : null;
|
|
587
654
|
}
|
|
588
655
|
case "url": {
|
|
589
|
-
if (typeof e != "string" || e.length >
|
|
656
|
+
if (typeof e != "string" || e.length > P.url)
|
|
590
657
|
return "Please enter a valid link.";
|
|
591
658
|
try {
|
|
592
659
|
return new URL(e), null;
|
|
@@ -595,85 +662,85 @@ function xe(r, e) {
|
|
|
595
662
|
}
|
|
596
663
|
}
|
|
597
664
|
case "datetime":
|
|
598
|
-
return
|
|
665
|
+
return $e.test(String(e)) ? null : "Please pick a date and time.";
|
|
599
666
|
case "select":
|
|
600
667
|
return (r.options || []).map((i) => i.id).includes(e) ? null : `Please choose one of the options for ${r.label.toLowerCase()}.`;
|
|
601
668
|
case "consent":
|
|
602
669
|
return e === !0 ? null : "Please confirm the rights statement so we can use what you send.";
|
|
603
670
|
case "location":
|
|
604
|
-
return
|
|
671
|
+
return Ee(r, e);
|
|
605
672
|
case "media":
|
|
606
673
|
return null;
|
|
607
674
|
default:
|
|
608
675
|
return `Unsupported field: ${r.kind}`;
|
|
609
676
|
}
|
|
610
677
|
}
|
|
611
|
-
function
|
|
678
|
+
function Ie(r) {
|
|
612
679
|
return r == null ? !0 : typeof r != "object" ? !1 : !r.county && !r.where && !(Array.isArray(r.gps) && r.gps.length);
|
|
613
680
|
}
|
|
614
|
-
function
|
|
681
|
+
function Ee(r, e) {
|
|
615
682
|
return typeof e != "object" || Array.isArray(e) ? "Please tell us where this was." : e.county !== void 0 && (typeof e.county != "string" || e.county.length > 100) ? "Please choose a county." : e.where !== void 0 && (typeof e.where != "string" || e.where.length > 500) ? "Please shorten the location description." : e.gps !== void 0 && !(Array.isArray(e.gps) && e.gps.length === 2 && e.gps.every((s) => typeof s == "number" && Number.isFinite(s))) ? "Location coordinates look wrong; try re-sharing your location." : r.required && !e.county && !e.where ? `Please fill in: ${r.label.toLowerCase()}.` : null;
|
|
616
683
|
}
|
|
617
|
-
function
|
|
684
|
+
function B(r, e = {}) {
|
|
618
685
|
const t = {};
|
|
619
686
|
for (const s of r) {
|
|
620
687
|
if (s.kind === "media") continue;
|
|
621
|
-
const i =
|
|
688
|
+
const i = Fe(s, e[s.key]);
|
|
622
689
|
i && (t[s.key] = i);
|
|
623
690
|
}
|
|
624
691
|
return { ok: Object.keys(t).length === 0, errors: t };
|
|
625
692
|
}
|
|
626
|
-
function
|
|
693
|
+
function E(r = [], e = {}, { required: t = !1 } = {}) {
|
|
627
694
|
const {
|
|
628
695
|
maxFiles: s = 5,
|
|
629
696
|
maxFileBytes: i = 512 * 1024 * 1024,
|
|
630
|
-
allowedTypes:
|
|
631
|
-
} = e,
|
|
632
|
-
return t && r.length === 0 &&
|
|
697
|
+
allowedTypes: n = []
|
|
698
|
+
} = e, o = [];
|
|
699
|
+
return t && r.length === 0 && o.push({ reason: "required", message: "Please attach at least one photo or video." }), r.length > s && o.push({
|
|
633
700
|
reason: "count",
|
|
634
701
|
message: `This form accepts at most ${s} ${s === 1 ? "file" : "files"}.`
|
|
635
|
-
}), r.forEach((
|
|
636
|
-
|
|
702
|
+
}), r.forEach((l, d) => {
|
|
703
|
+
n.length && !n.includes(l.type) && o.push({
|
|
637
704
|
index: d,
|
|
638
705
|
reason: "type",
|
|
639
|
-
message: `${
|
|
640
|
-
}),
|
|
706
|
+
message: `${l.name || "A file"} is a type this form does not accept.`
|
|
707
|
+
}), l.size > i && o.push({
|
|
641
708
|
index: d,
|
|
642
709
|
reason: "size",
|
|
643
|
-
message: `${
|
|
710
|
+
message: `${l.name || "A file"} is larger than this form allows.`
|
|
644
711
|
});
|
|
645
|
-
}), { ok:
|
|
712
|
+
}), { ok: o.length === 0, errors: o };
|
|
646
713
|
}
|
|
647
|
-
function
|
|
714
|
+
function q({ formId: r, requestId: e, files: t }) {
|
|
648
715
|
return {
|
|
649
716
|
formId: r,
|
|
650
717
|
requestId: e,
|
|
651
718
|
files: t.map((s) => ({ contentType: s.type, size: s.size }))
|
|
652
719
|
};
|
|
653
720
|
}
|
|
654
|
-
function
|
|
655
|
-
const s =
|
|
656
|
-
for (const
|
|
657
|
-
if (
|
|
658
|
-
const
|
|
659
|
-
if (!(
|
|
660
|
-
if (
|
|
721
|
+
function Ae({ form: r, steps: e, media: t = [] }) {
|
|
722
|
+
const s = xe(r, e), i = ve(e), n = {};
|
|
723
|
+
for (const o of s) {
|
|
724
|
+
if (o.kind === "media") continue;
|
|
725
|
+
const l = i[o.key];
|
|
726
|
+
if (!(l == null || l === "") && !(o.kind === "consent" && l !== !0)) {
|
|
727
|
+
if (o.kind === "location") {
|
|
661
728
|
const d = {};
|
|
662
|
-
|
|
729
|
+
l.county && (d.county = l.county), l.where && (d.where = l.where), Array.isArray(l.gps) && l.gps.length === 2 && (d.gps = l.gps), Object.keys(d).length && (n[o.key] = d);
|
|
663
730
|
continue;
|
|
664
731
|
}
|
|
665
|
-
|
|
732
|
+
n[o.key] = l;
|
|
666
733
|
}
|
|
667
734
|
}
|
|
668
735
|
return {
|
|
669
736
|
formId: r.formId,
|
|
670
737
|
flowVersion: r.flowVersion,
|
|
671
|
-
path:
|
|
672
|
-
answers:
|
|
673
|
-
media: t.map(({ assetId:
|
|
738
|
+
path: ke(e),
|
|
739
|
+
answers: n,
|
|
740
|
+
media: t.map(({ assetId: o, type: l }) => ({ assetId: o, type: l }))
|
|
674
741
|
};
|
|
675
742
|
}
|
|
676
|
-
function
|
|
743
|
+
function M(r, e) {
|
|
677
744
|
if (r === 429)
|
|
678
745
|
return {
|
|
679
746
|
kind: "throttled",
|
|
@@ -711,15 +778,15 @@ function $e(r, e) {
|
|
|
711
778
|
message: "Something went wrong on our end; please try again."
|
|
712
779
|
};
|
|
713
780
|
}
|
|
714
|
-
const
|
|
715
|
-
function
|
|
781
|
+
const Ce = 34, Se = 44;
|
|
782
|
+
function U(r, e) {
|
|
716
783
|
const t = String(r);
|
|
717
784
|
return t.length > e ? `${t.slice(0, e)}…` : t;
|
|
718
785
|
}
|
|
719
|
-
function
|
|
786
|
+
function Re(r) {
|
|
720
787
|
return !r || typeof r != "object" ? "" : [r.county, r.where].filter(Boolean).join(", ");
|
|
721
788
|
}
|
|
722
|
-
function
|
|
789
|
+
function Te(r, e = {}, t = []) {
|
|
723
790
|
const s = [];
|
|
724
791
|
for (const i of r) {
|
|
725
792
|
if (i.kind === "consent") continue;
|
|
@@ -727,21 +794,21 @@ function Ce(r, e = {}, t = []) {
|
|
|
727
794
|
t.length && s.push(`${t.length} ${t.length === 1 ? "file" : "files"}`);
|
|
728
795
|
continue;
|
|
729
796
|
}
|
|
730
|
-
const
|
|
731
|
-
|
|
797
|
+
const n = i.kind === "location" ? Re(e[i.key]) : e[i.key];
|
|
798
|
+
n == null || n === "" || (i.kind === "textarea" ? s.push(`"${U(n, Se)}"`) : s.push(U(n, Ce)));
|
|
732
799
|
}
|
|
733
800
|
return s.join(" · ") || "Details provided";
|
|
734
801
|
}
|
|
735
|
-
function
|
|
802
|
+
function De(r, e = [], t = null) {
|
|
736
803
|
const s = [];
|
|
737
|
-
for (const
|
|
738
|
-
const
|
|
739
|
-
|
|
804
|
+
for (const n of e) {
|
|
805
|
+
const o = m(r, n.nodeId);
|
|
806
|
+
n.kind === "choice" && o && s.push({ k: (o.prompt || "").replace(/\?$/, ""), v: n.label || n.optionId }), n.kind === "collect" && s.push({ k: "Details", v: n.summary || "Details provided" }), n.kind === "gate" && (n.anonymous ? s.push({ k: "Contact", v: "Anonymous — we will have no way to reach you" }) : (n.email || t) && s.push({ k: "Verified email", v: n.email || t }));
|
|
740
807
|
}
|
|
741
|
-
const i =
|
|
808
|
+
const i = _e(W(r, e));
|
|
742
809
|
return i && s.push({ k: "Priority", v: i === "urgent" ? "Urgent" : "Moderate", pill: i }), s;
|
|
743
810
|
}
|
|
744
|
-
function
|
|
811
|
+
function ze(r, e = []) {
|
|
745
812
|
const t = r?.confirmation || {};
|
|
746
813
|
return {
|
|
747
814
|
title: t.title || "Report received.",
|
|
@@ -749,12 +816,12 @@ function Ae(r, e = []) {
|
|
|
749
816
|
urgentNote: e.includes("urgent") ? t.urgentNote : void 0
|
|
750
817
|
};
|
|
751
818
|
}
|
|
752
|
-
function
|
|
819
|
+
function Pe(r, e) {
|
|
753
820
|
const t = e === "failed" ? " The notification is queued for a delivery retry." : "";
|
|
754
821
|
return r?.startsWith("studio+email:") ? `Sent to the Studio review queue; the desk is emailed.${t}` : r?.startsWith("studio:") ? "Sent to the Studio review queue." : r?.startsWith("jsm:") ? `A ticket is opened for tech support with your details as fields, not prose.${t}` : r?.startsWith("email:") ? `Emailed to the owning desk with a link to your report.${t}` : "Routed to the right team.";
|
|
755
822
|
}
|
|
756
|
-
function
|
|
757
|
-
const
|
|
823
|
+
function Be({ routing: r = {}, flags: e = [], reference: t = "", anonymous: s = !1 }) {
|
|
824
|
+
const i = e.includes("urgent");
|
|
758
825
|
return [
|
|
759
826
|
{
|
|
760
827
|
title: "Received",
|
|
@@ -762,12 +829,12 @@ function De({ routing: r = {}, flags: e = [], reference: t = "" }) {
|
|
|
762
829
|
},
|
|
763
830
|
{
|
|
764
831
|
title: "Routed",
|
|
765
|
-
body:
|
|
766
|
-
pill:
|
|
832
|
+
body: Pe(r.destination, r.state),
|
|
833
|
+
pill: i ? "Urgent · pinned first" : void 0
|
|
767
834
|
},
|
|
768
835
|
{
|
|
769
836
|
title: "Reviewed",
|
|
770
|
-
body: "An editor reviews it in the Report It queue: accept and promote with your credit, reject, or re-route."
|
|
837
|
+
body: s ? "An editor reviews it in the Report It queue: accept and promote it uncredited, reject, or re-route." : "An editor reviews it in the Report It queue: accept and promote with your credit, reject, or re-route."
|
|
771
838
|
},
|
|
772
839
|
{
|
|
773
840
|
title: "Monitored",
|
|
@@ -779,30 +846,30 @@ function De({ routing: r = {}, flags: e = [], reference: t = "" }) {
|
|
|
779
846
|
}
|
|
780
847
|
];
|
|
781
848
|
}
|
|
782
|
-
const
|
|
783
|
-
function
|
|
849
|
+
const C = "wral-report-it:draft:v1", Y = 1;
|
|
850
|
+
function qe(r, e) {
|
|
784
851
|
try {
|
|
785
|
-
r.setItem(
|
|
852
|
+
r.setItem(C, JSON.stringify({ ...e, v: Y, savedAt: Date.now() }));
|
|
786
853
|
} catch {
|
|
787
854
|
}
|
|
788
855
|
}
|
|
789
|
-
function
|
|
856
|
+
function Me(r) {
|
|
790
857
|
try {
|
|
791
|
-
const e = r.getItem(
|
|
858
|
+
const e = r.getItem(C);
|
|
792
859
|
if (!e) return null;
|
|
793
860
|
const t = JSON.parse(e);
|
|
794
|
-
return t?.v !==
|
|
861
|
+
return t?.v !== Y ? null : t;
|
|
795
862
|
} catch {
|
|
796
863
|
return null;
|
|
797
864
|
}
|
|
798
865
|
}
|
|
799
|
-
function
|
|
866
|
+
function O(r) {
|
|
800
867
|
try {
|
|
801
|
-
r.removeItem(
|
|
868
|
+
r.removeItem(C);
|
|
802
869
|
} catch {
|
|
803
870
|
}
|
|
804
871
|
}
|
|
805
|
-
function
|
|
872
|
+
function Ue({ apiOrigin: r, form: e, steps: t, requestId: s = null, mediaMeta: i = {} }) {
|
|
806
873
|
return {
|
|
807
874
|
apiOrigin: r,
|
|
808
875
|
formId: e.formId,
|
|
@@ -812,26 +879,26 @@ function Pe({ apiOrigin: r, form: e, steps: t, requestId: s = null, mediaMeta: i
|
|
|
812
879
|
media: i
|
|
813
880
|
};
|
|
814
881
|
}
|
|
815
|
-
function
|
|
882
|
+
function Oe(r, e, { apiOrigin: t } = {}) {
|
|
816
883
|
if (!r) return { status: "discarded" };
|
|
817
884
|
if (t && r.apiOrigin && r.apiOrigin !== t)
|
|
818
885
|
return { status: "discarded" };
|
|
819
|
-
const s = (e || []).find((
|
|
886
|
+
const s = (e || []).find((o) => o.formId === r.formId);
|
|
820
887
|
if (!s) return { status: "discarded" };
|
|
821
|
-
const { error: i } =
|
|
888
|
+
const { error: i } = N(s, r.steps || []);
|
|
822
889
|
if (i) return { status: "discarded" };
|
|
823
|
-
const
|
|
824
|
-
for (const [
|
|
825
|
-
|
|
890
|
+
const n = {};
|
|
891
|
+
for (const [o, l] of Object.entries(r.media || {}))
|
|
892
|
+
l?.length && (n[o] = l.map((d) => ({ ...d, lost: !0 })));
|
|
826
893
|
return {
|
|
827
894
|
status: r.flowVersion === s.flowVersion ? "ok" : "review-required",
|
|
828
895
|
form: s,
|
|
829
896
|
steps: r.steps || [],
|
|
830
897
|
requestId: r.requestId || null,
|
|
831
|
-
lostMedia:
|
|
898
|
+
lostMedia: n
|
|
832
899
|
};
|
|
833
900
|
}
|
|
834
|
-
function
|
|
901
|
+
function $(r = []) {
|
|
835
902
|
return {
|
|
836
903
|
stage: "idle",
|
|
837
904
|
resumeStage: null,
|
|
@@ -851,7 +918,7 @@ function k(r = []) {
|
|
|
851
918
|
error: null
|
|
852
919
|
};
|
|
853
920
|
}
|
|
854
|
-
function
|
|
921
|
+
function je(r, e) {
|
|
855
922
|
switch (e.type) {
|
|
856
923
|
case "START":
|
|
857
924
|
return { ...r, stage: r.files.length ? "minting" : "requesting", error: null };
|
|
@@ -872,29 +939,29 @@ function qe(r, e) {
|
|
|
872
939
|
return { ...r, stage: "uploading", files: t };
|
|
873
940
|
}
|
|
874
941
|
case "FILE_PROGRESS":
|
|
875
|
-
return
|
|
942
|
+
return k(r, e.i, (t) => ({
|
|
876
943
|
...t,
|
|
877
944
|
progress: e.total ? e.loaded / e.total : 0
|
|
878
945
|
}));
|
|
879
946
|
case "FILE_DONE": {
|
|
880
|
-
const t =
|
|
881
|
-
return
|
|
947
|
+
const t = k(r, e.i, (s) => ({ ...s, status: "done", progress: 1 }));
|
|
948
|
+
return Le(t);
|
|
882
949
|
}
|
|
883
950
|
case "FILE_FAIL":
|
|
884
|
-
return { ...
|
|
951
|
+
return { ...k(r, e.i, (s) => ({
|
|
885
952
|
...s,
|
|
886
953
|
status: "failed",
|
|
887
954
|
error: e.error || "upload failed"
|
|
888
955
|
})), stage: "uploading-error" };
|
|
889
956
|
case "RETRY_FILE":
|
|
890
|
-
return { ...
|
|
957
|
+
return { ...k(r, e.i, (s) => ({
|
|
891
958
|
...s,
|
|
892
959
|
status: "uploading",
|
|
893
960
|
progress: 0,
|
|
894
961
|
error: null
|
|
895
962
|
})), stage: "uploading" };
|
|
896
963
|
case "REMINT_FILE":
|
|
897
|
-
return { ...
|
|
964
|
+
return { ...k(r, e.i, (s) => ({
|
|
898
965
|
...s,
|
|
899
966
|
assetId: e.upload.assetId,
|
|
900
967
|
url: e.upload.url,
|
|
@@ -910,23 +977,23 @@ function qe(r, e) {
|
|
|
910
977
|
case "REQUEST_FAIL":
|
|
911
978
|
return { ...r, stage: "requesting-error", error: e.error };
|
|
912
979
|
case "RESET":
|
|
913
|
-
return
|
|
980
|
+
return $([]);
|
|
914
981
|
default:
|
|
915
982
|
return r;
|
|
916
983
|
}
|
|
917
984
|
}
|
|
918
|
-
function
|
|
919
|
-
const s = r.files.map((i,
|
|
985
|
+
function k(r, e, t) {
|
|
986
|
+
const s = r.files.map((i, n) => n === e ? t(i) : i);
|
|
920
987
|
return { ...r, files: s };
|
|
921
988
|
}
|
|
922
|
-
function
|
|
989
|
+
function Le(r) {
|
|
923
990
|
const e = r.files.every((s) => s.status === "done"), t = r.files.some((s) => s.status === "failed");
|
|
924
991
|
return e ? { ...r, stage: "requesting" } : t ? { ...r, stage: "uploading-error" } : r;
|
|
925
992
|
}
|
|
926
|
-
function
|
|
993
|
+
function j(r) {
|
|
927
994
|
return r.files.map((e, t) => ({ ...e, i: t })).filter((e) => e.status === "failed");
|
|
928
995
|
}
|
|
929
|
-
const
|
|
996
|
+
const Ne = [
|
|
930
997
|
"Wake",
|
|
931
998
|
"Durham",
|
|
932
999
|
"Orange",
|
|
@@ -943,9 +1010,18 @@ const Ue = [
|
|
|
943
1010
|
"Moore",
|
|
944
1011
|
"Sampson",
|
|
945
1012
|
"Other / outside the area"
|
|
946
|
-
],
|
|
947
|
-
|
|
948
|
-
|
|
1013
|
+
], L = "(919) 821-8600", We = "https://www.wral.com/my-wral/", Ve = Object.freeze([
|
|
1014
|
+
"We cannot come back to you for the detail that often turns a tip into a story.",
|
|
1015
|
+
"We cannot credit you if we use your photos or video.",
|
|
1016
|
+
"If you lose your reference number, we cannot look it up for you."
|
|
1017
|
+
]);
|
|
1018
|
+
function Ye(r) {
|
|
1019
|
+
const e = String(r).replace(/\D/g, "");
|
|
1020
|
+
return `tel:+1${e.length === 11 && e.startsWith("1") ? e.slice(1) : e}`;
|
|
1021
|
+
}
|
|
1022
|
+
const He = "https://api.wral.com/forms", Ke = 480, Qe = 2;
|
|
1023
|
+
class rt extends A {
|
|
1024
|
+
static styles = fe;
|
|
949
1025
|
static properties = {
|
|
950
1026
|
api: { type: String },
|
|
951
1027
|
_phase: { state: !0 },
|
|
@@ -961,34 +1037,35 @@ class Qe extends I {
|
|
|
961
1037
|
_notice: { state: !0 },
|
|
962
1038
|
_result: { state: !0 }
|
|
963
1039
|
};
|
|
964
|
-
#
|
|
1040
|
+
#l = null;
|
|
965
1041
|
#a = null;
|
|
966
1042
|
#u = null;
|
|
967
1043
|
#t = null;
|
|
968
1044
|
#r = {};
|
|
969
1045
|
#s = {};
|
|
970
1046
|
#i = /* @__PURE__ */ new Map();
|
|
971
|
-
#
|
|
972
|
-
#
|
|
973
|
-
#
|
|
1047
|
+
#b = null;
|
|
1048
|
+
#y = !1;
|
|
1049
|
+
#d = null;
|
|
1050
|
+
#F = 0;
|
|
974
1051
|
constructor() {
|
|
975
|
-
super(), this.api =
|
|
1052
|
+
super(), this.api = He, this._phase = "loading", this._forms = [], this._form = null, this._steps = [], this._typing = !1, this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, this._submit = $([]), this._banner = null, this._notice = null, this._result = null;
|
|
976
1053
|
}
|
|
977
1054
|
get client() {
|
|
978
|
-
return this.#
|
|
1055
|
+
return this.#l ? this.#l : ((!this.#a || this.#u !== this.api) && (this.#a = we({ baseUrl: this.api }), this.#u = this.api), this.#a);
|
|
979
1056
|
}
|
|
980
1057
|
set client(e) {
|
|
981
|
-
this.#
|
|
1058
|
+
this.#l = e || null, this.isConnected && this.#w();
|
|
982
1059
|
}
|
|
983
1060
|
connectedCallback() {
|
|
984
|
-
super.connectedCallback(), this.#
|
|
1061
|
+
super.connectedCallback(), this.#w();
|
|
985
1062
|
}
|
|
986
1063
|
disconnectedCallback() {
|
|
987
|
-
super.disconnectedCallback(), clearTimeout(this.#
|
|
1064
|
+
super.disconnectedCallback(), clearTimeout(this.#b), this.#d?.();
|
|
988
1065
|
for (const { abort: e } of this.#i.values()) e?.();
|
|
989
1066
|
this.#i.clear();
|
|
990
1067
|
}
|
|
991
|
-
get #
|
|
1068
|
+
get #D() {
|
|
992
1069
|
try {
|
|
993
1070
|
return matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
994
1071
|
} catch {
|
|
@@ -1004,28 +1081,45 @@ class Qe extends I {
|
|
|
1004
1081
|
} };
|
|
1005
1082
|
}
|
|
1006
1083
|
}
|
|
1084
|
+
/*
|
|
1085
|
+
* The anonymous route is offered only where it can actually complete.
|
|
1086
|
+
* The server is the authority: GET /v1/forms says whether anonymous
|
|
1087
|
+
* submission is enabled on this deployment, and a form whose desk needs
|
|
1088
|
+
* a way to reach the viewer opts out with allowAnonymous: false.
|
|
1089
|
+
*/
|
|
1090
|
+
get #z() {
|
|
1091
|
+
return this.client.anonymousCapability?.().enabled === !0 && this._form?.allowAnonymous !== !1;
|
|
1092
|
+
}
|
|
1093
|
+
/* Derived from the gate step, so a reload restores the choice. */
|
|
1094
|
+
get #h() {
|
|
1095
|
+
return this._steps.some((e) => e.kind === "gate" && e.anonymous === !0);
|
|
1096
|
+
}
|
|
1007
1097
|
// ── Loading + draft restore ─────────────────────────────────────
|
|
1008
|
-
async #
|
|
1098
|
+
async #w() {
|
|
1099
|
+
const e = ++this.#F, t = () => e === this.#F;
|
|
1009
1100
|
this._phase = "loading", this._banner = null;
|
|
1101
|
+
let s;
|
|
1010
1102
|
try {
|
|
1011
|
-
|
|
1103
|
+
s = await this.client.listForms();
|
|
1012
1104
|
} catch {
|
|
1013
|
-
this._phase = "load-error";
|
|
1105
|
+
t() && (this._phase = "load-error");
|
|
1014
1106
|
return;
|
|
1015
1107
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1108
|
+
if (!t()) return;
|
|
1109
|
+
this._forms = s;
|
|
1110
|
+
const i = Oe(Me(this.#p), this._forms, { apiOrigin: this.api });
|
|
1111
|
+
if (i.status === "ok" || i.status === "review-required") {
|
|
1112
|
+
this._form = i.form, this._steps = i.steps, this.#t = i.requestId, this.#s = i.lostMedia || {}, i.status === "review-required" ? this._notice = "This form changed since your last visit — please review your answers." : Object.keys(this.#s).length && (this._notice = "Welcome back — your answers were saved, but attachments need to be re-attached."), this.#o({ animate: !1 });
|
|
1019
1113
|
return;
|
|
1020
1114
|
}
|
|
1021
1115
|
this._phase = "pick";
|
|
1022
1116
|
}
|
|
1023
|
-
#
|
|
1117
|
+
#c() {
|
|
1024
1118
|
if (!this._form) return;
|
|
1025
1119
|
const e = {};
|
|
1026
1120
|
for (const [t, s] of Object.entries(this.#r))
|
|
1027
|
-
s.length && (e[t] = s.map(({ name: i, type:
|
|
1028
|
-
|
|
1121
|
+
s.length && (e[t] = s.map(({ name: i, type: n, size: o }) => ({ name: i, type: n, size: o })));
|
|
1122
|
+
qe(this.#p, Ue({
|
|
1029
1123
|
apiOrigin: this.api,
|
|
1030
1124
|
form: this._form,
|
|
1031
1125
|
steps: this._steps,
|
|
@@ -1034,77 +1128,77 @@ class Qe extends I {
|
|
|
1034
1128
|
}));
|
|
1035
1129
|
}
|
|
1036
1130
|
// ── Walk mechanics ──────────────────────────────────────────────
|
|
1037
|
-
#
|
|
1038
|
-
this._phase = "walk", this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, e && !this.#
|
|
1131
|
+
#o({ animate: e = !0 } = {}) {
|
|
1132
|
+
this._phase = "walk", this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, e && !this.#D ? (this._typing = !0, clearTimeout(this.#b), this.#b = setTimeout(() => {
|
|
1039
1133
|
this._typing = !1;
|
|
1040
|
-
},
|
|
1134
|
+
}, Ke)) : this._typing = !1;
|
|
1041
1135
|
}
|
|
1042
|
-
get #
|
|
1043
|
-
return this._form ?
|
|
1136
|
+
get #x() {
|
|
1137
|
+
return this._form ? N(this._form, this._steps) : { node: null };
|
|
1044
1138
|
}
|
|
1045
|
-
#
|
|
1046
|
-
this._form = e, this._steps = [], this.#t = null, this.#r = {}, this.#s = {}, this._notice = null, this.#
|
|
1139
|
+
#P(e) {
|
|
1140
|
+
this._form = e, this._steps = [], this.#t = null, this.#r = {}, this.#s = {}, this._notice = null, this.#c(), this.#o();
|
|
1047
1141
|
}
|
|
1048
|
-
#
|
|
1049
|
-
this._steps = [...this._steps, e], this.#
|
|
1142
|
+
#f(e) {
|
|
1143
|
+
this._steps = [...this._steps, e], this.#c(), this.#o();
|
|
1050
1144
|
}
|
|
1051
|
-
#
|
|
1145
|
+
#B() {
|
|
1052
1146
|
if (this._phase === "done" || this._phase === "submitting") return;
|
|
1053
1147
|
if (this._phase === "review") {
|
|
1054
|
-
this.#
|
|
1148
|
+
this.#o({ animate: !1 });
|
|
1055
1149
|
return;
|
|
1056
1150
|
}
|
|
1057
1151
|
if (!this._steps.length) {
|
|
1058
|
-
this.#
|
|
1152
|
+
this.#v();
|
|
1059
1153
|
return;
|
|
1060
1154
|
}
|
|
1061
1155
|
const e = this._steps.at(-1);
|
|
1062
|
-
this._steps = this._steps.slice(0, -1), e.kind === "collect" && (this._cardValues = { ...e.values }), this.#
|
|
1156
|
+
this._steps = this._steps.slice(0, -1), e.kind === "collect" && (this._cardValues = { ...e.values }), this.#c(), this.#o({ animate: !1 });
|
|
1063
1157
|
}
|
|
1064
|
-
#
|
|
1065
|
-
this._form = null, this._steps = [], this.#t = null, this.#r = {}, this.#s = {}, this._result = null, this._banner = null, this._notice = null, this._submit =
|
|
1158
|
+
#v() {
|
|
1159
|
+
this.client.endAnonSession?.(), this._form = null, this._steps = [], this.#t = null, this.#r = {}, this.#s = {}, this._result = null, this._banner = null, this._notice = null, this._submit = $([]), O(this.#p), this._phase = "pick";
|
|
1066
1160
|
}
|
|
1067
1161
|
// ── Collect card ────────────────────────────────────────────────
|
|
1068
|
-
#
|
|
1162
|
+
#k(e, t) {
|
|
1069
1163
|
this._cardValues = { ...this._cardValues, [e]: t };
|
|
1070
1164
|
}
|
|
1071
|
-
#
|
|
1072
|
-
const t = e.fields || [], { ok: s, errors: i } =
|
|
1073
|
-
let
|
|
1074
|
-
if (
|
|
1075
|
-
const d = this.#r[e.id] || [],
|
|
1076
|
-
required: !!
|
|
1165
|
+
#q(e) {
|
|
1166
|
+
const t = e.fields || [], { ok: s, errors: i } = B(t, this._cardValues), n = t.find((d) => d.kind === "media");
|
|
1167
|
+
let o = !0;
|
|
1168
|
+
if (n) {
|
|
1169
|
+
const d = this.#r[e.id] || [], u = E(d, this._form.budget, {
|
|
1170
|
+
required: !!n.required
|
|
1077
1171
|
});
|
|
1078
|
-
|
|
1172
|
+
u.ok ? d.length && (this.#s = { ...this.#s, [e.id]: [] }) : (o = !1, i[n.key] = u.errors[0].message);
|
|
1079
1173
|
}
|
|
1080
|
-
if (!s || !
|
|
1174
|
+
if (!s || !o) {
|
|
1081
1175
|
this._fieldErrors = i;
|
|
1082
1176
|
return;
|
|
1083
1177
|
}
|
|
1084
|
-
const
|
|
1085
|
-
this.#
|
|
1178
|
+
const l = this.#r[e.id] || [];
|
|
1179
|
+
this.#f({
|
|
1086
1180
|
nodeId: e.id,
|
|
1087
1181
|
kind: "collect",
|
|
1088
1182
|
values: { ...this._cardValues },
|
|
1089
|
-
summary:
|
|
1183
|
+
summary: Te(t, this._cardValues, l)
|
|
1090
1184
|
});
|
|
1091
1185
|
}
|
|
1092
1186
|
// ── Gate ────────────────────────────────────────────────────────
|
|
1093
|
-
async
|
|
1094
|
-
if (!(this._gate.stage || this.#
|
|
1095
|
-
this.#
|
|
1187
|
+
async #I() {
|
|
1188
|
+
if (!(this._gate.stage || this.#y)) {
|
|
1189
|
+
this.#y = !0;
|
|
1096
1190
|
try {
|
|
1097
1191
|
const e = await this.client.isAuthenticated();
|
|
1098
1192
|
this._gate = e ? { stage: "signedin", email: this.client.signedInEmail?.() || "", error: "", loading: !1 } : { stage: "email", email: "", error: "", loading: !1 };
|
|
1099
1193
|
} finally {
|
|
1100
|
-
this.#
|
|
1194
|
+
this.#y = !1;
|
|
1101
1195
|
}
|
|
1102
|
-
this._gate.stage === "email" && this.client.onCrossTabLogin && !this.#
|
|
1103
|
-
this.#
|
|
1196
|
+
this._gate.stage === "email" && this.client.onCrossTabLogin && !this.#d && (this.#d = this.client.onCrossTabLogin(() => {
|
|
1197
|
+
this.#d?.(), this.#d = null, this._gate = { stage: null, email: "", error: "", loading: !1 }, this.#I();
|
|
1104
1198
|
}));
|
|
1105
1199
|
}
|
|
1106
1200
|
}
|
|
1107
|
-
async #
|
|
1201
|
+
async #_() {
|
|
1108
1202
|
const e = this._gate.email.trim();
|
|
1109
1203
|
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)) {
|
|
1110
1204
|
this._gate = { ...this._gate, error: "Please enter a valid email address." };
|
|
@@ -1122,10 +1216,10 @@ class Qe extends I {
|
|
|
1122
1216
|
};
|
|
1123
1217
|
}
|
|
1124
1218
|
}
|
|
1125
|
-
async #
|
|
1219
|
+
async #E(e) {
|
|
1126
1220
|
this._gate = { ...this._gate, error: "", loading: !0 };
|
|
1127
1221
|
try {
|
|
1128
|
-
await this.client.verifyCode(e), this.#
|
|
1222
|
+
await this.client.verifyCode(e), this.#A(this._gate.email);
|
|
1129
1223
|
} catch (t) {
|
|
1130
1224
|
this._gate = {
|
|
1131
1225
|
...this._gate,
|
|
@@ -1134,19 +1228,53 @@ class Qe extends I {
|
|
|
1134
1228
|
};
|
|
1135
1229
|
}
|
|
1136
1230
|
}
|
|
1137
|
-
#
|
|
1231
|
+
#A(e) {
|
|
1138
1232
|
if (this._gate = { stage: null, email: "", error: "", loading: !1 }, this._submit.stage === "auth") {
|
|
1139
|
-
this.#e({ type: "AUTH_OK" }), this._phase = "submitting", this.#
|
|
1233
|
+
this.#e({ type: "AUTH_OK" }), this._phase = "submitting", this.#n();
|
|
1140
1234
|
return;
|
|
1141
1235
|
}
|
|
1142
|
-
const { node: t } = this.#
|
|
1143
|
-
t?.type === "gate" && this.#
|
|
1236
|
+
const { node: t } = this.#x;
|
|
1237
|
+
t?.type === "gate" && this.#f({ nodeId: t.id, kind: "gate", email: e });
|
|
1144
1238
|
}
|
|
1145
|
-
#
|
|
1239
|
+
#M() {
|
|
1146
1240
|
this.client.signOut?.(), this._gate = { stage: "email", email: "", error: "", loading: !1 };
|
|
1147
1241
|
}
|
|
1242
|
+
// ── Anonymous route ─────────────────────────────────────────────
|
|
1243
|
+
#U() {
|
|
1244
|
+
this._gate = { ...this._gate, stage: "anon-confirm", error: "" };
|
|
1245
|
+
}
|
|
1246
|
+
#O() {
|
|
1247
|
+
this._gate = { ...this._gate, stage: "email", error: "" };
|
|
1248
|
+
}
|
|
1249
|
+
/*
|
|
1250
|
+
* Records the choice only. The session is minted at submit, against
|
|
1251
|
+
* the requestId, so an abandoned form leaves nothing behind.
|
|
1252
|
+
*/
|
|
1253
|
+
#j() {
|
|
1254
|
+
const { node: e } = this.#x;
|
|
1255
|
+
e?.type === "gate" && (this._gate = { stage: null, email: "", error: "", loading: !1 }, this.#f({ nodeId: e.id, kind: "gate", anonymous: !0 }));
|
|
1256
|
+
}
|
|
1257
|
+
async #C() {
|
|
1258
|
+
try {
|
|
1259
|
+
return await this.client.createAnonSession({
|
|
1260
|
+
formId: this._form.formId,
|
|
1261
|
+
requestId: this.#t
|
|
1262
|
+
}), !0;
|
|
1263
|
+
} catch (e) {
|
|
1264
|
+
return this._banner = M(e?.status ?? 0, e?.body ?? null), !1;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
/* An anonymous session outliving the upload run re-mints in place; there
|
|
1268
|
+
* is no identity to send back to the sign-in card. */
|
|
1269
|
+
async #L() {
|
|
1270
|
+
if (await this.#C()) {
|
|
1271
|
+
this.#e({ type: "AUTH_OK" }), this._phase = "submitting", this.#n();
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1274
|
+
this.#e({ type: "REQUEST_FAIL", error: this._banner });
|
|
1275
|
+
}
|
|
1148
1276
|
// ── Submit pipeline ─────────────────────────────────────────────
|
|
1149
|
-
get #
|
|
1277
|
+
get #g() {
|
|
1150
1278
|
const e = [];
|
|
1151
1279
|
for (const t of this._steps)
|
|
1152
1280
|
if (t.kind === "collect")
|
|
@@ -1155,117 +1283,129 @@ class Qe extends I {
|
|
|
1155
1283
|
return e;
|
|
1156
1284
|
}
|
|
1157
1285
|
#e(e) {
|
|
1158
|
-
this._submit =
|
|
1286
|
+
this._submit = je(this._submit, e);
|
|
1159
1287
|
}
|
|
1160
|
-
async #
|
|
1288
|
+
async #N() {
|
|
1161
1289
|
this._banner = null;
|
|
1162
1290
|
for (let e = 0; e < this._steps.length; e++) {
|
|
1163
1291
|
const t = this._steps[e];
|
|
1164
1292
|
if (t.kind !== "collect") continue;
|
|
1165
|
-
const s =
|
|
1166
|
-
let
|
|
1167
|
-
if (
|
|
1168
|
-
const d = this.#r[t.nodeId] || [],
|
|
1169
|
-
required: !!
|
|
1293
|
+
const s = m(this._form, t.nodeId), { ok: i, errors: n } = B(s?.fields || [], t.values), o = (s?.fields || []).find((d) => d.kind === "media");
|
|
1294
|
+
let l = !0;
|
|
1295
|
+
if (o) {
|
|
1296
|
+
const d = this.#r[t.nodeId] || [], u = E(d, this._form.budget, {
|
|
1297
|
+
required: !!o.required
|
|
1170
1298
|
});
|
|
1171
|
-
|
|
1299
|
+
u.ok || (l = !1, n[o.key] = u.errors[0].message);
|
|
1172
1300
|
}
|
|
1173
|
-
if (!i || !
|
|
1174
|
-
this._steps = this._steps.slice(0, e), this._cardValues = { ...t.values }, this._fieldErrors =
|
|
1301
|
+
if (!i || !l) {
|
|
1302
|
+
this._steps = this._steps.slice(0, e), this._cardValues = { ...t.values }, this._fieldErrors = n, this.#c(), this.#o({ animate: !1 });
|
|
1175
1303
|
return;
|
|
1176
1304
|
}
|
|
1177
1305
|
}
|
|
1178
|
-
if (this.#t = this.#t || crypto.randomUUID(), this.#
|
|
1306
|
+
if (this.#t = this.#t || crypto.randomUUID(), this.#c(), this.#h) {
|
|
1307
|
+
if (!await this.#C()) return;
|
|
1308
|
+
} else
|
|
1309
|
+
this.client.endAnonSession?.();
|
|
1310
|
+
if (this._submit = $(this.#g), this._phase = "submitting", this.#h) {
|
|
1311
|
+
this.#e({ type: "START" }), this.#n();
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
if (!await this.client.isAuthenticated()) {
|
|
1179
1315
|
this.#e({ type: "START" }), this.#e({ type: "AUTH_REQUIRED" }), this._gate = { stage: "email", email: "", error: "", loading: !1 };
|
|
1180
1316
|
return;
|
|
1181
1317
|
}
|
|
1182
|
-
this.#e({ type: "START" }), this.#
|
|
1318
|
+
this.#e({ type: "START" }), this.#n();
|
|
1183
1319
|
}
|
|
1184
|
-
async #
|
|
1320
|
+
async #n() {
|
|
1185
1321
|
const e = this._submit.stage;
|
|
1186
|
-
if (e === "minting") return this.#
|
|
1187
|
-
if (e === "uploading") return this.#
|
|
1188
|
-
if (e === "requesting") return this.#
|
|
1322
|
+
if (e === "minting") return this.#W();
|
|
1323
|
+
if (e === "uploading") return this.#S();
|
|
1324
|
+
if (e === "requesting") return this.#H();
|
|
1189
1325
|
}
|
|
1190
|
-
async #
|
|
1326
|
+
async #W() {
|
|
1191
1327
|
try {
|
|
1192
|
-
const e = await this.client.createUploads(
|
|
1328
|
+
const e = await this.client.createUploads(q({
|
|
1193
1329
|
formId: this._form.formId,
|
|
1194
1330
|
requestId: this.#t,
|
|
1195
|
-
files: this.#
|
|
1331
|
+
files: this.#g
|
|
1196
1332
|
}));
|
|
1197
|
-
this.#e({ type: "MINTED", uploads: e }), this.#
|
|
1333
|
+
this.#e({ type: "MINTED", uploads: e }), this.#n();
|
|
1198
1334
|
} catch (e) {
|
|
1199
|
-
this
|
|
1335
|
+
this.#$(e);
|
|
1200
1336
|
}
|
|
1201
1337
|
}
|
|
1202
|
-
#
|
|
1338
|
+
#S() {
|
|
1203
1339
|
const e = this._submit.files, t = this.#i.size;
|
|
1204
1340
|
let s = 0;
|
|
1205
|
-
for (let i = 0; i < e.length && t + s <
|
|
1206
|
-
e[i].status !== "uploading" || this.#i.has(i) || (s += 1, this.#
|
|
1341
|
+
for (let i = 0; i < e.length && t + s < Qe; i++)
|
|
1342
|
+
e[i].status !== "uploading" || this.#i.has(i) || (s += 1, this.#V(i));
|
|
1207
1343
|
}
|
|
1208
|
-
#
|
|
1209
|
-
const t = this._submit.files[e], s = this.#
|
|
1344
|
+
#V(e) {
|
|
1345
|
+
const t = this._submit.files[e], s = this.#g[e], { promise: i, abort: n } = this.client.uploadFile({
|
|
1210
1346
|
url: t.url,
|
|
1211
1347
|
file: s,
|
|
1212
1348
|
contentType: t.type,
|
|
1213
|
-
onProgress: ({ loaded:
|
|
1214
|
-
this.#e({ type: "FILE_PROGRESS", i: e, loaded:
|
|
1349
|
+
onProgress: ({ loaded: o, total: l }) => {
|
|
1350
|
+
this.#e({ type: "FILE_PROGRESS", i: e, loaded: o, total: l });
|
|
1215
1351
|
}
|
|
1216
1352
|
});
|
|
1217
|
-
this.#i.set(e, { abort:
|
|
1218
|
-
this.#i.delete(e), this.#e({ type: "FILE_DONE", i: e }), this.#
|
|
1219
|
-
}).catch((
|
|
1353
|
+
this.#i.set(e, { abort: n }), i.then(() => {
|
|
1354
|
+
this.#i.delete(e), this.#e({ type: "FILE_DONE", i: e }), this.#n();
|
|
1355
|
+
}).catch((o) => {
|
|
1220
1356
|
this.#i.delete(e), this.#e({
|
|
1221
1357
|
type: "FILE_FAIL",
|
|
1222
1358
|
i: e,
|
|
1223
|
-
error:
|
|
1359
|
+
error: o?.status === 403 ? "expired" : "failed"
|
|
1224
1360
|
});
|
|
1225
1361
|
});
|
|
1226
1362
|
}
|
|
1227
|
-
async #
|
|
1363
|
+
async #Y(e) {
|
|
1228
1364
|
if (this._submit.files[e].error === "expired")
|
|
1229
1365
|
try {
|
|
1230
|
-
const [s] = await this.client.createUploads(
|
|
1366
|
+
const [s] = await this.client.createUploads(q({
|
|
1231
1367
|
formId: this._form.formId,
|
|
1232
1368
|
requestId: this.#t,
|
|
1233
|
-
files: [this.#
|
|
1369
|
+
files: [this.#g[e]]
|
|
1234
1370
|
}));
|
|
1235
1371
|
this.#e({ type: "REMINT_FILE", i: e, upload: s });
|
|
1236
1372
|
} catch (s) {
|
|
1237
|
-
this
|
|
1373
|
+
this.#$(s);
|
|
1238
1374
|
return;
|
|
1239
1375
|
}
|
|
1240
1376
|
else
|
|
1241
1377
|
this.#e({ type: "RETRY_FILE", i: e });
|
|
1242
|
-
this.#
|
|
1378
|
+
this.#S();
|
|
1243
1379
|
}
|
|
1244
|
-
async #
|
|
1380
|
+
async #H() {
|
|
1245
1381
|
try {
|
|
1246
|
-
const e = this._submit.files.map(({ assetId: s, type: i }) => ({ assetId: s, type: i })), t = await this.client.putRequest(this.#t,
|
|
1382
|
+
const e = this._submit.files.map(({ assetId: s, type: i }) => ({ assetId: s, type: i })), t = await this.client.putRequest(this.#t, Ae({
|
|
1247
1383
|
form: this._form,
|
|
1248
1384
|
steps: this._steps,
|
|
1249
1385
|
media: e
|
|
1250
1386
|
}));
|
|
1251
|
-
this.#e({ type: "REQUEST_OK", result: t }), this._result = t,
|
|
1387
|
+
this.#e({ type: "REQUEST_OK", result: t }), this._result = t, O(this.#p), this.client.endAnonSession?.(), this._phase = "done";
|
|
1252
1388
|
} catch (e) {
|
|
1253
|
-
this
|
|
1389
|
+
this.#$(e);
|
|
1254
1390
|
}
|
|
1255
1391
|
}
|
|
1256
|
-
|
|
1257
|
-
const t =
|
|
1392
|
+
#$(e) {
|
|
1393
|
+
const t = M(e?.status ?? 0, e?.body ?? null);
|
|
1258
1394
|
if (t.kind === "auth") {
|
|
1259
|
-
this.#e({ type: "AUTH_REQUIRED" }), this
|
|
1395
|
+
if (this.#e({ type: "AUTH_REQUIRED" }), this.#h) {
|
|
1396
|
+
this.#L();
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
this._gate = { stage: "email", email: "", error: "", loading: !1 };
|
|
1260
1400
|
return;
|
|
1261
1401
|
}
|
|
1262
1402
|
if (t.kind === "stale") {
|
|
1263
|
-
this._banner = t, this.#e({ type: "REQUEST_FAIL", error: t }), this.#
|
|
1403
|
+
this._banner = t, this.#e({ type: "REQUEST_FAIL", error: t }), this.#K();
|
|
1264
1404
|
return;
|
|
1265
1405
|
}
|
|
1266
1406
|
this._banner = t, this.#e({ type: "REQUEST_FAIL", error: t });
|
|
1267
1407
|
}
|
|
1268
|
-
async #
|
|
1408
|
+
async #K() {
|
|
1269
1409
|
try {
|
|
1270
1410
|
this._forms = await this.client.listForms();
|
|
1271
1411
|
const e = this._forms.find((t) => t.formId === this._form.formId);
|
|
@@ -1273,86 +1413,90 @@ class Qe extends I {
|
|
|
1273
1413
|
} catch {
|
|
1274
1414
|
}
|
|
1275
1415
|
}
|
|
1276
|
-
#
|
|
1277
|
-
this._banner = null, this.#e({ type: "REQUEST_START" }), this.#
|
|
1416
|
+
#Q() {
|
|
1417
|
+
this._banner = null, this.#e({ type: "REQUEST_START" }), this.#n();
|
|
1278
1418
|
}
|
|
1279
1419
|
// ── Render ──────────────────────────────────────────────────────
|
|
1280
1420
|
render() {
|
|
1281
|
-
return
|
|
1421
|
+
return a`
|
|
1282
1422
|
<div class="chat" aria-live="polite">
|
|
1283
|
-
${this.#
|
|
1423
|
+
${this.#G()}
|
|
1284
1424
|
</div>
|
|
1285
|
-
${this.#
|
|
1425
|
+
${this.#de()}
|
|
1286
1426
|
`;
|
|
1287
1427
|
}
|
|
1288
|
-
#
|
|
1428
|
+
#G() {
|
|
1289
1429
|
switch (this._phase) {
|
|
1290
1430
|
case "loading":
|
|
1291
|
-
return
|
|
1431
|
+
return I();
|
|
1292
1432
|
case "load-error":
|
|
1293
|
-
return
|
|
1433
|
+
return a`
|
|
1294
1434
|
${h("We could not load the forms.", "Check your connection and try again.", { error: !0 })}
|
|
1295
1435
|
<div class="options">
|
|
1296
|
-
<button type="button" class="chip" @click=${() => this.#
|
|
1436
|
+
<button type="button" class="chip" @click=${() => this.#w()}>Try again</button>
|
|
1297
1437
|
</div>
|
|
1298
1438
|
`;
|
|
1299
1439
|
case "pick":
|
|
1300
|
-
return this.#
|
|
1440
|
+
return this.#J();
|
|
1301
1441
|
case "walk":
|
|
1302
|
-
return
|
|
1442
|
+
return a`${this.#m()}${this._typing ? I() : this.#X()}`;
|
|
1303
1443
|
case "review":
|
|
1304
|
-
return
|
|
1444
|
+
return a`${this.#m()}${this.#T()}`;
|
|
1305
1445
|
case "submitting":
|
|
1306
|
-
return
|
|
1446
|
+
return a`${this.#m()}${this.#oe()}`;
|
|
1307
1447
|
case "done":
|
|
1308
|
-
return
|
|
1448
|
+
return a`${this.#m()}${this.#le()}`;
|
|
1309
1449
|
default:
|
|
1310
1450
|
return c;
|
|
1311
1451
|
}
|
|
1312
1452
|
}
|
|
1313
|
-
#
|
|
1453
|
+
#J() {
|
|
1314
1454
|
const e = this._forms;
|
|
1315
|
-
return
|
|
1455
|
+
return a`
|
|
1316
1456
|
${h(
|
|
1317
1457
|
"Welcome to Report It. What would you like to send us?",
|
|
1318
1458
|
"A few quick questions route your report to the right team."
|
|
1319
1459
|
)}
|
|
1320
1460
|
<div class="options" role="group" aria-label="What would you like to send us?">
|
|
1321
|
-
${e.map((t, s) =>
|
|
1461
|
+
${e.map((t, s) => a`
|
|
1322
1462
|
<button type="button" class="chip" style="animation-delay: ${60 + s * 50}ms"
|
|
1323
|
-
@click=${() => this.#
|
|
1463
|
+
@click=${() => this.#P(t)}>${t.title}</button>
|
|
1324
1464
|
`)}
|
|
1325
1465
|
</div>
|
|
1326
1466
|
`;
|
|
1327
1467
|
}
|
|
1328
|
-
#
|
|
1468
|
+
#m() {
|
|
1329
1469
|
const e = [];
|
|
1330
1470
|
this._form && (e.push(h(
|
|
1331
1471
|
"Welcome to Report It. What would you like to send us?",
|
|
1332
1472
|
"A few quick questions route your report to the right team.",
|
|
1333
1473
|
{ noAnim: !0 }
|
|
1334
|
-
)), e.push(
|
|
1474
|
+
)), e.push(_(this._form.title, { noAnim: !0 }))), this._notice && e.push(h(this._notice, "", { noAnim: !0 }));
|
|
1335
1475
|
for (const t of this._steps) {
|
|
1336
|
-
const s =
|
|
1337
|
-
s?.prompt && e.push(h(s.prompt, s.help, { noAnim: !0 })), s?.type === "gate" && e.push(h(
|
|
1476
|
+
const s = m(this._form, t.nodeId);
|
|
1477
|
+
s?.prompt && e.push(h(s.prompt, s.help, { noAnim: !0 })), s?.type === "gate" && e.push(t.anonymous ? h(
|
|
1478
|
+
"Last step: how can we reach you?",
|
|
1479
|
+
"You chose to send this anonymously.",
|
|
1480
|
+
{ noAnim: !0 }
|
|
1481
|
+
) : h(
|
|
1338
1482
|
"Last step: verify your email so we can follow up.",
|
|
1339
1483
|
"One address, one code. No password needed.",
|
|
1340
1484
|
{ noAnim: !0 }
|
|
1341
|
-
)), t.kind === "choice" && e.push(
|
|
1485
|
+
)), t.kind === "choice" && e.push(_(t.label || t.optionId, { noAnim: !0 })), t.kind === "collect" && e.push(_(t.summary || "Details provided", { noAnim: !0 })), t.kind === "gate" && e.push(_(t.anonymous ? "Send anonymously" : t.email, { noAnim: !0 }));
|
|
1342
1486
|
}
|
|
1343
1487
|
return e;
|
|
1344
1488
|
}
|
|
1345
|
-
#
|
|
1346
|
-
const { node: e, error: t } = this.#
|
|
1347
|
-
return t || !e ? h("Something went sideways with this form.", "Please start over.", { error: !0 }) : e.type === "choice" ? this.#
|
|
1489
|
+
#X() {
|
|
1490
|
+
const { node: e, error: t } = this.#x;
|
|
1491
|
+
return t || !e ? h("Something went sideways with this form.", "Please start over.", { error: !0 }) : e.type === "choice" ? this.#Z(e) : e.type === "collect" ? this.#ee(e) : e.type === "gate" ? this.#R(e) : e.type === "redirect" ? this.#ae(e) : e.type === "terminal" ? this.#T() : c;
|
|
1348
1492
|
}
|
|
1349
|
-
#
|
|
1350
|
-
return
|
|
1493
|
+
#Z(e) {
|
|
1494
|
+
return a`
|
|
1351
1495
|
${h(e.prompt, e.help)}
|
|
1352
1496
|
<div class="options" role="group" aria-label=${e.prompt || "Choose one"}>
|
|
1353
|
-
${(e.options || []).map((t, s) =>
|
|
1497
|
+
${(e.options || []).map((t, s) => a`
|
|
1354
1498
|
<button type="button" class="chip" style="animation-delay: ${60 + s * 50}ms"
|
|
1355
|
-
@click=${() => this.#
|
|
1499
|
+
@click=${() => this.#f({
|
|
1356
1500
|
nodeId: e.id,
|
|
1357
1501
|
kind: "choice",
|
|
1358
1502
|
optionId: t.id,
|
|
@@ -1362,61 +1506,61 @@ class Qe extends I {
|
|
|
1362
1506
|
</div>
|
|
1363
1507
|
`;
|
|
1364
1508
|
}
|
|
1365
|
-
#
|
|
1509
|
+
#ee(e) {
|
|
1366
1510
|
const t = e.fields || [];
|
|
1367
|
-
return
|
|
1511
|
+
return a`
|
|
1368
1512
|
${h(e.prompt, e.help)}
|
|
1369
1513
|
<div class="form-card">
|
|
1370
|
-
${t.map((s) => this.#
|
|
1371
|
-
<button type="button" class="btn-primary" @click=${() => this.#
|
|
1514
|
+
${t.map((s) => this.#te(e, s))}
|
|
1515
|
+
<button type="button" class="btn-primary" @click=${() => this.#q(e)}>
|
|
1372
1516
|
Continue
|
|
1373
1517
|
</button>
|
|
1374
1518
|
</div>
|
|
1375
1519
|
`;
|
|
1376
1520
|
}
|
|
1377
|
-
#
|
|
1378
|
-
const s = this._cardValues[t.key], i = this._fieldErrors[t.key],
|
|
1379
|
-
<label for="f-${t.key}">${t.label}${
|
|
1521
|
+
#te(e, t) {
|
|
1522
|
+
const s = this._cardValues[t.key], i = this._fieldErrors[t.key], n = !t.required && t.kind !== "consent" ? a` <span class="opt">optional</span>` : c, o = t.kind === "consent" ? c : a`
|
|
1523
|
+
<label for="f-${t.key}">${t.label}${n}</label>
|
|
1380
1524
|
`;
|
|
1381
|
-
return
|
|
1525
|
+
return a`
|
|
1382
1526
|
<div class="field">
|
|
1383
|
-
${
|
|
1384
|
-
${this.#
|
|
1385
|
-
${i ?
|
|
1527
|
+
${o}
|
|
1528
|
+
${this.#re(e, t, s)}
|
|
1529
|
+
${i ? a`<div class="err" role="alert">${i}</div>` : c}
|
|
1386
1530
|
</div>
|
|
1387
1531
|
`;
|
|
1388
1532
|
}
|
|
1389
|
-
#
|
|
1390
|
-
const i = (
|
|
1533
|
+
#re(e, t, s) {
|
|
1534
|
+
const i = (n) => (o) => this.#k(n, o.target.value);
|
|
1391
1535
|
switch (t.kind) {
|
|
1392
1536
|
case "text":
|
|
1393
|
-
return
|
|
1537
|
+
return a`<input type="text" id="f-${t.key}" .value=${s || ""}
|
|
1394
1538
|
placeholder=${t.placeholder || ""} @input=${i(t.key)}>`;
|
|
1395
1539
|
case "url":
|
|
1396
|
-
return
|
|
1540
|
+
return a`<input type="url" id="f-${t.key}" .value=${s || ""}
|
|
1397
1541
|
placeholder=${t.placeholder || ""} @input=${i(t.key)}>`;
|
|
1398
1542
|
case "textarea":
|
|
1399
|
-
return
|
|
1543
|
+
return a`<textarea id="f-${t.key}" .value=${s || ""}
|
|
1400
1544
|
placeholder=${t.placeholder || ""} @input=${i(t.key)}></textarea>`;
|
|
1401
1545
|
case "datetime":
|
|
1402
|
-
return
|
|
1546
|
+
return a`<input type="datetime-local" id="f-${t.key}" .value=${s || ""}
|
|
1403
1547
|
@input=${i(t.key)}>`;
|
|
1404
1548
|
case "select":
|
|
1405
|
-
return
|
|
1549
|
+
return a`
|
|
1406
1550
|
<select id="f-${t.key}" @change=${i(t.key)}>
|
|
1407
1551
|
<option value="">Choose one</option>
|
|
1408
|
-
${(t.options || []).map((
|
|
1409
|
-
<option value=${
|
|
1552
|
+
${(t.options || []).map((n) => a`
|
|
1553
|
+
<option value=${n.id} ?selected=${s === n.id}>${n.label}</option>
|
|
1410
1554
|
`)}
|
|
1411
1555
|
</select>
|
|
1412
1556
|
`;
|
|
1413
1557
|
case "location":
|
|
1414
|
-
return this.#
|
|
1558
|
+
return this.#se(t, s || {});
|
|
1415
1559
|
case "consent":
|
|
1416
|
-
return
|
|
1560
|
+
return a`
|
|
1417
1561
|
<div class="consent-row">
|
|
1418
1562
|
<input type="checkbox" id="f-${t.key}" .checked=${s === !0}
|
|
1419
|
-
@change=${(
|
|
1563
|
+
@change=${(n) => this.#k(t.key, n.target.checked)}>
|
|
1420
1564
|
<label for="f-${t.key}" style="all: unset; cursor: pointer;">
|
|
1421
1565
|
I took or own this material and give WRAL permission to use it
|
|
1422
1566
|
on air and online with credit to me.
|
|
@@ -1424,56 +1568,56 @@ class Qe extends I {
|
|
|
1424
1568
|
</div>
|
|
1425
1569
|
`;
|
|
1426
1570
|
case "media":
|
|
1427
|
-
return
|
|
1571
|
+
return a`
|
|
1428
1572
|
<wral-report-media
|
|
1429
1573
|
.files=${this.#r[e.id] || []}
|
|
1430
1574
|
.lostMeta=${this.#s[e.id] || []}
|
|
1431
1575
|
.budget=${this._form.budget || {}}
|
|
1432
1576
|
?required=${!!t.required}
|
|
1433
1577
|
label=${t.label}
|
|
1434
|
-
@files-changed=${(
|
|
1435
|
-
this.#r = { ...this.#r, [e.id]:
|
|
1578
|
+
@files-changed=${(n) => {
|
|
1579
|
+
this.#r = { ...this.#r, [e.id]: n.detail.files }, this.requestUpdate();
|
|
1436
1580
|
}}></wral-report-media>
|
|
1437
1581
|
`;
|
|
1438
1582
|
default:
|
|
1439
1583
|
return c;
|
|
1440
1584
|
}
|
|
1441
1585
|
}
|
|
1442
|
-
#
|
|
1443
|
-
const s = e.counties ||
|
|
1444
|
-
return
|
|
1586
|
+
#se(e, t) {
|
|
1587
|
+
const s = e.counties || Ne, i = (n) => this.#k(e.key, { ...t, ...n });
|
|
1588
|
+
return a`
|
|
1445
1589
|
<select id="f-${e.key}" aria-label="County"
|
|
1446
|
-
@change=${(
|
|
1590
|
+
@change=${(n) => i({ county: n.target.value || void 0 })}>
|
|
1447
1591
|
<option value="">Choose a county</option>
|
|
1448
|
-
${s.map((
|
|
1449
|
-
<option value=${
|
|
1592
|
+
${s.map((n) => a`
|
|
1593
|
+
<option value=${n} ?selected=${t.county === n}>${n}</option>
|
|
1450
1594
|
`)}
|
|
1451
1595
|
</select>
|
|
1452
1596
|
<input type="text" style="margin-top: 8px;"
|
|
1453
1597
|
aria-label="Nearest town or crossroads"
|
|
1454
1598
|
placeholder="Nearest town or crossroads"
|
|
1455
1599
|
.value=${t.where || ""}
|
|
1456
|
-
@input=${(
|
|
1600
|
+
@input=${(n) => i({ where: n.target.value || void 0 })}>
|
|
1457
1601
|
`;
|
|
1458
1602
|
}
|
|
1459
|
-
#
|
|
1460
|
-
this
|
|
1603
|
+
#R(e) {
|
|
1604
|
+
this.#I();
|
|
1461
1605
|
const t = this._gate, s = h(
|
|
1462
1606
|
"Last step: verify your email so we can follow up.",
|
|
1463
1607
|
"One address, one code. No password needed."
|
|
1464
1608
|
);
|
|
1465
|
-
return t.stage ? t.stage === "signedin" ?
|
|
1609
|
+
return t.stage ? t.stage === "signedin" ? a`
|
|
1466
1610
|
${s}
|
|
1467
1611
|
<div class="form-card">
|
|
1468
1612
|
<p style="margin: 0 0 12px; font-size: 14.5px;">
|
|
1469
1613
|
You are signed in as <strong>${t.email || "your My WRAL account"}</strong> on this device.
|
|
1470
1614
|
</p>
|
|
1471
1615
|
<button type="button" class="btn-primary"
|
|
1472
|
-
@click=${() => this.#
|
|
1616
|
+
@click=${() => this.#A(t.email)}>Continue</button>
|
|
1473
1617
|
<button type="button" class="btn-ghost"
|
|
1474
|
-
@click=${() => this.#
|
|
1618
|
+
@click=${() => this.#M()}>Use a different email</button>
|
|
1475
1619
|
</div>
|
|
1476
|
-
` : t.stage === "email" ?
|
|
1620
|
+
` : t.stage === "email" ? a`
|
|
1477
1621
|
${s}
|
|
1478
1622
|
<div class="form-card login-card">
|
|
1479
1623
|
<h2>Sign in or create account</h2>
|
|
@@ -1488,12 +1632,12 @@ class Qe extends I {
|
|
|
1488
1632
|
this._gate = { ...t, email: i.target.value };
|
|
1489
1633
|
}}
|
|
1490
1634
|
@keydown=${(i) => {
|
|
1491
|
-
i.key === "Enter" && this.#
|
|
1635
|
+
i.key === "Enter" && this.#_();
|
|
1492
1636
|
}}>
|
|
1493
1637
|
</div>
|
|
1494
|
-
${t.error ?
|
|
1638
|
+
${t.error ? a`<div class="err" role="alert">${t.error}</div>` : c}
|
|
1495
1639
|
<button type="button" class="login-btn" ?disabled=${t.loading}
|
|
1496
|
-
@click=${() => this.#
|
|
1640
|
+
@click=${() => this.#_()}>
|
|
1497
1641
|
${t.loading ? "Sending…" : "Continue with email"}
|
|
1498
1642
|
</button>
|
|
1499
1643
|
<div class="login-why">
|
|
@@ -1502,10 +1646,12 @@ class Qe extends I {
|
|
|
1502
1646
|
<li>We can follow up on your report</li>
|
|
1503
1647
|
<li>Your contact information fills in automatically next time</li>
|
|
1504
1648
|
<li>You are credited by name when we use your photos or video</li>
|
|
1649
|
+
<li><a href=${We} target="_blank" rel="noopener">All other My WRAL account benefits</a></li>
|
|
1505
1650
|
</ul>
|
|
1506
1651
|
</div>
|
|
1652
|
+
${this._submit.stage === "auth" ? c : this.#ie()}
|
|
1507
1653
|
</div>
|
|
1508
|
-
` :
|
|
1654
|
+
` : t.stage === "anon-confirm" ? this.#ne(s) : a`
|
|
1509
1655
|
${s}
|
|
1510
1656
|
<div class="form-card login-card">
|
|
1511
1657
|
<h2>Enter verification code</h2>
|
|
@@ -1519,27 +1665,71 @@ class Qe extends I {
|
|
|
1519
1665
|
<div class="field">
|
|
1520
1666
|
<label>Verification code</label>
|
|
1521
1667
|
<wral-code-input
|
|
1522
|
-
@code-complete=${(i) => this.#
|
|
1668
|
+
@code-complete=${(i) => this.#E(i.detail?.code ?? i.detail?.value ?? i.target.value)}>
|
|
1523
1669
|
</wral-code-input>
|
|
1524
1670
|
</div>
|
|
1525
|
-
${t.error ?
|
|
1671
|
+
${t.error ? a`<div class="err" role="alert">${t.error}</div>` : c}
|
|
1526
1672
|
<button type="button" class="login-btn" ?disabled=${t.loading}
|
|
1527
1673
|
@click=${() => {
|
|
1528
1674
|
const i = this.renderRoot.querySelector("wral-code-input");
|
|
1529
|
-
this.#
|
|
1675
|
+
this.#E(i?.value || "");
|
|
1530
1676
|
}}>
|
|
1531
1677
|
${t.loading ? "Checking…" : "Sign in"}
|
|
1532
1678
|
</button>
|
|
1533
1679
|
<p class="login-help">
|
|
1534
1680
|
Didn’t receive a code? Check your spam folder or
|
|
1535
|
-
<button type="button" @click=${() => this.#
|
|
1681
|
+
<button type="button" @click=${() => this.#_()}>resend a new code</button>.
|
|
1536
1682
|
</p>
|
|
1537
1683
|
</div>
|
|
1538
|
-
` :
|
|
1684
|
+
` : a`${s}${I()}`;
|
|
1685
|
+
}
|
|
1686
|
+
/* Collapsed by default: findable for whoever needs it, never the
|
|
1687
|
+
* first thing a viewer reaches for. */
|
|
1688
|
+
#ie() {
|
|
1689
|
+
return a`
|
|
1690
|
+
<details class="login-alt">
|
|
1691
|
+
<summary>Other ways to send this</summary>
|
|
1692
|
+
<div class="alt-body">
|
|
1693
|
+
<p class="alt-row">
|
|
1694
|
+
Call the newsroom desk at
|
|
1695
|
+
<a href=${Ye(L)}>${L}</a>.
|
|
1696
|
+
</p>
|
|
1697
|
+
${this.#z ? a`
|
|
1698
|
+
<p class="alt-row">
|
|
1699
|
+
<button type="button" class="alt-link"
|
|
1700
|
+
@click=${() => this.#U()}>Send this anonymously</button>
|
|
1701
|
+
— no follow-up, and no credit if we use your photos or video.
|
|
1702
|
+
</p>
|
|
1703
|
+
` : c}
|
|
1704
|
+
</div>
|
|
1705
|
+
</details>
|
|
1706
|
+
`;
|
|
1539
1707
|
}
|
|
1540
|
-
#
|
|
1708
|
+
#ne(e) {
|
|
1709
|
+
return a`
|
|
1710
|
+
${e}
|
|
1711
|
+
<div class="form-card login-card">
|
|
1712
|
+
<h2>Before you send anonymously</h2>
|
|
1713
|
+
<p class="login-sub">
|
|
1714
|
+
You can send this report without an account. Here is what it costs you.
|
|
1715
|
+
</p>
|
|
1716
|
+
<ul class="anon-costs">
|
|
1717
|
+
${Ve.map((t) => a`
|
|
1718
|
+
<li><span class="x" aria-hidden="true">✕</span><span>${t}</span></li>
|
|
1719
|
+
`)}
|
|
1720
|
+
</ul>
|
|
1721
|
+
<div class="anon-actions">
|
|
1722
|
+
<button type="button" class="login-btn"
|
|
1723
|
+
@click=${() => this.#O()}>Sign in instead</button>
|
|
1724
|
+
<button type="button" class="btn-ghost"
|
|
1725
|
+
@click=${() => this.#j()}>Continue anonymously</button>
|
|
1726
|
+
</div>
|
|
1727
|
+
</div>
|
|
1728
|
+
`;
|
|
1729
|
+
}
|
|
1730
|
+
#ae(e) {
|
|
1541
1731
|
const t = e.redirect || {};
|
|
1542
|
-
return
|
|
1732
|
+
return a`
|
|
1543
1733
|
<div class="form-card">
|
|
1544
1734
|
<p style="margin: 0 0 6px; font-weight: 600; font-size: 16px;
|
|
1545
1735
|
color: var(--wral-base-primary-1, #001D68);
|
|
@@ -1556,30 +1746,33 @@ class Qe extends I {
|
|
|
1556
1746
|
</div>
|
|
1557
1747
|
`;
|
|
1558
1748
|
}
|
|
1559
|
-
#
|
|
1560
|
-
const e =
|
|
1561
|
-
return
|
|
1749
|
+
#T() {
|
|
1750
|
+
const e = De(this._form, this._steps);
|
|
1751
|
+
return a`
|
|
1562
1752
|
${h("Here is what you are sending.", "Check it over, then submit.")}
|
|
1563
1753
|
<div class="form-card">
|
|
1564
1754
|
<ul class="review-list">
|
|
1565
|
-
${e.map((t) =>
|
|
1755
|
+
${e.map((t) => a`
|
|
1566
1756
|
<li>
|
|
1567
1757
|
<span class="k">${t.k}</span>
|
|
1568
|
-
<span>${t.pill ?
|
|
1758
|
+
<span>${t.pill ? ge(t.pill) : t.v}</span>
|
|
1569
1759
|
</li>
|
|
1570
1760
|
`)}
|
|
1571
1761
|
</ul>
|
|
1762
|
+
${this._banner ? a`
|
|
1763
|
+
<div class="err" role="alert" style="margin-top: 12px;">${this._banner.message}</div>
|
|
1764
|
+
` : c}
|
|
1572
1765
|
<div style="margin-top: 16px;">
|
|
1573
|
-
<button type="button" class="btn-primary" @click=${() => this.#
|
|
1766
|
+
<button type="button" class="btn-primary" @click=${() => this.#N()}>
|
|
1574
1767
|
Submit report
|
|
1575
1768
|
</button>
|
|
1576
1769
|
</div>
|
|
1577
1770
|
</div>
|
|
1578
1771
|
`;
|
|
1579
1772
|
}
|
|
1580
|
-
#
|
|
1773
|
+
#oe() {
|
|
1581
1774
|
const e = this._submit;
|
|
1582
|
-
if (e.stage === "auth") return this.#
|
|
1775
|
+
if (e.stage === "auth") return this.#R({ id: null, type: "gate" });
|
|
1583
1776
|
const t = {
|
|
1584
1777
|
minting: "Preparing your uploads…",
|
|
1585
1778
|
uploading: "Uploading your files…",
|
|
@@ -1587,10 +1780,10 @@ class Qe extends I {
|
|
|
1587
1780
|
requesting: "Sending your report…",
|
|
1588
1781
|
"requesting-error": this._banner?.message || "We could not send your report."
|
|
1589
1782
|
}[e.stage] || "Working…";
|
|
1590
|
-
return
|
|
1783
|
+
return a`
|
|
1591
1784
|
${h("Submitting your report.", t)}
|
|
1592
1785
|
<div class="form-card">
|
|
1593
|
-
${e.files.map((s, i) =>
|
|
1786
|
+
${e.files.map((s, i) => a`
|
|
1594
1787
|
<div class="upload-row">
|
|
1595
1788
|
<span class="name">${s.name}</span>
|
|
1596
1789
|
<div class="upload-bar" role="progressbar"
|
|
@@ -1601,62 +1794,63 @@ class Qe extends I {
|
|
|
1601
1794
|
<span class="state ${s.status === "failed" ? "failed" : ""}">
|
|
1602
1795
|
${s.status === "done" ? "Done" : s.status === "failed" ? "Failed" : "Uploading"}
|
|
1603
1796
|
</span>
|
|
1604
|
-
${s.status === "failed" ?
|
|
1605
|
-
<button type="button" class="retry-chip" @click=${() => this.#
|
|
1797
|
+
${s.status === "failed" ? a`
|
|
1798
|
+
<button type="button" class="retry-chip" @click=${() => this.#Y(i)}>
|
|
1606
1799
|
Retry
|
|
1607
1800
|
</button>
|
|
1608
1801
|
` : c}
|
|
1609
1802
|
</div>
|
|
1610
1803
|
`)}
|
|
1611
|
-
${e.stage === "requesting-error" ?
|
|
1804
|
+
${e.stage === "requesting-error" ? a`
|
|
1612
1805
|
<div class="err" role="alert">${this._banner?.message || ""}</div>
|
|
1613
|
-
${this._banner?.retryAfter ?
|
|
1806
|
+
${this._banner?.retryAfter ? a`
|
|
1614
1807
|
<div class="file-note">You can try again in about
|
|
1615
1808
|
${Math.ceil(this._banner.retryAfter / 60)} minutes.</div>
|
|
1616
1809
|
` : c}
|
|
1617
1810
|
<button type="button" class="btn-primary" style="margin-top: 8px;"
|
|
1618
|
-
@click=${() => this.#
|
|
1811
|
+
@click=${() => this.#Q()}>Try again</button>
|
|
1619
1812
|
` : c}
|
|
1620
|
-
${
|
|
1813
|
+
${j(e).length && e.stage === "uploading-error" ? a`
|
|
1621
1814
|
<div class="err" role="alert">Retry the failed
|
|
1622
|
-
${
|
|
1815
|
+
${j(e).length === 1 ? "file" : "files"} to continue.</div>
|
|
1623
1816
|
` : c}
|
|
1624
1817
|
</div>
|
|
1625
1818
|
`;
|
|
1626
1819
|
}
|
|
1627
|
-
#
|
|
1628
|
-
const e =
|
|
1820
|
+
#le() {
|
|
1821
|
+
const e = W(this._form, this._steps), t = ze(this._result, e), s = Be({
|
|
1629
1822
|
routing: this._result?.routing || {},
|
|
1630
1823
|
flags: e,
|
|
1631
|
-
reference: this._result?.reference || ""
|
|
1824
|
+
reference: this._result?.reference || "",
|
|
1825
|
+
anonymous: this.#h
|
|
1632
1826
|
});
|
|
1633
|
-
return
|
|
1827
|
+
return a`
|
|
1634
1828
|
<div class="confirm-card">
|
|
1635
1829
|
<div class="c-head">
|
|
1636
|
-
<div class="c-check">${
|
|
1830
|
+
<div class="c-check">${me()}</div>
|
|
1637
1831
|
<div>
|
|
1638
1832
|
<div class="eyebrow">Report received</div>
|
|
1639
1833
|
<h2>${t.title}</h2>
|
|
1640
1834
|
</div>
|
|
1641
1835
|
</div>
|
|
1642
1836
|
<p>${t.body}</p>
|
|
1643
|
-
${t.urgentNote ?
|
|
1837
|
+
${t.urgentNote ? a`<p>${t.urgentNote}</p>` : c}
|
|
1644
1838
|
<div class="refs">
|
|
1645
1839
|
<span class="ref"><span class="rk">Reference</span>${this._result?.reference || ""}</span>
|
|
1646
1840
|
</div>
|
|
1647
|
-
<button type="button" class="c-again" @click=${() => this.#
|
|
1841
|
+
<button type="button" class="c-again" @click=${() => this.#v()}>
|
|
1648
1842
|
Start a new report
|
|
1649
1843
|
</button>
|
|
1650
1844
|
</div>
|
|
1651
1845
|
<div class="journey">
|
|
1652
1846
|
<div class="j-eyebrow">Behind the scenes</div>
|
|
1653
1847
|
<div class="j-title">What happens to your report now</div>
|
|
1654
|
-
${s.map((i,
|
|
1848
|
+
${s.map((i, n) => a`
|
|
1655
1849
|
<div class="j-step">
|
|
1656
|
-
<div class="j-dot">${
|
|
1850
|
+
<div class="j-dot">${n + 1}</div>
|
|
1657
1851
|
<div class="j-body">
|
|
1658
1852
|
<div class="j-t">${i.title}
|
|
1659
|
-
${i.pill ?
|
|
1853
|
+
${i.pill ? a` <span class="flag-pill urgent">${i.pill}</span>` : c}
|
|
1660
1854
|
</div>
|
|
1661
1855
|
<div class="j-d">${i.body}</div>
|
|
1662
1856
|
</div>
|
|
@@ -1665,15 +1859,15 @@ class Qe extends I {
|
|
|
1665
1859
|
</div>
|
|
1666
1860
|
`;
|
|
1667
1861
|
}
|
|
1668
|
-
#
|
|
1862
|
+
#de() {
|
|
1669
1863
|
const e = this._phase === "submitting" || this._phase === "done" || this._phase === "loading" || this._phase === "load-error";
|
|
1670
|
-
return
|
|
1864
|
+
return a`
|
|
1671
1865
|
<div class="bottom-bar">
|
|
1672
1866
|
<div class="inner">
|
|
1673
1867
|
<button type="button" class="btn-ghost" ?disabled=${e || this._phase === "pick"}
|
|
1674
|
-
@click=${() => this.#
|
|
1868
|
+
@click=${() => this.#B()}>← Back</button>
|
|
1675
1869
|
<button type="button" class="btn-ghost" ?disabled=${this._phase === "submitting"}
|
|
1676
|
-
@click=${() => this.#
|
|
1870
|
+
@click=${() => this.#v()}>Start over</button>
|
|
1677
1871
|
<span class="note">Your report goes to a person on the right desk.</span>
|
|
1678
1872
|
</div>
|
|
1679
1873
|
</div>
|
|
@@ -1683,7 +1877,7 @@ class Qe extends I {
|
|
|
1683
1877
|
this.renderRoot?.querySelector(".chat")?.lastElementChild?.scrollIntoView?.({ block: "nearest" });
|
|
1684
1878
|
}
|
|
1685
1879
|
}
|
|
1686
|
-
class
|
|
1880
|
+
class st extends A {
|
|
1687
1881
|
static properties = {
|
|
1688
1882
|
files: { attribute: !1 },
|
|
1689
1883
|
lostMeta: { attribute: !1 },
|
|
@@ -1691,7 +1885,7 @@ class Ge extends I {
|
|
|
1691
1885
|
required: { type: Boolean },
|
|
1692
1886
|
label: { type: String }
|
|
1693
1887
|
};
|
|
1694
|
-
static styles =
|
|
1888
|
+
static styles = f`
|
|
1695
1889
|
:host { display: block; }
|
|
1696
1890
|
input[type=file] { font-family: inherit; font-size: 14px; }
|
|
1697
1891
|
.file-list { margin: 8px 0 0; padding: 0; list-style: none; font-size: 13.5px; }
|
|
@@ -1713,7 +1907,7 @@ class Ge extends I {
|
|
|
1713
1907
|
constructor() {
|
|
1714
1908
|
super(), this.files = [], this.lostMeta = [], this.budget = {}, this.required = !1, this.label = "Photos or video";
|
|
1715
1909
|
}
|
|
1716
|
-
get #
|
|
1910
|
+
get #l() {
|
|
1717
1911
|
return (this.budget?.allowedTypes || []).join(",");
|
|
1718
1912
|
}
|
|
1719
1913
|
#a(e) {
|
|
@@ -1732,18 +1926,18 @@ class Ge extends I {
|
|
|
1732
1926
|
t.splice(e, 1), this.#a(t);
|
|
1733
1927
|
}
|
|
1734
1928
|
render() {
|
|
1735
|
-
const e = this.files || [], { errors: t } =
|
|
1736
|
-
return
|
|
1929
|
+
const e = this.files || [], { errors: t } = E(e, this.budget, { required: !1 });
|
|
1930
|
+
return a`
|
|
1737
1931
|
<input type="file" multiple
|
|
1738
|
-
accept=${this.#
|
|
1932
|
+
accept=${this.#l || c}
|
|
1739
1933
|
aria-label=${this.label}
|
|
1740
1934
|
@change=${this.#u}>
|
|
1741
|
-
${e.length ?
|
|
1935
|
+
${e.length ? a`
|
|
1742
1936
|
<ul class="file-list">
|
|
1743
|
-
${e.map((s, i) =>
|
|
1937
|
+
${e.map((s, i) => a`
|
|
1744
1938
|
<li>
|
|
1745
1939
|
<span>${s.name}</span>
|
|
1746
|
-
<span class="size">${
|
|
1940
|
+
<span class="size">${Ge(s.size)}</span>
|
|
1747
1941
|
<button type="button" class="remove"
|
|
1748
1942
|
aria-label="Remove ${s.name}"
|
|
1749
1943
|
@click=${() => this.#t(i)}>✕</button>
|
|
@@ -1751,50 +1945,50 @@ class Ge extends I {
|
|
|
1751
1945
|
`)}
|
|
1752
1946
|
</ul>
|
|
1753
1947
|
` : c}
|
|
1754
|
-
${(this.lostMeta || []).length ?
|
|
1948
|
+
${(this.lostMeta || []).length ? a`
|
|
1755
1949
|
<div class="lost">
|
|
1756
1950
|
Please re-attach your ${this.lostMeta.length === 1 ? "file" : "files"}
|
|
1757
1951
|
(${this.lostMeta.map((s) => s.name).join(", ")}) —
|
|
1758
1952
|
attachments can't be saved between visits.
|
|
1759
1953
|
</div>
|
|
1760
1954
|
` : c}
|
|
1761
|
-
${t.map((s) =>
|
|
1955
|
+
${t.map((s) => a`<div class="err">${s.message}</div>`)}
|
|
1762
1956
|
`;
|
|
1763
1957
|
}
|
|
1764
1958
|
}
|
|
1765
|
-
function
|
|
1959
|
+
function Ge(r) {
|
|
1766
1960
|
return Number.isFinite(r) ? r >= 1024 * 1024 ? `${(r / (1024 * 1024)).toFixed(1)} MB` : r >= 1024 ? `${Math.round(r / 1024)} KB` : `${r} B` : "";
|
|
1767
1961
|
}
|
|
1768
|
-
const
|
|
1769
|
-
const i = e.target.value.replace(/\D/g, "").slice(-1),
|
|
1770
|
-
|
|
1771
|
-
const
|
|
1772
|
-
return s("code-change", { value:
|
|
1773
|
-
},
|
|
1962
|
+
const Je = (r, e, t, s) => {
|
|
1963
|
+
const i = e.target.value.replace(/\D/g, "").slice(-1), n = [...t];
|
|
1964
|
+
n[r] = i;
|
|
1965
|
+
const o = n.join(""), l = n.every((d) => d !== "");
|
|
1966
|
+
return s("code-change", { value: o, complete: l }), i && l && s("code-complete", { value: o }), n;
|
|
1967
|
+
}, Xe = (r, e, t, s) => {
|
|
1774
1968
|
if (e.key === "Backspace") {
|
|
1775
1969
|
const i = [...t];
|
|
1776
1970
|
!i[r] && r > 0 ? i[r - 1] = "" : i[r] && (i[r] = "");
|
|
1777
|
-
const
|
|
1778
|
-
return s("code-change", { value:
|
|
1971
|
+
const n = i.join("");
|
|
1972
|
+
return s("code-change", { value: n, complete: !1 }), i;
|
|
1779
1973
|
}
|
|
1780
1974
|
return t;
|
|
1781
|
-
},
|
|
1975
|
+
}, Ze = (r, e, t) => {
|
|
1782
1976
|
r.preventDefault();
|
|
1783
1977
|
const s = r.clipboardData.getData("text").replace(/\D/g, "").slice(0, 6);
|
|
1784
1978
|
if (s.length === 0) return e;
|
|
1785
1979
|
const i = [...e];
|
|
1786
|
-
for (let
|
|
1787
|
-
i[
|
|
1788
|
-
const
|
|
1789
|
-
return t("code-change", { value:
|
|
1980
|
+
for (let l = 0; l < s.length && l < 6; l++)
|
|
1981
|
+
i[l] = s[l];
|
|
1982
|
+
const n = i.join(""), o = i.every((l) => l !== "");
|
|
1983
|
+
return t("code-change", { value: n, complete: o }), s.length === 6 && t("code-complete", { value: n }), i;
|
|
1790
1984
|
};
|
|
1791
|
-
class
|
|
1985
|
+
class it extends A {
|
|
1792
1986
|
static formAssociated = !0;
|
|
1793
1987
|
static properties = {
|
|
1794
1988
|
_values: { type: Array, state: !0 },
|
|
1795
1989
|
disabled: { type: Boolean, reflect: !0 }
|
|
1796
1990
|
};
|
|
1797
|
-
static styles =
|
|
1991
|
+
static styles = f`
|
|
1798
1992
|
:host {
|
|
1799
1993
|
display: block;
|
|
1800
1994
|
width: 100%;
|
|
@@ -1893,7 +2087,7 @@ class Je extends I {
|
|
|
1893
2087
|
this.getInputs()[e]?.focus();
|
|
1894
2088
|
}
|
|
1895
2089
|
inputHandler(e, t) {
|
|
1896
|
-
this._values =
|
|
2090
|
+
this._values = Je(
|
|
1897
2091
|
e,
|
|
1898
2092
|
t,
|
|
1899
2093
|
this._values,
|
|
@@ -1903,7 +2097,7 @@ class Je extends I {
|
|
|
1903
2097
|
keydownHandler(e, t) {
|
|
1904
2098
|
if (t.key === "Backspace") {
|
|
1905
2099
|
const s = !this._values[e];
|
|
1906
|
-
this._values =
|
|
2100
|
+
this._values = Xe(
|
|
1907
2101
|
e,
|
|
1908
2102
|
t,
|
|
1909
2103
|
this._values,
|
|
@@ -1912,12 +2106,12 @@ class Je extends I {
|
|
|
1912
2106
|
}
|
|
1913
2107
|
}
|
|
1914
2108
|
pasteHandler(e) {
|
|
1915
|
-
this._values =
|
|
2109
|
+
this._values = Ze(e, this._values, this.dispatchCustomEvent.bind(this));
|
|
1916
2110
|
}
|
|
1917
2111
|
render() {
|
|
1918
|
-
return
|
|
2112
|
+
return a`
|
|
1919
2113
|
<div class="code-inputs">
|
|
1920
|
-
${[0, 1, 2, 3, 4, 5].map((e) =>
|
|
2114
|
+
${[0, 1, 2, 3, 4, 5].map((e) => a`
|
|
1921
2115
|
<input
|
|
1922
2116
|
type = "text"
|
|
1923
2117
|
inputmode = "numeric"
|
|
@@ -1937,10 +2131,10 @@ class Je extends I {
|
|
|
1937
2131
|
}
|
|
1938
2132
|
}
|
|
1939
2133
|
export {
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
2134
|
+
it as W,
|
|
2135
|
+
st as a,
|
|
2136
|
+
rt as b,
|
|
2137
|
+
ye as c,
|
|
2138
|
+
be as d,
|
|
2139
|
+
we as e
|
|
1946
2140
|
};
|