payload-plugin-newsletter 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin.d.ts +40 -1
- package/dist/admin.js +541 -0
- package/dist/collections.cjs +16 -0
- package/dist/collections.cjs.map +1 -1
- package/dist/collections.js +16 -0
- package/dist/collections.js.map +1 -1
- package/dist/server.js +16 -0
- package/package.json +1 -1
package/dist/admin.d.ts
CHANGED
|
@@ -24,4 +24,43 @@ declare const EmailPreview: React.FC<EmailPreviewProps>;
|
|
|
24
24
|
|
|
25
25
|
declare const WebhookConfiguration: React.FC;
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Field component that shows scheduling controls based on broadcast status
|
|
29
|
+
* Shows Schedule button for drafts, Cancel button for scheduled broadcasts
|
|
30
|
+
*/
|
|
31
|
+
declare const BroadcastScheduleField: React.FC;
|
|
32
|
+
|
|
33
|
+
interface BroadcastScheduleButtonProps {
|
|
34
|
+
broadcastId: string;
|
|
35
|
+
sendStatus?: string;
|
|
36
|
+
providerId?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Button to open the schedule modal for a broadcast
|
|
40
|
+
* Only shows for draft broadcasts that have been synced to the provider
|
|
41
|
+
*/
|
|
42
|
+
declare const BroadcastScheduleButton: React.FC<BroadcastScheduleButtonProps>;
|
|
43
|
+
|
|
44
|
+
interface CancelScheduleButtonProps {
|
|
45
|
+
broadcastId: string;
|
|
46
|
+
sendStatus?: string;
|
|
47
|
+
scheduledAt?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Button to cancel a scheduled broadcast
|
|
51
|
+
* Only shows for broadcasts with 'scheduled' status
|
|
52
|
+
*/
|
|
53
|
+
declare const CancelScheduleButton: React.FC<CancelScheduleButtonProps>;
|
|
54
|
+
|
|
55
|
+
interface ScheduleModalProps {
|
|
56
|
+
broadcastId: string;
|
|
57
|
+
onScheduled?: () => void;
|
|
58
|
+
onClose: () => void;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Modal for scheduling a broadcast
|
|
62
|
+
* Uses native HTML date-time inputs for compatibility
|
|
63
|
+
*/
|
|
64
|
+
declare const ScheduleModal: React.FC<ScheduleModalProps>;
|
|
65
|
+
|
|
66
|
+
export { BroadcastInlinePreview, type BroadcastInlinePreviewProps, BroadcastScheduleButton, BroadcastScheduleField, CancelScheduleButton, EmailPreview, type EmailPreviewProps, ScheduleModal, StatusBadge, type StatusBadgeProps, WebhookConfiguration };
|
package/dist/admin.js
CHANGED
|
@@ -332,9 +332,550 @@ var WebhookConfiguration = () => {
|
|
|
332
332
|
] })
|
|
333
333
|
] }) });
|
|
334
334
|
};
|
|
335
|
+
|
|
336
|
+
// src/components/Broadcasts/BroadcastScheduleField.tsx
|
|
337
|
+
import { useDocumentInfo, useFormFields as useFormFields3 } from "@payloadcms/ui";
|
|
338
|
+
|
|
339
|
+
// src/components/Broadcasts/BroadcastScheduleButton.tsx
|
|
340
|
+
import { useState as useState4 } from "react";
|
|
341
|
+
|
|
342
|
+
// src/components/Broadcasts/ScheduleModal.tsx
|
|
343
|
+
import { useState as useState3, useCallback as useCallback2 } from "react";
|
|
344
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
345
|
+
var ScheduleModal = ({
|
|
346
|
+
broadcastId,
|
|
347
|
+
onScheduled,
|
|
348
|
+
onClose
|
|
349
|
+
}) => {
|
|
350
|
+
const [selectedDate, setSelectedDate] = useState3("");
|
|
351
|
+
const [selectedTime, setSelectedTime] = useState3("");
|
|
352
|
+
const [timezone, setTimezone] = useState3(
|
|
353
|
+
Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
354
|
+
);
|
|
355
|
+
const [isLoading, setIsLoading] = useState3(false);
|
|
356
|
+
const [error, setError] = useState3(null);
|
|
357
|
+
const getMinDate = () => {
|
|
358
|
+
const today = /* @__PURE__ */ new Date();
|
|
359
|
+
return today.toISOString().split("T")[0];
|
|
360
|
+
};
|
|
361
|
+
const getMinTime = () => {
|
|
362
|
+
if (!selectedDate) return void 0;
|
|
363
|
+
const today = /* @__PURE__ */ new Date();
|
|
364
|
+
const selectedDateObj = new Date(selectedDate);
|
|
365
|
+
if (selectedDateObj.toDateString() === today.toDateString()) {
|
|
366
|
+
const minTime = new Date(today.getTime() + 5 * 60 * 1e3);
|
|
367
|
+
return `${String(minTime.getHours()).padStart(2, "0")}:${String(minTime.getMinutes()).padStart(2, "0")}`;
|
|
368
|
+
}
|
|
369
|
+
return void 0;
|
|
370
|
+
};
|
|
371
|
+
const handleSchedule = useCallback2(async () => {
|
|
372
|
+
if (!selectedDate || !selectedTime) {
|
|
373
|
+
setError("Please select both date and time");
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
setIsLoading(true);
|
|
377
|
+
setError(null);
|
|
378
|
+
try {
|
|
379
|
+
const scheduledAt = /* @__PURE__ */ new Date(`${selectedDate}T${selectedTime}:00`);
|
|
380
|
+
if (scheduledAt <= /* @__PURE__ */ new Date()) {
|
|
381
|
+
setError("Scheduled time must be in the future");
|
|
382
|
+
setIsLoading(false);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const response = await fetch(`/api/broadcasts/${broadcastId}/schedule`, {
|
|
386
|
+
method: "POST",
|
|
387
|
+
headers: { "Content-Type": "application/json" },
|
|
388
|
+
body: JSON.stringify({
|
|
389
|
+
scheduledAt: scheduledAt.toISOString(),
|
|
390
|
+
timezone
|
|
391
|
+
})
|
|
392
|
+
});
|
|
393
|
+
const data = await response.json();
|
|
394
|
+
if (!data.success) {
|
|
395
|
+
setError(data.error || "Failed to schedule broadcast");
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
onScheduled?.();
|
|
399
|
+
onClose();
|
|
400
|
+
window.location.reload();
|
|
401
|
+
} catch (err) {
|
|
402
|
+
setError("Network error. Please try again.");
|
|
403
|
+
} finally {
|
|
404
|
+
setIsLoading(false);
|
|
405
|
+
}
|
|
406
|
+
}, [selectedDate, selectedTime, timezone, broadcastId, onScheduled, onClose]);
|
|
407
|
+
const commonTimezones = [
|
|
408
|
+
"America/New_York",
|
|
409
|
+
"America/Chicago",
|
|
410
|
+
"America/Denver",
|
|
411
|
+
"America/Los_Angeles",
|
|
412
|
+
"Europe/London",
|
|
413
|
+
"Europe/Paris",
|
|
414
|
+
"Asia/Tokyo",
|
|
415
|
+
"Australia/Sydney"
|
|
416
|
+
];
|
|
417
|
+
return /* @__PURE__ */ jsx5(
|
|
418
|
+
"div",
|
|
419
|
+
{
|
|
420
|
+
style: {
|
|
421
|
+
position: "fixed",
|
|
422
|
+
top: 0,
|
|
423
|
+
left: 0,
|
|
424
|
+
right: 0,
|
|
425
|
+
bottom: 0,
|
|
426
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
427
|
+
display: "flex",
|
|
428
|
+
alignItems: "center",
|
|
429
|
+
justifyContent: "center",
|
|
430
|
+
zIndex: 1e4
|
|
431
|
+
},
|
|
432
|
+
onClick: (e) => {
|
|
433
|
+
if (e.target === e.currentTarget) onClose();
|
|
434
|
+
},
|
|
435
|
+
children: /* @__PURE__ */ jsxs4(
|
|
436
|
+
"div",
|
|
437
|
+
{
|
|
438
|
+
style: {
|
|
439
|
+
backgroundColor: "var(--theme-elevation-0, #fff)",
|
|
440
|
+
borderRadius: "8px",
|
|
441
|
+
padding: "24px",
|
|
442
|
+
maxWidth: "400px",
|
|
443
|
+
width: "100%",
|
|
444
|
+
boxShadow: "0 4px 20px rgba(0, 0, 0, 0.15)"
|
|
445
|
+
},
|
|
446
|
+
children: [
|
|
447
|
+
/* @__PURE__ */ jsx5(
|
|
448
|
+
"h2",
|
|
449
|
+
{
|
|
450
|
+
style: {
|
|
451
|
+
margin: "0 0 16px 0",
|
|
452
|
+
fontSize: "18px",
|
|
453
|
+
fontWeight: "600",
|
|
454
|
+
color: "var(--theme-elevation-1000, #000)"
|
|
455
|
+
},
|
|
456
|
+
children: "Schedule Broadcast"
|
|
457
|
+
}
|
|
458
|
+
),
|
|
459
|
+
error && /* @__PURE__ */ jsx5(
|
|
460
|
+
"div",
|
|
461
|
+
{
|
|
462
|
+
style: {
|
|
463
|
+
padding: "12px",
|
|
464
|
+
marginBottom: "16px",
|
|
465
|
+
backgroundColor: "var(--theme-error-100, #fef2f2)",
|
|
466
|
+
color: "var(--theme-error-500, #ef4444)",
|
|
467
|
+
borderRadius: "4px",
|
|
468
|
+
fontSize: "14px"
|
|
469
|
+
},
|
|
470
|
+
children: error
|
|
471
|
+
}
|
|
472
|
+
),
|
|
473
|
+
/* @__PURE__ */ jsxs4("div", { style: { marginBottom: "16px" }, children: [
|
|
474
|
+
/* @__PURE__ */ jsx5(
|
|
475
|
+
"label",
|
|
476
|
+
{
|
|
477
|
+
style: {
|
|
478
|
+
display: "block",
|
|
479
|
+
marginBottom: "4px",
|
|
480
|
+
fontSize: "14px",
|
|
481
|
+
fontWeight: "500",
|
|
482
|
+
color: "var(--theme-elevation-800, #333)"
|
|
483
|
+
},
|
|
484
|
+
children: "Date"
|
|
485
|
+
}
|
|
486
|
+
),
|
|
487
|
+
/* @__PURE__ */ jsx5(
|
|
488
|
+
"input",
|
|
489
|
+
{
|
|
490
|
+
type: "date",
|
|
491
|
+
value: selectedDate,
|
|
492
|
+
onChange: (e) => setSelectedDate(e.target.value),
|
|
493
|
+
min: getMinDate(),
|
|
494
|
+
style: {
|
|
495
|
+
width: "100%",
|
|
496
|
+
padding: "8px 12px",
|
|
497
|
+
border: "1px solid var(--theme-elevation-150, #ddd)",
|
|
498
|
+
borderRadius: "4px",
|
|
499
|
+
fontSize: "14px",
|
|
500
|
+
backgroundColor: "var(--theme-input-bg, #fff)",
|
|
501
|
+
color: "var(--theme-elevation-1000, #000)"
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
)
|
|
505
|
+
] }),
|
|
506
|
+
/* @__PURE__ */ jsxs4("div", { style: { marginBottom: "16px" }, children: [
|
|
507
|
+
/* @__PURE__ */ jsx5(
|
|
508
|
+
"label",
|
|
509
|
+
{
|
|
510
|
+
style: {
|
|
511
|
+
display: "block",
|
|
512
|
+
marginBottom: "4px",
|
|
513
|
+
fontSize: "14px",
|
|
514
|
+
fontWeight: "500",
|
|
515
|
+
color: "var(--theme-elevation-800, #333)"
|
|
516
|
+
},
|
|
517
|
+
children: "Time"
|
|
518
|
+
}
|
|
519
|
+
),
|
|
520
|
+
/* @__PURE__ */ jsx5(
|
|
521
|
+
"input",
|
|
522
|
+
{
|
|
523
|
+
type: "time",
|
|
524
|
+
value: selectedTime,
|
|
525
|
+
onChange: (e) => setSelectedTime(e.target.value),
|
|
526
|
+
min: getMinTime(),
|
|
527
|
+
style: {
|
|
528
|
+
width: "100%",
|
|
529
|
+
padding: "8px 12px",
|
|
530
|
+
border: "1px solid var(--theme-elevation-150, #ddd)",
|
|
531
|
+
borderRadius: "4px",
|
|
532
|
+
fontSize: "14px",
|
|
533
|
+
backgroundColor: "var(--theme-input-bg, #fff)",
|
|
534
|
+
color: "var(--theme-elevation-1000, #000)"
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
)
|
|
538
|
+
] }),
|
|
539
|
+
/* @__PURE__ */ jsxs4("div", { style: { marginBottom: "24px" }, children: [
|
|
540
|
+
/* @__PURE__ */ jsx5(
|
|
541
|
+
"label",
|
|
542
|
+
{
|
|
543
|
+
style: {
|
|
544
|
+
display: "block",
|
|
545
|
+
marginBottom: "4px",
|
|
546
|
+
fontSize: "14px",
|
|
547
|
+
fontWeight: "500",
|
|
548
|
+
color: "var(--theme-elevation-800, #333)"
|
|
549
|
+
},
|
|
550
|
+
children: "Timezone"
|
|
551
|
+
}
|
|
552
|
+
),
|
|
553
|
+
/* @__PURE__ */ jsxs4(
|
|
554
|
+
"select",
|
|
555
|
+
{
|
|
556
|
+
value: timezone,
|
|
557
|
+
onChange: (e) => setTimezone(e.target.value),
|
|
558
|
+
style: {
|
|
559
|
+
width: "100%",
|
|
560
|
+
padding: "8px 12px",
|
|
561
|
+
border: "1px solid var(--theme-elevation-150, #ddd)",
|
|
562
|
+
borderRadius: "4px",
|
|
563
|
+
fontSize: "14px",
|
|
564
|
+
backgroundColor: "var(--theme-input-bg, #fff)",
|
|
565
|
+
color: "var(--theme-elevation-1000, #000)"
|
|
566
|
+
},
|
|
567
|
+
children: [
|
|
568
|
+
commonTimezones.includes(timezone) ? null : /* @__PURE__ */ jsx5("option", { value: timezone, children: timezone }),
|
|
569
|
+
commonTimezones.map((tz) => /* @__PURE__ */ jsx5("option", { value: tz, children: tz.replace("_", " ") }, tz))
|
|
570
|
+
]
|
|
571
|
+
}
|
|
572
|
+
)
|
|
573
|
+
] }),
|
|
574
|
+
/* @__PURE__ */ jsxs4(
|
|
575
|
+
"div",
|
|
576
|
+
{
|
|
577
|
+
style: {
|
|
578
|
+
display: "flex",
|
|
579
|
+
gap: "12px",
|
|
580
|
+
justifyContent: "flex-end"
|
|
581
|
+
},
|
|
582
|
+
children: [
|
|
583
|
+
/* @__PURE__ */ jsx5(
|
|
584
|
+
"button",
|
|
585
|
+
{
|
|
586
|
+
onClick: onClose,
|
|
587
|
+
disabled: isLoading,
|
|
588
|
+
style: {
|
|
589
|
+
padding: "8px 16px",
|
|
590
|
+
border: "1px solid var(--theme-elevation-150, #ddd)",
|
|
591
|
+
borderRadius: "4px",
|
|
592
|
+
backgroundColor: "transparent",
|
|
593
|
+
color: "var(--theme-elevation-800, #333)",
|
|
594
|
+
fontSize: "14px",
|
|
595
|
+
cursor: "pointer"
|
|
596
|
+
},
|
|
597
|
+
children: "Cancel"
|
|
598
|
+
}
|
|
599
|
+
),
|
|
600
|
+
/* @__PURE__ */ jsx5(
|
|
601
|
+
"button",
|
|
602
|
+
{
|
|
603
|
+
onClick: handleSchedule,
|
|
604
|
+
disabled: isLoading || !selectedDate || !selectedTime,
|
|
605
|
+
style: {
|
|
606
|
+
padding: "8px 16px",
|
|
607
|
+
border: "none",
|
|
608
|
+
borderRadius: "4px",
|
|
609
|
+
backgroundColor: isLoading || !selectedDate || !selectedTime ? "var(--theme-elevation-200, #ccc)" : "var(--theme-success-500, #22c55e)",
|
|
610
|
+
color: "#fff",
|
|
611
|
+
fontSize: "14px",
|
|
612
|
+
fontWeight: "500",
|
|
613
|
+
cursor: isLoading || !selectedDate || !selectedTime ? "not-allowed" : "pointer"
|
|
614
|
+
},
|
|
615
|
+
children: isLoading ? "Scheduling..." : "Schedule"
|
|
616
|
+
}
|
|
617
|
+
)
|
|
618
|
+
]
|
|
619
|
+
}
|
|
620
|
+
)
|
|
621
|
+
]
|
|
622
|
+
}
|
|
623
|
+
)
|
|
624
|
+
}
|
|
625
|
+
);
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
// src/components/Broadcasts/BroadcastScheduleButton.tsx
|
|
629
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
630
|
+
var BroadcastScheduleButton = ({
|
|
631
|
+
broadcastId,
|
|
632
|
+
sendStatus = "draft",
|
|
633
|
+
providerId
|
|
634
|
+
}) => {
|
|
635
|
+
const [showModal, setShowModal] = useState4(false);
|
|
636
|
+
if (sendStatus !== "draft") {
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
if (!providerId) {
|
|
640
|
+
return /* @__PURE__ */ jsxs5(
|
|
641
|
+
"button",
|
|
642
|
+
{
|
|
643
|
+
disabled: true,
|
|
644
|
+
title: "Save the broadcast first to sync with the email provider",
|
|
645
|
+
style: {
|
|
646
|
+
padding: "8px 16px",
|
|
647
|
+
border: "none",
|
|
648
|
+
borderRadius: "4px",
|
|
649
|
+
backgroundColor: "var(--theme-elevation-200, #ccc)",
|
|
650
|
+
color: "var(--theme-elevation-500, #666)",
|
|
651
|
+
fontSize: "14px",
|
|
652
|
+
fontWeight: "500",
|
|
653
|
+
cursor: "not-allowed",
|
|
654
|
+
display: "inline-flex",
|
|
655
|
+
alignItems: "center",
|
|
656
|
+
gap: "6px"
|
|
657
|
+
},
|
|
658
|
+
children: [
|
|
659
|
+
/* @__PURE__ */ jsx6("span", { children: "\u{1F4C5}" }),
|
|
660
|
+
"Schedule (save first)"
|
|
661
|
+
]
|
|
662
|
+
}
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
666
|
+
/* @__PURE__ */ jsxs5(
|
|
667
|
+
"button",
|
|
668
|
+
{
|
|
669
|
+
onClick: () => setShowModal(true),
|
|
670
|
+
style: {
|
|
671
|
+
padding: "8px 16px",
|
|
672
|
+
border: "none",
|
|
673
|
+
borderRadius: "4px",
|
|
674
|
+
backgroundColor: "var(--theme-success-500, #22c55e)",
|
|
675
|
+
color: "#fff",
|
|
676
|
+
fontSize: "14px",
|
|
677
|
+
fontWeight: "500",
|
|
678
|
+
cursor: "pointer",
|
|
679
|
+
display: "inline-flex",
|
|
680
|
+
alignItems: "center",
|
|
681
|
+
gap: "6px"
|
|
682
|
+
},
|
|
683
|
+
children: [
|
|
684
|
+
/* @__PURE__ */ jsx6("span", { children: "\u{1F4C5}" }),
|
|
685
|
+
"Schedule Send"
|
|
686
|
+
]
|
|
687
|
+
}
|
|
688
|
+
),
|
|
689
|
+
showModal && /* @__PURE__ */ jsx6(
|
|
690
|
+
ScheduleModal,
|
|
691
|
+
{
|
|
692
|
+
broadcastId,
|
|
693
|
+
onClose: () => setShowModal(false)
|
|
694
|
+
}
|
|
695
|
+
)
|
|
696
|
+
] });
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
// src/components/Broadcasts/CancelScheduleButton.tsx
|
|
700
|
+
import { useState as useState5, useCallback as useCallback3 } from "react";
|
|
701
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
702
|
+
var CancelScheduleButton = ({
|
|
703
|
+
broadcastId,
|
|
704
|
+
sendStatus = "draft",
|
|
705
|
+
scheduledAt
|
|
706
|
+
}) => {
|
|
707
|
+
const [isLoading, setIsLoading] = useState5(false);
|
|
708
|
+
if (sendStatus !== "scheduled") {
|
|
709
|
+
return null;
|
|
710
|
+
}
|
|
711
|
+
const handleCancel = useCallback3(async () => {
|
|
712
|
+
const formattedDate = scheduledAt ? new Date(scheduledAt).toLocaleString() : "unknown time";
|
|
713
|
+
const confirmed = window.confirm(
|
|
714
|
+
`Are you sure you want to cancel this scheduled broadcast?
|
|
715
|
+
|
|
716
|
+
It was scheduled for: ${formattedDate}
|
|
717
|
+
|
|
718
|
+
The broadcast will be returned to draft status.`
|
|
719
|
+
);
|
|
720
|
+
if (!confirmed) return;
|
|
721
|
+
setIsLoading(true);
|
|
722
|
+
try {
|
|
723
|
+
const response = await fetch(`/api/broadcasts/${broadcastId}/schedule`, {
|
|
724
|
+
method: "DELETE"
|
|
725
|
+
});
|
|
726
|
+
const data = await response.json();
|
|
727
|
+
if (!data.success) {
|
|
728
|
+
alert(data.error || "Failed to cancel schedule");
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
window.location.reload();
|
|
732
|
+
} catch (err) {
|
|
733
|
+
alert("Network error. Please try again.");
|
|
734
|
+
} finally {
|
|
735
|
+
setIsLoading(false);
|
|
736
|
+
}
|
|
737
|
+
}, [broadcastId, scheduledAt]);
|
|
738
|
+
const formattedScheduledAt = scheduledAt ? new Date(scheduledAt).toLocaleString() : null;
|
|
739
|
+
return /* @__PURE__ */ jsxs6(
|
|
740
|
+
"div",
|
|
741
|
+
{
|
|
742
|
+
style: {
|
|
743
|
+
display: "flex",
|
|
744
|
+
alignItems: "center",
|
|
745
|
+
gap: "16px"
|
|
746
|
+
},
|
|
747
|
+
children: [
|
|
748
|
+
formattedScheduledAt && /* @__PURE__ */ jsxs6(
|
|
749
|
+
"span",
|
|
750
|
+
{
|
|
751
|
+
style: {
|
|
752
|
+
fontSize: "14px",
|
|
753
|
+
color: "var(--theme-elevation-600, #666)"
|
|
754
|
+
},
|
|
755
|
+
children: [
|
|
756
|
+
"Scheduled for: ",
|
|
757
|
+
/* @__PURE__ */ jsx7("strong", { children: formattedScheduledAt })
|
|
758
|
+
]
|
|
759
|
+
}
|
|
760
|
+
),
|
|
761
|
+
/* @__PURE__ */ jsxs6(
|
|
762
|
+
"button",
|
|
763
|
+
{
|
|
764
|
+
onClick: handleCancel,
|
|
765
|
+
disabled: isLoading,
|
|
766
|
+
style: {
|
|
767
|
+
padding: "8px 16px",
|
|
768
|
+
border: "1px solid var(--theme-error-500, #ef4444)",
|
|
769
|
+
borderRadius: "4px",
|
|
770
|
+
backgroundColor: "transparent",
|
|
771
|
+
color: "var(--theme-error-500, #ef4444)",
|
|
772
|
+
fontSize: "14px",
|
|
773
|
+
fontWeight: "500",
|
|
774
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
775
|
+
display: "inline-flex",
|
|
776
|
+
alignItems: "center",
|
|
777
|
+
gap: "6px",
|
|
778
|
+
opacity: isLoading ? 0.6 : 1
|
|
779
|
+
},
|
|
780
|
+
children: [
|
|
781
|
+
/* @__PURE__ */ jsx7("span", { children: "\u2715" }),
|
|
782
|
+
isLoading ? "Cancelling..." : "Cancel Schedule"
|
|
783
|
+
]
|
|
784
|
+
}
|
|
785
|
+
)
|
|
786
|
+
]
|
|
787
|
+
}
|
|
788
|
+
);
|
|
789
|
+
};
|
|
790
|
+
|
|
791
|
+
// src/components/Broadcasts/BroadcastScheduleField.tsx
|
|
792
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
793
|
+
var BroadcastScheduleField = () => {
|
|
794
|
+
const { id } = useDocumentInfo();
|
|
795
|
+
const sendStatusField = useFormFields3(([fields]) => fields.sendStatus);
|
|
796
|
+
const providerIdField = useFormFields3(([fields]) => fields.providerId);
|
|
797
|
+
const scheduledAtField = useFormFields3(([fields]) => fields.scheduledAt);
|
|
798
|
+
const sendStatus = sendStatusField?.value;
|
|
799
|
+
const providerId = providerIdField?.value;
|
|
800
|
+
const scheduledAt = scheduledAtField?.value;
|
|
801
|
+
if (!id) {
|
|
802
|
+
return /* @__PURE__ */ jsx8(
|
|
803
|
+
"div",
|
|
804
|
+
{
|
|
805
|
+
style: {
|
|
806
|
+
padding: "16px",
|
|
807
|
+
backgroundColor: "var(--theme-elevation-50, #f9f9f9)",
|
|
808
|
+
borderRadius: "4px",
|
|
809
|
+
fontSize: "14px",
|
|
810
|
+
color: "var(--theme-elevation-600, #666)"
|
|
811
|
+
},
|
|
812
|
+
children: "Save the broadcast to enable scheduling options."
|
|
813
|
+
}
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
if (sendStatus === "sent" || sendStatus === "sending") {
|
|
817
|
+
return /* @__PURE__ */ jsx8(
|
|
818
|
+
"div",
|
|
819
|
+
{
|
|
820
|
+
style: {
|
|
821
|
+
padding: "16px",
|
|
822
|
+
backgroundColor: "var(--theme-elevation-50, #f9f9f9)",
|
|
823
|
+
borderRadius: "4px",
|
|
824
|
+
fontSize: "14px",
|
|
825
|
+
color: "var(--theme-elevation-600, #666)"
|
|
826
|
+
},
|
|
827
|
+
children: sendStatus === "sent" ? "This broadcast has been sent and cannot be rescheduled." : "This broadcast is currently being sent."
|
|
828
|
+
}
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
if (sendStatus === "failed") {
|
|
832
|
+
return /* @__PURE__ */ jsx8(
|
|
833
|
+
"div",
|
|
834
|
+
{
|
|
835
|
+
style: {
|
|
836
|
+
padding: "16px",
|
|
837
|
+
backgroundColor: "var(--theme-error-100, #fef2f2)",
|
|
838
|
+
borderRadius: "4px",
|
|
839
|
+
fontSize: "14px",
|
|
840
|
+
color: "var(--theme-error-600, #dc2626)"
|
|
841
|
+
},
|
|
842
|
+
children: "This broadcast failed to send. Edit and save to return it to draft status."
|
|
843
|
+
}
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
return /* @__PURE__ */ jsx8(
|
|
847
|
+
"div",
|
|
848
|
+
{
|
|
849
|
+
style: {
|
|
850
|
+
padding: "16px",
|
|
851
|
+
backgroundColor: "var(--theme-elevation-50, #f9f9f9)",
|
|
852
|
+
borderRadius: "4px"
|
|
853
|
+
},
|
|
854
|
+
children: sendStatus === "scheduled" ? /* @__PURE__ */ jsx8(
|
|
855
|
+
CancelScheduleButton,
|
|
856
|
+
{
|
|
857
|
+
broadcastId: String(id),
|
|
858
|
+
sendStatus,
|
|
859
|
+
scheduledAt
|
|
860
|
+
}
|
|
861
|
+
) : /* @__PURE__ */ jsx8(
|
|
862
|
+
BroadcastScheduleButton,
|
|
863
|
+
{
|
|
864
|
+
broadcastId: String(id),
|
|
865
|
+
sendStatus,
|
|
866
|
+
providerId
|
|
867
|
+
}
|
|
868
|
+
)
|
|
869
|
+
}
|
|
870
|
+
);
|
|
871
|
+
};
|
|
335
872
|
export {
|
|
336
873
|
BroadcastInlinePreview,
|
|
874
|
+
BroadcastScheduleButton,
|
|
875
|
+
BroadcastScheduleField,
|
|
876
|
+
CancelScheduleButton,
|
|
337
877
|
EmailPreview,
|
|
878
|
+
ScheduleModal,
|
|
338
879
|
StatusBadge,
|
|
339
880
|
WebhookConfiguration
|
|
340
881
|
};
|
package/dist/collections.cjs
CHANGED
|
@@ -886,6 +886,20 @@ var createBroadcastInlinePreviewField = () => {
|
|
|
886
886
|
};
|
|
887
887
|
};
|
|
888
888
|
|
|
889
|
+
// src/fields/broadcastSchedule.ts
|
|
890
|
+
var createBroadcastScheduleField = () => {
|
|
891
|
+
return {
|
|
892
|
+
name: "scheduleControls",
|
|
893
|
+
type: "ui",
|
|
894
|
+
label: "Scheduling",
|
|
895
|
+
admin: {
|
|
896
|
+
components: {
|
|
897
|
+
Field: "payload-plugin-newsletter/components#BroadcastScheduleField"
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
};
|
|
902
|
+
|
|
889
903
|
// src/utils/emailSafeHtml.ts
|
|
890
904
|
var import_isomorphic_dompurify = __toESM(require("isomorphic-dompurify"), 1);
|
|
891
905
|
var EMAIL_SAFE_CONFIG = {
|
|
@@ -2080,6 +2094,8 @@ var createBroadcastsCollection = (pluginConfig) => {
|
|
|
2080
2094
|
}
|
|
2081
2095
|
}
|
|
2082
2096
|
},
|
|
2097
|
+
// Scheduling controls - shows schedule/cancel buttons based on status
|
|
2098
|
+
createBroadcastScheduleField(),
|
|
2083
2099
|
{
|
|
2084
2100
|
name: "settings",
|
|
2085
2101
|
type: "group",
|