diff --git a/.vscode/launch.json b/.vscode/launch.json index 497b5f7fca0bf..22bf39b718019 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -70,7 +70,8 @@ "DATABASE_URL": "postgres://posthog:posthog@localhost:5432/posthog", "SKIP_SERVICE_VERSION_REQUIREMENTS": "1", "PRINT_SQL": "1", - "REPLAY_EVENTS_NEW_CONSUMER_RATIO": "1.0" + "REPLAY_EVENTS_NEW_CONSUMER_RATIO": "1.0", + "BILLING_SERVICE_URL": "https://billing.dev.posthog.dev" }, "console": "integratedTerminal", "python": "${workspaceFolder}/env/bin/python", diff --git a/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-edit.png b/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-edit.png index 223fedaac0365..8958fe5dc51ba 100644 Binary files a/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-edit.png and b/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-edit.png differ diff --git a/frontend/src/layout/GlobalModals.tsx b/frontend/src/layout/GlobalModals.tsx index 1d4751bf7fdbf..83e61a3476da0 100644 --- a/frontend/src/layout/GlobalModals.tsx +++ b/frontend/src/layout/GlobalModals.tsx @@ -3,6 +3,14 @@ import { CreateOrganizationModal } from 'scenes/organization/CreateOrganizationM import { CreateProjectModal } from 'scenes/project/CreateProjectModal' import type { globalModalsLogicType } from './GlobalModalsType' +import { FeaturePreviewsModal } from './FeaturePreviews' +import { UpgradeModal } from 'scenes/UpgradeModal' +import { LemonModal } from '@posthog/lemon-ui' +import { Setup2FA } from 'scenes/authentication/Setup2FA' +import { userLogic } from 'scenes/userLogic' +import { membersLogic } from 'scenes/organization/membersLogic' +import { FlaggedFeature } from 'lib/components/FlaggedFeature' +import { Prompt } from 'lib/logic/newPrompt/Prompt' import { inviteLogic } from 'scenes/settings/organization/inviteLogic' import { InviteModal } from 'scenes/settings/organization/InviteModal' @@ -37,12 +45,37 @@ export function GlobalModals(): JSX.Element { const { hideCreateOrganizationModal, hideCreateProjectModal } = useActions(globalModalsLogic) const { isInviteModalShown } = useValues(inviteLogic) const { hideInviteModal } = useActions(inviteLogic) + const { user } = useValues(userLogic) return ( <> + + + + {user && user.organization?.enforce_2fa && !user.is_2fa_enabled && ( + +

+ Your organization requires you to set up 2FA. +

+

+ + Use an authenticator app like Google Authenticator or 1Password to scan the QR code below. + +

