Skip to content

Commit

Permalink
fix: gap cursor to insert
Browse files Browse the repository at this point in the history
  • Loading branch information
daibhin committed Oct 24, 2023
1 parent 7ce0d34 commit 822c065
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 49 deletions.
37 changes: 35 additions & 2 deletions frontend/src/scenes/notebooks/Nodes/NodeWrapper.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
--border-color: var(--border);

transform: translate3d(0, 0, 0);
margin: 0.65rem 0px 0.35rem 0px;

.NotebookNode__box {
transform: translate3d(0, 0, 0);
Expand Down Expand Up @@ -44,13 +43,35 @@
margin-top: 0;
}

.NotebookNode__insertion_prompt {
width: 100%;
padding: 0.1rem 0px;
visibility: hidden;
cursor: pointer;

.NotebookNode__insertion_prompt__divider {
height: 1px;
}
}

&:hover {
.NotebookNode__insertion_prompt {
visibility: visible;

.NotebookNode__insertion_prompt__divider {
background: var(--primary-3000);
}
}
}

&:hover,
&--selected {
.NotebookNode__actions {
opacity: 1;
height: 2rem;
margin-top: 0.5rem;
margin-top: 0.2rem;
transition: all 150ms linear;
margin-bottom: 19px;
}
}

Expand Down Expand Up @@ -111,3 +132,15 @@
}
}
}

