Skip to content

Commit

Permalink
Bunch of work for dedicated panel
Browse files Browse the repository at this point in the history
  • Loading branch information
benjackwhite committed Oct 27, 2023
1 parent 796a73d commit 37bd438
Show file tree
Hide file tree
Showing 14 changed files with 307 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,32 +1,8 @@
import { useActions, useValues } from 'kea'
import { NotebookPopoverCard } from 'scenes/notebooks/Notebook/NotebookPopover'
import { notebookPopoverLogic } from 'scenes/notebooks/Notebook/notebookPopoverLogic'
import { sidePanelLogic } from '../sidePanelLogic'
import { useEffect } from 'react'
import { NotebookPanel } from 'scenes/notebooks/NotebookPanel/NotebookPanel'

export const SidePanelNotebook = (): JSX.Element => {
const { closeSidePanel } = useActions(sidePanelLogic)
const { selectedTab } = useValues(sidePanelLogic)
// const { closeSidePanel } = useActions(sidePanelLogic)
// const { selectedTab } = useValues(sidePanelLogic)

const { visibility } = useValues(notebookPopoverLogic)
const { setVisibility } = useActions(notebookPopoverLogic)

// useEffect(() => {
// // When something sets the popover to hidden - close the side panel
// return () => {
// if (selectedTab === 'notebook') {
// closeSidePanel()
// }
// }
// }, [visibility === 'hidden'])

useEffect(() => {
setVisibility('visible')
// On unmount - hide the popover
return () => {
setVisibility('hidden')
}
}, [])

return <NotebookPopoverCard />
return <NotebookPanel />
}
2 changes: 1 addition & 1 deletion frontend/src/layout/navigation/SideBar/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import { Tooltip } from 'lib/lemon-ui/Tooltip'
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 { NotebookPopover } from 'scenes/notebooks/NotebookPanel/NotebookPopover'
import { FlaggedFeature } from 'lib/components/FlaggedFeature'
import { IconNotebook } from 'scenes/notebooks/IconNotebook'

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/layout/navigation/TopBar/NotebookButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useActions, useValues } from 'kea'
import { notebookPopoverLogic } from 'scenes/notebooks/Notebook/notebookPopoverLogic'
import { notebookPopoverLogic } from 'scenes/notebooks/NotebookPanel/notebookPopoverLogic'
import { LemonButton, LemonButtonWithSideActionProps } from '@posthog/lemon-ui'
import { useFeatureFlag } from 'lib/hooks/useFeatureFlag'
import { IconNotebook } from 'scenes/notebooks/IconNotebook'
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/models/notebooksModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import posthog from 'posthog-js'
import { LOCAL_NOTEBOOK_TEMPLATES } from 'scenes/notebooks/NotebookTemplates/notebookTemplates'
import { deleteWithUndo } from 'lib/utils'
import { teamLogic } from 'scenes/teamLogic'
import { notebookPopoverLogic } from 'scenes/notebooks/Notebook/notebookPopoverLogic'
import { notebookPopoverLogic } from 'scenes/notebooks/NotebookPanel/notebookPopoverLogic'
import { defaultNotebookContent, EditorFocusPosition, JSONContent } from 'scenes/notebooks/Notebook/utils'

import type { notebooksModelType } from './notebooksModelType'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState } from 'react'
import { NotebookNodeType } from '~/types'
import './DraggableToNotebook.scss'
import { useActions, useValues } from 'kea'
import { notebookPopoverLogic } from '../Notebook/notebookPopoverLogic'
import { notebookPopoverLogic } from '../NotebookPanel/notebookPopoverLogic'
import clsx from 'clsx'
import { FlaggedFeature } from 'lib/components/FlaggedFeature'
import { FEATURE_FLAGS } from 'lib/constants'
Expand Down
67 changes: 67 additions & 0 deletions frontend/src/scenes/notebooks/NotebookPanel/NotebookPanel.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
@import '../../../styles/mixins';

.NotebookPanel {
flex: 1;
display: flex;
flex-direction: column;
border-radius: var(--radius);
background-color: var(--bg-3000);
border: 1px solid var(--border-3000);
box-shadow: 0px 16px 16px rgba(0, 0, 0, 0);
transition: box-shadow 150ms linear;
overflow: hidden;
}

