@@ -609,6 +534,6 @@ const ProjectAlertsInner = ({ deferredData }: ProjectAlertsInnerProps) => {
)
}
-const ProjectAlerts = ProjectAlertsWrapper
+const ProjectAlerts = ProjectAlertsInner
export default ProjectAlerts
diff --git a/web/app/pages/Project/Settings/ProjectSettings.tsx b/web/app/pages/Project/Settings/ProjectSettings.tsx
index 6977b7585..a70015d6e 100644
--- a/web/app/pages/Project/Settings/ProjectSettings.tsx
+++ b/web/app/pages/Project/Settings/ProjectSettings.tsx
@@ -22,6 +22,7 @@ import {
ShieldCheckIcon,
CurrencyDollarIcon,
DownloadIcon,
+ BellRingingIcon,
} from '@phosphor-icons/react'
import React, { useState, useEffect, useMemo, useRef } from 'react'
import { Trans, useTranslation } from 'react-i18next'
@@ -65,6 +66,7 @@ import DangerZone from './tabs/DangerZone'
import General from './tabs/General'
import Revenue from './tabs/Revenue'
import Shields from './tabs/Shields'
+import ProjectAlerts from './Alerts/ProjectAlertsView'
import DataImportTab from './components/DataImportTab'
const MAX_NAME_LENGTH = 50
@@ -353,6 +355,7 @@ const ProjectSettings = () => {
| 'access'
| 'captcha'
| 'integrations'
+ | 'alerts'
| 'revenue'
| 'emails'
| 'people'
@@ -403,6 +406,14 @@ const ProjectSettings = () => {
iconColor: 'text-purple-500',
visible: !isSelfhosted,
},
+ {
+ id: 'alerts',
+ label: t('project.settings.tabs.alerts'),
+ description: t('project.settings.tabs.alertsDesc'),
+ icon: BellRingingIcon,
+ iconColor: 'text-cyan-500',
+ visible: !isSelfhosted && project?.role === 'owner',
+ },
{
id: 'revenue',
label: t('project.settings.tabs.revenue'),
@@ -1225,6 +1236,18 @@ const ProjectSettings = () => {
) : null}
+ {activeTab === 'alerts' && activeTabConfig ? (
+ <>
+
+
+ >
+ ) : null}
+
{activeTab === 'captcha' && activeTabConfig ? (
{
label: t('dashboard.askAi'),
icon: SparkleIcon,
},
- {
- id: PROJECT_TABS.alerts,
- label: t('dashboard.alerts'),
- icon: BellRingingIcon,
- },
{
id: PROJECT_TABS.experiments,
label: t('dashboard.experiments'),
@@ -1126,10 +1119,6 @@ const ViewProjectContent = () => {
}
if (pair.period === 'compare') {
- if (activeTab === PROJECT_TABS.alerts) {
- return
- }
-
if (isActiveCompare) {
compareDisable()
} else {
@@ -1535,9 +1524,6 @@ const ViewProjectContent = () => {
{activeTab === PROJECT_TABS.funnels ? (
) : null}
- {activeTab === PROJECT_TABS.alerts ? (
-
- ) : null}
{activeTab === PROJECT_TABS.profiles ? (
) : null}
diff --git a/web/app/pages/Project/View/components/ProjectSidebar.tsx b/web/app/pages/Project/View/components/ProjectSidebar.tsx
index 3277420b6..2163bcee9 100644
--- a/web/app/pages/Project/View/components/ProjectSidebar.tsx
+++ b/web/app/pages/Project/View/components/ProjectSidebar.tsx
@@ -64,7 +64,6 @@ const ICON_COLORS: Record = {
traffic: 'text-blue-500',
performance: 'text-amber-500',
funnels: 'text-teal-500',
- alerts: 'text-cyan-500',
// Product Analytics
profiles: 'text-fuchsia-500',
sessions: 'text-indigo-500',
@@ -399,12 +398,7 @@ const ProjectSidebar: React.FC = ({
const groups: TabGroup[] = []
const webAnalyticsTabs = tabs.filter((tab) =>
- [
- PROJECT_TABS.traffic,
- PROJECT_TABS.performance,
- PROJECT_TABS.funnels,
- PROJECT_TABS.alerts,
- ]
+ [PROJECT_TABS.traffic, PROJECT_TABS.performance, PROJECT_TABS.funnels]
.filter(Boolean)
.includes(tab.id as any),
)
diff --git a/web/app/routes/projects.$id.tsx b/web/app/routes/projects.$id.tsx
index e724719ea..d861e90f9 100644
--- a/web/app/routes/projects.$id.tsx
+++ b/web/app/routes/projects.$id.tsx
@@ -25,7 +25,6 @@ import {
getErrorOverviewServer,
getProjectFeatureFlagsServer,
getProjectGoalsServer,
- getProjectAlertsServer,
getFunnelDataServer,
type TrafficLogResponse,
type OverallObject,
@@ -38,7 +37,6 @@ import {
type ErrorOverviewResponse,
type FeatureFlagsResponse,
type GoalsResponse,
- type AlertsResponse,
type FunnelDataResponse,
type AnalyticsFilter,
} from '~/api/api.server'
@@ -175,7 +173,6 @@ export const meta: MetaFunction = ({ data, location }) => {
[PROJECT_TABS.featureFlags]: t('dashboard.featureFlags'),
[PROJECT_TABS.captcha]: t('common.captcha'),
[PROJECT_TABS.ai]: t('dashboard.askAi'),
- [PROJECT_TABS.alerts]: t('dashboard.alerts'),
[PROJECT_TABS.experiments]: t('dashboard.experiments'),
settings: t('common.settings'),
}
@@ -310,8 +307,6 @@ export interface ProjectLoaderData {
featureFlagsData?: Promise
// Goals data
goalsData?: Promise
- // Alerts data
- alertsData?: Promise
// Funnels data
funnelData?: Promise
// Data import
@@ -431,7 +426,6 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
let errorOverview: Promise | undefined
let featureFlagsData: Promise | undefined
let goalsData: Promise | undefined
- let alertsData: Promise | undefined
let funnelData: Promise | undefined
let hasImportedData: Promise | undefined
@@ -535,10 +529,6 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
goalsData = getProjectGoalsServer(request, projectId).then(
(res) => res.data,
)
- } else if (tab === PROJECT_TABS.alerts) {
- alertsData = getProjectAlertsServer(request, projectId).then(
- (res) => res.data,
- )
} else if (tab === PROJECT_TABS.funnels) {
// Fetch funnel data if funnelId is in URL
const funnelId = url.searchParams.get('funnelId')
@@ -591,7 +581,6 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
errorOverview,
featureFlagsData,
goalsData,
- alertsData,
funnelData,
hasImportedData,
},
diff --git a/web/public/locales/en.json b/web/public/locales/en.json
index da9bbb826..a6b4abcbd 100644
--- a/web/public/locales/en.json
+++ b/web/public/locales/en.json
@@ -1734,6 +1734,8 @@
"dangerDesc": "Destructive actions that cannot be undone.",
"integrations": "Integrations",
"integrationsDesc": "Connect external services to enrich your analytics.",
+ "alerts": "Alerts",
+ "alertsDesc": "Get notified about traffic spikes, errors, and custom events.",
"revenue": "Revenue",
"revenueDesc": "Track revenue and attribute sales to campaigns.",
"import": "Import data",