diff --git a/cypress/e2e/notebooks-creation-and-deletion.cy.ts b/cypress/e2e/notebooks-creation-and-deletion.cy.ts
index 6206880118a81..4f73a7676b513 100644
--- a/cypress/e2e/notebooks-creation-and-deletion.cy.ts
+++ b/cypress/e2e/notebooks-creation-and-deletion.cy.ts
@@ -1,9 +1,9 @@
import { randomString } from '../support/random'
function visitNotebooksList(): void {
- cy.clickNavMenu('dashboards')
- cy.location('pathname').should('include', '/dashboard')
- cy.get('h1').should('contain', 'Dashboards & Notebooks')
+ cy.clickNavMenu('notebooks')
+ cy.location('pathname').should('include', '/notebooks')
+ cy.get('h1').should('contain', 'Notebooks')
cy.get('li').contains('Notebooks').should('exist').click()
}
diff --git a/cypress/e2e/notebooks.cy.ts b/cypress/e2e/notebooks.cy.ts
index a178b49afdbf6..d3d2945a3f245 100644
--- a/cypress/e2e/notebooks.cy.ts
+++ b/cypress/e2e/notebooks.cy.ts
@@ -27,12 +27,12 @@ describe('Notebooks', () => {
}).as('patchNotebook')
})
- cy.clickNavMenu('dashboards')
- cy.location('pathname').should('include', '/dashboard')
+ cy.clickNavMenu('notebooks')
+ cy.location('pathname').should('include', '/notebooks')
})
it('Notebooks are enabled', () => {
- cy.get('h1').should('contain', 'Dashboards & Notebooks')
+ cy.get('h1').should('contain', 'Notebooks')
cy.get('li').contains('Notebooks').should('exist').click()
})
diff --git a/frontend/__snapshots__/lemon-ui-icons--shelf-j.png b/frontend/__snapshots__/lemon-ui-icons--shelf-j.png
index d20b56618c56e..9812781502e35 100644
Binary files a/frontend/__snapshots__/lemon-ui-icons--shelf-j.png and b/frontend/__snapshots__/lemon-ui-icons--shelf-j.png differ
diff --git a/frontend/__snapshots__/lemon-ui-icons--shelf-n.png b/frontend/__snapshots__/lemon-ui-icons--shelf-n.png
index ee7f32ed29cef..9a82995334fba 100644
Binary files a/frontend/__snapshots__/lemon-ui-icons--shelf-n.png and b/frontend/__snapshots__/lemon-ui-icons--shelf-n.png differ
diff --git a/frontend/__snapshots__/scenes-app-experiments--experiments-list-pay-gate.png b/frontend/__snapshots__/scenes-app-experiments--experiments-list-pay-gate.png
index bafae37113a1b..7e96b5125fdab 100644
Binary files a/frontend/__snapshots__/scenes-app-experiments--experiments-list-pay-gate.png and b/frontend/__snapshots__/scenes-app-experiments--experiments-list-pay-gate.png differ
diff --git a/frontend/__snapshots__/scenes-app-experiments--experiments-list.png b/frontend/__snapshots__/scenes-app-experiments--experiments-list.png
index 28a9ce47379e4..5a3d3dd285231 100644
Binary files a/frontend/__snapshots__/scenes-app-experiments--experiments-list.png and b/frontend/__snapshots__/scenes-app-experiments--experiments-list.png differ
diff --git a/frontend/__snapshots__/scenes-app-feature-flags--feature-flags-list.png b/frontend/__snapshots__/scenes-app-feature-flags--feature-flags-list.png
index c0e66d04fb20d..a30dc1ed64cb0 100644
Binary files a/frontend/__snapshots__/scenes-app-feature-flags--feature-flags-list.png and b/frontend/__snapshots__/scenes-app-feature-flags--feature-flags-list.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--lifecycle.png b/frontend/__snapshots__/scenes-app-insights--lifecycle.png
index 2ab70086dee61..0f5f19aac9013 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--lifecycle.png and b/frontend/__snapshots__/scenes-app-insights--lifecycle.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--stickiness.png b/frontend/__snapshots__/scenes-app-insights--stickiness.png
index 885c792dbff15..1f58fbc9b518b 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--stickiness.png and b/frontend/__snapshots__/scenes-app-insights--stickiness.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--trends-number.png b/frontend/__snapshots__/scenes-app-insights--trends-number.png
index c4b27d87904c5..5e11ddb074351 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--trends-number.png and b/frontend/__snapshots__/scenes-app-insights--trends-number.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--trends-table-breakdown.png b/frontend/__snapshots__/scenes-app-insights--trends-table-breakdown.png
index 1d66d872793ef..60eb90e01d46e 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--trends-table-breakdown.png and b/frontend/__snapshots__/scenes-app-insights--trends-table-breakdown.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--trends-table.png b/frontend/__snapshots__/scenes-app-insights--trends-table.png
index 83727bad0e64a..1e44c590b7ab1 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--trends-table.png and b/frontend/__snapshots__/scenes-app-insights--trends-table.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--headings.png b/frontend/__snapshots__/scenes-app-notebooks--headings.png
index 0a118977b5422..eb890f7ef2025 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--headings.png and b/frontend/__snapshots__/scenes-app-notebooks--headings.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--notebook-not-found.png b/frontend/__snapshots__/scenes-app-notebooks--notebook-not-found.png
index da370b037075e..41cd092223d0b 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--notebook-not-found.png and b/frontend/__snapshots__/scenes-app-notebooks--notebook-not-found.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--notebooks-list.png b/frontend/__snapshots__/scenes-app-notebooks--notebooks-list.png
index 1d3a565259700..29840a3cd8ae5 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--notebooks-list.png and b/frontend/__snapshots__/scenes-app-notebooks--notebooks-list.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--recordings-playlist.png b/frontend/__snapshots__/scenes-app-notebooks--recordings-playlist.png
index 326a46e19d3ad..7d63a60ab61a0 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--recordings-playlist.png and b/frontend/__snapshots__/scenes-app-notebooks--recordings-playlist.png differ
diff --git a/frontend/src/layout/navigation/SideBar/SideBar.tsx b/frontend/src/layout/navigation/SideBar/SideBar.tsx
index 1c345e6c652b6..7594457385193 100644
--- a/frontend/src/layout/navigation/SideBar/SideBar.tsx
+++ b/frontend/src/layout/navigation/SideBar/SideBar.tsx
@@ -14,6 +14,7 @@ import {
IconGauge,
IconLive,
IconMessages,
+ IconNotebook,
IconOpenInApp,
IconPerson,
IconPinOutline,
@@ -38,7 +39,6 @@ import { AvailableFeature } from '~/types'
import './SideBar.scss'
import { navigationLogic } from '../navigationLogic'
import { FEATURE_FLAGS } from 'lib/constants'
-import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { groupsModel } from '~/models/groupsModel'
import { userLogic } from 'scenes/userLogic'
import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic'
@@ -52,13 +52,13 @@ import { Spinner } from 'lib/lemon-ui/Spinner/Spinner'
import { DebugNotice } from 'lib/components/DebugNotice'
import ActivationSidebar from 'lib/components/ActivationSidebar/ActivationSidebar'
import { NotebookPopover } from 'scenes/notebooks/Notebook/NotebookPopover'
+import { FlaggedFeature } from 'lib/components/FlaggedFeature'
function Pages(): JSX.Element {
const { currentOrganization } = useValues(organizationLogic)
const { hideSideBarMobile, toggleProjectSwitcher, hideProjectSwitcher } = useActions(navigationLogic)
const { isProjectSwitcherShown } = useValues(navigationLogic)
const { pinnedDashboards } = useValues(dashboardsModel)
- const { featureFlags } = useValues(featureFlagLogic)
const { showGroupsOptions } = useValues(groupsModel)
const { hasAvailableFeature } = useValues(userLogic)
const { preflight } = useValues(preflightLogic)
@@ -150,6 +150,20 @@ function Pages(): JSX.Element {
},
}}
/>
+
+ }
+ identifier={Scene.Notebooks}
+ to={urls.notebooks()}
+ sideAction={{
+ icon: ,
+ to: urls.notebook('new'),
+ tooltip: 'New notebook',
+ identifier: Scene.Notebook,
+ onClick: hideSideBarMobile,
+ }}
+ />
+
}
identifier={Scene.SavedInsights}
@@ -167,6 +181,7 @@ function Pages(): JSX.Element {
Feature Management
} identifier={Scene.FeatureFlags} to={urls.featureFlags()} />
+
{(hasAvailableFeature(AvailableFeature.EXPERIMENTATION) ||
!preflight?.instance_preferences?.disable_paid_fs) && (
} identifier={Scene.Experiments} to={urls.experiments()} />
@@ -186,15 +201,14 @@ function Pages(): JSX.Element {
highlight="beta"
/>
- {featureFlags[FEATURE_FLAGS.WEB_ANALYTICS] && (
+
}
identifier={Scene.WebAnalytics}
to={urls.webAnalytics()}
highlight="alpha"
/>
- )}
-
+
Data
- {featureFlags[FEATURE_FLAGS.DATA_WAREHOUSE] && (
+
}
identifier={Scene.DataWarehouse}
@@ -222,7 +236,7 @@ function Pages(): JSX.Element {
to={urls.dataWarehouse()}
highlight="beta"
/>
- )}
+
} identifier={Scene.Cohorts} to={urls.cohorts()} />
} identifier={Scene.Annotations} to={urls.annotations()} />
{canViewPlugins(currentOrganization) || Object.keys(frontendApps).length > 0 ? (
@@ -240,9 +254,9 @@ function Pages(): JSX.Element {
{Object.keys(frontendApps).length > 0 && }
>
) : null}
- {featureFlags[FEATURE_FLAGS.FEEDBACK_SCENE] && (
+
} identifier={Scene.Feedback} to={urls.feedback()} />
- )}
+
Configuration
}
+ icon={}
type={visibility === 'visible' ? 'primary' : 'tertiary'}
onClick={() => setVisibility(visibility === 'visible' ? 'hidden' : 'visible')}
status="primary-alt"
diff --git a/frontend/src/lib/lemon-ui/icons/icons.tsx b/frontend/src/lib/lemon-ui/icons/icons.tsx
index 3ef6f11d75e1e..b90b81c10bbfa 100644
--- a/frontend/src/lib/lemon-ui/icons/icons.tsx
+++ b/frontend/src/lib/lemon-ui/icons/icons.tsx
@@ -2383,28 +2383,6 @@ export function IconDatabase(props: LemonIconProps): JSX.Element {
)
}
-export function IconJournal(props: LemonIconProps): JSX.Element {
- return (
-
-
-
- )
-}
-
-export function IconJournalPlus(props: LemonIconProps): JSX.Element {
- return (
-
-
-
- )
-}
-
export function IconDragHandle(props: LemonIconProps): JSX.Element {
return (
@@ -2483,3 +2461,17 @@ export function IconTarget(props: LemonIconProps): JSX.Element {
)
}
+
+export function IconNotebook(props: LemonIconProps): JSX.Element {
+ return (
+
+
+
+ )
+}
diff --git a/frontend/src/models/notebooksModel.ts b/frontend/src/models/notebooksModel.ts
index 2c7ec1eb9efd4..c70d4a2a674de 100644
--- a/frontend/src/models/notebooksModel.ts
+++ b/frontend/src/models/notebooksModel.ts
@@ -40,7 +40,11 @@ export const openNotebook = async (
if (popoverLogic?.values.visibility === 'visible') {
popoverLogic?.actions.selectNotebook(notebookId, focus)
} else {
- router.actions.push(urls.notebook(notebookId))
+ if (router.values.location.pathname === urls.notebook('new')) {
+ router.actions.replace(urls.notebook(notebookId))
+ } else {
+ router.actions.push(urls.notebook(notebookId))
+ }
}
const theNotebookLogic = notebookLogic({ shortId: notebookId })
diff --git a/frontend/src/scenes/appScenes.ts b/frontend/src/scenes/appScenes.ts
index c72cdcf50a97f..21eb1fa403df5 100644
--- a/frontend/src/scenes/appScenes.ts
+++ b/frontend/src/scenes/appScenes.ts
@@ -76,6 +76,7 @@ export const appScenes: Record any> = {
[Scene.DebugQuery]: () => import('./debug/DebugScene'),
[Scene.VerifyEmail]: () => import('./authentication/signup/verify-email/VerifyEmail'),
[Scene.Feedback]: () => import('./feedback/Feedback'),
+ [Scene.Notebooks]: () => import('./notebooks/NotebooksScene'),
[Scene.Notebook]: () => import('./notebooks/NotebookScene'),
[Scene.Products]: () => import('./products/Products'),
[Scene.Onboarding]: () => import('./onboarding/Onboarding'),
diff --git a/frontend/src/scenes/dashboard/dashboards/Dashboards.tsx b/frontend/src/scenes/dashboard/dashboards/Dashboards.tsx
index d2dad15ee317a..6c70731560a5a 100644
--- a/frontend/src/scenes/dashboard/dashboards/Dashboards.tsx
+++ b/frontend/src/scenes/dashboard/dashboards/Dashboards.tsx
@@ -13,11 +13,6 @@ import { NoDashboards } from 'scenes/dashboard/dashboards/NoDashboards'
import { DashboardsTableContainer } from 'scenes/dashboard/dashboards/DashboardsTable'
import { DashboardTemplatesTable } from 'scenes/dashboard/dashboards/templates/DashboardTemplatesTable'
import { LemonTab, LemonTabs } from 'lib/lemon-ui/LemonTabs'
-import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
-import { FEATURE_FLAGS } from 'lib/constants'
-import { NotebooksTable } from 'scenes/notebooks/NotebooksTable/NotebooksTable'
-import { notebooksModel } from '~/models/notebooksModel'
-import { LemonTag } from '@posthog/lemon-ui'
export const scene: SceneExport = {
component: Dashboards,
@@ -30,11 +25,6 @@ export function Dashboards(): JSX.Element {
const { dashboards, currentTab, isFiltering } = useValues(dashboardsLogic)
const { showNewDashboardModal } = useActions(newDashboardLogic)
const { closePrompts } = useActions(inAppPromptLogic)
- const { featureFlags } = useValues(featureFlagLogic)
- const { notebooksLoading } = useValues(notebooksModel)
- const { createNotebook } = useActions(notebooksModel)
-
- const notebooksEnabled = featureFlags[FEATURE_FLAGS.NOTEBOOKS]
const enabledTabs: LemonTab[] = [
{
@@ -46,19 +36,6 @@ export function Dashboards(): JSX.Element {
label: 'Templates',
},
]
- if (notebooksEnabled) {
- enabledTabs.splice(1, 0, {
- key: DashboardsTab.Notebooks,
- label: (
- <>
- Notebooks
-
- Beta
-
- >
- ),
- })
- }
return (
@@ -66,38 +43,23 @@ export function Dashboards(): JSX.Element {
{
- createNotebook()
- }}
- type="primary"
- disabledReason={notebooksLoading ? 'Loading...' : undefined}
- >
- New notebook
-
- ) : (
- {
- closePrompts()
- showNewDashboardModal()
- }}
- type="primary"
- >
- New dashboard
-
- )
+ {
+ closePrompts()
+ showNewDashboardModal()
+ }}
+ type="primary"
+ >
+ New dashboard
+
}
/>
setCurrentTab(newKey)} tabs={enabledTabs} />
{currentTab === DashboardsTab.Templates ? (
- ) : currentTab === DashboardsTab.Notebooks ? (
-
) : dashboardsLoading || dashboards.length > 0 || isFiltering ? (
) : (
diff --git a/frontend/src/scenes/dashboard/dashboards/dashboardsLogic.ts b/frontend/src/scenes/dashboard/dashboards/dashboardsLogic.ts
index 065220e5b48b7..015a792e1b3af 100644
--- a/frontend/src/scenes/dashboard/dashboards/dashboardsLogic.ts
+++ b/frontend/src/scenes/dashboard/dashboards/dashboardsLogic.ts
@@ -10,7 +10,6 @@ import { DashboardBasicType } from '~/types'
export enum DashboardsTab {
Dashboards = 'dashboards',
- Notebooks = 'notebooks',
Templates = 'templates',
}
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeBacklink.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeBacklink.tsx
index fa8a0b818484c..0345103e983b9 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodeBacklink.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeBacklink.tsx
@@ -10,7 +10,7 @@ import {
IconLive,
IconPerson,
IconCohort,
- IconJournal,
+ IconNotebook,
} from 'lib/lemon-ui/icons'
import { TaxonomicFilterGroupType } from 'lib/components/TaxonomicFilter/types'
import { urls } from 'scenes/urls'
@@ -31,7 +31,7 @@ const ICON_MAP = {
events: ,
persons: ,
cohorts: ,
- notebooks: ,
+ notebooks: ,
}
const Component = (props: NodeViewProps): JSX.Element => {
diff --git a/frontend/src/scenes/notebooks/Notebook/NotebookListMini.tsx b/frontend/src/scenes/notebooks/Notebook/NotebookListMini.tsx
index e3e525a8cda9d..e573eecd30c3f 100644
--- a/frontend/src/scenes/notebooks/Notebook/NotebookListMini.tsx
+++ b/frontend/src/scenes/notebooks/Notebook/NotebookListMini.tsx
@@ -1,6 +1,6 @@
import { LemonButton } from '@posthog/lemon-ui'
import { useValues } from 'kea'
-import { IconJournal } from 'lib/lemon-ui/icons'
+import { IconNotebook } from 'lib/lemon-ui/icons'
import { notebooksModel } from '~/models/notebooksModel'
import { NotebookListItemType } from '~/types'
import { NotebookSelectPopover } from '../NotebookSelectButton/NotebookSelectButton'
@@ -23,7 +23,7 @@ export function NotebookListMini({ selectedNotebookId }: NotebookListMiniProps):
return (
- } status="primary-alt" sideIcon={null}>
+ } status="primary-alt" sideIcon={null}>
{selectedTitle || 'Notebooks'}
diff --git a/frontend/src/scenes/notebooks/NotebookScene.tsx b/frontend/src/scenes/notebooks/NotebookScene.tsx
index 39caa1dd0589a..a69e66f2ce483 100644
--- a/frontend/src/scenes/notebooks/NotebookScene.tsx
+++ b/frontend/src/scenes/notebooks/NotebookScene.tsx
@@ -24,6 +24,7 @@ import { LOCAL_NOTEBOOK_TEMPLATES } from './NotebookTemplates/notebookTemplates'
import './NotebookScene.scss'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { FEATURE_FLAGS } from 'lib/constants'
+import { NotebookLoadingState } from './Notebook/NotebookLoadingState'
interface NotebookSceneProps {
shortId?: string
@@ -38,10 +39,8 @@ export const scene: SceneExport = {
}
export function NotebookScene(): JSX.Element {
- const { notebookId } = useValues(notebookSceneLogic)
- const { notebook, notebookLoading, conflictWarningVisible, showHistory } = useValues(
- notebookLogic({ shortId: notebookId })
- )
+ const { notebookId, loading } = useValues(notebookSceneLogic)
+ const { notebook, conflictWarningVisible, showHistory } = useValues(notebookLogic({ shortId: notebookId }))
const { exportJSON, setShowHistory } = useActions(notebookLogic({ shortId: notebookId }))
const { selectNotebook, setVisibility } = useActions(notebookPopoverLogic)
const { selectedNotebook, visibility } = useValues(notebookPopoverLogic)
@@ -49,7 +48,7 @@ export function NotebookScene(): JSX.Element {
const { featureFlags } = useValues(featureFlagLogic)
const buttonSize = featureFlags[FEATURE_FLAGS.POSTHOG_3000] ? 'small' : 'medium'
- if (!notebook && !notebookLoading && !conflictWarningVisible) {
+ if (!notebook && !loading && !conflictWarningVisible) {
return
}
@@ -74,6 +73,10 @@ export function NotebookScene(): JSX.Element {
const isTemplate = notebook?.is_template
+ if (notebookId === 'new') {
+ return
+ }
+
return (
diff --git a/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.tsx b/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.tsx
index b04e2a4fe4e2c..edc4a3a3173b7 100644
--- a/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.tsx
+++ b/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.tsx
@@ -1,6 +1,6 @@
import { LemonButton, LemonButtonProps } from 'lib/lemon-ui/LemonButton'
-import { IconJournalPlus, IconPlus, IconWithCount } from 'lib/lemon-ui/icons'
+import { IconNotebook, IconPlus, IconWithCount } from 'lib/lemon-ui/icons'
import {
NotebookSelectButtonLogicProps,
notebookSelectButtonLogic,
@@ -206,7 +206,7 @@ export function NotebookSelectButton({ children, ...props }: NotebookSelectButto
-
+
}
data-attr={nodeLogic ? 'notebooks-add-button-in-a-notebook' : 'notebooks-add-button'}
diff --git a/frontend/src/scenes/notebooks/NotebooksScene.tsx b/frontend/src/scenes/notebooks/NotebooksScene.tsx
new file mode 100644
index 0000000000000..7caede1f116db
--- /dev/null
+++ b/frontend/src/scenes/notebooks/NotebooksScene.tsx
@@ -0,0 +1,34 @@
+import { SceneExport } from 'scenes/sceneTypes'
+import './NotebookScene.scss'
+import { NotebooksTable } from './NotebooksTable/NotebooksTable'
+import { LemonButton, LemonTag } from '@posthog/lemon-ui'
+import { PageHeader } from 'lib/components/PageHeader'
+import { urls } from 'scenes/urls'
+
+export const scene: SceneExport = {
+ component: NotebooksScene,
+}
+
+export function NotebooksScene(): JSX.Element {
+ return (
+
+
+ Notebooks
+
+ Beta
+
+
+ }
+ buttons={
+
+ New notebook
+
+ }
+ />
+
+
+
+ )
+}
diff --git a/frontend/src/scenes/notebooks/notebookSceneLogic.ts b/frontend/src/scenes/notebooks/notebookSceneLogic.ts
index 3129323a931fe..e7659c203c5d0 100644
--- a/frontend/src/scenes/notebooks/notebookSceneLogic.ts
+++ b/frontend/src/scenes/notebooks/notebookSceneLogic.ts
@@ -4,6 +4,7 @@ import { Breadcrumb } from '~/types'
import type { notebookSceneLogicType } from './notebookSceneLogicType'
import { notebookLogic } from './Notebook/notebookLogic'
import { urls } from 'scenes/urls'
+import { notebooksModel } from '~/models/notebooksModel'
export type NotebookSceneLogicProps = {
shortId: string
@@ -13,31 +14,36 @@ export const notebookSceneLogic = kea
([
props({} as NotebookSceneLogicProps),
key(({ shortId }) => shortId),
connect((props: NotebookSceneLogicProps) => ({
- values: [notebookLogic(props), ['notebook', 'notebookLoading']],
- actions: [notebookLogic(props), ['loadNotebook']],
+ values: [notebookLogic(props), ['notebook', 'notebookLoading'], notebooksModel, ['notebooksLoading']],
+ actions: [notebookLogic(props), ['loadNotebook'], notebooksModel, ['createNotebook']],
})),
selectors(() => ({
notebookId: [() => [(_, props) => props], (props): string => props.shortId],
+ loading: [
+ (s) => [s.notebookLoading, s.notebooksLoading],
+ (notebookLoading, notebooksLoading) => notebookLoading || notebooksLoading,
+ ],
+
breadcrumbs: [
- (s) => [s.notebook, s.notebookLoading],
- (notebook, notebookLoading): Breadcrumb[] => [
+ (s) => [s.notebook, s.loading],
+ (notebook, loading): Breadcrumb[] => [
{
name: 'Notebooks',
- path: urls.dashboards() + '?tab=notebooks',
+ path: urls.notebooks(),
},
{
- name: notebook
- ? notebook?.title || 'Unnamed'
- : notebookLoading
- ? 'Loading...'
- : 'Notebook not found',
+ name: notebook ? notebook?.title || 'Unnamed' : loading ? 'Loading...' : 'Notebook not found',
},
],
],
})),
- afterMount(({ actions }) => {
- actions.loadNotebook()
+ afterMount(({ actions, props }) => {
+ if (props.shortId === 'new') {
+ actions.createNotebook()
+ } else {
+ actions.loadNotebook()
+ }
}),
])
diff --git a/frontend/src/scenes/sceneTypes.ts b/frontend/src/scenes/sceneTypes.ts
index 60ab9f17c9f01..370665987fa95 100644
--- a/frontend/src/scenes/sceneTypes.ts
+++ b/frontend/src/scenes/sceneTypes.ts
@@ -79,6 +79,7 @@ export enum Scene {
DebugQuery = 'DebugQuery',
VerifyEmail = 'VerifyEmail',
Feedback = 'Feedback',
+ Notebooks = 'Notebooks',
Notebook = 'Notebook',
Products = 'Products',
Onboarding = 'Onboarding',
diff --git a/frontend/src/scenes/scenes.ts b/frontend/src/scenes/scenes.ts
index 647b369ff8798..eec5a2c0dacca 100644
--- a/frontend/src/scenes/scenes.ts
+++ b/frontend/src/scenes/scenes.ts
@@ -318,6 +318,10 @@ export const sceneConfigurations: Partial> = {
name: 'Notebook',
layout: 'app-raw',
},
+ [Scene.Notebooks]: {
+ projectBased: true,
+ name: 'Notebooks',
+ },
}
const preserveParams = (url: string) => (_params: Params, searchParams: Params, hashParams: Params) => {
@@ -487,4 +491,5 @@ export const routes: Record = {
[urls.feedback()]: Scene.Feedback,
[urls.feedback() + '/*']: Scene.Feedback,
[urls.notebook(':shortId')]: Scene.Notebook,
+ [urls.notebooks()]: Scene.Notebooks,
}
diff --git a/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx b/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx
index b93793c4783b5..c6e511e0ccf7a 100644
--- a/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx
+++ b/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx
@@ -4,7 +4,7 @@ import {
} from 'scenes/session-recordings/player/sessionRecordingPlayerLogic'
import { useActions, useValues } from 'kea'
import { LemonButton, LemonButtonProps } from 'lib/lemon-ui/LemonButton'
-import { IconComment, IconDelete, IconJournalPlus, IconLink, IconPinFilled, IconPinOutline } from 'lib/lemon-ui/icons'
+import { IconComment, IconDelete, IconNotebook, IconLink, IconPinFilled, IconPinOutline } from 'lib/lemon-ui/icons'
import { openPlayerShareDialog } from 'scenes/session-recordings/player/share/PlayerShare'
import { PlaylistPopoverButton } from './playlist-popover/PlaylistPopover'
import { LemonDialog } from 'lib/lemon-ui/LemonDialog'
@@ -85,7 +85,7 @@ export function PlayerMetaLinks(): JSX.Element {
{nodeLogic?.props.nodeType === NotebookNodeType.RecordingPlaylist ? (
}
+ icon={}
size="small"
onClick={() => {
nodeLogic.actions.insertAfter({
diff --git a/frontend/src/scenes/urls.ts b/frontend/src/scenes/urls.ts
index dfccee2129218..239e16cbda9a6 100644
--- a/frontend/src/scenes/urls.ts
+++ b/frontend/src/scenes/urls.ts
@@ -183,9 +183,6 @@ export const urls = {
combineUrl('/debug', {}, query ? { q: typeof query === 'string' ? query : JSON.stringify(query) } : {}).url,
feedback: (): string => '/feedback',
issues: (): string => '/issues',
- notebooks: (): string =>
- combineUrl(urls.dashboards(), {
- tab: 'notebooks',
- }).url,
+ notebooks: (): string => '/notebooks',
notebook: (shortId: string): string => `/notebooks/${shortId}`,
}