.NotebookPanelDropzone {
box-shadow: 0px 16px 16px rgba(0, 0, 0, 0.15);
border: 2px dashed var(--border-3000);
border-radius: var(--radius);

transition: all 150ms;
height: 4rem;
margin-bottom: 1rem;
backdrop-filter: blur(5px);
display: flex;

.NotebookPanelDropzone__message {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-weight: 700;
font-size: 1rem;
color: var(--muted-alt);
text-align: center;
pointer-events: none;
background-color: var(--bg-light);
padding: 1rem;
opacity: 0.75;
transition: all 150ms;
}

.NotebookPanelDropzone__dropped {
overflow: hidden;
flex: 1;
display: flex;
flex-direction: column;
}

&--active {
border-color: var(--primary);
height: 8rem;

.NotebookPanelDropzone__message {
opacity: 1;
}
}

&--dropped {
padding: 1rem;
border-color: var(--primary);
background-color: var(--bg-light);
height: 100%;
justify-content: flex-start;
align-items: initial;
}
}
83 changes: 83 additions & 0 deletions frontend/src/scenes/notebooks/NotebookPanel/NotebookPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useActions, useValues } from 'kea'
import './NotebookPanel.scss'
import { Notebook } from '../Notebook/Notebook'
import { LemonButton } from '@posthog/lemon-ui'
import { IconFullScreen, IconShare } from 'lib/lemon-ui/icons'
import { useMemo } from 'react'
import { NotebookListMini } from '../Notebook/NotebookListMini'
import { notebooksModel } from '~/models/notebooksModel'
import { NotebookExpandButton, NotebookSyncInfo } from '../Notebook/NotebookMeta'
import { notebookLogic } from '../Notebook/notebookLogic'
import { useResizeBreakpoints } from 'lib/hooks/useResizeObserver'
import { openNotebookShareDialog } from '../Notebook/NotebookShare'
import { notebookPanelLogic } from './notebookPanelLogic'