+ { + userLogic.actions.loadUser() + membersLogic.actions.loadMembers() + }} + /> +
+ )} + + + ) } diff --git a/frontend/src/layout/navigation-3000/Navigation.tsx b/frontend/src/layout/navigation-3000/Navigation.tsx index 06cf9b3db6abb..04d577454aadd 100644 --- a/frontend/src/layout/navigation-3000/Navigation.tsx +++ b/frontend/src/layout/navigation-3000/Navigation.tsx @@ -12,7 +12,6 @@ import { Scene, SceneConfig } from 'scenes/sceneTypes' import { FlaggedFeature } from 'lib/components/FlaggedFeature' import { FEATURE_FLAGS } from 'lib/constants' import { SidePanel } from './sidepanel/SidePanel' -import { GlobalModals } from '../GlobalModals' export function Navigation({ children, @@ -30,6 +29,9 @@ export function Navigation({ document.getElementById('bottom-notice')?.remove() }, []) + if (sceneConfig?.layout === 'plain') { + return <>{children} + } return (
@@ -49,7 +51,6 @@ export function Navigation({ -
) } diff --git a/frontend/src/layout/navigation-3000/themeLogic.ts b/frontend/src/layout/navigation-3000/themeLogic.ts index 98ae67f02c45b..a97fbd12c2d7f 100644 --- a/frontend/src/layout/navigation-3000/themeLogic.ts +++ b/frontend/src/layout/navigation-3000/themeLogic.ts @@ -4,6 +4,7 @@ import { FEATURE_FLAGS } from 'lib/constants' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import type { themeLogicType } from './themeLogicType' +import { sceneLogic } from 'scenes/sceneLogic' export const themeLogic = kea([ path(['layout', 'navigation-3000', 'themeLogic']), @@ -32,8 +33,17 @@ export const themeLogic = kea([ }), selectors({ isDarkModeOn: [ - (s) => [s.darkModeSavedPreference, s.darkModeSystemPreference, featureFlagLogic.selectors.featureFlags], - (darkModeSavedPreference, darkModeSystemPreference, featureFlags) => { + (s) => [ + s.darkModeSavedPreference, + s.darkModeSystemPreference, + featureFlagLogic.selectors.featureFlags, + sceneLogic.selectors.sceneConfig, + ], + (darkModeSavedPreference, darkModeSystemPreference, featureFlags, sceneConfig) => { + // NOTE: Unauthenticated users always get the light mode until we have full support across onboarding flows + if (sceneConfig?.layout === 'plain' || sceneConfig?.allowUnauthenticated) { + return false + } // Dark mode is a PostHog 3000 feature // User-saved preference is used when set, oterwise we fall back to the system value return featureFlags[FEATURE_FLAGS.POSTHOG_3000] diff --git a/frontend/src/layout/navigation/TopBar/TopBar.tsx b/frontend/src/layout/navigation/TopBar/TopBar.tsx index c2d4426e1ba8d..c769d91869ba1 100644 --- a/frontend/src/layout/navigation/TopBar/TopBar.tsx +++ b/frontend/src/layout/navigation/TopBar/TopBar.tsx @@ -16,7 +16,6 @@ import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { FEATURE_FLAGS } from 'lib/constants' import { NotebookButton } from '~/layout/navigation/TopBar/NotebookButton' import { ActivationSidebarToggle } from 'lib/components/ActivationSidebar/ActivationSidebarToggle' -import { GlobalModals } from '~/layout/GlobalModals' export function TopBar(): JSX.Element { const { isSideBarShown, noSidebar, minimalTopBar, mobileLayout } = useValues(navigationLogic) @@ -83,7 +82,6 @@ export function TopBar(): JSX.Element { - ) } diff --git a/frontend/src/lib/logic/featureFlagLogic.ts b/frontend/src/lib/logic/featureFlagLogic.ts index 7b2869d12cc0a..061bca49a70ea 100644 --- a/frontend/src/lib/logic/featureFlagLogic.ts +++ b/frontend/src/lib/logic/featureFlagLogic.ts @@ -1,4 +1,4 @@ -import { kea, path, actions, reducers, events } from 'kea' +import { kea, path, actions, reducers, afterMount } from 'kea' import type { featureFlagLogicType } from './featureFlagLogicType' import posthog from 'posthog-js' import { getAppContext } from 'lib/utils/getAppContext' @@ -84,9 +84,7 @@ export const featureFlagLogic = kea([ }, ], }), - events(({ actions }) => ({ - afterMount: () => { - posthog.onFeatureFlags(actions.setFeatureFlags) - }, - })), + afterMount(({ actions }) => { + posthog.onFeatureFlags(actions.setFeatureFlags) + }), ]) diff --git a/frontend/src/scenes/App.tsx b/frontend/src/scenes/App.tsx index ae1be15257f9c..8bdbae99205ea 100644 --- a/frontend/src/scenes/App.tsx +++ b/frontend/src/scenes/App.tsx @@ -3,7 +3,6 @@ import { ToastContainer, Slide } from 'react-toastify' import { preflightLogic } from './PreflightCheck/preflightLogic' import { userLogic } from 'scenes/userLogic' import { sceneLogic } from 'scenes/sceneLogic' -import { UpgradeModal } from './UpgradeModal' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import type { appLogicType } from './AppType' import { models } from '~/models' @@ -18,15 +17,11 @@ import { ToastCloseButton } from 'lib/lemon-ui/lemonToast' import { frontendAppsLogic } from 'scenes/apps/frontendAppsLogic' import { inAppPromptLogic } from 'lib/logic/inAppPrompt/inAppPromptLogic' import { SpinnerOverlay } from 'lib/lemon-ui/Spinner/Spinner' -import { LemonModal } from '@posthog/lemon-ui' -import { Setup2FA } from './authentication/Setup2FA' -import { membersLogic } from './organization/membersLogic' import { FEATURE_FLAGS } from 'lib/constants' import { Navigation as Navigation3000 } from '~/layout/navigation-3000/Navigation' -import { Prompt } from 'lib/logic/newPrompt/Prompt' import { useEffect } from 'react' import { themeLogic } from '~/layout/navigation-3000/themeLogic' -import { FeaturePreviewsModal } from '~/layout/FeaturePreviews' +import { GlobalModals } from '~/layout/GlobalModals' export const appLogic = kea([ path(['scenes', 'App']), @@ -182,27 +177,7 @@ function AppScene(): JSX.Element | null { {wrappedSceneElement} {toastContainer} - - - {user.organization?.enforce_2fa && !user.is_2fa_enabled && ( - -

- Your organization requires you to set up 2FA. -

-

- - Use an authenticator app like Google Authenticator or 1Password to scan the QR code below. - -

- { - userLogic.actions.loadUser() - membersLogic.actions.loadMembers() - }} - /> -
- )} - {featureFlags[FEATURE_FLAGS.ENABLE_PROMPTS] && } + ) } diff --git a/frontend/src/scenes/scenes.ts b/frontend/src/scenes/scenes.ts index a59cc3e2ff2c4..dc5aa42bb885e 100644 --- a/frontend/src/scenes/scenes.ts +++ b/frontend/src/scenes/scenes.ts @@ -266,6 +266,7 @@ export const sceneConfigurations: Partial> = { }, [Scene.Unsubscribe]: { allowUnauthenticated: true, + layout: 'app-raw', }, [Scene.DebugQuery]: { projectBased: true, diff --git a/posthog/api/test/test_preflight.py b/posthog/api/test/test_preflight.py index f277580857099..74d5a8b2e490b 100644 --- a/posthog/api/test/test_preflight.py +++ b/posthog/api/test/test_preflight.py @@ -49,7 +49,6 @@ def preflight_dict(self, options={}): def preflight_authenticated_dict(self, options={}): preflight = { "opt_out_capture": False, - "is_debug": False, "licensed_users_available": None, "site_url": "http://localhost:8000", "can_create_org": False, diff --git a/posthog/views.py b/posthog/views.py index 5e12d332f7b2e..4750cf170cc27 100644 --- a/posthog/views.py +++ b/posthog/views.py @@ -116,12 +116,14 @@ def preflight_check(request: HttpRequest) -> JsonResponse: "object_storage": is_cloud() or is_object_storage_available(), } + if settings.DEBUG or settings.E2E_TESTING: + response["is_debug"] = True + if request.user.is_authenticated: response = { **response, "available_timezones": get_available_timezones_with_offsets(), "opt_out_capture": os.environ.get("OPT_OUT_CAPTURE", False), - "is_debug": settings.DEBUG or settings.E2E_TESTING, "licensed_users_available": get_licensed_users_available() if not is_cloud() else None, "openai_available": bool(os.environ.get("OPENAI_API_KEY")), "site_url": settings.SITE_URL,