@@ -40,7 +40,7 @@ import { Button, LinkButton } from "~/components/primitives/Buttons";
4040import { Callout } from "~/components/primitives/Callout" ;
4141import { formatDateTime , RelativeDateTime } from "~/components/primitives/DateTime" ;
4242import { Header3 } from "~/components/primitives/Headers" ;
43- import { NavBar , PageTitle } from "~/components/primitives/PageHeader" ;
43+ import { NavBar , PageAccessories , PageTitle } from "~/components/primitives/PageHeader" ;
4444import { Paragraph } from "~/components/primitives/Paragraph" ;
4545import { PopoverSectionHeader } from "~/components/primitives/Popover" ;
4646import { SearchInput } from "~/components/primitives/SearchInput" ;
@@ -67,10 +67,15 @@ import { SimpleTooltip } from "~/components/primitives/Tooltip";
6767import TooltipPortal from "~/components/primitives/TooltipPortal" ;
6868import { appliedSummary , FilterMenuProvider , TimeFilter } from "~/components/runs/v3/SharedFilters" ;
6969import { $replica } from "~/db.server" ;
70+ import { useEnvironment } from "~/hooks/useEnvironment" ;
71+ import { useOrganization } from "~/hooks/useOrganizations" ;
72+ import { useProject } from "~/hooks/useProject" ;
73+ import { CreateAlertButton } from "~/components/alerts/CreateAlertButton" ;
74+ import { NEW_ERROR_ALERT_PREFILL } from "~/components/alerts/errorAlertPrefill" ;
7075import { useInterval } from "~/hooks/useInterval" ;
7176import { useOptimisticLocation } from "~/hooks/useOptimisticLocation" ;
7277import { useSearchParams } from "~/hooks/useSearchParam" ;
73- import { findProjectBySlug } from "~/models/project.server" ;
78+ import { findProjectWithOrgFlagsBySlug } from "~/models/project.server" ;
7479import { findEnvironmentBySlug } from "~/models/runtimeEnvironment.server" ;
7580import {
7681 ErrorsListPresenter ,
@@ -84,6 +89,7 @@ import { getCurrentPlan } from "~/services/platform.v3.server";
8489import { requireUser } from "~/services/session.server" ;
8590import { formatNumberCompact } from "~/utils/numberFormatter" ;
8691import { EnvironmentParamSchema , v3ErrorPath } from "~/utils/pathBuilder" ;
92+ import { canUseAlertsList } from "~/v3/canUseAlertsList.server" ;
8793import { ServiceValidationError } from "~/v3/services/baseService.server" ;
8894import { errorsAgentPageContext } from "~/components/dashboard-agent/suggested-prompts" ;
8995import type { Handle } from "~/utils/handle" ;
@@ -101,7 +107,7 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
101107
102108 const { projectParam, organizationSlug, envParam } = EnvironmentParamSchema . parse ( params ) ;
103109
104- const project = await findProjectBySlug ( organizationSlug , projectParam , userId ) ;
110+ const project = await findProjectWithOrgFlagsBySlug ( organizationSlug , projectParam , userId ) ;
105111 if ( ! project ) {
106112 throw new Response ( "Project not found" , { status : 404 } ) ;
107113 }
@@ -130,6 +136,11 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
130136 const direction =
131137 directionRaw === "forward" || directionRaw === "backward" ? directionRaw : undefined ;
132138
139+ const alertsEnabled = await canUseAlertsList ( {
140+ orgFeatureFlags : ( project . organization . featureFlags as Record < string , unknown > ) ?? { } ,
141+ userId,
142+ } ) ;
143+
133144 const plan = await getCurrentPlan ( project . organizationId ) ;
134145 const retentionLimitDays = plan ?. v3Subscription ?. plan ?. limits . logRetentionDays . number ?? 30 ;
135146
@@ -181,6 +192,7 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
181192 occurrences : occurrencesPromise ,
182193 defaultPeriod : "1d" ,
183194 retentionLimitDays,
195+ alertsEnabled,
184196 organizationSlug,
185197 projectParam,
186198 envParam,
@@ -193,6 +205,7 @@ export default function Page() {
193205 occurrences,
194206 defaultPeriod,
195207 retentionLimitDays,
208+ alertsEnabled,
196209 organizationSlug,
197210 projectParam,
198211 envParam,
@@ -209,17 +222,31 @@ export default function Page() {
209222 } , [ revalidator ] ) ,
210223 } ) ;
211224
225+ const organization = useOrganization ( ) ;
226+ const project = useProject ( ) ;
227+ const environment = useEnvironment ( ) ;
212228 const location = useOptimisticLocation ( ) ;
213229 const alertsHref = useMemo ( ( ) => {
230+ if ( alertsEnabled ) return undefined ;
214231 const params = new URLSearchParams ( location . search ) ;
215232 params . set ( "alerts" , "true" ) ;
216233 return `?${ params . toString ( ) } ` ;
217- } , [ location . search ] ) ;
234+ } , [ alertsEnabled , location . search ] ) ;
218235
219236 return (
220237 < >
221238 < NavBar >
222239 < PageTitle title = "Errors" />
240+ { alertsEnabled ? (
241+ < PageAccessories >
242+ < CreateAlertButton
243+ organization = { organization }
244+ project = { project }
245+ environment = { environment }
246+ prefill = { NEW_ERROR_ALERT_PREFILL }
247+ />
248+ </ PageAccessories >
249+ ) : null }
223250 </ NavBar >
224251
225252 < PageBody scrollable = { false } >
@@ -417,7 +444,7 @@ function FiltersBar({
417444 list ?: ErrorsListData ;
418445 defaultPeriod ?: string ;
419446 retentionLimitDays : number ;
420- alertsHref : string ;
447+ alertsHref ? : string ;
421448} ) {
422449 const location = useOptimisticLocation ( ) ;
423450 const searchParams = new URLSearchParams ( location . search ) ;
@@ -483,16 +510,18 @@ function FiltersBar({
483510 ) }
484511 </ div >
485512 < div className = "flex shrink-0 items-center gap-1.5" >
486- < LinkButton
487- to = { alertsHref }
488- variant = "secondary/small"
489- LeadingIcon = { BellAlertIcon }
490- leadingIconClassName = "text-alerts"
491- shortcut = { alertsShortcut }
492- tooltip = "Configure alerts"
493- >
494- Configure alerts…
495- </ LinkButton >
513+ { alertsHref ? (
514+ < LinkButton
515+ to = { alertsHref }
516+ variant = "secondary/small"
517+ LeadingIcon = { BellAlertIcon }
518+ leadingIconClassName = "text-alerts"
519+ shortcut = { alertsShortcut }
520+ tooltip = "Configure alerts"
521+ >
522+ Configure alerts…
523+ </ LinkButton >
524+ ) : null }
496525 { list && < ListPagination list = { list } /> }
497526 </ div >
498527 </ div >
0 commit comments