-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Joe Fusco <[email protected]>
- Loading branch information
1 parent
afbef5a
commit 58b2f48
Showing
16 changed files
with
824 additions
and
22 deletions.
There are no files selected for viewing
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,36 @@ | ||
import { Allotment } from "allotment"; | ||
import PropTypes from "prop-types"; | ||
import React from "react"; | ||
import "allotment/dist/style.css"; | ||
|
||
// DraggablePaneContainer: A component that uses Allotment to create a resizable pane container. | ||
// Fixed height is set on the container wrapping the Allotment component. | ||
const DraggablePaneContainer = ({ children, height = '500px' }) => { | ||
// Ensure children is an array with two elements for two panes. | ||
if (children.length !== 2) { | ||
throw new Error("DraggablePaneContainer requires exactly two children."); | ||
} | ||
|
||
const containerStyle = { height }; | ||
const innerPaneStyle = { overflowY: "auto", height: "100%" }; | ||
|
||
return ( | ||
<div style={containerStyle}> | ||
<Allotment> | ||
<Allotment.Pane> | ||
<div style={innerPaneStyle}>{children[0]}</div> | ||
</Allotment.Pane> | ||
<Allotment.Pane> | ||
<div style={innerPaneStyle}>{children[1]}</div> | ||
</Allotment.Pane> | ||
</Allotment> | ||
</div> | ||
); | ||
}; | ||
|
||
DraggablePaneContainer.propTypes = { | ||
children: PropTypes.arrayOf(PropTypes.node).isRequired, | ||
height: PropTypes.string, | ||
}; | ||
|
||
export default DraggablePaneContainer; |
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,128 @@ | ||
import hljs from 'highlight.js/lib/core' | ||
import graphql from 'highlight.js/lib/languages/graphql' | ||
import json from 'highlight.js/lib/languages/json' | ||
import React, { useState, useEffect, useRef } from 'react' | ||
|
||
import 'highlight.js/styles/atom-one-dark.css' | ||
import DraggablePaneContainer from './DraggablePaneContainer' | ||
|
||
// Register GraphQL and JSON for syntax highlighting | ||
hljs.registerLanguage('graphql', graphql) | ||
hljs.registerLanguage('json', json) | ||
|
||
export function MiniGraphQL({ initialQuery, initialVariables, endpoint }) { | ||
const [query, setQuery] = useState(initialQuery || '') | ||
const [variables, setVariables] = useState(initialVariables || {}) | ||
const [data, setData] = useState(null) | ||
const [loading, setLoading] = useState(false) | ||
const [error, setError] = useState(null) | ||
const queryRef = useRef(null) | ||
|
||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
useEffect(highlightQuery, []) // Highlight query on mount | ||
|
||
function highlightQuery() { | ||
if (query && queryRef.current) { | ||
queryRef.current.innerHTML = hljs.highlight(query, { | ||
language: 'graphql', | ||
}).value | ||
} | ||
} | ||
|
||
function resetForm() { | ||
setQuery(initialQuery || '') // Reset query to initial | ||
setVariables(initialVariables || {}) // Reset variables to initial | ||
setData(null) // Clear fetched data | ||
setError(null) // Clear any errors | ||
} | ||
|
||
async function fetchData() { | ||
if (loading) return // Prevent fetching if already loading | ||
|
||
setLoading(true) | ||
setError(null) | ||
|
||
try { | ||
const response = await fetch(endpoint, { | ||
method: 'POST', | ||
headers: { 'Content-Type': 'application/json' }, | ||
body: JSON.stringify({ query, variables }), | ||
}) | ||
|
||
const result = await response.json() | ||
if (response.ok && result.data) { | ||
setData(result.data) | ||
} else { | ||
setError( | ||
new Error( | ||
result.errors?.map((e) => e.message).join('\n') || | ||
'Error fetching data', | ||
), | ||
) | ||
} | ||
} catch (e) { | ||
setError(e) | ||
} finally { | ||
setLoading(false) | ||
} | ||
} | ||
|
||
function handleQueryChange() { | ||
if (queryRef.current) { | ||
setQuery(queryRef.current.textContent) | ||
resetForm() // Reset the form when query changes | ||
} | ||
} | ||
|
||
function handleBlur() { | ||
highlightQuery() // Re-highlight the query on blur | ||
} | ||
|
||
function handleRunQuery() { | ||
if (data) { | ||
resetForm() // Act as reset if data is present | ||
} else { | ||
fetchData() // Fetch data if no data present | ||
} | ||
} | ||
|
||
return ( | ||
<div className="mini-graphql flex w-full flex-col"> | ||
<DraggablePaneContainer> | ||
<div className="query-panel h-full flex-1 overflow-auto"> | ||
<pre | ||
ref={queryRef} | ||
className="not-prose graphql-query content-editable overflow-auto p-1 dark:bg-gray-800 dark:text-white text-sm" | ||
contentEditable={!loading} | ||
onInput={handleQueryChange} | ||
onBlur={handleBlur} | ||
suppressContentEditableWarning={true} | ||
/> | ||
</div> | ||
<div className="response-panel h-full flex-1 overflow-auto"> | ||
<div className="data-panel h-full"> | ||
{error && ( | ||
<pre className="not-prose p-1 text-red-500 text-sm">{error.message}</pre> | ||
)} | ||
{data && ( | ||
<pre className="not-prose json-data h-full overflow-auto p-1 dark:bg-gray-800 dark:text-white text-sm"> | ||
<code className="whitespace-pre-wrap"> | ||
{JSON.stringify(data, null, 2)} | ||
</code> | ||
</pre> | ||
)} | ||
</div> | ||
</div> | ||
</DraggablePaneContainer> | ||
<div className="button-panel flex py-4"> | ||
<button | ||
onClick={handleRunQuery} | ||
disabled={loading} | ||
className="run-query-button rounded bg-blue-500 px-4 py-2 text-sm text-white font-semibold hover:bg-blue-700 disabled:bg-blue-300 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 dark:disabled:bg-gray-500 lg:text-base" | ||
> | ||
{loading ? 'Loading...' : data ? 'Reset' : 'Run Query'} | ||
</button> | ||
</div> | ||
</div> | ||
) | ||
} |
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,12 @@ | ||
export function CheckIcon() { | ||
return ( | ||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
<path | ||
fill-rule="evenodd" | ||
clip-rule="evenodd" | ||
d="M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z" | ||
fill="currentColor" | ||
/> | ||
</svg> | ||
) | ||
} |
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,12 @@ | ||
export function PlayIcon() { | ||
return ( | ||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
<path | ||
fill-rule="evenodd" | ||
clip-rule="evenodd" | ||
d="M3.24182 2.32181C3.3919 2.23132 3.5784 2.22601 3.73338 2.30781L12.7334 7.05781C12.8974 7.14436 13 7.31457 13 7.5C13 7.68543 12.8974 7.85564 12.7334 7.94219L3.73338 12.6922C3.5784 12.774 3.3919 12.7687 3.24182 12.6782C3.09175 12.5877 3 12.4252 3 12.25V2.75C3 2.57476 3.09175 2.4123 3.24182 2.32181ZM4 3.57925V11.4207L11.4288 7.5L4 3.57925Z" | ||
fill="currentColor" | ||
/> | ||
</svg> | ||
) | ||
} |
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
Oops, something went wrong.