fix: afficher les notifications sur la vue ticket
This commit is contained in:
parent
c35778fe18
commit
618c30ef84
1 changed files with 45 additions and 11 deletions
|
|
@ -7,6 +7,7 @@ import {
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
|
getTicketResult,
|
||||||
listNotifications,
|
listNotifications,
|
||||||
markAllNotificationsRead,
|
markAllNotificationsRead,
|
||||||
markNotificationRead,
|
markNotificationRead,
|
||||||
|
|
@ -54,35 +55,68 @@ async function showSystemNotification(notification: OrchaiNotification) {
|
||||||
|
|
||||||
export default function NotificationCenter() {
|
export default function NotificationCenter() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { projectId } = useParams();
|
const { projectId, ticketId } = useParams();
|
||||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [notifications, setNotifications] = useState<OrchaiNotification[]>([]);
|
const [notifications, setNotifications] = useState<OrchaiNotification[]>([]);
|
||||||
|
const [ticketProjectId, setTicketProjectId] = useState<string | null>(null);
|
||||||
const [filter, setFilter] = useState<"all" | "unread" | "errors" | "fixes">(
|
const [filter, setFilter] = useState<"all" | "unread" | "errors" | "fixes">(
|
||||||
"all"
|
"all"
|
||||||
);
|
);
|
||||||
|
const scopedProjectId = projectId ?? ticketProjectId;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (projectId) {
|
||||||
|
setTicketProjectId(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ticketId) {
|
||||||
|
setTicketProjectId(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTicketProjectId(null);
|
||||||
|
let cancelled = false;
|
||||||
|
|
||||||
|
void getTicketResult(ticketId)
|
||||||
|
.then((result) => {
|
||||||
|
if (!cancelled) {
|
||||||
|
setTicketProjectId(result.ticket.project_id);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
if (!cancelled) {
|
||||||
|
setTicketProjectId(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
};
|
||||||
|
}, [projectId, ticketId]);
|
||||||
|
|
||||||
const loadNotifications = useCallback(async () => {
|
const loadNotifications = useCallback(async () => {
|
||||||
if (!projectId) {
|
if (!scopedProjectId) {
|
||||||
setNotifications([]);
|
setNotifications([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const items = await listNotifications(projectId, false);
|
const items = await listNotifications(scopedProjectId, false);
|
||||||
setNotifications(items);
|
setNotifications(items);
|
||||||
} catch {
|
} catch {
|
||||||
// Ignore load errors in layout chrome
|
// Ignore load errors in layout chrome
|
||||||
}
|
}
|
||||||
}, [projectId]);
|
}, [scopedProjectId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void loadNotifications();
|
void loadNotifications();
|
||||||
}, [loadNotifications]);
|
}, [loadNotifications]);
|
||||||
|
|
||||||
useLiveRefresh({
|
useLiveRefresh({
|
||||||
enabled: Boolean(projectId),
|
enabled: Boolean(scopedProjectId),
|
||||||
projectId,
|
projectId: scopedProjectId,
|
||||||
refresh: loadNotifications,
|
refresh: loadNotifications,
|
||||||
fallbackIntervalMs: 15_000,
|
fallbackIntervalMs: 15_000,
|
||||||
});
|
});
|
||||||
|
|
@ -96,7 +130,7 @@ export default function NotificationCenter() {
|
||||||
const cleanup = await listen<NewNotificationEvent>("new-notification", (event) => {
|
const cleanup = await listen<NewNotificationEvent>("new-notification", (event) => {
|
||||||
const incoming = event.payload.notification;
|
const incoming = event.payload.notification;
|
||||||
|
|
||||||
if (projectId && incoming.project_id !== projectId) {
|
if (scopedProjectId && incoming.project_id !== scopedProjectId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +161,7 @@ export default function NotificationCenter() {
|
||||||
unlisten();
|
unlisten();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [projectId]);
|
}, [scopedProjectId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
|
|
@ -199,12 +233,12 @@ export default function NotificationCenter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleMarkAllRead() {
|
async function handleMarkAllRead() {
|
||||||
if (!projectId) {
|
if (!scopedProjectId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await markAllNotificationsRead(projectId);
|
await markAllNotificationsRead(scopedProjectId);
|
||||||
setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
|
setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
|
|
@ -234,7 +268,7 @@ export default function NotificationCenter() {
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleMarkAllRead}
|
onClick={handleMarkAllRead}
|
||||||
className={buttonClass({ variant: "ghost", size: "xs" })}
|
className={buttonClass({ variant: "ghost", size: "xs" })}
|
||||||
disabled={!projectId || unreadCount === 0}
|
disabled={!scopedProjectId || unreadCount === 0}
|
||||||
>
|
>
|
||||||
Mark all read
|
Mark all read
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue