Add a development-only button to send test push notifications to all subscribers.
Replit-Commit-Author: Agent Replit-Commit-Session-Id: 0aa507c2-4fa6-42bc-9ce7-ee6f559c10a5 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/9dda30b6-4149-4bce-89dc-76333005952c/c6cce535-1f81-43c1-8b69-181a5f1f9aa1.jpg
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
||||
Rss,
|
||||
Bell,
|
||||
BellOff,
|
||||
BellRing,
|
||||
} from "lucide-react";
|
||||
import { useNewsletters, useNewsletterSearch, type NewslettersResponse } from "@/lib/newsletter-data";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
@@ -35,6 +36,7 @@ const ITEMS_PER_PAGE = 20;
|
||||
export default function Home() {
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [isImporting, setIsImporting] = useState(false);
|
||||
const [isSendingTestNotification, setIsSendingTestNotification] = useState(false);
|
||||
const [page, setPage] = useState(1);
|
||||
const [isSubscribed, setIsSubscribed] = useState(false);
|
||||
const [allItems, setAllItems] = useState<Newsletter[]>([]);
|
||||
@@ -134,6 +136,25 @@ export default function Home() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleSendTestNotification = async () => {
|
||||
try {
|
||||
setIsSendingTestNotification(true);
|
||||
const response = await apiRequest("POST", "/api/notifications/test");
|
||||
toast({
|
||||
title: "Test Notifications Sent",
|
||||
description: `Results: ${response.succeeded} succeeded, ${response.failed} failed out of ${response.total} subscriptions`,
|
||||
});
|
||||
} catch (error: any) {
|
||||
toast({
|
||||
title: "Error",
|
||||
description: error.message || "Failed to send test notifications",
|
||||
variant: "destructive",
|
||||
});
|
||||
} finally {
|
||||
setIsSendingTestNotification(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubscribe = async () => {
|
||||
try {
|
||||
if (!("serviceWorker" in navigator) || !("Notification" in window)) {
|
||||
@@ -243,16 +264,29 @@ export default function Home() {
|
||||
/>
|
||||
</div>
|
||||
{isDevelopment && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={handleImport}
|
||||
disabled={isImporting}
|
||||
>
|
||||
<RefreshCw
|
||||
className={`h-4 w-4 ${isImporting ? "animate-spin" : ""}`}
|
||||
/>
|
||||
</Button>
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={handleImport}
|
||||
disabled={isImporting}
|
||||
>
|
||||
<RefreshCw
|
||||
className={`h-4 w-4 ${isImporting ? "animate-spin" : ""}`}
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={handleSendTestNotification}
|
||||
disabled={isSendingTestNotification}
|
||||
title="Send test notification to all subscribers"
|
||||
>
|
||||
<BellRing
|
||||
className={`h-4 w-4 ${isSendingTestNotification ? "animate-pulse" : ""}`}
|
||||
/>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
|
||||
@@ -309,6 +309,63 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
}
|
||||
});
|
||||
|
||||
// New endpoint for sending test notifications to all subscribers
|
||||
app.post("/api/notifications/test", async (_req, res) => {
|
||||
try {
|
||||
// Only allow this in development mode
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
return res.status(403).json({ message: "This endpoint is only available in development mode" });
|
||||
}
|
||||
|
||||
const subscriptions = await storage.getActiveSubscriptions();
|
||||
|
||||
if (subscriptions.length === 0) {
|
||||
return res.status(200).json({ message: "No active subscriptions found" });
|
||||
}
|
||||
|
||||
console.log(`Sending test notification to ${subscriptions.length} subscribers`);
|
||||
|
||||
const notificationPayload = JSON.stringify({
|
||||
title: "Test Notification",
|
||||
body: "This is a test notification from The Downtowner",
|
||||
icon: "/icon.png",
|
||||
});
|
||||
|
||||
const results = await Promise.allSettled(
|
||||
subscriptions.map((subscription) =>
|
||||
webpush.sendNotification(
|
||||
{
|
||||
endpoint: subscription.endpoint,
|
||||
keys: {
|
||||
auth: subscription.auth,
|
||||
p256dh: subscription.p256dh,
|
||||
},
|
||||
},
|
||||
notificationPayload,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
const succeeded = results.filter((r) => r.status === "fulfilled").length;
|
||||
const failed = results.filter((r) => r.status === "rejected").length;
|
||||
|
||||
console.log(`Test notification results: ${succeeded} succeeded, ${failed} failed`);
|
||||
|
||||
res.status(200).json({
|
||||
message: `Test notifications sent: ${succeeded} succeeded, ${failed} failed`,
|
||||
succeeded,
|
||||
failed,
|
||||
total: subscriptions.length
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error sending test notifications:", error);
|
||||
res.status(500).json({
|
||||
message: "Failed to send test notifications",
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/subscriptions", async (req, res) => {
|
||||
try {
|
||||
console.log("Received subscription request:", {
|
||||
|
||||
Reference in New Issue
Block a user