feat: add employee push test button
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { FastifyInstance } from "fastify"
|
import { FastifyInstance } from "fastify"
|
||||||
import { and, eq, isNull } from "drizzle-orm"
|
import { and, eq, isNull } from "drizzle-orm"
|
||||||
import { authUsers, notificationMobilePushDevices } from "../../db/schema"
|
import { authProfiles, authUsers, notificationMobilePushDevices } from "../../db/schema"
|
||||||
import { NotificationService, UserDirectory } from "../modules/notification.service"
|
import { NotificationService, UserDirectory } from "../modules/notification.service"
|
||||||
import { pushServerClient } from "../modules/push-server.client"
|
import { pushServerClient } from "../modules/push-server.client"
|
||||||
|
|
||||||
@@ -174,6 +174,60 @@ export default async function notificationsRoutes(server: FastifyInstance) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
server.post("/notifications/test-push/profile/:profileId", async (req, reply) => {
|
||||||
|
const tenantId = requireTenant(req.user.tenant_id)
|
||||||
|
const { profileId } = req.params as { profileId: string }
|
||||||
|
const [profile] = await server.db
|
||||||
|
.select({
|
||||||
|
userId: authProfiles.user_id,
|
||||||
|
})
|
||||||
|
.from(authProfiles)
|
||||||
|
.where(and(
|
||||||
|
eq(authProfiles.id, profileId),
|
||||||
|
eq(authProfiles.tenant_id, tenantId)
|
||||||
|
))
|
||||||
|
.limit(1)
|
||||||
|
|
||||||
|
if (!profile) {
|
||||||
|
return reply.code(404).send({ error: "Mitarbeiter nicht gefunden" })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!profile.userId) {
|
||||||
|
return reply.code(409).send({
|
||||||
|
error: "Der Mitarbeiter ist noch nicht mit einem Benutzerkonto verknüpft",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await svc.trigger({
|
||||||
|
tenantId,
|
||||||
|
userId: profile.userId,
|
||||||
|
eventType: "system.test_push",
|
||||||
|
title: "FEDEO Push ist aktiv",
|
||||||
|
message: "Diese Testbenachrichtigung wurde einmalig über das Mitarbeiterprofil ausgelöst.",
|
||||||
|
payload: {
|
||||||
|
link: "/",
|
||||||
|
icon: "/favicon.ico",
|
||||||
|
},
|
||||||
|
channels: ["push"],
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result.created === 0) {
|
||||||
|
return reply.code(409).send({
|
||||||
|
error: "Pushnachrichten sind für diesen Mitarbeiter deaktiviert",
|
||||||
|
result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.success || result.delivered === 0) {
|
||||||
|
return reply.code(424).send({
|
||||||
|
error: "Die Pushnachricht konnte an kein aktives Gerät zugestellt werden",
|
||||||
|
result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
|
||||||
server.post("/notifications/trigger", async (req, reply) => {
|
server.post("/notifications/trigger", async (req, reply) => {
|
||||||
try {
|
try {
|
||||||
const body = req.body as any
|
const body = req.body as any
|
||||||
|
|||||||
@@ -76,6 +76,12 @@ export const useDesktopPush = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sendTestPushToProfile = async (profileId) => {
|
||||||
|
return await $api(`/api/notifications/test-push/profile/${encodeURIComponent(profileId)}`, {
|
||||||
|
method: "POST",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
supported,
|
supported,
|
||||||
permission,
|
permission,
|
||||||
@@ -85,5 +91,6 @@ export const useDesktopPush = () => {
|
|||||||
loadConfig,
|
loadConfig,
|
||||||
subscribe,
|
subscribe,
|
||||||
sendTestPush,
|
sendTestPush,
|
||||||
|
sendTestPushToProfile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const route = useRoute()
|
|||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
const auth = useAuthStore()
|
const auth = useAuthStore()
|
||||||
const admin = useAdmin()
|
const admin = useAdmin()
|
||||||
|
const desktopPush = useDesktopPush()
|
||||||
const { $api } = useNuxtApp()
|
const { $api } = useNuxtApp()
|
||||||
const runtimeConfig = useRuntimeConfig()
|
const runtimeConfig = useRuntimeConfig()
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ const creatingLinkedUser = ref(false)
|
|||||||
const createLinkedUserModalOpen = ref(false)
|
const createLinkedUserModalOpen = ref(false)
|
||||||
const createdLinkedUserPassword = ref("")
|
const createdLinkedUserPassword = ref("")
|
||||||
const generatingCalendarSubscription = ref(false)
|
const generatingCalendarSubscription = ref(false)
|
||||||
|
const sendingTestPush = ref(false)
|
||||||
const createLinkedUserForm = reactive({
|
const createLinkedUserForm = reactive({
|
||||||
email: "",
|
email: "",
|
||||||
})
|
})
|
||||||
@@ -270,6 +272,30 @@ async function copyCalendarSubscriptionUrl(value: string, successTitle: string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function sendTestPush() {
|
||||||
|
if (!profile.value?.user_id || sendingTestPush.value) return
|
||||||
|
|
||||||
|
sendingTestPush.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
await desktopPush.sendTestPushToProfile(profile.value.id)
|
||||||
|
toast.add({
|
||||||
|
title: "Test-Push gesendet",
|
||||||
|
description: `Die Nachricht wurde einmalig an ${profile.value.full_name || "den Mitarbeiter"} gesendet.`,
|
||||||
|
color: "green"
|
||||||
|
})
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error("[sendTestPush]", err)
|
||||||
|
toast.add({
|
||||||
|
title: "Test-Push fehlgeschlagen",
|
||||||
|
description: err?.data?.error || err?.message || "Die Testnachricht konnte nicht zugestellt werden.",
|
||||||
|
color: "red"
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
sendingTestPush.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const weekdays = [
|
const weekdays = [
|
||||||
{ key: '1', label: 'Montag' },
|
{ key: '1', label: 'Montag' },
|
||||||
{ key: '2', label: 'Dienstag' },
|
{ key: '2', label: 'Dienstag' },
|
||||||
@@ -456,6 +482,35 @@ onMounted(async () => {
|
|||||||
description="Lege fest, unter welcher Nebenstelle dieser Benutzer erreichbar ist."
|
description="Lege fest, unter welcher Nebenstelle dieser Benutzer erreichbar ist."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<UCard v-if="!pending && profile" class="mt-3">
|
||||||
|
<USeparator label="Push-Benachrichtigung" />
|
||||||
|
|
||||||
|
<div class="mt-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||||
|
<div>
|
||||||
|
<p class="text-sm font-medium text-gray-900 dark:text-white">Push-Zustellung testen</p>
|
||||||
|
<p class="mt-1 text-sm text-gray-500">
|
||||||
|
<template v-if="profile.user_id">
|
||||||
|
Sendet einmalig eine Testnachricht an alle aktiven Push-Geräte dieses Mitarbeiters.
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
Für einen Push-Test muss der Mitarbeiter zuerst mit einem Benutzerkonto verknüpft werden.
|
||||||
|
</template>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<UButton
|
||||||
|
icon="i-heroicons-paper-airplane"
|
||||||
|
color="neutral"
|
||||||
|
variant="outline"
|
||||||
|
:loading="sendingTestPush"
|
||||||
|
:disabled="!profile.user_id"
|
||||||
|
@click="sendTestPush"
|
||||||
|
>
|
||||||
|
Test-Push senden
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</UCard>
|
||||||
|
|
||||||
<UCard v-if="!pending && profile" class="mt-3">
|
<UCard v-if="!pending && profile" class="mt-3">
|
||||||
<USeparator label="Vertragsinformationen" />
|
<USeparator label="Vertragsinformationen" />
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user