-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
7 changed files
with
275 additions
and
17 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import React, { forwardRef } from 'react'; | ||
import { css, cx } from '@leafygreen-ui/emotion'; | ||
|
||
const iframeStyle = css` | ||
border: none; | ||
`; | ||
|
||
const InstruqtFrame = forwardRef(({ title, height, embedValue }, ref) => { | ||
const labTitle = title || 'MongoDB Interactive Lab'; | ||
const frameTitle = `Instruqt - ${labTitle}`; | ||
const frameHeight = height || '640'; | ||
const frameSrc = `https://play.instruqt.com/embed${embedValue}`; | ||
|
||
return ( | ||
<iframe | ||
ref={ref} | ||
className={cx(iframeStyle)} | ||
allowFullScreen | ||
sandbox="allow-same-origin allow-scripts allow-popups allow-forms allow-modals" | ||
title={frameTitle} | ||
height={frameHeight} | ||
width="100%" | ||
src={frameSrc} | ||
/> | ||
); | ||
}); | ||
|
||
export default InstruqtFrame; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import { createPortal } from 'react-dom'; | ||
import { Resizable } from 'react-resizable'; | ||
import { cx, css } from '@leafygreen-ui/emotion'; | ||
import { palette } from '@leafygreen-ui/palette'; | ||
import useViewport from '../../hooks/useViewport'; | ||
import { theme } from '../../theme/docsTheme'; | ||
import InstruqtFrame from './InstruqtFrame'; | ||
|
||
const labContainerStyle = css` | ||
background-color: ${palette.gray.dark3}; | ||
z-index: 9999; | ||
position: fixed !important; | ||
bottom: 0; | ||
padding-top: 21px; | ||
color: ${palette.white}; | ||
`; | ||
|
||
const handleContainerStyle = css` | ||
width: 100%; | ||
display: flex; | ||
justify-content: center; | ||
`; | ||
|
||
const handleStyle = css` | ||
position: absolute; | ||
border-radius: 4px; | ||
cursor: ns-resize; | ||
top: 10px; | ||
background-color: ${palette.white}; | ||
width: 50px; | ||
height: 4px; | ||
@media ${theme.screenSize.upToMedium} { | ||
display: none; | ||
} | ||
`; | ||
|
||
const topContainerStyle = css` | ||
margin-bottom: 11px; | ||
padding-left: 17px; | ||
height: 28px; | ||
display: flex; | ||
justify-content: center; | ||
@media ${theme.screenSize.upToSmall} { | ||
display: block; | ||
} | ||
`; | ||
|
||
const titleStyle = css` | ||
line-height: 28px; | ||
width: 50vw; | ||
white-space: nowrap; | ||
overflow: hidden; | ||
text-overflow: ellipsis; | ||
text-align: center; | ||
@media ${theme.screenSize.upToSmall} { | ||
text-align: left; | ||
} | ||
`; | ||
|
||
const CustomResizeHandle = React.forwardRef((props, ref) => { | ||
const { handleAxis, ...restProps } = props; | ||
return ( | ||
<div className={cx(handleContainerStyle)}> | ||
<div className={cx(handleStyle)} ref={ref} {...restProps} /> | ||
</div> | ||
); | ||
}); | ||
|
||
const LabDrawer = ({ title, embedValue }) => { | ||
const viewportSize = useViewport(); | ||
const labTitle = title || 'MongoDB Interactive Lab'; | ||
|
||
const defaultMeasurement = 200; | ||
const defaultWidth = viewportSize.width ?? defaultMeasurement; | ||
const defaultHeight = (viewportSize.height * 2) / 3 ?? defaultMeasurement; | ||
|
||
const minHeight = 60; | ||
const maxHeight = viewportSize.height ?? defaultMeasurement; | ||
const [height, setHeight] = useState(defaultHeight); | ||
|
||
const frameHeight = height - minHeight; | ||
|
||
// Shrink height of the drawer if new max height is less than the current height | ||
useEffect(() => { | ||
if (maxHeight < height) { | ||
setHeight(maxHeight); | ||
} | ||
}, [height, maxHeight]); | ||
|
||
const handleResize = (_e, { size }) => { | ||
setHeight(size.height); | ||
}; | ||
|
||
return createPortal( | ||
<Resizable | ||
className={cx(labContainerStyle)} | ||
height={height} | ||
maxConstraints={[defaultWidth, maxHeight]} | ||
minConstraints={[defaultWidth, minHeight]} | ||
width={defaultWidth} | ||
resizeHandles={['n']} | ||
handle={<CustomResizeHandle />} | ||
onResize={handleResize} | ||
> | ||
{/* Need this div with style as a wrapper to help with resizing */} | ||
<div style={{ width: defaultWidth + 'px', height: height + 'px' }}> | ||
<div className={cx(topContainerStyle)}> | ||
<div className={cx(titleStyle)}>{labTitle}</div> | ||
</div> | ||
<InstruqtFrame title={title} embedValue={embedValue} height={frameHeight} /> | ||
</div> | ||
</Resizable>, | ||
document.body | ||
); | ||
}; | ||
|
||
export default LabDrawer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React from 'react'; | ||
import { render } from '@testing-library/react'; | ||
import Instruqt from '../../src/components/Instruqt'; | ||
import { InstruqtProvider } from '../../src/components/Instruqt/instruqt-context'; | ||
import mockData from './data/Instruqt.test.json'; | ||
|
||
const renderComponent = (nodeData, hasLabDrawer = false) => { | ||
return render( | ||
<InstruqtProvider hasInstruqtLab={hasLabDrawer}> | ||
<Instruqt nodeData={nodeData} /> | ||
</InstruqtProvider> | ||
); | ||
}; | ||
|
||
describe('Instruqt', () => { | ||
beforeEach(() => { | ||
process.env.GATSBY_FEATURE_LAB_DRAWER = false; | ||
}); | ||
|
||
it('renders null when directive argument does not exist', () => { | ||
const wrapper = renderComponent(mockData.noArgument); | ||
expect(wrapper.queryByTitle('Instruqt', { exact: false })).toBeFalsy(); | ||
}); | ||
|
||
it('renders as embedded content', () => { | ||
const wrapper = renderComponent(mockData.example); | ||
expect(wrapper.queryByTitle('Instruqt', { exact: false })).toBeTruthy(); | ||
}); | ||
|
||
describe('lab drawer', () => { | ||
it('renders in a drawer', () => { | ||
// This may be removed as the feature work is complete | ||
process.env.GATSBY_FEATURE_LAB_DRAWER = true; | ||
const hasLabDrawer = true; | ||
const wrapper = renderComponent(mockData.example, hasLabDrawer); | ||
expect(wrapper.queryByTitle('Instruqt', { exact: false })).toBeTruthy(); | ||
expect(wrapper.queryByText('MongoDB Interactive Lab')).toBeTruthy(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"noArgument": { | ||
"type": "directive", | ||
"children": [], | ||
"domain": "mongodb", | ||
"name": "instruqt", | ||
"argument": [] | ||
}, | ||
"example": { | ||
"type": "directive", | ||
"children": [], | ||
"domain": "mongodb", | ||
"name": "instruqt", | ||
"argument": [ | ||
{ | ||
"type": "text", | ||
"value": "/mongodb-docs/tracks/getting-started-with-mongodb?token=em_j_d_wUT93QTFvgsZ" | ||
} | ||
] | ||
} | ||
} |