payload-subscribers-plugin 0.0.6 → 0.0.8
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 +112 -21
- package/dist/components/app/RequestMagicLink.d.ts +13 -1
- package/dist/components/app/RequestMagicLink.js +18 -4
- package/dist/components/app/RequestMagicLink.js.map +1 -1
- package/dist/components/app/RequestOrSubscribe.d.ts +21 -5
- package/dist/components/app/RequestOrSubscribe.js +18 -4
- package/dist/components/app/RequestOrSubscribe.js.map +1 -1
- package/dist/components/app/SelectOptInChannels.d.ts +9 -0
- package/dist/components/app/SelectOptInChannels.js +7 -1
- package/dist/components/app/SelectOptInChannels.js.map +1 -1
- package/dist/components/app/Subscribe.d.ts +12 -1
- package/dist/components/app/Subscribe.js +22 -4
- package/dist/components/app/Subscribe.js.map +1 -1
- package/dist/components/app/SubscriberMenu.d.ts +16 -3
- package/dist/components/app/SubscriberMenu.js +26 -17
- package/dist/components/app/SubscriberMenu.js.map +1 -1
- package/dist/components/app/VerifyMagicLink.d.ts +14 -2
- package/dist/components/app/VerifyMagicLink.js +23 -22
- package/dist/components/app/VerifyMagicLink.js.map +1 -1
- package/dist/components/app/helpers.d.ts +8 -0
- package/dist/components/app/helpers.js +8 -1
- package/dist/components/app/helpers.js.map +1 -1
- package/dist/components/app/shared.module.css +10 -1
- package/dist/contexts/SubscriberProvider.d.ts +16 -0
- package/dist/contexts/SubscriberProvider.js +14 -3
- package/dist/contexts/SubscriberProvider.js.map +1 -1
- package/dist/endpoints/getOptInChannels.d.ts +6 -2
- package/dist/endpoints/getOptInChannels.js +6 -2
- package/dist/endpoints/getOptInChannels.js.map +1 -1
- package/dist/endpoints/logout.d.ts +5 -5
- package/dist/endpoints/logout.js +6 -8
- package/dist/endpoints/logout.js.map +1 -1
- package/dist/endpoints/requestMagicLink.d.ts +5 -5
- package/dist/endpoints/requestMagicLink.js +14 -17
- package/dist/endpoints/requestMagicLink.js.map +1 -1
- package/dist/endpoints/subscribe.d.ts +6 -5
- package/dist/endpoints/subscribe.js +21 -23
- package/dist/endpoints/subscribe.js.map +1 -1
- package/dist/endpoints/subscriberAuth.d.ts +5 -5
- package/dist/endpoints/subscriberAuth.js +11 -12
- package/dist/endpoints/subscriberAuth.js.map +1 -1
- package/dist/endpoints/verifyMagicLink.d.ts +5 -5
- package/dist/endpoints/verifyMagicLink.js +11 -13
- package/dist/endpoints/verifyMagicLink.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
A plugin to manage subscribers and the "channels" they can subscribe to.
|
|
4
4
|
|
|
5
5
|
This includes ways to allow your subscribers to:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
|
|
7
|
+
- Sign up or sign in by requesting a magic link email
|
|
8
|
+
- Verify the magic link to authenticate
|
|
9
|
+
- Opt in or out of "opt-in channels"
|
|
9
10
|
|
|
10
11
|
You manage the opt-in channels via the Payload admin.
|
|
11
12
|
|
|
12
13
|
The plugin relies on your email adapter configured in your payload config to send emails.
|
|
13
14
|
|
|
14
|
-
That is all this plugin does currently. Potential features might include email authoring and send scheduler or simple CRM features.
|
|
15
|
-
|
|
15
|
+
That is all this plugin does currently. Potential features might include email authoring and send scheduler or simple CRM features.
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
@@ -44,7 +44,7 @@ export default buildConfig({
|
|
|
44
44
|
// Specify the collection to use as the subscribers collection
|
|
45
45
|
// - Optional. If not specified, the plugin will add a 'subscribers' collection.
|
|
46
46
|
// - Sets auth if not already
|
|
47
|
-
// - Adds (or overrides) fields: email, firstName, status, optIns,
|
|
47
|
+
// - Adds (or overrides) fields: email, firstName, status, optIns,
|
|
48
48
|
// verificationToken, verificationTokenExpires, and source
|
|
49
49
|
subscribersCollectionSlug?: CollectionSlug
|
|
50
50
|
|
|
@@ -202,7 +202,9 @@ Shows the [Subscribe](#subscribe) component to authenticated subscribers, otherw
|
|
|
202
202
|
</div> -->
|
|
203
203
|
|
|
204
204
|
```typescript
|
|
205
|
-
<
|
|
205
|
+
<RequestOrSubscribe
|
|
206
|
+
// Provide the URL the user should go to after clicking the link in the email and having it verified
|
|
207
|
+
afterVerifyUrl={new URL(window.href)}
|
|
206
208
|
// Provide your own global class names to add to the component elements. Optional
|
|
207
209
|
classNames={{
|
|
208
210
|
button: 'customCssClassNames',
|
|
@@ -224,6 +226,8 @@ Shows the [Subscribe](#subscribe) component to authenticated subscribers, otherw
|
|
|
224
226
|
{text}
|
|
225
227
|
</button>
|
|
226
228
|
}
|
|
229
|
+
// Provide the URL to your route that has the VerifyMagicLink component on it.
|
|
230
|
+
verifyUrl={verifyUrl}
|
|
227
231
|
/>
|
|
228
232
|
```
|
|
229
233
|
|
|
@@ -235,6 +239,8 @@ Form to input email address and get a magic link email sent.
|
|
|
235
239
|
|
|
236
240
|
```typescript
|
|
237
241
|
<RequestMagicLink
|
|
242
|
+
// Provide the URL the user should go to after clicking the link in the email and having it verified
|
|
243
|
+
afterVerifyUrl={new URL(window.href)}
|
|
238
244
|
// Provide your own global class names to add to the component elements. Optional
|
|
239
245
|
classNames={{
|
|
240
246
|
button: 'customCssClassNames',
|
|
@@ -252,9 +258,22 @@ Form to input email address and get a magic link email sent.
|
|
|
252
258
|
{text}
|
|
253
259
|
</button>
|
|
254
260
|
}
|
|
261
|
+
// Provide the URL to your route that has the VerifyMagicLink component on it.
|
|
262
|
+
verifyUrl={verifyUrl}
|
|
255
263
|
/>
|
|
256
264
|
```
|
|
257
265
|
|
|
266
|
+
```html
|
|
267
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
268
|
+
<div class="subscribers-request subscribers-container">
|
|
269
|
+
<p class="subscribers-message subscribers-error">{result}</p>
|
|
270
|
+
<form class="subscribers-form">
|
|
271
|
+
<input class="subscribers-emailInput" type="email" />
|
|
272
|
+
<button class="subscribers-button">Request magic link</button>
|
|
273
|
+
</form>
|
|
274
|
+
</div>
|
|
275
|
+
```
|
|
276
|
+
|
|
258
277
|
#### **VerifyMagicLink**
|
|
259
278
|
|
|
260
279
|
Component that verifies a magic link using expected url parameters.
|
|
@@ -277,20 +296,37 @@ Component that verifies a magic link using expected url parameters.
|
|
|
277
296
|
// Called after a magic link has been verified. Optional
|
|
278
297
|
handleMagicLinkVerified={async (result: RequestMagicLinkResponse) => {}}
|
|
279
298
|
// Provided your own button component. Optional
|
|
280
|
-
renderButton={({ name,
|
|
281
|
-
forwardUrl ? (
|
|
282
|
-
<a href={forwardUrl}>
|
|
283
|
-
<button name={name} type="button">
|
|
284
|
-
{text}
|
|
285
|
-
</button>
|
|
286
|
-
</a>
|
|
287
|
-
) : (
|
|
299
|
+
renderButton={({ name, onClick, text }) =>
|
|
288
300
|
<button name={name} onClick={onClick} type="button">
|
|
289
301
|
{text}
|
|
290
302
|
</button>
|
|
291
|
-
)
|
|
292
303
|
}
|
|
293
|
-
|
|
304
|
+
// Provide the URL to your route that has the VerifyMagicLink component on it.
|
|
305
|
+
// Used when this VerifyMagicLink component provides an option to request another link
|
|
306
|
+
// when verifying the current one fails.
|
|
307
|
+
verifyUrl={verifyUrl}
|
|
308
|
+
>
|
|
309
|
+
// Provide children to render after link is verified. Optional
|
|
310
|
+
// Since you provide the verifyUrl to any of the plugin components, you can include a forwardUrl
|
|
311
|
+
// as a search param, which your route can then use here.
|
|
312
|
+
<a href={forwardUrl}>
|
|
313
|
+
<button className={'customCss'} name={'continue'} type="button">
|
|
314
|
+
Continue
|
|
315
|
+
</button>
|
|
316
|
+
</a>
|
|
317
|
+
</VerifyMagicLink>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
```html
|
|
321
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
322
|
+
<div class="subscribers-verify subscribers-container">
|
|
323
|
+
<p class="subscribers-loading">verifying...</p>
|
|
324
|
+
<p class="subscribers-message">{result}</p>
|
|
325
|
+
<div class="subscribers-form">
|
|
326
|
+
{renderButton({ name: "request", onClick: handleRequestAnother, text:"Request another magic
|
|
327
|
+
link", })} {children}
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
294
330
|
```
|
|
295
331
|
|
|
296
332
|
#### **Subscribe**
|
|
@@ -301,6 +337,8 @@ Allows a subscriber to select from among all active optInChannels.
|
|
|
301
337
|
|
|
302
338
|
```typescript
|
|
303
339
|
<Subscribe
|
|
340
|
+
// Provide the URL the user should go to after clicking the link in the email and having it verified
|
|
341
|
+
afterVerifyUrl={new URL(window.href)}
|
|
304
342
|
// Provide your own global class names to add to the component elements. Optional
|
|
305
343
|
classNames={{
|
|
306
344
|
button: 'customCssClassNames',
|
|
@@ -320,9 +358,43 @@ Allows a subscriber to select from among all active optInChannels.
|
|
|
320
358
|
{text}
|
|
321
359
|
</button>
|
|
322
360
|
}
|
|
361
|
+
// Provide the URL to your route that has the VerifyMagicLink component on it.
|
|
362
|
+
verifyUrl={verifyUrl}
|
|
323
363
|
/>
|
|
324
364
|
```
|
|
325
365
|
|
|
366
|
+
```html
|
|
367
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
368
|
+
<div class="subscribers-subscribe subscribers-container">
|
|
369
|
+
<h2>Subscribe</h2>
|
|
370
|
+
<div class="subscribers-section">
|
|
371
|
+
<!-- START: SelectOptInChannels -->
|
|
372
|
+
<div class="subscribers-container">
|
|
373
|
+
<h3>Opt-in Channels</h3>
|
|
374
|
+
<p class="subscribers-loading">verifying...</p>
|
|
375
|
+
<div class="subscribers-optionsGroup">
|
|
376
|
+
<!-- START: FOR EACH CHANNEL -->
|
|
377
|
+
<div class="subscribers-optInCheckboxItem">
|
|
378
|
+
<label class="subscribers-optInCheckboxLabel" ,>
|
|
379
|
+
<input class="subscribers-optInCheckbox" type="checkbox" />
|
|
380
|
+
{channel.title}
|
|
381
|
+
</label>
|
|
382
|
+
</div>
|
|
383
|
+
<!-- END: FOR EACH CHANNEL -->
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
<!-- END: SelectOptInChannels -->
|
|
387
|
+
</div>
|
|
388
|
+
<form class="subscribers-form">
|
|
389
|
+
<div class="subscribers-section">
|
|
390
|
+
<input class="subscribers-emailInput" placeholder="enter your email" type="email" />
|
|
391
|
+
<button class="subscribers-button" type="submit">Save choices</button>
|
|
392
|
+
</div>
|
|
393
|
+
</form>
|
|
394
|
+
<p class="subscribers-message subscribers-error">{result}</p>
|
|
395
|
+
</div>
|
|
396
|
+
```
|
|
397
|
+
|
|
326
398
|
#### **SubscriberMenu**
|
|
327
399
|
|
|
328
400
|
A simple user menu, most useful for testing. Seen in the screenshots above. Includes a "welcome" message, a link to a /subscribe route, and a log out button.
|
|
@@ -330,10 +402,29 @@ A simple user menu, most useful for testing. Seen in the screenshots above. Incl
|
|
|
330
402
|
```typescript
|
|
331
403
|
// classNames prop
|
|
332
404
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
405
|
+
<SubscriberMenu
|
|
406
|
+
classNames={{
|
|
407
|
+
button: 'customCssClassNames',
|
|
408
|
+
container: 'customCssClassNames',
|
|
409
|
+
}}
|
|
410
|
+
subscribeUrl={new URL('/subscribe', serverURL)}
|
|
411
|
+
/>
|
|
412
|
+
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
```html
|
|
416
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
417
|
+
<div class="subscribers-menu subscribers-container">
|
|
418
|
+
<div class="subscribers-group">
|
|
419
|
+
<div class="subscribers-welcome">Welcome, {subscriber email}</div>
|
|
420
|
+
<div class="subscribers-subs-link">
|
|
421
|
+
<a href="{subscribeUrl}">Manage subscriptions</a>
|
|
422
|
+
</div>
|
|
423
|
+
<div class="subscribers-logout">
|
|
424
|
+
<button class="subscribers-button" type="button">Log out</button>
|
|
425
|
+
</div>
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
337
428
|
```
|
|
338
429
|
|
|
339
430
|
## Contributing
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import type { RequestMagicLinkResponse } from '../../endpoints/requestMagicLink.js';
|
|
2
2
|
export { RequestMagicLinkResponse };
|
|
3
|
+
/**
|
|
4
|
+
* Props for the RequestMagicLink component.
|
|
5
|
+
*/
|
|
3
6
|
export interface IRequestMagicLink {
|
|
4
7
|
classNames?: RequestMagicLinkClasses;
|
|
5
8
|
handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void;
|
|
6
9
|
props?: any;
|
|
10
|
+
verifyUrl?: string | URL;
|
|
7
11
|
}
|
|
12
|
+
/** Optional CSS class overrides for RequestMagicLink elements. */
|
|
8
13
|
export type RequestMagicLinkClasses = {
|
|
9
14
|
button?: string;
|
|
10
15
|
container?: string;
|
|
@@ -13,4 +18,11 @@ export type RequestMagicLinkClasses = {
|
|
|
13
18
|
form?: string;
|
|
14
19
|
message?: string;
|
|
15
20
|
};
|
|
16
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Form component that lets users request a magic-login link by email. Submits to POST /api/emailToken
|
|
23
|
+
* and shows success or error message. Uses SubscriberProvider for pre-filling email when available.
|
|
24
|
+
*
|
|
25
|
+
* @param props - See IRequestMagicLink
|
|
26
|
+
* @returns Form UI with email input and "Request magic link" button
|
|
27
|
+
*/
|
|
28
|
+
export declare const RequestMagicLink: ({ classNames, handleMagicLinkRequested, verifyUrl, }: IRequestMagicLink) => import("react").JSX.Element;
|
|
@@ -6,14 +6,23 @@ import { useSubscriber } from '../../contexts/SubscriberProvider.js';
|
|
|
6
6
|
import { useServerUrl } from '../../react-hooks/useServerUrl.js';
|
|
7
7
|
import { mergeClassNames } from './helpers.js';
|
|
8
8
|
import styles from './shared.module.css';
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Form component that lets users request a magic-login link by email. Submits to POST /api/emailToken
|
|
11
|
+
* and shows success or error message. Uses SubscriberProvider for pre-filling email when available.
|
|
12
|
+
*
|
|
13
|
+
* @param props - See IRequestMagicLink
|
|
14
|
+
* @returns Form UI with email input and "Request magic link" button
|
|
15
|
+
*/ export const RequestMagicLink = ({ classNames = {
|
|
10
16
|
button: '',
|
|
11
17
|
container: '',
|
|
12
18
|
emailInput: '',
|
|
13
19
|
error: '',
|
|
14
20
|
form: '',
|
|
15
21
|
message: ''
|
|
16
|
-
}, handleMagicLinkRequested })=>{
|
|
22
|
+
}, handleMagicLinkRequested, verifyUrl })=>{
|
|
23
|
+
if (typeof verifyUrl == 'string') {
|
|
24
|
+
verifyUrl = new URL(verifyUrl);
|
|
25
|
+
}
|
|
17
26
|
const { subscriber } = useSubscriber();
|
|
18
27
|
const { serverURL } = useServerUrl();
|
|
19
28
|
const [status, setStatus] = useState('default');
|
|
@@ -29,11 +38,10 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
29
38
|
]);
|
|
30
39
|
const handleSubmit = async (e)=>{
|
|
31
40
|
e.preventDefault();
|
|
32
|
-
const forwardUrl = window.location.pathname + '?now=' + new Date().toISOString();
|
|
33
41
|
const emailTokenResponse = await sdk.request({
|
|
34
42
|
json: {
|
|
35
43
|
email,
|
|
36
|
-
|
|
44
|
+
verifyUrl: verifyUrl?.href
|
|
37
45
|
},
|
|
38
46
|
method: 'POST',
|
|
39
47
|
path: '/api/emailToken'
|
|
@@ -63,15 +71,18 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
63
71
|
};
|
|
64
72
|
return /*#__PURE__*/ _jsxs("div", {
|
|
65
73
|
className: mergeClassNames([
|
|
74
|
+
'subscribers-request subscribers-container',
|
|
66
75
|
styles.container,
|
|
67
76
|
classNames.container
|
|
68
77
|
]),
|
|
69
78
|
children: [
|
|
70
79
|
result ? /*#__PURE__*/ _jsx("p", {
|
|
71
80
|
className: mergeClassNames([
|
|
81
|
+
'subscribers-message',
|
|
72
82
|
styles.message,
|
|
73
83
|
classNames.message,
|
|
74
84
|
status == 'error' ? [
|
|
85
|
+
'subscribers-error',
|
|
75
86
|
styles.error,
|
|
76
87
|
classNames.error
|
|
77
88
|
] : []
|
|
@@ -80,6 +91,7 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
80
91
|
}) : /*#__PURE__*/ _jsx(_Fragment, {}),
|
|
81
92
|
/*#__PURE__*/ _jsxs("form", {
|
|
82
93
|
className: mergeClassNames([
|
|
94
|
+
'subscribers-form',
|
|
83
95
|
styles.form,
|
|
84
96
|
classNames.form
|
|
85
97
|
]),
|
|
@@ -89,6 +101,7 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
89
101
|
/*#__PURE__*/ _jsx("input", {
|
|
90
102
|
"aria-label": "enter your email",
|
|
91
103
|
className: mergeClassNames([
|
|
104
|
+
'subscribers-emailInput',
|
|
92
105
|
styles.emailInput,
|
|
93
106
|
classNames.emailInput
|
|
94
107
|
]),
|
|
@@ -99,6 +112,7 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
99
112
|
}),
|
|
100
113
|
/*#__PURE__*/ _jsx("button", {
|
|
101
114
|
className: mergeClassNames([
|
|
115
|
+
'subscribers-button',
|
|
102
116
|
styles.button,
|
|
103
117
|
classNames.button
|
|
104
118
|
]),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/app/RequestMagicLink.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { type ChangeEvent, type SubmitEvent, useEffect, useState } from 'react'\n\nimport type { Config } from '../../copied/payload-types.js'\nimport type { RequestMagicLinkResponse } from '../../endpoints/requestMagicLink.js'\n\nimport { useSubscriber } from '../../contexts/SubscriberProvider.js'\nimport { useServerUrl } from '../../react-hooks/useServerUrl.js'\nimport { mergeClassNames } from './helpers.js'\nimport styles from './shared.module.css'\n\nexport { RequestMagicLinkResponse }\n\nexport interface IRequestMagicLink {\n classNames?: RequestMagicLinkClasses\n handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void\n props?: any\n}\n\nexport type RequestMagicLinkClasses = {\n button?: string\n container?: string\n emailInput?: string\n error?: string\n form?: string\n message?: string\n}\n\ntype statusValues = 'default' | 'error' | 'sent'\n\nexport const RequestMagicLink = ({\n classNames = {\n button: '',\n container: '',\n emailInput: '',\n error: '',\n form: '',\n message: '',\n },\n handleMagicLinkRequested,\n}: IRequestMagicLink) => {\n const { subscriber } = useSubscriber()\n const { serverURL } = useServerUrl()\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/app/RequestMagicLink.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { type ChangeEvent, type SubmitEvent, useEffect, useState } from 'react'\n\nimport type { Config } from '../../copied/payload-types.js'\nimport type { RequestMagicLinkResponse } from '../../endpoints/requestMagicLink.js'\n\nimport { useSubscriber } from '../../contexts/SubscriberProvider.js'\nimport { useServerUrl } from '../../react-hooks/useServerUrl.js'\nimport { mergeClassNames } from './helpers.js'\nimport styles from './shared.module.css'\n\nexport { RequestMagicLinkResponse }\n\n/**\n * Props for the RequestMagicLink component.\n */\nexport interface IRequestMagicLink {\n classNames?: RequestMagicLinkClasses\n handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void\n props?: any\n verifyUrl?: string | URL\n}\n\n/** Optional CSS class overrides for RequestMagicLink elements. */\nexport type RequestMagicLinkClasses = {\n button?: string\n container?: string\n emailInput?: string\n error?: string\n form?: string\n message?: string\n}\n\ntype statusValues = 'default' | 'error' | 'sent'\n\n/**\n * Form component that lets users request a magic-login link by email. Submits to POST /api/emailToken\n * and shows success or error message. Uses SubscriberProvider for pre-filling email when available.\n *\n * @param props - See IRequestMagicLink\n * @returns Form UI with email input and \"Request magic link\" button\n */\nexport const RequestMagicLink = ({\n classNames = {\n button: '',\n container: '',\n emailInput: '',\n error: '',\n form: '',\n message: '',\n },\n handleMagicLinkRequested,\n verifyUrl,\n}: IRequestMagicLink) => {\n if (typeof verifyUrl == 'string') {\n verifyUrl = new URL(verifyUrl)\n }\n\n const { subscriber } = useSubscriber()\n const { serverURL } = useServerUrl()\n const [status, setStatus] = useState<statusValues>('default')\n\n const sdk = new PayloadSDK<Config>({\n baseURL: serverURL || '',\n })\n\n const [result, setResult] = useState<string>()\n const [email, setEmail] = useState(subscriber?.email || '')\n\n useEffect(() => {\n setEmail(subscriber?.email || '')\n }, [subscriber])\n\n const handleSubmit = async (e: SubmitEvent<HTMLFormElement>) => {\n e.preventDefault()\n const emailTokenResponse = await sdk.request({\n json: {\n email,\n verifyUrl: verifyUrl?.href,\n },\n method: 'POST',\n path: '/api/emailToken',\n })\n if (emailTokenResponse.ok) {\n const emailTokenResponseJson: RequestMagicLinkResponse = await emailTokenResponse.json()\n if (handleMagicLinkRequested) {\n handleMagicLinkRequested(emailTokenResponseJson)\n }\n // @ts-expect-error One or the other exists\n const { emailResult, error } = emailTokenResponseJson\n if (error) {\n setStatus('error')\n setResult(`An error occured. Please try again. \\n ${error}`)\n } else if (emailResult) {\n setStatus('sent')\n setResult('An email has been sent containing your magic link.')\n } else {\n setStatus('error')\n setResult(`An error occured. Please try again. \\nResult unknown`)\n }\n } else {\n const emailTokenResponseText = await emailTokenResponse.text()\n setStatus('error')\n setResult(`An error occured. Please try again. \\n${emailTokenResponseText}`)\n }\n }\n\n return (\n <div\n className={mergeClassNames([\n 'subscribers-request subscribers-container',\n styles.container,\n classNames.container,\n ])}\n >\n {result ? (\n <p\n className={mergeClassNames([\n 'subscribers-message',\n styles.message,\n classNames.message,\n status == 'error' ? ['subscribers-error', styles.error, classNames.error] : [],\n ])}\n >\n {result}\n </p>\n ) : (\n <></>\n )}\n <form\n className={mergeClassNames(['subscribers-form', styles.form, classNames.form])}\n method=\"POST\"\n onSubmit={handleSubmit}\n >\n <input\n aria-label=\"enter your email\"\n className={mergeClassNames([\n 'subscribers-emailInput',\n styles.emailInput,\n classNames.emailInput,\n ])}\n onChange={(e: ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}\n placeholder=\"enter your email\"\n type=\"email\"\n value={email}\n />\n <button\n className={mergeClassNames(['subscribers-button', styles.button, classNames.button])}\n type=\"submit\"\n >\n Request magic link\n </button>\n </form>\n </div>\n )\n}\n"],"names":["PayloadSDK","useEffect","useState","useSubscriber","useServerUrl","mergeClassNames","styles","RequestMagicLink","classNames","button","container","emailInput","error","form","message","handleMagicLinkRequested","verifyUrl","URL","subscriber","serverURL","status","setStatus","sdk","baseURL","result","setResult","email","setEmail","handleSubmit","e","preventDefault","emailTokenResponse","request","json","href","method","path","ok","emailTokenResponseJson","emailResult","emailTokenResponseText","text","div","className","p","onSubmit","input","aria-label","onChange","target","value","placeholder","type"],"mappings":"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"}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { type RequestMagicLinkResponse, type SubscribeResponse } from '../../exports/ui.js';
|
|
2
2
|
export type { RequestMagicLinkResponse, SubscribeResponse };
|
|
3
|
+
/**
|
|
4
|
+
* Props for the RequestOrSubscribe component.
|
|
5
|
+
*/
|
|
6
|
+
export interface IRequestOrSubscribe {
|
|
7
|
+
classNames?: RequestOrSubscribeClasses;
|
|
8
|
+
handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void;
|
|
9
|
+
handleSubscribe?: (result: SubscribeResponse) => void;
|
|
10
|
+
verifyUrl?: string | URL;
|
|
11
|
+
}
|
|
12
|
+
/** Optional CSS class overrides for RequestOrSubscribe and its child components. */
|
|
3
13
|
export type RequestOrSubscribeClasses = {
|
|
4
14
|
button?: string;
|
|
5
15
|
container?: string;
|
|
@@ -10,8 +20,14 @@ export type RequestOrSubscribeClasses = {
|
|
|
10
20
|
message?: string;
|
|
11
21
|
section?: string;
|
|
12
22
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Composite component that shows Subscribe when a subscriber is authenticated, otherwise
|
|
25
|
+
* RequestMagicLink. Used as a single entry point for "sign in or manage subscriptions."
|
|
26
|
+
*
|
|
27
|
+
* @param props.classNames - Optional class overrides passed to child components
|
|
28
|
+
* @param props.handleMagicLinkRequested - Callback when a magic link is requested (no subscriber yet)
|
|
29
|
+
* @param props.handleSubscribe - Callback when subscription/opt-ins are updated (subscriber present)
|
|
30
|
+
* @param props.verifyUrl - Base URL for verify links in emails
|
|
31
|
+
* @returns Either Subscribe or RequestMagicLink based on subscriber context
|
|
32
|
+
*/
|
|
33
|
+
export declare function RequestOrSubscribe({ classNames, handleMagicLinkRequested, handleSubscribe, verifyUrl, }: IRequestOrSubscribe): import("react").JSX.Element;
|
|
@@ -2,7 +2,16 @@
|
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useSubscriber } from '../../contexts/SubscriberProvider.js';
|
|
4
4
|
import { RequestMagicLink, Subscribe } from '../../exports/ui.js';
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Composite component that shows Subscribe when a subscriber is authenticated, otherwise
|
|
7
|
+
* RequestMagicLink. Used as a single entry point for "sign in or manage subscriptions."
|
|
8
|
+
*
|
|
9
|
+
* @param props.classNames - Optional class overrides passed to child components
|
|
10
|
+
* @param props.handleMagicLinkRequested - Callback when a magic link is requested (no subscriber yet)
|
|
11
|
+
* @param props.handleSubscribe - Callback when subscription/opt-ins are updated (subscriber present)
|
|
12
|
+
* @param props.verifyUrl - Base URL for verify links in emails
|
|
13
|
+
* @returns Either Subscribe or RequestMagicLink based on subscriber context
|
|
14
|
+
*/ export function RequestOrSubscribe({ classNames = {
|
|
6
15
|
button: '',
|
|
7
16
|
container: '',
|
|
8
17
|
emailInput: '',
|
|
@@ -11,16 +20,21 @@ export function RequestOrSubscribe({ classNames = {
|
|
|
11
20
|
loading: '',
|
|
12
21
|
message: '',
|
|
13
22
|
section: ''
|
|
14
|
-
}, handleMagicLinkRequested, handleSubscribe }) {
|
|
23
|
+
}, handleMagicLinkRequested, handleSubscribe, verifyUrl }) {
|
|
24
|
+
if (typeof verifyUrl == 'string') {
|
|
25
|
+
verifyUrl = new URL(verifyUrl);
|
|
26
|
+
}
|
|
15
27
|
const { subscriber } = useSubscriber();
|
|
16
28
|
// Example: Conditionally render something or pass the state to children
|
|
17
29
|
return /*#__PURE__*/ _jsx(_Fragment, {
|
|
18
30
|
children: subscriber ? /*#__PURE__*/ _jsx(Subscribe, {
|
|
19
31
|
classNames: classNames,
|
|
20
|
-
handleSubscribe: handleSubscribe
|
|
32
|
+
handleSubscribe: handleSubscribe,
|
|
33
|
+
verifyUrl: verifyUrl
|
|
21
34
|
}) : /*#__PURE__*/ _jsx(RequestMagicLink, {
|
|
22
35
|
classNames: classNames,
|
|
23
|
-
handleMagicLinkRequested: handleMagicLinkRequested
|
|
36
|
+
handleMagicLinkRequested: handleMagicLinkRequested,
|
|
37
|
+
verifyUrl: verifyUrl
|
|
24
38
|
})
|
|
25
39
|
});
|
|
26
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/app/RequestOrSubscribe.tsx"],"sourcesContent":["'use client'\n\nimport { useSubscriber } from '../../contexts/SubscriberProvider.js'\nimport {\n RequestMagicLink,\n type RequestMagicLinkResponse,\n Subscribe,\n type SubscribeResponse,\n} from '../../exports/ui.js'\n\nexport type { RequestMagicLinkResponse, SubscribeResponse }\n\nexport type RequestOrSubscribeClasses = {\n button?: string\n container?: string\n emailInput?: string\n error?: string\n form?: string\n loading?: string\n message?: string\n section?: string\n}\n\nexport function RequestOrSubscribe({\n classNames = {\n button: '',\n container: '',\n emailInput: '',\n error: '',\n form: '',\n loading: '',\n message: '',\n section: '',\n },\n handleMagicLinkRequested,\n handleSubscribe,\n}: {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/app/RequestOrSubscribe.tsx"],"sourcesContent":["'use client'\n\nimport { useSubscriber } from '../../contexts/SubscriberProvider.js'\nimport {\n RequestMagicLink,\n type RequestMagicLinkResponse,\n Subscribe,\n type SubscribeResponse,\n} from '../../exports/ui.js'\n\nexport type { RequestMagicLinkResponse, SubscribeResponse }\n\n/**\n * Props for the RequestOrSubscribe component.\n */\nexport interface IRequestOrSubscribe {\n classNames?: RequestOrSubscribeClasses\n handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void\n handleSubscribe?: (result: SubscribeResponse) => void\n verifyUrl?: string | URL\n}\n\n/** Optional CSS class overrides for RequestOrSubscribe and its child components. */\nexport type RequestOrSubscribeClasses = {\n button?: string\n container?: string\n emailInput?: string\n error?: string\n form?: string\n loading?: string\n message?: string\n section?: string\n}\n\n/**\n * Composite component that shows Subscribe when a subscriber is authenticated, otherwise\n * RequestMagicLink. Used as a single entry point for \"sign in or manage subscriptions.\"\n *\n * @param props.classNames - Optional class overrides passed to child components\n * @param props.handleMagicLinkRequested - Callback when a magic link is requested (no subscriber yet)\n * @param props.handleSubscribe - Callback when subscription/opt-ins are updated (subscriber present)\n * @param props.verifyUrl - Base URL for verify links in emails\n * @returns Either Subscribe or RequestMagicLink based on subscriber context\n */\nexport function RequestOrSubscribe({\n classNames = {\n button: '',\n container: '',\n emailInput: '',\n error: '',\n form: '',\n loading: '',\n message: '',\n section: '',\n },\n handleMagicLinkRequested,\n handleSubscribe,\n verifyUrl,\n}: IRequestOrSubscribe) {\n if (typeof verifyUrl == 'string') {\n verifyUrl = new URL(verifyUrl)\n }\n\n const { subscriber } = useSubscriber()\n\n // Example: Conditionally render something or pass the state to children\n return (\n <>\n {subscriber ? (\n <Subscribe\n classNames={classNames}\n handleSubscribe={handleSubscribe}\n verifyUrl={verifyUrl}\n />\n ) : (\n <RequestMagicLink\n classNames={classNames}\n handleMagicLinkRequested={handleMagicLinkRequested}\n verifyUrl={verifyUrl}\n />\n )}\n {/* <div>subscriber = {JSON.stringify(subscriber)}</div> */}\n </>\n )\n}\n"],"names":["useSubscriber","RequestMagicLink","Subscribe","RequestOrSubscribe","classNames","button","container","emailInput","error","form","loading","message","section","handleMagicLinkRequested","handleSubscribe","verifyUrl","URL","subscriber"],"mappings":"AAAA;;AAEA,SAASA,aAAa,QAAQ,uCAAsC;AACpE,SACEC,gBAAgB,EAEhBC,SAAS,QAEJ,sBAAqB;AA0B5B;;;;;;;;;CASC,GACD,OAAO,SAASC,mBAAmB,EACjCC,aAAa;IACXC,QAAQ;IACRC,WAAW;IACXC,YAAY;IACZC,OAAO;IACPC,MAAM;IACNC,SAAS;IACTC,SAAS;IACTC,SAAS;AACX,CAAC,EACDC,wBAAwB,EACxBC,eAAe,EACfC,SAAS,EACW;IACpB,IAAI,OAAOA,aAAa,UAAU;QAChCA,YAAY,IAAIC,IAAID;IACtB;IAEA,MAAM,EAAEE,UAAU,EAAE,GAAGjB;IAEvB,wEAAwE;IACxE,qBACE;kBACGiB,2BACC,KAACf;YACCE,YAAYA;YACZU,iBAAiBA;YACjBC,WAAWA;2BAGb,KAACd;YACCG,YAAYA;YACZS,0BAA0BA;YAC1BE,WAAWA;;;AAMrB"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { OptInChannel } from '../../copied/payload-types.js';
|
|
2
|
+
/** Props for the SelectOptInChannels component. */
|
|
2
3
|
export interface ISelectOptInChannels {
|
|
3
4
|
classNames?: SelectOptInChannelsClasses;
|
|
4
5
|
handleOptInChannelsSelected?: (result: OptInChannel[]) => void;
|
|
5
6
|
props?: any;
|
|
6
7
|
selectedOptInChannelIDs?: string[];
|
|
7
8
|
}
|
|
9
|
+
/** Optional CSS class overrides for SelectOptInChannels elements. */
|
|
8
10
|
export type SelectOptInChannelsClasses = {
|
|
9
11
|
button?: string;
|
|
10
12
|
container?: string;
|
|
@@ -17,4 +19,11 @@ export type SelectOptInChannelsClasses = {
|
|
|
17
19
|
optInCheckboxLabel?: string;
|
|
18
20
|
optionsGroup?: string;
|
|
19
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* Fetches active opt-in channels from GET /api/optinchannels and renders a list of checkboxes.
|
|
24
|
+
* Reports selected channels via handleOptInChannelsSelected. Supports pre-selection via selectedOptInChannelIDs.
|
|
25
|
+
*
|
|
26
|
+
* @param props - See ISelectOptInChannels
|
|
27
|
+
* @returns Section titled "Opt-in Channels" with checkboxes and loading/error state
|
|
28
|
+
*/
|
|
20
29
|
export declare const SelectOptInChannels: ({ classNames, handleOptInChannelsSelected, selectedOptInChannelIDs, }: ISelectOptInChannels) => import("react").JSX.Element;
|
|
@@ -5,7 +5,13 @@ import { useEffect, useState } from 'react';
|
|
|
5
5
|
import { useServerUrl } from '../../react-hooks/useServerUrl.js';
|
|
6
6
|
import { mergeClassNames } from './helpers.js';
|
|
7
7
|
import styles from './shared.module.css';
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Fetches active opt-in channels from GET /api/optinchannels and renders a list of checkboxes.
|
|
10
|
+
* Reports selected channels via handleOptInChannelsSelected. Supports pre-selection via selectedOptInChannelIDs.
|
|
11
|
+
*
|
|
12
|
+
* @param props - See ISelectOptInChannels
|
|
13
|
+
* @returns Section titled "Opt-in Channels" with checkboxes and loading/error state
|
|
14
|
+
*/ export const SelectOptInChannels = ({ classNames = {
|
|
9
15
|
button: '',
|
|
10
16
|
container: '',
|
|
11
17
|
error: '',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/app/SelectOptInChannels.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { useEffect, useState } from 'react'\n\nimport type { Config, OptInChannel } from '../../copied/payload-types.js'\nimport type { GetOptInChannelsResponse } from '../../endpoints/getOptInChannels.js'\n\nimport { useServerUrl } from '../../react-hooks/useServerUrl.js'\nimport { mergeClassNames } from './helpers.js'\nimport styles from './shared.module.css'\n\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/app/SelectOptInChannels.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { useEffect, useState } from 'react'\n\nimport type { Config, OptInChannel } from '../../copied/payload-types.js'\nimport type { GetOptInChannelsResponse } from '../../endpoints/getOptInChannels.js'\n\nimport { useServerUrl } from '../../react-hooks/useServerUrl.js'\nimport { mergeClassNames } from './helpers.js'\nimport styles from './shared.module.css'\n\n/** Props for the SelectOptInChannels component. */\nexport interface ISelectOptInChannels {\n classNames?: SelectOptInChannelsClasses\n handleOptInChannelsSelected?: (result: OptInChannel[]) => void\n props?: any\n selectedOptInChannelIDs?: string[]\n}\n\n/** Optional CSS class overrides for SelectOptInChannels elements. */\nexport type SelectOptInChannelsClasses = {\n button?: string\n container?: string\n error?: string\n form?: string\n loading?: string\n message?: string\n optInCheckbox?: string\n optInCheckboxItem?: string\n optInCheckboxLabel?: string\n optionsGroup?: string\n}\n\n/**\n * Fetches active opt-in channels from GET /api/optinchannels and renders a list of checkboxes.\n * Reports selected channels via handleOptInChannelsSelected. Supports pre-selection via selectedOptInChannelIDs.\n *\n * @param props - See ISelectOptInChannels\n * @returns Section titled \"Opt-in Channels\" with checkboxes and loading/error state\n */\nexport const SelectOptInChannels = ({\n classNames = {\n button: '',\n container: '',\n error: '',\n form: '',\n loading: '',\n message: '',\n optInCheckbox: '',\n optInCheckboxItem: '',\n optInCheckboxLabel: '',\n optionsGroup: '',\n },\n handleOptInChannelsSelected,\n selectedOptInChannelIDs,\n}: ISelectOptInChannels) => {\n const { serverURL } = useServerUrl()\n // const { serverURL } = { serverURL: 'http://localhost:3001' }\n type OptInChannelCheckbox = {\n isChecked: boolean\n } & OptInChannel\n const [result, setResult] = useState<any>()\n const [allOptInChannels, setAllOptInChannels] = useState<OptInChannelCheckbox[]>([])\n\n useEffect(() => {\n async function verify() {\n const sdk = new PayloadSDK<Config>({\n baseURL: serverURL || '',\n })\n\n console.log('calling optinchannels endpoint')\n const result = await sdk.request({\n method: 'GET',\n path: '/api/optinchannels',\n })\n if (result.ok) {\n const resultJson: GetOptInChannelsResponse = await result.json()\n setResult(resultJson)\n } else {\n const resultText = await result.text()\n setResult(resultText)\n }\n }\n void verify()\n }, [serverURL])\n\n useEffect(() => {\n const channels = result?.optInChannels?.map((channel: OptInChannel) => ({\n ...channel,\n isChecked: selectedOptInChannelIDs?.includes(channel.id),\n }))\n setAllOptInChannels(channels)\n }, [result, selectedOptInChannelIDs])\n\n return (\n <div className={mergeClassNames([styles.container, classNames.container])}>\n <h3>Opt-in Channels</h3>\n {!result ? (\n <p className={mergeClassNames([styles.loading, classNames.loading])}>verifying...</p>\n ) : (\n <div className={mergeClassNames([styles.optionsGroup, classNames.optionsGroup])}>\n {// Map over the tasks array to render each checkbox\n allOptInChannels?.map((channel) => (\n <div\n className={mergeClassNames([styles.optInCheckboxItem, classNames.optInCheckboxItem])}\n key={channel.id}\n >\n <label\n className={mergeClassNames([\n styles.optInCheckboxLabel,\n classNames.optInCheckboxLabel,\n ])}\n >\n <input\n aria-label={channel.title}\n // The checked prop is controlled by the state\n checked={channel.isChecked}\n className={mergeClassNames([styles.optInCheckbox, classNames.optInCheckbox])}\n // The onChange handler calls the update function with the item's ID\n onChange={(event) => {\n event.preventDefault()\n\n const checked = event.target.checked\n\n if (handleOptInChannelsSelected) {\n handleOptInChannelsSelected(\n allOptInChannels\n .map((channel) => ({\n ...channel,\n isChecked:\n channel.title == event.target.value ? checked : channel.isChecked,\n }))\n .filter((c) => c.isChecked)\n .map((channel) => ({ ...channel, isChecked: undefined })),\n )\n }\n }}\n type=\"checkbox\"\n value={channel.title}\n />\n {channel.title}\n </label>\n </div>\n ))}\n </div>\n )}\n </div>\n )\n}\n"],"names":["PayloadSDK","useEffect","useState","useServerUrl","mergeClassNames","styles","SelectOptInChannels","classNames","button","container","error","form","loading","message","optInCheckbox","optInCheckboxItem","optInCheckboxLabel","optionsGroup","handleOptInChannelsSelected","selectedOptInChannelIDs","serverURL","result","setResult","allOptInChannels","setAllOptInChannels","verify","sdk","baseURL","console","log","request","method","path","ok","resultJson","json","resultText","text","channels","optInChannels","map","channel","isChecked","includes","id","div","className","h3","p","label","input","aria-label","title","checked","onChange","event","preventDefault","target","value","filter","c","undefined","type"],"mappings":"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"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { SubscribeResponse } from '../../endpoints/subscribe.js';
|
|
2
2
|
export { SubscribeResponse };
|
|
3
|
+
/** Props for the Subscribe component. */
|
|
3
4
|
export interface ISubscribe {
|
|
4
5
|
classNames?: SubscribeClasses;
|
|
5
6
|
handleSubscribe?: (result: SubscribeResponse) => void;
|
|
6
7
|
props?: any;
|
|
8
|
+
verifyUrl?: string | URL;
|
|
7
9
|
}
|
|
10
|
+
/** Optional CSS class overrides for Subscribe elements. */
|
|
8
11
|
export type SubscribeClasses = {
|
|
9
12
|
button?: string;
|
|
10
13
|
container?: string;
|
|
@@ -15,4 +18,12 @@ export type SubscribeClasses = {
|
|
|
15
18
|
message?: string;
|
|
16
19
|
section?: string;
|
|
17
20
|
};
|
|
18
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Subscribe/preferences form for authenticated subscribers. Shows SelectOptInChannels and an email
|
|
23
|
+
* input when not yet authenticated. Submits to POST /api/subscribe to update opt-ins or trigger
|
|
24
|
+
* verification email. Calls refreshSubscriber and handleSubscribe on success.
|
|
25
|
+
*
|
|
26
|
+
* @param props - See ISubscribe
|
|
27
|
+
* @returns Form with channel checkboxes, optional email field, "Save choices" button, and status message
|
|
28
|
+
*/
|
|
29
|
+
export declare const Subscribe: ({ classNames, handleSubscribe, verifyUrl, }: ISubscribe) => import("react").JSX.Element;
|