.react-renderer {
.NotebookNode__actions {
padding-bottom: 19px;
}

& + & {
.NotebookNode__actions {
padding-bottom: 0px;
}
}
}
28 changes: 24 additions & 4 deletions frontend/src/scenes/notebooks/Nodes/NodeWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
IconDragHandle,
IconFilter,
IconLink,
IconPlus,
IconPlusMini,
IconUnfoldLess,
IconUnfoldMore,
Expand All @@ -28,7 +29,7 @@ import { useInView } from 'react-intersection-observer'
import { NotebookNodeType } from '~/types'
import { ErrorBoundary } from '~/layout/ErrorBoundary'
import { NotebookNodeContext, NotebookNodeLogicProps, notebookNodeLogic } from './notebookNodeLogic'
import { posthogNodePasteRule, useSyncedAttributes } from './utils'
import { isCustomNode, posthogNodePasteRule, useSyncedAttributes } from './utils'
import {
NotebookNodeAttributes,
NotebookNodeProps,
Expand All @@ -37,6 +38,7 @@ import {
} from '../Notebook/utils'
import { useWhyDidIRender } from 'lib/hooks/useWhyDidIRender'
import { NotebookNodeTitle } from './components/NotebookNodeTitle'
import { NotebookNodeInsertionPrompt } from './NotebookNodeInsertionPrompt'

export interface NodeWrapperProps<T extends CustomNotebookNodeAttributes> {
nodeType: NotebookNodeType
Expand Down Expand Up @@ -104,8 +106,8 @@ function NodeWrapper<T extends CustomNotebookNodeAttributes>(
titlePlaceholder,
}
const nodeLogic = useMountedLogic(notebookNodeLogic(nodeLogicProps))
const { resizeable, expanded, actions } = useValues(nodeLogic)
const { setExpanded, deleteNode, toggleEditing } = useActions(nodeLogic)
const { resizeable, expanded, actions, nextNode, previousNode } = useValues(nodeLogic)
const { setExpanded, deleteNode, toggleEditing, insertAfter, insertBefore } = useActions(nodeLogic)

useWhyDidIRender('NodeWrapper.logicProps', {
resizeable,
Expand Down Expand Up @@ -146,6 +148,10 @@ function NodeWrapper<T extends CustomNotebookNodeAttributes>(

// Element is resizable if resizable is set to true. If expandable is set to true then is is only resizable if expanded is true
const isResizeable = resizeable && (!expandable || expanded)
const hasActions = actions && actions.length > 0

const insertContentBefore = (): void => insertBefore([{ type: 'paragraph' }])
const insertContentAfter = (): void => insertAfter([{ type: 'paragraph' }])

return (
<NotebookNodeContext.Provider value={nodeLogic}>
Expand All @@ -158,6 +164,7 @@ function NodeWrapper<T extends CustomNotebookNodeAttributes>(
'NotebookNode--auto-hide-metadata': autoHideMetadata,
})}
>
{!previousNode && <NotebookNodeInsertionPrompt onInsert={insertContentBefore} />}
<div className="NotebookNode__box">
<ErrorBoundary>
{!inView ? (
Expand Down Expand Up @@ -229,12 +236,22 @@ function NodeWrapper<T extends CustomNotebookNodeAttributes>(
)}
</ErrorBoundary>
</div>
{isEditable && actions.length ? (
{isEditable && hasActions ? (
<div
className="NotebookNode__actions"
// UX improvement so that the actions don't get in the way of the cursor
onClick={() => setTextSelection(getPos() + 1)}
>
<LemonButton
size="small"
type="secondary"
status="primary"
icon={<IconPlus />}
onClick={(e) => {
e.stopPropagation()
insertContentAfter()
}}
/>
{actions.map((x, i) => (
<LemonButton
key={i}
Expand All @@ -252,6 +269,9 @@ function NodeWrapper<T extends CustomNotebookNodeAttributes>(
))}
</div>
) : null}
{(!nextNode || isCustomNode(nextNode)) && !hasActions && (
<NotebookNodeInsertionPrompt onInsert={insertContentAfter} />
)}
</div>
</NodeViewWrapper>
</BindLogic>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const NotebookNodeInsertionPrompt = ({ onInsert }: { onInsert: () => void }): JSX.Element => {
return (
<div className="NotebookNode__insertion_prompt flex items-center space-x-2" onClick={onInsert}>
<div className="NotebookNode__insertion_prompt__divider flex flex-1" />
<div className="NotebookNode__insertion_prompt__label text-xs text-primary">Add content</div>
<div className="NotebookNode__insertion_prompt__divider flex flex-1" />
</div>
)
}
8 changes: 7 additions & 1 deletion frontend/src/scenes/notebooks/Nodes/notebookNodeLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export const notebookNodeLogic = kea<notebookNodeLogicType>([
setResizeable: (resizeable: boolean) => ({ resizeable }),
setActions: (actions: (NotebookNodeAction | undefined)[]) => ({ actions }),
insertAfter: (content: JSONContent) => ({ content }),
insertBefore: (content: JSONContent) => ({ content }),
insertAfterLastNodeOfType: (nodeType: string, content: JSONContent) => ({ content, nodeType }),
updateAttributes: (attributes: Partial<NotebookNodeAttributes<any>>) => ({ attributes }),
insertReplayCommentByTimestamp: (timestamp: number, sessionRecordingId: string) => ({
Expand Down Expand Up @@ -164,7 +165,12 @@ export const notebookNodeLogic = kea<notebookNodeLogicType>([

insertAfter: ({ content }) => {
const logic = values.notebookLogic
logic.values.editor?.insertContentAfterNode(props.getPos(), content)
logic.values.editor?.insertContentAfterNodeAtPosition(props.getPos(), content)
},

insertBefore: ({ content }) => {
const logic = values.notebookLogic
logic.values.editor?.insertContentBeforeNodeAtPosition(props.getPos(), content)
},

deleteNode: () => {
Expand Down
20 changes: 19 additions & 1 deletion frontend/src/scenes/notebooks/Nodes/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { ExtendedRegExpMatchArray, NodeViewProps, PasteRule } from '@tiptap/core
import posthog from 'posthog-js'
import { NodeType } from '@tiptap/pm/model'
import { Editor as TTEditor } from '@tiptap/core'
import { CustomNotebookNodeAttributes, NotebookNodeAttributes } from '../Notebook/utils'
import { CustomNotebookNodeAttributes, NotebookNodeAttributes, Node } from '../Notebook/utils'
import { useCallback, useMemo, useRef } from 'react'
import { tryJsonParse, uuid } from 'lib/utils'
import { NotebookNodeType } from '~/types'

export function createUrlRegex(path: string | RegExp, origin?: string): RegExp {
origin = (origin || window.location.origin).replace('.', '\\.')
Expand Down Expand Up @@ -146,3 +147,20 @@ export function useSyncedAttributes<T extends CustomNotebookNodeAttributes>(

return [parsedAttrs.current, updateAttributes]
}

export function isCustomNode(node: Node): boolean {
return [
NotebookNodeType.Query,
NotebookNodeType.Recording,
NotebookNodeType.RecordingPlaylist,
NotebookNodeType.FeatureFlag,
NotebookNodeType.FeatureFlagCodeExample,
NotebookNodeType.Experiment,
NotebookNodeType.EarlyAccessFeature,
NotebookNodeType.Survey,
NotebookNodeType.Person,
NotebookNodeType.Group,
NotebookNodeType.Cohort,
NotebookNodeType.Image,
].includes(node.type.name as NotebookNodeType)
}
10 changes: 6 additions & 4 deletions frontend/src/scenes/notebooks/Notebook/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import { BacklinkCommandsExtension } from './BacklinkCommands'
import { NotebookNodeEarlyAccessFeature } from '../Nodes/NotebookNodeEarlyAccessFeature'
import { NotebookNodeSurvey } from '../Nodes/NotebookNodeSurvey'
import { InlineMenu } from './InlineMenu'
import NodeGapInsertionExtension from './Extensions/NodeGapInsertion'
import { notebookLogic } from './notebookLogic'
import { sampleOne } from 'lib/utils'
import { NotebookNodeGroup } from '../Nodes/NotebookNodeGroup'
Expand Down Expand Up @@ -111,7 +110,6 @@ export function Editor(): JSX.Element {
NotebookNodeImage,
SlashCommandsExtension,
BacklinkCommandsExtension,
NodeGapInsertionExtension,
],
editorProps: {
handleDrop: (view, event, _slice, moved) => {
Expand Down Expand Up @@ -208,13 +206,17 @@ export function Editor(): JSX.Element {
destroy: () => editor.destroy(),
deleteRange: (range: EditorRange) => editor.chain().focus().deleteRange(range),
insertContent: (content: JSONContent) => editor.chain().insertContent(content).focus().run(),
insertContentAfterNode: (position: number, content: JSONContent) => {
insertContentAfterNodeAtPosition: (position: number, content: JSONContent) => {
const endPosition = findEndPositionOfNode(editor, position)
if (endPosition) {
editor.chain().focus().insertContentAt(endPosition, content).run()
editor.chain().focus().insertContentAt(endPosition, content, { updateSelection: true }).run()
editor.commands.scrollIntoView()
}
},
insertContentBeforeNodeAtPosition: (position: number, content: JSONContent) => {
editor.chain().focus().insertContentAt(position, content).run()
editor.commands.scrollIntoView()
},
pasteContent: (position: number, text: string) => {
editor?.chain().focus().setTextSelection(position).run()
editor?.view.pasteText(text)
Expand Down

This file was deleted.

6 changes: 3 additions & 3 deletions frontend/src/scenes/notebooks/Notebook/notebookLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ export const notebookLogic = kea<notebookLogicType>([
nextNode = values.editor?.nextNode(insertionPosition)
}

values.editor?.insertContentAfterNode(insertionPosition, content)
values.editor?.insertContentAfterNodeAtPosition(insertionPosition, content)
}
)
},
Expand All @@ -404,7 +404,7 @@ export const notebookLogic = kea<notebookLogicType>([
nextNode = values.editor?.nextNode(insertionPosition)
}

values.editor?.insertContentAfterNode(insertionPosition, content)
values.editor?.insertContentAfterNodeAtPosition(insertionPosition, content)
}
)
},
Expand All @@ -427,7 +427,7 @@ export const notebookLogic = kea<notebookLogicType>([
}
}

values.editor?.insertContentAfterNode(
values.editor?.insertContentAfterNodeAtPosition(
insertionPosition,
buildTimestampCommentContent({
playbackTime: timestamp,
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/scenes/notebooks/Notebook/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ export interface NotebookEditor {
destroy: () => void
deleteRange: (range: EditorRange) => EditorCommands
insertContent: (content: JSONContent) => void
insertContentAfterNode: (position: number, content: JSONContent) => void
insertContentAfterNodeAtPosition: (position: number, content: JSONContent) => void
insertContentBeforeNodeAtPosition: (position: number, content: JSONContent) => void
pasteContent: (position: number, text: string) => void
findNode: (position: number) => Node | null
findNodePositionByAttrs: (attrs: Record<string, any>) => any
Expand Down

0 comments on commit 822c065

Please sign in to comment.