fix(request-snippets): prevent scrolling errors from missing function (#7941)

* fix(request-snippets): prevent scrolling errors from missing function

* refactor(request-snippets): migrate to functional component

* fix(curl): remove undefined prop and function

* test(live-response): fix import of RequestSnippets
This commit is contained in:
Tim Lai
2022-03-24 11:23:42 -07:00
committed by GitHub
parent cd2f434438
commit 9250e209d4
4 changed files with 150 additions and 118 deletions

View File

@@ -21,7 +21,6 @@ export default class Curl extends React.Component {
? <SyntaxHighlighter ? <SyntaxHighlighter
language="bash" language="bash"
className="curl microlight" className="curl microlight"
onWheel={this.preventYScrollingBeyondElement}
style={getStyle(get(config, "syntaxHighlight.theme"))} style={getStyle(get(config, "syntaxHighlight.theme"))}
> >
{curl} {curl}

View File

@@ -1,6 +1,6 @@
import * as fn from "./fn" import * as fn from "./fn"
import * as selectors from "./selectors" import * as selectors from "./selectors"
import { RequestSnippets } from "./request-snippets" import RequestSnippets from "./request-snippets"
export default () => { export default () => {
return { return {
components: { components: {

View File

@@ -1,38 +1,10 @@
import React from "react" import React, { useRef, useEffect, useState } from "react"
import { CopyToClipboard } from "react-copy-to-clipboard"
import PropTypes from "prop-types" import PropTypes from "prop-types"
import get from "lodash/get" import get from "lodash/get"
import isFunction from "lodash/isFunction"
import { CopyToClipboard } from "react-copy-to-clipboard"
import { SyntaxHighlighter, getStyle } from "core/syntax-highlighting" import { SyntaxHighlighter, getStyle } from "core/syntax-highlighting"
export class RequestSnippets extends React.Component {
constructor() {
super()
this.state = {
activeLanguage: this.props?.requestSnippetsSelectors?.getSnippetGenerators()?.keySeq().first(),
expanded: this.props?.requestSnippetsSelectors?.getDefaultExpanded(),
}
}
static propTypes = {
request: PropTypes.object.isRequired,
requestSnippetsSelectors: PropTypes.object.isRequired,
getConfigs: PropTypes.object.isRequired,
requestSnippetsActions: PropTypes.object.isRequired,
}
render() {
const {request, getConfigs, requestSnippetsSelectors } = this.props
const snippetGenerators = requestSnippetsSelectors.getSnippetGenerators()
const activeLanguage = this.state.activeLanguage || snippetGenerators.keySeq().first()
const activeGenerator = snippetGenerators.get(activeLanguage)
const snippet = activeGenerator.get("fn")(request)
const onGenChange = (key) => {
const needsChange = activeLanguage !== key
if(needsChange) {
this.setState({
activeLanguage: key
})
}
}
const style = { const style = {
cursor: "pointer", cursor: "pointer",
lineHeight: 1, lineHeight: 1,
@@ -45,6 +17,7 @@ export class RequestSnippets extends React.Component {
boxShadow: "none", boxShadow: "none",
borderBottom: "none" borderBottom: "none"
} }
const activeStyle = { const activeStyle = {
cursor: "pointer", cursor: "pointer",
lineHeight: 1, lineHeight: 1,
@@ -61,19 +34,72 @@ export class RequestSnippets extends React.Component {
zIndex: "9999", zIndex: "9999",
borderBottom: "none" borderBottom: "none"
} }
const getBtnStyle = (key) => {
const RequestSnippets = ({ request, requestSnippetsSelectors, getConfigs }) => {
const config = isFunction(getConfigs) ? getConfigs() : null
const canSyntaxHighlight = get(config, "syntaxHighlight") !== false && get(config, "syntaxHighlight.activated", true)
const rootRef = useRef(null)
const [activeLanguage, setActiveLanguage] = useState(requestSnippetsSelectors.getSnippetGenerators()?.keySeq().first())
const [isExpanded, setIsExpanded] = useState(requestSnippetsSelectors?.getDefaultExpanded())
useEffect(() => {
const doIt = () => {
}
doIt()
}, [])
useEffect(() => {
const childNodes = Array
.from(rootRef.current.childNodes)
.filter(node => !!node.nodeType && node.classList?.contains("curl-command"))
// eslint-disable-next-line no-use-before-define
childNodes.forEach(node => node.addEventListener("mousewheel", handlePreventYScrollingBeyondElement, { passive: false }))
return () => {
// eslint-disable-next-line no-use-before-define
childNodes.forEach(node => node.removeEventListener("mousewheel", handlePreventYScrollingBeyondElement))
}
}, [request])
const snippetGenerators = requestSnippetsSelectors.getSnippetGenerators()
const activeGenerator = snippetGenerators.get(activeLanguage)
const snippet = activeGenerator.get("fn")(request)
const handleGenChange = (key) => {
const needsChange = activeLanguage !== key
if (needsChange) {
setActiveLanguage(key)
}
}
const handleSetIsExpanded = () => {
setIsExpanded(!isExpanded)
}
const handleGetBtnStyle = (key) => {
if (key === activeLanguage) { if (key === activeLanguage) {
return activeStyle return activeStyle
} }
return style return style
} }
const config = getConfigs()
const SnippetComponent = config?.syntaxHighlight?.activated const handlePreventYScrollingBeyondElement = (e) => {
const { target, deltaY } = e
const { scrollHeight: contentHeight, offsetHeight: visibleHeight, scrollTop } = target
const scrollOffset = visibleHeight + scrollTop
const isElementScrollable = contentHeight > visibleHeight
const isScrollingPastTop = scrollTop === 0 && deltaY < 0
const isScrollingPastBottom = scrollOffset >= contentHeight && deltaY > 0
if (isElementScrollable && (isScrollingPastTop || isScrollingPastBottom)) {
e.preventDefault()
}
}
const SnippetComponent = canSyntaxHighlight
? <SyntaxHighlighter ? <SyntaxHighlighter
language={activeGenerator.get("syntax")} language={activeGenerator.get("syntax")}
className="curl microlight" className="curl microlight"
onWheel={function(e) {return this.preventYScrollingBeyondElement(e)}}
style={getStyle(get(config, "syntaxHighlight.theme"))} style={getStyle(get(config, "syntaxHighlight.theme"))}
> >
{snippet} {snippet}
@@ -81,30 +107,30 @@ export class RequestSnippets extends React.Component {
: :
<textarea readOnly={true} className="curl" value={snippet}></textarea> <textarea readOnly={true} className="curl" value={snippet}></textarea>
const expanded = this.state.expanded === undefined ? this.props?.requestSnippetsSelectors?.getDefaultExpanded() : this.state.expanded
return ( return (
<div> <div className="request-snippets" ref={rootRef}>
Just a test
<div style={{ width: "100%", display: "flex", justifyContent: "flex-start", alignItems: "center", marginBottom: "15px" }}> <div style={{ width: "100%", display: "flex", justifyContent: "flex-start", alignItems: "center", marginBottom: "15px" }}>
<h4 <h4
onClick={() => handleSetIsExpanded()}
style={{ cursor: "pointer" }} style={{ cursor: "pointer" }}
onClick={() => this.setState({expanded: !expanded})}
>Snippets</h4> >Snippets</h4>
<button <button
onClick={() => this.setState({expanded: !expanded})} onClick={() => handleSetIsExpanded()}
style={{ border: "none", background: "none" }} style={{ border: "none", background: "none" }}
title={expanded ? "Collapse operation": "Expand operation"} title={isExpanded ? "Collapse operation" : "Expand operation"}
> >
<svg className="arrow" width="10" height="10"> <svg className="arrow" width="10" height="10">
<use href={expanded ? "#large-arrow-down" : "#large-arrow"} xlinkHref={expanded ? "#large-arrow-down" : "#large-arrow"} /> <use href={isExpanded ? "#large-arrow-down" : "#large-arrow"} xlinkHref={isExpanded ? "#large-arrow-down" : "#large-arrow"} />
</svg> </svg>
</button> </button>
</div> </div>
{ {
expanded && <div className="curl-command"> isExpanded && <div className="curl-command">
<div style={{ paddingLeft: "15px", paddingRight: "10px", width: "100%", display: "flex" }}> <div style={{ paddingLeft: "15px", paddingRight: "10px", width: "100%", display: "flex" }}>
{ {
snippetGenerators.entrySeq().map(([key, gen]) => { snippetGenerators.entrySeq().map(([key, gen]) => {
return (<div style={getBtnStyle(key)} className="btn" key={key} onClick={() => onGenChange(key)}> return (<div style={handleGetBtnStyle(key)} className="btn" key={key} onClick={() => handleGenChange(key)}>
<h4 style={key === activeLanguage ? { color: "white", } : {}}>{gen.get("title")}</h4> <h4 style={key === activeLanguage ? { color: "white", } : {}}>{gen.get("title")}</h4>
</div>) </div>)
}) })
@@ -121,7 +147,14 @@ export class RequestSnippets extends React.Component {
</div> </div>
} }
</div> </div>
) )
} }
RequestSnippets.propTypes = {
request: PropTypes.object.isRequired,
requestSnippetsSelectors: PropTypes.object.isRequired,
getConfigs: PropTypes.object.isRequired,
requestSnippetsActions: PropTypes.object,
} }
export default RequestSnippets

View File

@@ -6,7 +6,7 @@ import expect from "expect"
import { shallow } from "enzyme" import { shallow } from "enzyme"
import LiveResponse from "components/live-response" import LiveResponse from "components/live-response"
import ResponseBody from "components/response-body" import ResponseBody from "components/response-body"
import { RequestSnippets } from "core/plugins/request-snippets/request-snippets" import RequestSnippets from "core/plugins/request-snippets/request-snippets"
describe("<LiveResponse/>", function () { describe("<LiveResponse/>", function () {
let request = fromJSOrdered({ let request = fromJSOrdered({