export function NotebookPanel(): JSX.Element | null {
const { fullScreen, selectedNotebook, initialAutofocus, droppedResource, dropProperties } =
useValues(notebookPanelLogic)
const { setFullScreen, selectNotebook } = useActions(notebookPanelLogic)
const { createNotebook } = useActions(notebooksModel)
const { notebook } = useValues(notebookLogic({ shortId: selectedNotebook }))
// const { activeScene } = useValues(sceneLogic)

// const showEditor = activeScene === Scene.Notebook ? visibility !== 'hidden' : shownAtLeastOnce
const editable = !notebook?.is_template

const { ref, size } = useResizeBreakpoints({
0: 'small',
832: 'medium',
})

const contentWidthHasEffect = useMemo(() => fullScreen && size === 'medium', [fullScreen, size])

if (droppedResource) {
return null
}

return (
<div ref={ref} className="NotebookPanel" {...dropProperties}>
<header className="flex items-center justify-between gap-2 font-semibold shrink-0 p-1 border-b">
<span className="flex items-center gap-1 text-primary-alt overflow-hidden">
<NotebookListMini
selectedNotebookId={selectedNotebook}
onSelectNotebook={(notebook) => selectNotebook(notebook.short_id)}
onNewNotebook={() => createNotebook()}
/>
</span>
<span className="flex items-center gap-1 px-1">
{selectedNotebook && <NotebookSyncInfo shortId={selectedNotebook} />}

<LemonButton
size="small"
onClick={() => openNotebookShareDialog({ shortId: selectedNotebook })}
status="primary-alt"
icon={<IconShare />}
tooltip="Share notebook"
tooltipPlacement="left"
/>

{contentWidthHasEffect && <NotebookExpandButton status="primary-alt" size="small" />}

<LemonButton
size="small"
onClick={() => setFullScreen(!fullScreen)}
status="primary-alt"
active={fullScreen}
icon={<IconFullScreen />}
tooltip="Toggle full screen"
tooltipPlacement="left"
/>
</span>
</header>

<div className="flex flex-col flex-1 overflow-y-auto px-4 py-2">
<Notebook
key={selectedNotebook}
shortId={selectedNotebook}
editable={editable}
initialAutofocus={initialAutofocus}
/>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { useActions, useValues } from 'kea'
import clsx from 'clsx'
import './NotebookPopover.scss'
import { Notebook } from './Notebook'
import { notebookPopoverLogic } from 'scenes/notebooks/Notebook/notebookPopoverLogic'
import { Notebook } from '../Notebook/Notebook'
import { notebookPopoverLogic } from 'scenes/notebooks/NotebookPanel/notebookPopoverLogic'
import { LemonButton } from '@posthog/lemon-ui'
import { IconFullScreen, IconChevronRight, IconOpenInNew, IconShare } from 'lib/lemon-ui/icons'
import { useEffect, useMemo, useRef } from 'react'
import { useKeyboardHotkeys } from 'lib/hooks/useKeyboardHotkeys'
import { NotebookListMini } from './NotebookListMini'
import { NotebookListMini } from '../Notebook/NotebookListMini'
import { notebooksModel } from '~/models/notebooksModel'
import { NotebookExpandButton, NotebookSyncInfo } from './NotebookMeta'
import { notebookLogic } from './notebookLogic'
import { NotebookExpandButton, NotebookSyncInfo } from '../Notebook/NotebookMeta'
import { notebookLogic } from '../Notebook/notebookLogic'
import { urls } from 'scenes/urls'
import { NotebookPopoverDropzone } from './NotebookPopoverDropzone'
import { useResizeBreakpoints } from 'lib/hooks/useResizeObserver'
import { openNotebookShareDialog } from './NotebookShare'
import { openNotebookShareDialog } from '../Notebook/NotebookShare'
import { sceneLogic } from 'scenes/sceneLogic'
import { Scene } from 'scenes/sceneTypes'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { notebookPopoverLogic } from './notebookPopoverLogic'
import { useActions, useValues } from 'kea'
import { NotebookNodeType } from '~/types'
import { NotebookSelectList } from '../NotebookSelectButton/NotebookSelectButton'
import { notebookLogicType } from './notebookLogicType'
import { notebookLogicType } from '../Notebook/notebookLogicType'
import { LemonButton } from '@posthog/lemon-ui'

export function NotebookPopoverDropzone(): JSX.Element | null {
Expand Down
139 changes: 139 additions & 0 deletions frontend/src/scenes/notebooks/NotebookPanel/notebookPanelLogic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { actions, kea, reducers, path, listeners, selectors, connect } from 'kea'

import { HTMLProps, RefObject } from 'react'
import { EditorFocusPosition } from '../Notebook/utils'

import type { notebookPanelLogicType } from './notebookPanelLogicType'
import { NotebookNodeResource } from '~/types'
import { SidePanelTab, sidePanelLogic } from '~/layout/navigation-3000/sidepanel/sidePanelLogic'

export const MIN_NOTEBOOK_SIDEBAR_WIDTH = 600

export const notebookPanelLogic = kea<notebookPanelLogicType>([
path(['scenes', 'notebooks', 'Notebook', 'notebookPanelLogic']),
connect({
values: [sidePanelLogic, ['sidePanelOpen']],
actions: [sidePanelLogic, ['openSidePanel']],
}),
actions({
setFullScreen: (full: boolean) => ({ full }),
selectNotebook: (id: string, autofocus: EditorFocusPosition | undefined = undefined) => ({ id, autofocus }),
startDropMode: true,
endDropMode: true,
setDropDistance: (distance: number) => ({ distance }),
setDroppedResource: (resource: NotebookNodeResource | string | null) => ({ resource }),
}),

reducers(() => ({
selectedNotebook: [
'scratchpad',
{ persist: true },
{
selectNotebook: (_, { id }) => id,
},
],
fullScreen: [
false,
{
setFullScreen: (_, { full }) => full,
setVisibility: (state, { visibility }) => (visibility === 'hidden' ? false : state),
},
],
initialAutofocus: [
'start' as EditorFocusPosition,
{
selectNotebook: (_, { autofocus }) => autofocus ?? 'start',
},
],
elementRef: [
null as RefObject<HTMLElement> | null,
{
setElementRef: (_, { element }) => element,
},
],
shownAtLeastOnce: [
false,
{
setVisibility: (state, { visibility }) => visibility !== 'hidden' || state,
},
],
dropMode: [
false,
{
startDropMode: () => true,
endDropMode: () => false,
},
],
dropDistance: [
0,
{
startDropMode: () => -1,
endDropMode: () => -1,
setDropDistance: (_, { distance }) => distance,
},
],
droppedResource: [
null as NotebookNodeResource | string | null,
{
setVisibility: (state, { visibility }) => (visibility === 'hidden' ? null : state),
setDroppedResource: (_, { resource }) => resource,
},
],
})),

selectors(({ cache, actions }) => ({
dropProperties: [
(s) => [s.dropMode, s.dropDistance, s.sidePanelOpen],
(
dropMode,
dropDistance,
sidePanelOpen
): Pick<HTMLProps<HTMLDivElement>, 'onDragEnter' | 'onDragLeave' | 'style'> => {
return dropMode
? {
onDragEnter: () => {
cache.dragEntercount = (cache.dragEntercount || 0) + 1
if (cache.dragEntercount === 1) {
actions.openSidePanel(SidePanelTab.Notebooks)
}
},

onDragLeave: () => {
cache.dragEntercount = (cache.dragEntercount || 0) - 1

if (cache.dragEntercount <= 0) {
cache.dragEntercount = 0
actions.openSidePanel(SidePanelTab.Notebooks)
}
},
}
: {}
},
],
})),

listeners(({ cache, actions }) => ({
startDropMode: () => {
cache.dragEntercount = 0
cache.dragStart = null
actions.openSidePanel(SidePanelTab.Notebooks)

cache.dragListener = (event: MouseEvent) => {
if (!cache.dragStart) {
cache.dragStart = event.pageX
}

// The drop distance is the percentage between where the drag started and where it now is
const dropDistance = (event.pageX - cache.dragStart) / window.innerWidth
actions.setDropDistance(dropDistance)
}
window.addEventListener('drag', cache.dragListener)
},
endDropMode: () => {
// if (values.visibility === 'peek') {
// actions.setVisibility('hidden')
// }
window.removeEventListener('drag', cache.dragListener)
},
})),
])
Loading

0 comments on commit 37bd438

Please sign in to comment.