Skip to content

Commit f198650

Browse files
committed
Fix status URL query param handling in my-data form
1 parent aeb4394 commit f198650

4 files changed

Lines changed: 48 additions & 57 deletions

File tree

‎src/components/Forms/Privacy/client/__tests__/index.spec.ts‎

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,7 @@ describe('PrivacyForm behavior', () => {
5151
container,
5252
component: PrivacyForm,
5353
moduleSpecifier: '@components/Forms/Privacy/client/index',
54-
args: {
55-
props: {
56-
status: undefined,
57-
},
58-
},
54+
args: {},
5955
waitForReady: async (element: PrivacyFormElementInstance) => {
6056
window.history.replaceState({}, '', 'http://localhost/privacy/my-data')
6157
element.initialize()
@@ -83,11 +79,7 @@ describe('PrivacyForm behavior', () => {
8379
container,
8480
component: PrivacyForm,
8581
moduleSpecifier: '@components/Forms/Privacy/client/index',
86-
args: {
87-
props: {
88-
status: undefined,
89-
},
90-
},
82+
args: {},
9183
waitForReady: async (element: PrivacyFormElementInstance) => {
9284
window.history.replaceState({}, '', 'http://localhost/privacy/my-data')
9385
element.initialize()
@@ -119,11 +111,7 @@ describe('PrivacyForm behavior', () => {
119111
container,
120112
component: PrivacyForm,
121113
moduleSpecifier: '@components/Forms/Privacy/client/index',
122-
args: {
123-
props: {
124-
status: undefined,
125-
},
126-
},
114+
args: {},
127115
waitForReady: async (element: PrivacyFormElementInstance) => {
128116
window.history.replaceState({}, '', 'http://localhost/privacy/my-data?token=unit-test-token')
129117
;(element as unknown as { downloadJson: typeof downloadJsonSpy }).downloadJson = downloadJsonSpy

‎src/components/Forms/Privacy/client/index.ts‎

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,28 @@ type DsarVerifyResult =
1616

1717
type RequestDataResult = { message: string }
1818

19+
const statusMessages: Record<string, { type: MessageType; message: string }> = {
20+
sent: {
21+
type: 'success',
22+
message:
23+
'Verification email sent! Please check your inbox and click the link to complete your request.',
24+
},
25+
invalid: {
26+
type: 'error',
27+
message: 'Invalid or expired verification link. Please submit a new request.',
28+
},
29+
expired: {
30+
type: 'error',
31+
message: 'This verification link has expired. Please submit a new request.',
32+
},
33+
'already-completed': { type: 'info', message: 'This request has already been completed.' },
34+
deleted: {
35+
type: 'success',
36+
message: 'Your data has been successfully deleted from our systems.',
37+
},
38+
error: { type: 'error', message: 'An error occurred. Please try again or contact support.' },
39+
}
40+
1941
export class PrivacyFormElement extends LitElement {
2042
static readonly registeredName = 'privacy-form'
2143

@@ -67,7 +89,7 @@ export class PrivacyFormElement extends LitElement {
6789
this.bindEvents()
6890
this.isInitialized = true
6991

70-
this.focusStatusMessage()
92+
this.renderStatusFromQueryString()
7193
void this.handleVerificationToken()
7294
} catch (error) {
7395
handleScriptError(error, context)
@@ -114,12 +136,6 @@ export class PrivacyFormElement extends LitElement {
114136
})
115137
}
116138

117-
private focusStatusMessage(): void {
118-
if (this.statusMessage) {
119-
this.statusMessage.focus()
120-
}
121-
}
122-
123139
private setMessage(target: HTMLElement, message: string, type: MessageType): void {
124140
target.setAttribute('role', type === 'error' ? 'alert' : 'status')
125141
target.setAttribute('aria-live', type === 'error' ? 'assertive' : 'polite')
@@ -154,6 +170,18 @@ export class PrivacyFormElement extends LitElement {
154170
target.focus()
155171
}
156172

173+
private renderStatusFromQueryString(): void {
174+
if (!this.statusMessage) return
175+
176+
const status = new URLSearchParams(window.location.search).get('status')
177+
if (!status) return
178+
179+
const statusMessage = statusMessages[status]
180+
if (!statusMessage) return
181+
182+
this.setMessage(this.statusMessage, statusMessage.message, statusMessage.type)
183+
}
184+
157185
private resolveTokenFromQueryString(): string {
158186
const params = new URLSearchParams(window.location.search)
159187
return params.get('token') ?? ''

‎src/components/Forms/Privacy/index.astro‎

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
---
2-
import { statusMessages } from '@components/Forms/Privacy/server'
3-
4-
export interface Props {
5-
status?: string | null
6-
}
7-
8-
const { status } = Astro.props
9-
const statusMessage = status ? statusMessages[status] : undefined
102
---
113

12-
<privacy-form class="block" status={status ?? undefined}>
4+
<privacy-form class="block">
135
<div class="container mx-auto px-4 py-16 max-w-5xl space-y-10">
146
<header class="space-y-3">
157
<h1 class="text-3xl md:text-4xl font-bold">My Data &amp; Privacy Rights</h1>
@@ -18,25 +10,14 @@ const statusMessage = status ? statusMessages[status] : undefined
1810
</p>
1911
</header>
2012

21-
{
22-
statusMessage && (
23-
<div
24-
id="status-message"
25-
tabindex="-1"
26-
role={statusMessage.type === 'error' ? 'alert' : 'status'}
27-
aria-live={statusMessage.type === 'error' ? 'assertive' : 'polite'}
28-
aria-atomic="true"
29-
class:list={[
30-
'rounded-xl border px-4 py-3 text-sm',
31-
statusMessage.type === 'success' && 'border-success bg-success-inverse text-success',
32-
statusMessage.type === 'error' && 'border-danger bg-danger-offset text-danger',
33-
statusMessage.type === 'info' && 'border-info bg-info-inverse text-info',
34-
]}
35-
>
36-
{statusMessage.message}
37-
</div>
38-
)
39-
}
13+
<div
14+
id="status-message"
15+
tabindex="-1"
16+
role="status"
17+
aria-live="polite"
18+
aria-atomic="true"
19+
class="hidden rounded-xl border px-4 py-3 text-sm"
20+
></div>
4021

4122
<section class="bg-page-offset border border-trim rounded-2xl p-6" aria-labelledby="my-data-intro-title">
4223
<h2 class="sr-only" id="my-data-intro-title">Overview</h2>

‎src/pages/privacy/my-data.astro‎

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,9 @@ const pageTitle = 'My Data - Privacy Rights'
55
const path = 'privacy/my-data'
66
const description =
77
'Exercise your GDPR rights by requesting a copy of your data or asking us to delete it.'
8-
9-
// Get status from query params
10-
const status = Astro.url.searchParams.get('status')
118
---
129

1310
<BaseLayout pageTitle={pageTitle} path={path} description={description}>
14-
<PrivacyForm {status} />
11+
<PrivacyForm />
1512
</BaseLayout>
1613

17-
18-
19-

0 commit comments

Comments
 (0)