diff --git a/components/quotes/ticket-detail-modal.tsx b/components/quotes/ticket-detail-modal.tsx index 6288bac..65835c2 100644 --- a/components/quotes/ticket-detail-modal.tsx +++ b/components/quotes/ticket-detail-modal.tsx @@ -32,6 +32,8 @@ import { // noteType values that are system/automated (workflow rules, monitoring, auto-close, etc.) const SYSTEM_NOTE_TYPES = new Set([13, 91, 93, 94, 99, 101]); +// publish=1 means Internal Users Only in Autotask +const INTERNAL_PUBLISH = 1; const URL_REGEX = /https?:\/\/[^\s<>"'\[\]()]+/g; @@ -47,12 +49,7 @@ function renderTextWithLinks(text: string): React.ReactNode[] { if (before) parts.push(before); } const url = match[0].replace(/[.,;:!?]+$/, ''); - let label: string; - try { - label = new URL(url).hostname.replace(/^www\./, ''); - } catch { - label = 'link'; - } + const label = 'link'; parts.push( { setLoading(true); @@ -117,6 +115,7 @@ export function TicketDetailModal({ ticketNumber, open, onOpenChange }: TicketDe setTimelineFetched(false); setTimelineOpen(false); setShowSystem(false); + setShowInternal(false); try { const response = await fetch(`/api/tickets/by-number/${encodeURIComponent(ticketNumber)}`); if (response.ok) { @@ -176,14 +175,14 @@ export function TicketDetailModal({ ticketNumber, open, onOpenChange }: TicketDe const visibleTimeline = useMemo( () => - showSystem - ? timeline - : timeline.filter( - (item) => - item.kind === 'time' || - !SYSTEM_NOTE_TYPES.has(item.data.noteType) - ), - [timeline, showSystem] + timeline.filter((item) => { + if (item.kind === 'time') return true; + const n = item.data; + if (!showSystem && SYSTEM_NOTE_TYPES.has(n.noteType)) return false; + if (!showInternal && n.publish === INTERNAL_PUBLISH) return false; + return true; + }), + [timeline, showSystem, showInternal] ); const systemCount = useMemo( @@ -194,6 +193,14 @@ export function TicketDetailModal({ ticketNumber, open, onOpenChange }: TicketDe [timeline] ); + const internalCount = useMemo( + () => + timeline.filter( + (item) => item.kind === 'note' && item.data.publish === INTERNAL_PUBLISH && !SYSTEM_NOTE_TYPES.has(item.data.noteType) + ).length, + [timeline] + ); + const totalHours = timeEntries.reduce((sum, e) => sum + (e.hoursWorked || 0), 0); const getStatusBadge = (status: number, label?: string | null) => { @@ -386,17 +393,29 @@ export function TicketDetailModal({ ticketNumber, open, onOpenChange }: TicketDe {!timelineLoading && timelineFetched && ( <> - {/* System notes toggle */} - {systemCount > 0 && ( -
- + {/* Toggles for system / internal notes */} + {(systemCount > 0 || internalCount > 0) && ( +
+ {internalCount > 0 && ( + + )} + {systemCount > 0 && ( + + )}
)}