Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import { capitalizeFirstLetter } from 'lib/utils/strings'
import { BreakdownTag } from 'scenes/insights/filters/BreakdownFilter/BreakdownTag'
import { humanizePathsEventTypes, hasUnsupportedBreakdownForDataWarehouseTrends } from 'scenes/insights/utils'
import { QUERY_TYPES_METADATA } from 'scenes/saved-insights/SavedInsights'
import { QUERY_TYPES_METADATA } from 'scenes/saved-insights/insightTypesMetadata'
import { urls } from 'scenes/urls'

import {
Expand Down Expand Up @@ -206,7 +206,7 @@
)
}

function SeriesDisplay({

Check warning on line 209 in frontend/src/lib/components/Cards/InsightCard/InsightDetails.tsx

View workflow job for this annotation

GitHub Actions / Frontend formatting

lint:complexity

`SeriesDisplay` has cyclomatic complexity 13 (warn >10)
query,
seriesIndex,
}: {
Expand Down Expand Up @@ -724,7 +724,7 @@
}

export const InsightDetails = React.memo(
React.forwardRef<HTMLDivElement, InsightDetailsProps>(function InsightDetailsInternal(

Check warning on line 727 in frontend/src/lib/components/Cards/InsightCard/InsightDetails.tsx

View workflow job for this annotation

GitHub Actions / Frontend formatting

lint:complexity

`InsightDetailsInternal` has cyclomatic complexity 26 (warn >10)
{
query,
footerInfo,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CardTopHeadingRow } from 'lib/components/Cards/CardTopHeadingRow'
import { dateFilterToText } from 'lib/utils/dateFilters'
import { alignResolvedDateRangeToInterval, formatResolvedDateRange } from 'lib/utils/datetime'
import { InsightTypeMetadata, QUERY_TYPES_METADATA } from 'scenes/saved-insights/SavedInsights'
import { InsightTypeMetadata, QUERY_TYPES_METADATA } from 'scenes/saved-insights/insightTypesMetadata'

import { Node, NodeKind, ResolvedDateRangeResponse } from '~/queries/schema/schema-general'
import {
Expand All @@ -26,7 +26,7 @@
return QUERY_TYPES_METADATA[NodeKind.TrendsQuery]
}

export function TopHeading({

Check warning on line 29 in frontend/src/lib/components/Cards/InsightCard/TopHeading.tsx

View workflow job for this annotation

GitHub Actions / Frontend formatting

lint:complexity

`TopHeading` has cyclomatic complexity 17 (warn >10)
query,
lastRefresh,
hasTileOverrides,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { insightVizDataLogic } from 'scenes/insights/insightVizDataLogic'
import { keyForInsightLogicProps } from 'scenes/insights/sharedUtils'
import MaxTool from 'scenes/max/MaxTool'
import { castAssistantQuery } from 'scenes/max/utils'
import { QUERY_TYPES_METADATA } from 'scenes/saved-insights/SavedInsights'
import { QUERY_TYPES_METADATA } from 'scenes/saved-insights/insightTypesMetadata'

import { AnyAssistantGeneratedQuery } from '~/queries/schema/schema-assistant-messages'
import {
Expand Down
33 changes: 31 additions & 2 deletions frontend/src/scenes/dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import './Dashboard.scss'

import { BindLogic, useActions, useMountedLogic, useValues } from 'kea'
import posthog from 'posthog-js'
import { Suspense } from 'react'

import { AccessDenied } from 'lib/components/AccessDenied'
import { dashboardTileScreenshotKey } from 'lib/components/Cards/InsightCard/insightCardImageCapture'
Expand All @@ -10,6 +12,7 @@
import { useOnMountEffect } from 'lib/hooks/useOnMountEffect'
import { Link } from 'lib/lemon-ui/Link'
import { cn } from 'lib/utils/css-classes'
import { lazyWithRetry } from 'lib/utils/retryImport'
import { DashboardFilterBar } from 'scenes/dashboard/DashboardFilters'
import { DashboardItems } from 'scenes/dashboard/DashboardItems'
import { DashboardLoadAction, DashboardLogicProps, dashboardLogic } from 'scenes/dashboard/dashboardLogic'
Expand All @@ -26,16 +29,23 @@
import { useAttachedContext } from 'products/posthog_ai/frontend/api/logics'

import { teamLogic } from '../teamLogic'
import { AddInsightToDashboardModal } from './addInsightToDashboardModal/AddInsightToDashboardModal'
import { addInsightToDashboardLogic } from './addInsightToDashboardModalLogic'
import { DashboardHeader } from './DashboardHeader'
import { DashboardEmbeddedShareButton } from './DashboardHeaderActions'
import { DashboardModalLoading } from './DashboardModalLoading'
import { DashboardQueryScanBanner } from './DashboardQueryScanBanner'
import { DashboardRetentionBanner } from './DashboardRetentionBanner'
import { dashboardSubscribeNudgeLogic } from './dashboardSubscribeNudgeLogic'
import { DashboardZoomControl } from './DashboardZoomControl'
import { EmptyDashboardComponent } from './EmptyDashboardComponent'

// The modal renders the saved insights list, which no dashboard needs until someone adds an insight.
const AddInsightToDashboardModal = lazyWithRetry(() =>
import('./addInsightToDashboardModal/AddInsightToDashboardModal').then((m) => ({
default: m.AddInsightToDashboardModal,
}))
)

// Mount-only: runs the subscribe-nudge eligibility machinery for this dashboard; renders nothing.
function DashboardSubscribeNudgeTrigger({ dashboardId }: { dashboardId: number }): null {
useMountedLogic(dashboardSubscribeNudgeLogic({ dashboardId }))
Expand Down Expand Up @@ -91,7 +101,7 @@
)
}

function DashboardScene({

Check warning on line 104 in frontend/src/scenes/dashboard/Dashboard.tsx

View workflow job for this annotation

GitHub Actions / Frontend formatting

lint:complexity

`DashboardScene` has cyclomatic complexity 26 (warn >10)
backTo,
showCreateAnomalyAlertButton,
}: {
Expand All @@ -115,6 +125,13 @@
const { currentTeamId } = useValues(teamLogic)
const { reportDashboardViewed, abortAnyRunningQuery, loadDashboard, setLayoutZoom } = useActions(dashboardLogic)
const { addInsightToDashboardModalVisible } = useValues(addInsightToDashboardLogic)
const { hideAddInsightToDashboardModal } = useActions(addInsightToDashboardLogic)
const closeAddInsightToDashboardModal = (): void => {
// Mirror AddInsightToDashboardModal.handleClose, so a close during the chunk load still
// emits this event. 'insight dashboard modal - closed' is a frozen event name; keep both in sync.
posthog.capture('insight dashboard modal - closed')
hideAddInsightToDashboardModal()
}

useAttachedContext(
dashboard ? [{ type: 'dashboard', key: dashboard.id, label: dashboard.name ?? undefined }] : null
Expand Down Expand Up @@ -162,7 +179,19 @@
{placement == DashboardPlacement.Dashboard && !!dashboard?.id && (
<DashboardSubscribeNudgeTrigger dashboardId={dashboard.id} />
)}
{canEditDashboard && addInsightToDashboardModalVisible && <AddInsightToDashboardModal />}
{canEditDashboard && addInsightToDashboardModalVisible && (
<Suspense
fallback={
<DashboardModalLoading
isOpen={addInsightToDashboardModalVisible}
onClose={closeAddInsightToDashboardModal}
label="Loading insights"
/>
}
>
<AddInsightToDashboardModal />
</Suspense>
)}
{/* Lets a tile copied as a PNG be annotated before it is shared. Export placement renders headlessly. */}
{placement !== DashboardPlacement.Export && (
<ScreenShotEditor screenshotKey={dashboardTileScreenshotKey(dashboard?.id)} />
Expand Down
26 changes: 26 additions & 0 deletions frontend/src/scenes/dashboard/DashboardModalLoading.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import '@testing-library/jest-dom'

import { act, cleanup, render } from '@testing-library/react'

import { DashboardModalLoading } from './DashboardModalLoading'

describe('DashboardModalLoading', () => {
beforeEach(() => jest.useFakeTimers())

afterEach(() => {
jest.useRealTimers()
cleanup()
})

it('shows the loading modal only once the chunk is slow', () => {
render(<DashboardModalLoading isOpen onClose={jest.fn()} />)

expect(document.querySelector('.Spinner')).not.toBeInTheDocument()

act(() => {
jest.advanceTimersByTime(200)
})

expect(document.querySelector('.Spinner')).toBeInTheDocument()
})
})
34 changes: 34 additions & 0 deletions frontend/src/scenes/dashboard/DashboardModalLoading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useEffect, useState } from 'react'

import { LemonModal } from 'lib/lemon-ui/LemonModal'
import { Spinner } from 'lib/lemon-ui/Spinner'

// A short delay keeps a cached chunk from opening this modal for one frame before the real one.
const SHOW_AFTER_MS = 200

/** Suspense fallback for a lazily loaded dashboard modal, so the click that opened it gets a response. */
export function DashboardModalLoading({
isOpen,
onClose,
label = 'Loading',
}: {
isOpen: boolean
onClose: () => void
label?: string
}): JSX.Element | null {
const [visible, setVisible] = useState(false)

useEffect(() => {
const timeoutId = window.setTimeout(() => setVisible(true), SHOW_AFTER_MS)
return () => window.clearTimeout(timeoutId)
}, [])

return visible ? (
<LemonModal isOpen={isOpen} onClose={onClose} simple>
{/* role="status" with a name gives the spinner-only dialog an accessible loading announcement. */}
<div role="status" aria-label={label} className="flex justify-center p-8">
<Spinner />
Comment thread
pauldambra marked this conversation as resolved.
</div>
</LemonModal>
) : null
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { addSavedInsightsModalLogic } from 'scenes/saved-insights/addSavedInsightsModalLogic'
import { AddSavedInsightsToDashboard } from 'scenes/saved-insights/AddSavedInsightsToDashboard'
import { isInsightTypeCreatable } from 'scenes/saved-insights/insightTypesMetadata'
import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/SavedInsights'
import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/insightTypesMetadata'
import { urls } from 'scenes/urls'

import { InsightType } from '~/types'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { createdAtColumn, createdByColumn } from 'lib/lemon-ui/LemonTable/column
import { LemonTableLink } from 'lib/lemon-ui/LemonTable/LemonTableLink'
import { INSIGHTS_PER_PAGE, eventInsightsLogic } from 'scenes/data-management/events/eventInsightsLogic'
import { useSummarizeInsight } from 'scenes/insights/summarizeInsight'
import { InsightIcon } from 'scenes/saved-insights/SavedInsights'
import { InsightIcon } from 'scenes/saved-insights/InsightIcon'
import { urls } from 'scenes/urls'

import { SceneSection } from '~/layout/scenes/components/SceneSection'
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/insights/InsightNav/InsightsNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Link } from 'lib/lemon-ui/Link'
import { Tooltip } from 'lib/lemon-ui/Tooltip'
import { insightNavLogic } from 'scenes/insights/InsightNav/insightNavLogic'
import { INSIGHT_TYPE_URLS } from 'scenes/insights/utils'
import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/SavedInsights'
import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/insightTypesMetadata'

import { AlertDeletionWarning } from 'products/alerts/frontend/components/AlertDeletionWarning'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Link } from 'lib/lemon-ui/Link'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { INSIGHT_TYPE_URLS } from 'scenes/insights/utils'
import { isInsightTypeCreatable } from 'scenes/saved-insights/insightTypesMetadata'
import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/SavedInsights'
import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/insightTypesMetadata'
import { SceneExport } from 'scenes/sceneTypes'
import { urls } from 'scenes/urls'

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/project-homepage/RecentInsights.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CompactList } from 'lib/components/CompactList/CompactList'
import { dayjs } from 'lib/dayjs'
import { useOnMountEffect } from 'lib/hooks/useOnMountEffect'
import { eventUsageLogic } from 'lib/utils/eventUsageLogic'
import { InsightIcon } from 'scenes/saved-insights/SavedInsights'
import { InsightIcon } from 'scenes/saved-insights/InsightIcon'
import { urls } from 'scenes/urls'

import { InsightModel } from '~/types'
Expand Down
20 changes: 20 additions & 0 deletions frontend/src/scenes/saved-insights/InsightIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ComponentType } from 'react'

import { isNonEmptyObject } from 'lib/utils/guards'

import { isNodeWithSource } from '~/queries/utils'
import { InsightModel } from '~/types'

import { QUERY_TYPES_METADATA } from './insightTypesMetadata'

export function InsightIcon({ insight, className }: { insight: InsightModel; className?: string }): JSX.Element | null {
let Icon: ComponentType<any> | null = null

if ('query' in insight && isNonEmptyObject(insight.query)) {
const insightType = isNodeWithSource(insight.query) ? insight.query.source.kind : insight.query.kind
const insightMetadata = QUERY_TYPES_METADATA[insightType]
Icon = insightMetadata && insightMetadata.icon
}

return Icon ? <Icon className={className} /> : null
}
2 changes: 1 addition & 1 deletion frontend/src/scenes/saved-insights/InsightRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { urls } from 'scenes/urls'
import { Query } from '~/queries/Query/Query'
import { InsightModel } from '~/types'

import { InsightIcon } from './SavedInsights'
import { InsightIcon } from './InsightIcon'

interface InsightRowProps {
insight: InsightModel
Expand Down
22 changes: 2 additions & 20 deletions frontend/src/scenes/saved-insights/SavedInsights.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { useActions, useValues } from 'kea'
import { router } from 'kea-router'
import { ComponentType } from 'react'

import { IconHeart, IconHeartFilled, IconTrash } from '@posthog/icons'

Expand All @@ -25,7 +24,6 @@
import { accessLevelSatisfied } from 'lib/utils/accessControlUtils'
import { cn } from 'lib/utils/css-classes'
import { deleteInsightWithUndo } from 'lib/utils/deleteWithUndo'
import { isNonEmptyObject } from 'lib/utils/guards'
import { SavedInsightsEmptyState, SavedInsightsErrorState } from 'scenes/insights/EmptyStates'
import { useSummarizeInsight } from 'scenes/insights/summarizeInsight'
import { projectLogic } from 'scenes/projectLogic'
Expand All @@ -38,20 +36,16 @@
import { SceneContent } from '~/layout/scenes/components/SceneContent'
import { SceneTitleSection } from '~/layout/scenes/components/SceneTitleSection'
import { ProductKey } from '~/queries/schema/schema-general'
import { isNodeWithSource } from '~/queries/utils'
import { AccessControlLevel, AccessControlResourceType, ActivityScope, InsightModel, SavedInsightsTabs } from '~/types'
import { AccessControlLevel, AccessControlResourceType, ActivityScope, SavedInsightsTabs } from '~/types'

import { productAnalyticsEmptyState } from 'products/product_analytics/frontend/emptyState/productAnalyticsEmptyState'

export * from './insightTypesMetadata'

import { ProductAnalyticsNotifications } from 'products/product_analytics/frontend/notifications/ProductAnalyticsNotifications'
import { productAnalyticsNotificationsLogic } from 'products/product_analytics/frontend/notifications/productAnalyticsNotificationsLogic'

import { isDraftInsightRow } from './draftInsight'
import { DraftInsightMoreMenu, DraftInsightNameCell } from './DraftInsightRow'
import { HomeTab } from './HomeTab'
import { QUERY_TYPES_METADATA } from './insightTypesMetadata'
import { InsightIcon } from './InsightIcon'
import { NewInsightButton } from './NewInsightMenu'
import { SavedInsightListItem, savedInsightsLogic } from './savedInsightsLogic'

Expand All @@ -62,19 +56,7 @@
emptyState: productAnalyticsEmptyState,
}

export function InsightIcon({ insight, className }: { insight: InsightModel; className?: string }): JSX.Element | null {
let Icon: ComponentType<any> | null = null

if ('query' in insight && isNonEmptyObject(insight.query)) {
const insightType = isNodeWithSource(insight.query) ? insight.query.source.kind : insight.query.kind
const insightMetadata = QUERY_TYPES_METADATA[insightType]
Icon = insightMetadata && insightMetadata.icon
}

return Icon ? <Icon className={className} /> : null
}

export function SavedInsights(): JSX.Element {

Check warning on line 59 in frontend/src/scenes/saved-insights/SavedInsights.tsx

View workflow job for this annotation

GitHub Actions / Frontend formatting

lint:complexity

`SavedInsights` has cyclomatic complexity 17 (warn >10)
const { push } = useActions(router)
const {
loadInsights,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/saved-insights/SavedInsightsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { InsightModel } from '~/types'

import { addSavedInsightsModalLogic } from './addSavedInsightsModalLogic'
import { InsightIcon } from './SavedInsights'
import { InsightIcon } from './InsightIcon'

interface SavedInsightsTableProps {
isSelected?: (insight: InsightModel) => boolean
Expand All @@ -27,7 +27,7 @@
filterFn?: (insight: InsightModel) => boolean
}

export function SavedInsightsTable({

Check warning on line 30 in frontend/src/scenes/saved-insights/SavedInsightsTable.tsx

View workflow job for this annotation

GitHub Actions / Frontend formatting

lint:complexity

`SavedInsightsTable` has cyclomatic complexity 19 (warn >10)
isSelected,
onToggle,
isToggling,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import posthog from 'posthog-js'

import { LemonSelect } from 'lib/lemon-ui/LemonSelect'
import { INSIGHT_TYPE_OPTIONS } from 'scenes/saved-insights/SavedInsights'
import { INSIGHT_TYPE_OPTIONS } from 'scenes/saved-insights/insightTypesMetadata'
import { SavedInsightFilters } from 'scenes/saved-insights/savedInsightsLogic'

export function SavedInsightsTypeFilter({
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/saved-insights/newInsightsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { FEATURE_FLAGS } from 'lib/constants'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { eventUsageLogic } from 'lib/utils/eventUsageLogic'
import { INSIGHT_TYPE_URLS } from 'scenes/insights/utils'
import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/SavedInsights'
import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/insightTypesMetadata'
import { Scene } from 'scenes/sceneTypes'

import { InsightType } from '~/types'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { TeamMembershipLevel } from 'lib/constants'
import { LemonCheckbox } from 'lib/lemon-ui/LemonCheckbox'
import { LemonTable } from 'lib/lemon-ui/LemonTable'
import { uuid } from 'lib/utils/dom'
import { QUERY_TYPES_METADATA } from 'scenes/saved-insights/SavedInsights'
import { QUERY_TYPES_METADATA } from 'scenes/saved-insights/insightTypesMetadata'

import { SceneSection } from '~/layout/scenes/components/SceneSection'
import { ConversionGoalFilter, NodeKind } from '~/queries/schema/schema-general'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { TZLabel } from 'lib/components/TZLabel'
import { LemonTable } from 'lib/lemon-ui/LemonTable'
import { Tooltip } from 'lib/lemon-ui/Tooltip'
import { useSummarizeInsight } from 'scenes/insights/summarizeInsight'
import { InsightIcon } from 'scenes/saved-insights/SavedInsights'
import { InsightIcon } from 'scenes/saved-insights/InsightIcon'
import { urls } from 'scenes/urls'

import { InsightModel } from '~/types'
Expand Down
2 changes: 1 addition & 1 deletion products/endpoints/frontend/InsightPickerEndpointModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { LemonButton } from 'lib/lemon-ui/LemonButton'
import { LemonModal } from 'lib/lemon-ui/LemonModal'
import { Popover } from 'lib/lemon-ui/Popover'
import { addSavedInsightsModalLogic } from 'scenes/saved-insights/addSavedInsightsModalLogic'
import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/SavedInsights'
import { INSIGHT_TYPES_METADATA } from 'scenes/saved-insights/insightTypesMetadata'
import { SavedInsightsTable } from 'scenes/saved-insights/SavedInsightsTable'
import { urls } from 'scenes/urls'

Expand Down
Loading