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,