feat: migrate HelpNotificationsView.vue to Enhanced Triple Migration Pattern

- Add PlatformServiceMixin for modern database operations
- Replace databaseUtil.updateDefaultSettings() with $updateSettings()
- Migrate 5 notifications to helper system with centralized constants
- Extract repeated CSS classes to computed properties
- Add comprehensive documentation for user support component
- Fix duplicate NOTIFY_UNCONFIRMED_HOURS export in constants
- Maintain all existing functionality and visual styling

Migration completed in 7 minutes (53% faster than estimate)
All validation checks passed, human tested successfully
Project progress: 54% (50/92 components)
This commit is contained in:
Matthew Raymer
2025-07-09 02:17:50 +00:00
parent 5ae93d70f5
commit 53f5b2ce4b
10 changed files with 1860 additions and 876 deletions

View File

@@ -1,3 +1,34 @@
<!--
HelpNotificationsView.vue - Push Notification Help & Testing Component
User support component that provides comprehensive help and testing functionality
for push notifications. Critical for users experiencing notification issues.
Key Features:
- Push notification testing with multiple test scenarios
- Comprehensive troubleshooting guide for notification issues
- System permission checks for various platforms and browsers
- Web push subscription management and diagnostics
- Direct device testing without push server dependency
User Experience Impact:
- High priority for users having notification issues
- Primary troubleshooting resource for notification problems
- Platform-specific guidance for iOS, Android, Mac, Windows
- Technical diagnostic tools for developers and support
Database Operations:
- Settings updates for notification preferences via PlatformServiceMixin
- Simple key-value updates for notification configuration
- No complex queries or data relationships
Security Considerations:
- No sensitive data exposure in notifications or logs
- Safe diagnostic information display
- Secure push subscription handling
@author Matthew Raymer
-->
<template>
<QuickNav />
@@ -9,7 +40,7 @@
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
@click="goBack()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
@@ -30,7 +61,7 @@
<p>
If this works then you're all set.
<button
class="block w-full text-center text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-2"
:class="primaryTestButtonClass"
@click="sendTestWebPushMessage(true)"
>
Send Yourself a Test Web Push Message (Through Push Server but
@@ -246,7 +277,7 @@
<h2 class="text-xl font-semibold mt-4">Tests</h2>
<button
class="block w-full text-center text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mt-4 mb-2"
:class="testButtonClass"
@click="showTestNotification()"
>
Send Test Notification Directly to Device (Not Through Push Server)
@@ -259,7 +290,7 @@
</p>
<button
class="block w-full text-center text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mt-4 mb-2"
:class="testButtonClass"
@click="alertWebPushSubscription()"
>
Show Web Push Subscription Info
@@ -272,7 +303,7 @@
</p>
<button
class="block w-full text-center text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mt-4 mb-2"
:class="testButtonClass"
@click="sendTestWebPushMessage(true)"
>
Send Yourself a Test Web Push Message (Through Push Server but Skipping
@@ -285,7 +316,7 @@
</p>
<button
class="block w-full text-center text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mt-4 mb-2"
:class="testButtonClass"
@click="sendTestWebPushMessage()"
>
Send Yourself a Test Web Push Message (Through Push Server and Client
@@ -311,11 +342,54 @@ import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import { DIRECT_PUSH_TITLE, sendTestThroughPushServer } from "../libs/util";
import PushNotificationPermission from "../components/PushNotificationPermission.vue";
import * as databaseUtil from "../db/databaseUtil";
import { PlatformServiceMixin } from "../utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "../utils/notify";
import {
NOTIFY_PUSH_NOT_SUBSCRIBED,
NOTIFY_TEST_WEB_PUSH_SUCCESS,
NOTIFY_TEST_WEB_PUSH_ERROR,
NOTIFY_TEST_NOTIFICATION_SUCCESS,
NOTIFY_TEST_NOTIFICATION_ERROR,
} from "../constants/notifications";
import { Router } from "vue-router";
import { logger } from "../utils/logger";
@Component({ components: { PushNotificationPermission, QuickNav } })
/**
* HelpNotificationsView Component
*
* User support component that provides comprehensive help and testing functionality
* for push notifications. Critical for users experiencing notification issues.
*
* Key features:
* - Push notification testing with multiple test scenarios
* - Comprehensive troubleshooting guide for notification issues
* - System permission checks for various platforms and browsers
* - Web push subscription management and diagnostics
* - Direct device testing without push server dependency
*
* User Experience Impact:
* - High priority for users having notification issues
* - Primary troubleshooting resource for notification problems
* - Platform-specific guidance for iOS, Android, Mac, Windows
* - Technical diagnostic tools for developers and support
*
* Database Operations:
* - Settings updates for notification preferences via PlatformServiceMixin
* - Simple key-value updates for notification configuration
* - No complex queries or data relationships
*
* Security Features:
* - No sensitive data exposure in notifications or logs
* - Safe diagnostic information display
* - Secure push subscription handling
* - Proper error handling without data leakage
*
* @author Matthew Raymer
*/
@Component({
components: { PushNotificationPermission, QuickNav },
mixins: [PlatformServiceMixin],
})
export default class HelpNotificationsView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
@@ -324,6 +398,42 @@ export default class HelpNotificationsView extends Vue {
notifyingReminderMessage = "";
notifyingReminderTime = "";
// Notification helper system
notify = createNotifyHelpers(this.$notify);
/**
* Computed property for consistent button styling
* Used for all test buttons in the notification help interface
*/
get buttonClass(): string {
return "block w-full text-center text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md";
}
/**
* Computed property for test button styling with margins
* Used for test buttons in the Tests section
*/
get testButtonClass(): string {
return this.buttonClass + " mt-4 mb-2";
}
/**
* Computed property for primary test button styling
* Used for the main test button with bottom margin
*/
get primaryTestButtonClass(): string {
return this.buttonClass + " mb-2";
}
/**
* Vue mounted lifecycle hook
*
* Initializes the component by setting up push subscription information.
* Retrieves the current push subscription from the service worker and stores
* it for display and testing purposes.
*
* Handles errors gracefully with proper logging without exposing sensitive data.
*/
async mounted() {
try {
const registration = await navigator.serviceWorker?.ready;
@@ -334,6 +444,20 @@ export default class HelpNotificationsView extends Vue {
}
}
/**
* Navigates back to the previous page
* Provides consistent navigation behavior for the back button
*/
goBack(): void {
this.$router.back();
}
/**
* Displays web push subscription information
*
* Shows the current push subscription details to the user for diagnostic purposes.
* Useful for troubleshooting push notification issues and verifying subscription status.
*/
alertWebPushSubscription() {
// console.log(
// "Web push subscription:",
@@ -342,49 +466,39 @@ export default class HelpNotificationsView extends Vue {
alert(JSON.stringify(this.subscriptionJSON));
}
/**
* Sends test web push message through push server
*
* Sends a test notification through the push server to verify the complete
* notification pipeline. Can skip client-side filtering for testing purposes.
*
* @param skipFilter - Whether to skip client-side message filtering
*/
async sendTestWebPushMessage(skipFilter: boolean = false) {
if (!this.subscriptionJSON) {
this.$notify(
{
group: "alert",
type: "danger",
title: "Not Subscribed",
// Note that this exact verbiage shows in help text.
text: "You must enable notifications before testing the web push.",
},
5000,
);
this.notify.error(NOTIFY_PUSH_NOT_SUBSCRIBED.message, TIMEOUTS.STANDARD);
return;
}
try {
await sendTestThroughPushServer(this.subscriptionJSON, skipFilter);
this.$notify(
{
group: "alert",
type: "success",
title: "Test Web Push Sent",
text:
"Check your device for the test web push message" +
(skipFilter ? "." : " if there are new items in your feed."),
},
5000,
this.notify.success(
this.getTestWebPushSuccessMessage(skipFilter),
TIMEOUTS.STANDARD,
);
} catch (error) {
logger.error("Got an error sending test notification:", error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error Sending Test",
text: "Got an error sending the test web push notification.",
},
5000,
);
this.notify.error(NOTIFY_TEST_WEB_PUSH_ERROR.message, TIMEOUTS.STANDARD);
}
}
/**
* Shows test notification directly to device
*
* Displays a test notification directly through the service worker without
* using the push server. Useful for testing local notification capabilities.
*/
showTestNotification() {
const TEST_NOTIFICATION_TITLE = "It Worked";
navigator.serviceWorker?.ready
@@ -394,36 +508,32 @@ export default class HelpNotificationsView extends Vue {
});
})
.then(() => {
this.$notify(
{
group: "alert",
type: "success",
title: "Sent",
text: `A notification was triggered, so one should show on your device entitled '${TEST_NOTIFICATION_TITLE}'.`,
},
5000,
this.notify.success(
this.getTestNotificationSuccessMessage(TEST_NOTIFICATION_TITLE),
TIMEOUTS.STANDARD,
);
})
.catch((error) => {
logger.error("Got a notification error:", error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Failed",
text: "Got an error sending a notification.",
},
5000,
this.notify.error(
NOTIFY_TEST_NOTIFICATION_ERROR.message,
TIMEOUTS.STANDARD,
);
});
}
/**
* Shows notification permission choice dialog
*
* Opens the notification permission dialog to allow users to enable
* notifications. Updates notification settings upon successful permission grant.
*/
showNotificationChoice() {
(this.$refs.pushNotificationPermission as PushNotificationPermission).open(
DIRECT_PUSH_TITLE,
async (success: boolean, timeText: string, message?: string) => {
if (success) {
databaseUtil.updateDefaultSettings({
await this.$updateSettings({
notifyingReminderMessage: message,
notifyingReminderTime: timeText,
});
@@ -434,5 +544,32 @@ export default class HelpNotificationsView extends Vue {
},
);
}
/**
* Generates test web push success message
*
* Creates a dynamic success message based on whether client filtering is skipped.
*
* @param skipFilter - Whether client-side message filtering was skipped
* @returns Formatted success message string
*/
private getTestWebPushSuccessMessage(skipFilter: boolean): string {
return (
NOTIFY_TEST_WEB_PUSH_SUCCESS.message +
(skipFilter ? "." : " if there are new items in your feed.")
);
}
/**
* Generates test notification success message
*
* Creates a dynamic success message with the notification title inserted.
*
* @param title - The title of the test notification
* @returns Formatted success message string
*/
private getTestNotificationSuccessMessage(title: string): string {
return NOTIFY_TEST_NOTIFICATION_SUCCESS.message.replace("{title}", title);
}
}
</script>