Extract notification section into reusable component
- Created NotificationSection.vue with complete notification functionality - Updated AccountViewView to use new component via props - Removed notification methods from AccountViewView - Fixed FontAwesome import to use FontAwesomeIcon - Cleaned up unused imports and dependencies
This commit is contained in:
212
src/components/NotificationSection.vue
Normal file
212
src/components/NotificationSection.vue
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
<template>
|
||||||
|
<section
|
||||||
|
v-if="isRegistered"
|
||||||
|
id="sectionNotifications"
|
||||||
|
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
||||||
|
aria-labelledby="notificationsHeading"
|
||||||
|
>
|
||||||
|
<h2 id="notificationsHeading" class="mb-2 font-bold">Notifications</h2>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
Reminder Notification
|
||||||
|
<button
|
||||||
|
class="text-slate-400 fa-fw cursor-pointer"
|
||||||
|
aria-label="Learn more about reminder notifications"
|
||||||
|
@click.stop="showReminderNotificationInfo"
|
||||||
|
>
|
||||||
|
<font-awesome-icon
|
||||||
|
icon="question-circle"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="relative ml-2 cursor-pointer"
|
||||||
|
role="switch"
|
||||||
|
:aria-checked="notifyingReminder"
|
||||||
|
aria-label="Toggle reminder notifications"
|
||||||
|
tabindex="0"
|
||||||
|
@click="showReminderNotificationChoice()"
|
||||||
|
>
|
||||||
|
<!-- input -->
|
||||||
|
<input v-model="notifyingReminder" type="checkbox" class="sr-only" />
|
||||||
|
<!-- line -->
|
||||||
|
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div>
|
||||||
|
<!-- dot -->
|
||||||
|
<div
|
||||||
|
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="notifyingReminder" class="w-full flex justify-between">
|
||||||
|
<span class="ml-8 mr-8">Message: "{{ notifyingReminderMessage }}"</span>
|
||||||
|
<span>{{ notifyingReminderTime.replace(" ", " ") }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 flex items-center justify-between">
|
||||||
|
<!-- label -->
|
||||||
|
<div>
|
||||||
|
New Activity Notification
|
||||||
|
<font-awesome-icon
|
||||||
|
icon="question-circle"
|
||||||
|
class="text-slate-400 fa-fw cursor-pointer"
|
||||||
|
@click.stop="showNewActivityNotificationInfo"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- toggle -->
|
||||||
|
<div
|
||||||
|
class="relative ml-2 cursor-pointer"
|
||||||
|
@click="showNewActivityNotificationChoice()"
|
||||||
|
>
|
||||||
|
<!-- input -->
|
||||||
|
<input v-model="notifyingNewActivity" type="checkbox" class="sr-only" />
|
||||||
|
<!-- line -->
|
||||||
|
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div>
|
||||||
|
<!-- dot -->
|
||||||
|
<div
|
||||||
|
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="notifyingNewActivityTime" class="w-full text-right">
|
||||||
|
{{ notifyingNewActivityTime.replace(" ", " ") }}
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 text-center">
|
||||||
|
<router-link class="text-sm text-blue-500" to="/help-notifications">
|
||||||
|
Troubleshoot your notifications…
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<PushNotificationPermission ref="pushNotificationPermission" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
|
import { Router } from "vue-router";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||||
|
import PushNotificationPermission from "./PushNotificationPermission.vue";
|
||||||
|
import { createNotifyHelpers } from "@/utils/notify";
|
||||||
|
import { ACCOUNT_VIEW_CONSTANTS } from "@/constants/accountView";
|
||||||
|
import { DAILY_CHECK_TITLE, DIRECT_PUSH_TITLE } from "@/libs/util";
|
||||||
|
import { NotificationIface } from "@/constants/app";
|
||||||
|
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NotificationSection.vue - Extracted notification management component
|
||||||
|
*
|
||||||
|
* This component handles all notification-related functionality including:
|
||||||
|
* - Reminder notifications with custom messages
|
||||||
|
* - New activity notifications
|
||||||
|
* - Notification permission management
|
||||||
|
* - Help and troubleshooting links
|
||||||
|
*
|
||||||
|
* @author Matthew Raymer
|
||||||
|
* @component NotificationSection
|
||||||
|
* @vue-facing-decorator
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
FontAwesomeIcon,
|
||||||
|
PushNotificationPermission,
|
||||||
|
},
|
||||||
|
mixins: [PlatformServiceMixin],
|
||||||
|
})
|
||||||
|
export default class NotificationSection extends Vue {
|
||||||
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||||
|
$router!: Router;
|
||||||
|
|
||||||
|
// Props
|
||||||
|
isRegistered: boolean = false;
|
||||||
|
notifyingNewActivity: boolean = false;
|
||||||
|
notifyingNewActivityTime: string = "";
|
||||||
|
notifyingReminder: boolean = false;
|
||||||
|
notifyingReminderMessage: string = "";
|
||||||
|
notifyingReminderTime: string = "";
|
||||||
|
|
||||||
|
private notify!: ReturnType<typeof createNotifyHelpers>;
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.notify = createNotifyHelpers(this.$notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
async showNewActivityNotificationInfo(): Promise<void> {
|
||||||
|
this.notify.confirm(
|
||||||
|
ACCOUNT_VIEW_CONSTANTS.NOTIFICATIONS.NEW_ACTIVITY_INFO,
|
||||||
|
async () => {
|
||||||
|
await (this.$router as Router).push({
|
||||||
|
name: "help-notification-types",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async showNewActivityNotificationChoice(): Promise<void> {
|
||||||
|
if (!this.notifyingNewActivity) {
|
||||||
|
(
|
||||||
|
this.$refs.pushNotificationPermission as PushNotificationPermission
|
||||||
|
).open(DAILY_CHECK_TITLE, async (success: boolean, timeText: string) => {
|
||||||
|
if (success) {
|
||||||
|
await this.$saveSettings({
|
||||||
|
notifyingNewActivityTime: timeText,
|
||||||
|
});
|
||||||
|
this.notifyingNewActivity = true;
|
||||||
|
this.notifyingNewActivityTime = timeText;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.notify.notificationOff(DAILY_CHECK_TITLE, async (success) => {
|
||||||
|
if (success) {
|
||||||
|
await this.$saveSettings({
|
||||||
|
notifyingNewActivityTime: "",
|
||||||
|
});
|
||||||
|
this.notifyingNewActivity = false;
|
||||||
|
this.notifyingNewActivityTime = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async showReminderNotificationInfo(): Promise<void> {
|
||||||
|
this.notify.confirm(
|
||||||
|
ACCOUNT_VIEW_CONSTANTS.NOTIFICATIONS.REMINDER_INFO,
|
||||||
|
async () => {
|
||||||
|
await (this.$router as Router).push({
|
||||||
|
name: "help-notification-types",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async showReminderNotificationChoice(): Promise<void> {
|
||||||
|
if (!this.notifyingReminder) {
|
||||||
|
(
|
||||||
|
this.$refs.pushNotificationPermission as PushNotificationPermission
|
||||||
|
).open(
|
||||||
|
DIRECT_PUSH_TITLE,
|
||||||
|
async (success: boolean, timeText: string, message?: string) => {
|
||||||
|
if (success) {
|
||||||
|
await this.$saveSettings({
|
||||||
|
notifyingReminderMessage: message,
|
||||||
|
notifyingReminderTime: timeText,
|
||||||
|
});
|
||||||
|
this.notifyingReminder = true;
|
||||||
|
this.notifyingReminderMessage = message || "";
|
||||||
|
this.notifyingReminderTime = timeText;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.notify.notificationOff(DIRECT_PUSH_TITLE, async (success) => {
|
||||||
|
if (success) {
|
||||||
|
await this.$saveSettings({
|
||||||
|
notifyingReminderMessage: "",
|
||||||
|
notifyingReminderTime: "",
|
||||||
|
});
|
||||||
|
this.notifyingReminder = false;
|
||||||
|
this.notifyingReminderMessage = "";
|
||||||
|
this.notifyingReminderTime = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -60,88 +60,14 @@
|
|||||||
@share-info="onShareInfo"
|
@share-info="onShareInfo"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<section
|
<NotificationSection
|
||||||
v-if="isRegistered"
|
:is-registered="isRegistered"
|
||||||
id="sectionNotifications"
|
:notifying-new-activity="notifyingNewActivity"
|
||||||
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
:notifying-new-activity-time="notifyingNewActivityTime"
|
||||||
aria-labelledby="notificationsHeading"
|
:notifying-reminder="notifyingReminder"
|
||||||
>
|
:notifying-reminder-message="notifyingReminderMessage"
|
||||||
<h2 id="notificationsHeading" class="mb-2 font-bold">Notifications</h2>
|
:notifying-reminder-time="notifyingReminderTime"
|
||||||
<div class="flex items-center justify-between">
|
/>
|
||||||
<div>
|
|
||||||
Reminder Notification
|
|
||||||
<button
|
|
||||||
class="text-slate-400 fa-fw cursor-pointer"
|
|
||||||
aria-label="Learn more about reminder notifications"
|
|
||||||
@click.stop="showReminderNotificationInfo"
|
|
||||||
>
|
|
||||||
<font-awesome
|
|
||||||
icon="question-circle"
|
|
||||||
aria-hidden="true"
|
|
||||||
></font-awesome>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="relative ml-2 cursor-pointer"
|
|
||||||
role="switch"
|
|
||||||
:aria-checked="notifyingReminder"
|
|
||||||
aria-label="Toggle reminder notifications"
|
|
||||||
tabindex="0"
|
|
||||||
@click="showReminderNotificationChoice()"
|
|
||||||
>
|
|
||||||
<!-- input -->
|
|
||||||
<input v-model="notifyingReminder" type="checkbox" class="sr-only" />
|
|
||||||
<!-- line -->
|
|
||||||
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div>
|
|
||||||
<!-- dot -->
|
|
||||||
<div
|
|
||||||
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="notifyingReminder" class="w-full flex justify-between">
|
|
||||||
<span class="ml-8 mr-8">Message: "{{ notifyingReminderMessage }}"</span>
|
|
||||||
<span>{{ notifyingReminderTime.replace(" ", " ") }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="mt-2 flex items-center justify-between">
|
|
||||||
<!-- label -->
|
|
||||||
<div>
|
|
||||||
New Activity Notification
|
|
||||||
<font-awesome
|
|
||||||
icon="question-circle"
|
|
||||||
class="text-slate-400 fa-fw cursor-pointer"
|
|
||||||
@click.stop="showNewActivityNotificationInfo"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<!-- toggle -->
|
|
||||||
<div
|
|
||||||
class="relative ml-2 cursor-pointer"
|
|
||||||
@click="showNewActivityNotificationChoice()"
|
|
||||||
>
|
|
||||||
<!-- input -->
|
|
||||||
<input
|
|
||||||
v-model="notifyingNewActivity"
|
|
||||||
type="checkbox"
|
|
||||||
class="sr-only"
|
|
||||||
/>
|
|
||||||
<!-- line -->
|
|
||||||
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div>
|
|
||||||
<!-- dot -->
|
|
||||||
<div
|
|
||||||
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="notifyingNewActivityTime" class="w-full text-right">
|
|
||||||
{{ notifyingNewActivityTime.replace(" ", " ") }}
|
|
||||||
</div>
|
|
||||||
<div class="mt-2 text-center">
|
|
||||||
<router-link class="text-sm text-blue-500" to="/help-notifications">
|
|
||||||
Troubleshoot your notifications…
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<PushNotificationPermission ref="pushNotificationPermission" />
|
|
||||||
|
|
||||||
<LocationSearchSection :search-box="searchBox" />
|
<LocationSearchSection :search-box="searchBox" />
|
||||||
|
|
||||||
@@ -759,12 +685,13 @@ import { Capacitor } from "@capacitor/core";
|
|||||||
|
|
||||||
import EntityIcon from "../components/EntityIcon.vue";
|
import EntityIcon from "../components/EntityIcon.vue";
|
||||||
import ImageMethodDialog from "../components/ImageMethodDialog.vue";
|
import ImageMethodDialog from "../components/ImageMethodDialog.vue";
|
||||||
import PushNotificationPermission from "../components/PushNotificationPermission.vue";
|
|
||||||
import QuickNav from "../components/QuickNav.vue";
|
import QuickNav from "../components/QuickNav.vue";
|
||||||
import TopMessage from "../components/TopMessage.vue";
|
import TopMessage from "../components/TopMessage.vue";
|
||||||
import UserNameDialog from "../components/UserNameDialog.vue";
|
import UserNameDialog from "../components/UserNameDialog.vue";
|
||||||
import DataExportSection from "../components/DataExportSection.vue";
|
import DataExportSection from "../components/DataExportSection.vue";
|
||||||
import IdentitySection from "@/components/IdentitySection.vue";
|
import IdentitySection from "@/components/IdentitySection.vue";
|
||||||
|
import NotificationSection from "@/components/NotificationSection.vue";
|
||||||
import RegistrationNotice from "@/components/RegistrationNotice.vue";
|
import RegistrationNotice from "@/components/RegistrationNotice.vue";
|
||||||
import LocationSearchSection from "@/components/LocationSearchSection.vue";
|
import LocationSearchSection from "@/components/LocationSearchSection.vue";
|
||||||
import UsageLimitsSection from "@/components/UsageLimitsSection.vue";
|
import UsageLimitsSection from "@/components/UsageLimitsSection.vue";
|
||||||
@@ -790,11 +717,7 @@ import {
|
|||||||
getHeaders,
|
getHeaders,
|
||||||
tokenExpiryTimeDescription,
|
tokenExpiryTimeDescription,
|
||||||
} from "../libs/endorserServer";
|
} from "../libs/endorserServer";
|
||||||
import {
|
import { retrieveAccountMetadata } from "../libs/util";
|
||||||
DAILY_CHECK_TITLE,
|
|
||||||
DIRECT_PUSH_TITLE,
|
|
||||||
retrieveAccountMetadata,
|
|
||||||
} from "../libs/util";
|
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
import { PlatformServiceMixin } from "../utils/PlatformServiceMixin";
|
import { PlatformServiceMixin } from "../utils/PlatformServiceMixin";
|
||||||
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
||||||
@@ -823,7 +746,7 @@ interface UserNameDialogRef {
|
|||||||
LMap,
|
LMap,
|
||||||
LMarker,
|
LMarker,
|
||||||
LTileLayer,
|
LTileLayer,
|
||||||
PushNotificationPermission,
|
NotificationSection,
|
||||||
QuickNav,
|
QuickNav,
|
||||||
TopMessage,
|
TopMessage,
|
||||||
UserNameDialog,
|
UserNameDialog,
|
||||||
@@ -1102,87 +1025,6 @@ export default class AccountViewView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async showNewActivityNotificationInfo(): Promise<void> {
|
|
||||||
this.notify.confirm(
|
|
||||||
ACCOUNT_VIEW_CONSTANTS.NOTIFICATIONS.NEW_ACTIVITY_INFO,
|
|
||||||
async () => {
|
|
||||||
await (this.$router as Router).push({
|
|
||||||
name: "help-notification-types",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async showNewActivityNotificationChoice(): Promise<void> {
|
|
||||||
if (!this.notifyingNewActivity) {
|
|
||||||
(
|
|
||||||
this.$refs.pushNotificationPermission as PushNotificationPermission
|
|
||||||
).open(DAILY_CHECK_TITLE, async (success: boolean, timeText: string) => {
|
|
||||||
if (success) {
|
|
||||||
await this.$saveSettings({
|
|
||||||
notifyingNewActivityTime: timeText,
|
|
||||||
});
|
|
||||||
this.notifyingNewActivity = true;
|
|
||||||
this.notifyingNewActivityTime = timeText;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.notify.notificationOff(DAILY_CHECK_TITLE, async (success) => {
|
|
||||||
if (success) {
|
|
||||||
await this.$saveSettings({
|
|
||||||
notifyingNewActivityTime: "",
|
|
||||||
});
|
|
||||||
this.notifyingNewActivity = false;
|
|
||||||
this.notifyingNewActivityTime = "";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async showReminderNotificationInfo(): Promise<void> {
|
|
||||||
this.notify.confirm(
|
|
||||||
ACCOUNT_VIEW_CONSTANTS.NOTIFICATIONS.REMINDER_INFO,
|
|
||||||
async () => {
|
|
||||||
await (this.$router as Router).push({
|
|
||||||
name: "help-notification-types",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async showReminderNotificationChoice(): Promise<void> {
|
|
||||||
if (!this.notifyingReminder) {
|
|
||||||
(
|
|
||||||
this.$refs.pushNotificationPermission as PushNotificationPermission
|
|
||||||
).open(
|
|
||||||
DIRECT_PUSH_TITLE,
|
|
||||||
async (success: boolean, timeText: string, message?: string) => {
|
|
||||||
if (success) {
|
|
||||||
await this.$saveSettings({
|
|
||||||
notifyingReminderMessage: message,
|
|
||||||
notifyingReminderTime: timeText,
|
|
||||||
});
|
|
||||||
this.notifyingReminder = true;
|
|
||||||
this.notifyingReminderMessage = message || "";
|
|
||||||
this.notifyingReminderTime = timeText;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.notify.notificationOff(DIRECT_PUSH_TITLE, async (success) => {
|
|
||||||
if (success) {
|
|
||||||
await this.$saveSettings({
|
|
||||||
notifyingReminderMessage: "",
|
|
||||||
notifyingReminderTime: "",
|
|
||||||
});
|
|
||||||
this.notifyingReminder = false;
|
|
||||||
this.notifyingReminderMessage = "";
|
|
||||||
this.notifyingReminderTime = "";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async toggleHideRegisterPromptOnNewContact(): Promise<void> {
|
public async toggleHideRegisterPromptOnNewContact(): Promise<void> {
|
||||||
const newSetting = !this.hideRegisterPromptOnNewContact;
|
const newSetting = !this.hideRegisterPromptOnNewContact;
|
||||||
await this.$saveSettings({
|
await this.$saveSettings({
|
||||||
|
|||||||
Reference in New Issue
Block a user