import { ChevronRight, CircleHelpIcon, Plus } from 'lucide-react' import Link from 'next/link' import { useRouter } from 'next/router' import React, { useState } from 'react' import { IS_PLATFORM, useFlag, useParams } from 'common' import { useFeaturePreviewModal, useUnifiedLogsPreview, } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' import { useIsETLPrivateAlpha } from 'components/interfaces/Database/Replication/useIsETLPrivateAlpha' import { LOG_DRAIN_TYPES } from 'components/interfaces/LogDrains/LogDrains.constants' import SavedQueriesItem from 'components/interfaces/Settings/Logs/Logs.SavedQueriesItem' import { LogsSidebarItem } from 'components/interfaces/Settings/Logs/SidebarV2/SidebarItem' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useContentQuery } from 'data/content/content-query' import { useReplicationSourcesQuery } from 'data/replication/sources-query' import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { Badge, Button, cn, Collapsible_Shadcn_, CollapsibleContent_Shadcn_, CollapsibleTrigger_Shadcn_, Separator, } from 'ui' import { InnerSideBarEmptyPanel, InnerSideBarFilters, InnerSideBarFilterSearchInput, InnerSideMenuItem, } from 'ui-patterns/InnerSideMenu' import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' import { FeaturePreviewSidebarPanel } from '../../ui/FeaturePreviewSidebarPanel' const SupaIcon = ({ className }: { className?: string }) => { return ( ) } export function SidebarCollapsible({ children, title, defaultOpen, }: { children: React.ReactNode title: string defaultOpen?: boolean }) { return ( {title} {children} ) } export function LogsSidebarMenuV2() { const router = useRouter() const { ref } = useParams() as { ref: string } const unifiedLogsFlagEnabled = useFlag('unifiedLogs') const { selectFeaturePreview } = useFeaturePreviewModal() const { enable: enableUnifiedLogs } = useUnifiedLogsPreview() const [searchText, setSearchText] = useState('') const { projectAuthAll: authEnabled, projectStorageAll: storageEnabled, realtimeAll: realtimeEnabled, logsTemplates: templatesEnabled, logsCollections: collectionsEnabled, } = useIsFeatureEnabled([ 'project_storage:all', 'project_auth:all', 'realtime:all', 'logs:templates', 'logs:collections', ]) const enablePgReplicate = useIsETLPrivateAlpha() const { data: etlData, isPending: isETLLoading } = useReplicationSourcesQuery( { projectRef: ref, }, { enabled: enablePgReplicate, retry: false, refetchOnMount: false, refetchOnWindowFocus: false, } ) // [Jordi] We only want to show ETL logs if the user has the feature enabled AND they're using the feature aka they've created a source. const showETLLogs = enablePgReplicate && (etlData?.sources?.length ?? 0) > 0 && !isETLLoading const { plan: orgPlan } = useCurrentOrgPlan() const isFreePlan = orgPlan?.id === 'free' const { data: savedQueriesRes, isPending: savedQueriesLoading } = useContentQuery({ projectRef: ref, type: 'log_sql', }) const savedQueries = [...(savedQueriesRes?.content ?? [])] .filter((c) => c.type === 'log_sql') .sort((a, b) => a.name.localeCompare(b.name)) function isActive(path: string) { return router.asPath.includes(path) } const BASE_COLLECTIONS = [ { name: 'API Gateway', key: 'edge-logs', url: `/project/${ref}/logs/edge-logs`, items: [], }, { name: 'Postgres', key: 'postgres-logs', url: `/project/${ref}/logs/postgres-logs`, items: [], }, { name: 'PostgREST', key: 'postgrest-logs', url: `/project/${ref}/logs/postgrest-logs`, items: [], }, IS_PLATFORM ? { name: isFreePlan ? 'Pooler' : 'Shared Pooler', key: 'pooler-logs', url: `/project/${ref}/logs/pooler-logs`, items: [], } : null, !isFreePlan && IS_PLATFORM ? { name: 'Dedicated Pooler', key: 'dedicated-pooler-logs', url: `/project/${ref}/logs/dedicated-pooler-logs`, items: [], } : null, authEnabled ? { name: 'Auth', key: 'auth-logs', url: `/project/${ref}/logs/auth-logs`, items: [], } : null, storageEnabled ? { name: 'Storage', key: 'storage-logs', url: `/project/${ref}/logs/storage-logs`, items: [], } : null, realtimeEnabled ? { name: 'Realtime', key: 'realtime-logs', url: `/project/${ref}/logs/realtime-logs`, items: [], } : null, { name: 'Edge Functions', key: 'edge-functions-logs', url: `/project/${ref}/logs/edge-functions-logs`, items: [], }, { name: 'Cron', key: 'pg_cron', url: `/project/${ref}/logs/pgcron-logs`, items: [], }, showETLLogs ? { name: 'Replication', key: 'replication_logs', url: `/project/${ref}/logs/replication-logs`, items: [], } : null, ].filter((x) => x !== null) const OPERATIONAL_COLLECTIONS = IS_PLATFORM ? [ { name: 'Postgres Version Upgrade', key: 'pg-upgrade-logs', url: `/project/${ref}/logs/pg-upgrade-logs`, items: [], }, ] : [] const filteredLogs = BASE_COLLECTIONS.filter((collection) => { return collection?.name.toLowerCase().includes(searchText.toLowerCase()) }) const filteredOperationalLogs = OPERATIONAL_COLLECTIONS.filter((collection) => { return collection?.name.toLowerCase().includes(searchText.toLowerCase()) }) return (
{IS_PLATFORM && !unifiedLogsFlagEnabled && ( Coming soon} title="New logs" description="Get early access" actions={ } /> )} {unifiedLogsFlagEnabled && ( New} actions={ <> } onClick={() => selectFeaturePreview('supabase-ui-preview-unified-logs')} tooltip={{ content: { side: 'bottom', text: 'More information' } }} /> } /> )}
setSearchText(e.target.value)} >
{templatesEnabled && (
Templates
)} {collectionsEnabled && ( <> {filteredLogs.map((collection) => { const isItemActive = isActive(collection?.url ?? '') return ( } label={collection?.name ?? ''} /> ) })} {OPERATIONAL_COLLECTIONS.length > 0 && ( <> {filteredOperationalLogs.map((collection) => ( } label={collection.name} /> ))} )} )} {savedQueriesLoading && (
)} {savedQueries.length === 0 && ( Create query } /> )} {savedQueries.map((query) => ( // kemal: i know, i know, temp any fix. ))}
{LOG_DRAIN_TYPES.map((type) => React.cloneElement(type.icon, { height: 20, width: 20 }) )}
} actions={ } /> ) }