Skip to content

Commit

Permalink
feat(flows): ability to insert cells inline (#18750)
Browse files Browse the repository at this point in the history
* feat: show previous result helper in script cells regardless of position

* feat: enable adding a cell at a specific index

* refactor: give markdown cells some default text

* feat: introduce components for inline cell insertion

* feat: replace static divider with inline insert divider

* refactor: consolidate AddButtons & InsertCellMenu

Keeping it DRY
  • Loading branch information
alexpaxton authored Jun 29, 2020
1 parent f988f85 commit fbdbd6c
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 33 deletions.
23 changes: 17 additions & 6 deletions ui/src/notebooks/components/AddButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ import {PIPE_DEFINITIONS} from 'src/notebooks'
import {event} from 'src/notebooks/shared/event'
import {isFlagEnabled} from 'src/shared/utils/featureFlag'

const AddButtons: FC = () => {
interface Props {
index?: number
onInsert?: () => void
eventName: string
}

const AddButtons: FC<Props> = ({index, onInsert, eventName}) => {
const {addPipe} = useContext(NotebookContext)

const pipes = Object.entries(PIPE_DEFINITIONS)
Expand Down Expand Up @@ -40,14 +46,19 @@ const AddButtons: FC = () => {
data = data()
}

event('Notebook Add Button Clicked', {
onInsert && onInsert()

event(eventName, {
type: def.type,
})

addPipe({
...data,
type,
})
addPipe(
{
...data,
type,
},
index
)
}}
color={ComponentColor.Secondary}
/>
Expand Down
2 changes: 1 addition & 1 deletion ui/src/notebooks/components/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const Header: FC = () => (
<Page.ControlBar fullWidth={FULL_WIDTH}>
<Page.ControlBarLeft>
<h3 className="notebook--add-cell-label">Add Cell:</h3>
<AddButtons />
<AddButtons eventName="Notebook Add Button Clicked" />
</Page.ControlBarLeft>
<Page.ControlBarRight>
<MiniMapToggle />
Expand Down
60 changes: 60 additions & 0 deletions ui/src/notebooks/components/panel/InsertCellButton.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
@import '@influxdata/clockface/dist/variables.scss';
@import '~src/notebooks/NotebookVariables.scss';

.notebook-divider {
height: 12px;
margin: $cf-marg-a $notebook-panel--gutter;
position: relative;

&:after {
content: '';
position: absolute;
top: 50%;
left: 0;
right: 0;
background-color: $notebook-divider-color;
height: $cf-border;
transform: translateY(-50%);
z-index: 0;
}

&:hover {
cursor: pointer;
}

&:last-of-type {
margin-bottom: 25vh;
}
}

.notebook-divider--button {
position: absolute;
z-index: 1;
top: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
opacity: 0;
cursor: pointer;

&:after {
border-radius: 50%;
}

.notebook-divider:hover &,
.notebook-divider__popped &,
.notebook-divider__popped:hover & {
opacity: 1;
}
}

.insert-cell-menu {
padding: $cf-marg-c;
font-size: 14px;
}

.insert-cell-menu--title {
font-weight: $cf-font-weight--medium;
margin-top: 0;
margin-bottom: $cf-marg-b !important;
user-select: none;
}
120 changes: 120 additions & 0 deletions ui/src/notebooks/components/panel/InsertCellButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Libraries
import React, {FC, useRef, useEffect} from 'react'

// Components
import {
Popover,
Appearance,
ComponentColor,
ComponentSize,
SquareButton,
IconFont,
FlexBox,
FlexDirection,
AlignItems,
} from '@influxdata/clockface'
import AddButtons from 'src/notebooks/components/AddButtons'

// Styles
import 'src/notebooks/components/panel/InsertCellButton.scss'

interface Props {
index: number
}

const InsertCellButton: FC<Props> = ({index}) => {
const dividerRef = useRef<HTMLDivElement>(null)
const buttonRef = useRef<HTMLButtonElement>(null)
const popoverVisible = useRef<boolean>(false)
const buttonPositioningEnabled = useRef<boolean>(false)

useEffect(() => {
window.addEventListener('mousemove', handleMouseMove)

return () => {
window.removeEventListener('mousemove', handleMouseMove)
}
}, [])

const handleMouseMove = (e: MouseEvent): void => {
if (!dividerRef.current || !buttonRef.current) {
return
}

if (
popoverVisible.current === false &&
buttonPositioningEnabled.current === true
) {
const {pageX} = e
const {left, width} = dividerRef.current.getBoundingClientRect()

const minLeft = 0
const maxLeft = width

const buttonLeft = Math.min(Math.max(pageX - left, minLeft), maxLeft)
buttonRef.current.setAttribute('style', `left: ${buttonLeft}px`)
}
}

const handleMouseEnter = () => {
buttonPositioningEnabled.current = true
}

const handleMouseLeave = () => {
buttonPositioningEnabled.current = false
}

const handlePopoverShow = () => {
popoverVisible.current = true
dividerRef.current &&
dividerRef.current.classList.add('notebook-divider__popped')
}

const handlePopoverHide = () => {
popoverVisible.current = false
dividerRef.current &&
dividerRef.current.classList.remove('notebook-divider__popped')
}

return (
<div
className="notebook-divider"
ref={dividerRef}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<SquareButton
icon={IconFont.Plus}
ref={buttonRef}
className="notebook-divider--button"
color={ComponentColor.Secondary}
active={popoverVisible.current}
/>
<Popover
enableDefaultStyles={false}
appearance={Appearance.Outline}
color={ComponentColor.Secondary}
triggerRef={buttonRef}
onShow={handlePopoverShow}
onHide={handlePopoverHide}
contents={onHide => (
<FlexBox
direction={FlexDirection.Column}
alignItems={AlignItems.Stretch}
margin={ComponentSize.Small}
className="insert-cell-menu"
>
<p className="insert-cell-menu--title">Insert Cell Here</p>
<AddButtons
index={index}
onInsert={onHide}
eventName="Notebook Insert Cell Inline"
/>
</FlexBox>
)}
/>
</div>
)
}

export default InsertCellButton
16 changes: 10 additions & 6 deletions ui/src/notebooks/components/panel/NotebookPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
ClickOutside,
} from '@influxdata/clockface'
import RemovePanelButton from 'src/notebooks/components/panel/RemovePanelButton'
import InsertCellButton from 'src/notebooks/components/panel/InsertCellButton'
import PanelVisibilityToggle from 'src/notebooks/components/panel/PanelVisibilityToggle'
import MovePanelButton from 'src/notebooks/components/panel/MovePanelButton'
import NotebookPanelTitle from 'src/notebooks/components/panel/NotebookPanelTitle'
Expand Down Expand Up @@ -113,12 +114,15 @@ const NotebookPanel: FC<Props> = ({index, children, controls}) => {
}

return (
<ClickOutside onClickOutside={handleClickOutside}>
<div className={panelClassName} onClick={handleClick} ref={panelRef}>
<NotebookPanelHeader index={index} controls={controls} />
<div className="notebook-panel--body">{children}</div>
</div>
</ClickOutside>
<>
<ClickOutside onClickOutside={handleClickOutside}>
<div className={panelClassName} onClick={handleClick} ref={panelRef}>
<NotebookPanelHeader index={index} controls={controls} />
<div className="notebook-panel--body">{children}</div>
</div>
</ClickOutside>
<InsertCellButton index={index} />
</>
)
}

Expand Down
18 changes: 12 additions & 6 deletions ui/src/notebooks/context/notebook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface NotebookContextType {
pipes: PipeData[]
meta: PipeMeta[] // data only used for the view layer for Notebooks
results: BothResults[]
addPipe: (pipe: PipeData) => void
addPipe: (pipe: PipeData, insertAtIndex?: number) => void
updatePipe: (idx: number, pipe: PipeData) => void
updateMeta: (idx: number, pipe: PipeMeta) => void
updateResult: (idx: number, result: BothResults) => void
Expand Down Expand Up @@ -84,14 +84,23 @@ export const NotebookProvider: FC = ({children}) => {
const _setResults = useCallback(setResults, [id])

const addPipe = useCallback(
(pipe: PipeData) => {
const add = data => {
(pipe: PipeData, insertAtIndex?: number) => {
let add = data => {
return pipes => {
pipes.push(data)
return pipes.slice()
}
}

if (insertAtIndex !== undefined) {
add = data => {
return pipes => {
pipes.splice(insertAtIndex + 1, 0, data)
return pipes.slice()
}
}
}

if (pipes.length && pipe.type !== 'query') {
_setResults(add({...results[results.length - 1]}))
_setMeta(
Expand Down Expand Up @@ -123,9 +132,6 @@ export const NotebookProvider: FC = ({children}) => {
queries: [
{
...pipe.queries[0],
text:
pipe.queries[0].text +
'\n\n// tip: use the __PREVIOUS_RESULT__ variable to use results from the previous cell',
},
],
}
Expand Down
3 changes: 2 additions & 1 deletion ui/src/notebooks/pipes/Query/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ register({
activeQuery: 0,
queries: [
{
text: '// Write Flux script here',
text:
'// Write Flux script here\n// use __PREVIOUS_RESULT__ to continue building from the previous cell',
editMode: 'advanced',
builderConfig: {
buckets: [],
Expand Down
2 changes: 1 addition & 1 deletion ui/src/notebooks/pipes/markdown/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ register({
component: MarkdownPanel,
button: 'Markdown',
initial: () => ({
text: TEST_MODE ? TESTCASE : '',
text: TEST_MODE ? TESTCASE : 'Type markdown here',
mode: 'edit',
}),
})
12 changes: 0 additions & 12 deletions ui/src/notebooks/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,6 @@
align-items: stretch;
border-radius: $cf-radius;
margin: 0 $notebook-panel--gutter;

&:after {
content: '';
height: $cf-border;
background-color: $notebook-divider-color;
border-radius: $cf-border / 2;
margin: $cf-marg-a 0;
}

&:last-of-type:after {
display: none;
}
}

.notebook-panel--header,
Expand Down

0 comments on commit fbdbd6c

Please sign in to comment.