Skip to content

Commit 4433a6a

Browse files
committed
wip - editable boxes
1 parent 43b3a7d commit 4433a6a

File tree

2 files changed

+89
-42
lines changed

2 files changed

+89
-42
lines changed

src/components/QuestDbSqlRunnerEmbedded/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ export function QuestDbSqlRunnerEmbedded({
5252
if (!response.ok) {
5353
try {
5454
const errorJson = JSON.parse(responseBody) as { error?: string; position?: number };
55-
throw new Error(`QuestDB Error (HTTP ${response.status}): ${errorJson.error || responseBody} at position ${errorJson.position || 'N/A'}`);
55+
throw new Error(`Bad query: ${errorJson.error || responseBody} at position ${errorJson.position || 'N/A'}`);
5656
} catch (e: any) {
57-
if (e.message.startsWith('QuestDB Error')) throw e;
57+
if (e.message.startsWith('Bad query')) throw e;
5858
throw new Error(`HTTP Error ${response.status}: ${response.statusText}. Response: ${responseBody}`);
5959
}
6060
}

src/theme/CodeBlock/Content/String.tsx

Lines changed: 87 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from "react"; // Ensure React and useState are imported
1+
import React, { useState, useEffect } from "react";
22
import clsx from "clsx";
33
import { useThemeConfig, usePrismTheme } from "@docusaurus/theme-common";
44
import {
@@ -14,7 +14,7 @@ import WordWrapButton from "@theme/CodeBlock/WordWrapButton";
1414
import Container from "@theme/CodeBlock/Container";
1515
import type { Props as OriginalProps } from "@theme/CodeBlock";
1616

17-
import { QuestDbSqlRunnerEmbedded } from '@site/src/components/QuestDbSqlRunnerEmbedded'; // Adjust path as needed
17+
import { QuestDbSqlRunnerEmbedded } from '@site/src/components/QuestDbSqlRunnerEmbedded';
1818

1919
import styles from "./styles.module.css";
2020

@@ -59,15 +59,22 @@ export default function CodeBlockString({
5959
const demo = parseCodeBlockDemo(metastring) || demoProp;
6060
const enableExecute = parseCodeBlockExecute(metastring) || executeProp;
6161

62-
const { lineClassNames, code } = parseLines(children, {
62+
const { lineClassNames, code: initialCode, tokens: initialTokens } = parseLines(children, {
6363
metastring,
6464
language,
6565
magicComments,
6666
});
6767
const showLineNumbers = showLineNumbersProp ?? containsLineNumbers(metastring);
6868

69+
const [editableCode, setEditableCode] = useState<string>(initialCode);
70+
const [isEditing, setIsEditing] = useState<boolean>(false);
71+
72+
useEffect(() => {
73+
setEditableCode(initialCode);
74+
}, [initialCode]);
75+
6976
const demoUrl = demo
70-
? `https://demo.questdb.io/?query=${encodeURIComponent(code)}&executeQuery=true`
77+
? `https://demo.questdb.io/?query=${encodeURIComponent(editableCode)}&executeQuery=true` // Use editableCode
7178
: null;
7279

7380
const handleDemoClick = () => {
@@ -78,20 +85,30 @@ export default function CodeBlockString({
7885

7986
const [showExecutionResults, setShowExecutionResults] = useState<boolean>(false);
8087

81-
const currentQuestDbUrl = questdbUrlProp; // If passed, use it, otherwise QuestDbSqlRunnerEmbedded will use its default.
88+
const currentQuestDbUrl = questdbUrlProp;
8289

8390
const handleExecuteToggle = () => {
8491
setShowExecutionResults(prev => !prev);
8592
};
8693

94+
const handleEditToggle = () => {
95+
setIsEditing(prev => !prev);
96+
};
97+
98+
const currentLineClassNames = isEditing
99+
? lineClassNames
100+
: parseLines(editableCode, { metastring, language, magicComments }).lineClassNames;
101+
102+
87103
return (
88104
<Container
89105
as="div"
90106
className={clsx(
91107
blockClassName,
92108
language &&
93-
!blockClassName.includes(`language-${language}`) &&
94-
`language-${language}`,
109+
!blockClassName.includes(`language-${language}`) &&
110+
`language-${language}`,
111+
isEditing && styles.codeBlockEditing
95112
)}
96113
>
97114
{title && (
@@ -111,47 +128,77 @@ export default function CodeBlockString({
111128
</div>
112129
)}
113130
<div className={styles.codeBlockContent}>
114-
<Highlight
115-
theme={prismTheme}
116-
code={code}
117-
language={(language ?? "text") as Language}
118-
>
119-
{({ className, style, tokens, getLineProps, getTokenProps }) => (
120-
<pre
121-
tabIndex={0}
122-
ref={wordWrap.codeBlockRef}
123-
className={clsx(className, styles.codeBlock, "thin-scrollbar")}
124-
style={style}
125-
>
126-
<code
127-
className={clsx(
128-
styles.codeBlockLines,
129-
showLineNumbers && styles.codeBlockLinesWithNumbering,
130-
)}
131+
{isEditing ? (
132+
<textarea
133+
value={editableCode}
134+
onChange={(e) => setEditableCode(e.target.value)}
135+
className={clsx(styles.codeBlock, styles.editableCodeArea, "thin-scrollbar")}
136+
spellCheck="false"
137+
autoCapitalize="off"
138+
autoComplete="off"
139+
autoCorrect="off"
140+
rows={Math.max(10, editableCode.split('\n').length)}
141+
style={{
142+
width: '100%',
143+
fontFamily: 'var(--ifm-font-family-monospace)',
144+
fontSize: 'var(--ifm-code-font-size)',
145+
lineHeight: 'var(--ifm-pre-line-height)',
146+
backgroundColor: prismTheme.plain.backgroundColor,
147+
color: prismTheme.plain.color,
148+
border: 'none',
149+
resize: 'vertical',
150+
}}
151+
/>
152+
) : (
153+
<Highlight
154+
theme={prismTheme}
155+
code={editableCode} // Use editableCode
156+
language={(language ?? "text") as Language}
157+
>
158+
{({ className, style, tokens, getLineProps, getTokenProps }) => (
159+
<pre
160+
tabIndex={0}
161+
ref={wordWrap.codeBlockRef}
162+
className={clsx(className, styles.codeBlock, "thin-scrollbar")}
163+
style={style}
131164
>
132-
{tokens.map((line, i) => (
133-
<Line
134-
key={i}
135-
line={line}
136-
getLineProps={getLineProps}
137-
getTokenProps={getTokenProps}
138-
classNames={lineClassNames[i]}
139-
showLineNumbers={showLineNumbers}
140-
/>
141-
))}
142-
</code>
143-
</pre>
144-
)}
145-
</Highlight>
165+
<code
166+
className={clsx(
167+
styles.codeBlockLines,
168+
showLineNumbers && styles.codeBlockLinesWithNumbering,
169+
)}
170+
>
171+
{tokens.map((line, i) => (
172+
<Line
173+
key={i}
174+
line={line}
175+
getLineProps={getLineProps}
176+
getTokenProps={getTokenProps}
177+
classNames={currentLineClassNames[i]}
178+
showLineNumbers={showLineNumbers}
179+
/>
180+
))}
181+
</code>
182+
</pre>
183+
)}
184+
</Highlight>
185+
)}
146186
<div className={styles.buttonGroup}>
187+
<button
188+
onClick={handleEditToggle}
189+
className={clsx(styles.codeButton, styles.editButton)}
190+
title={isEditing ? "View Code" : "Edit Code"}
191+
>
192+
{isEditing ? 'View Code' : 'Edit Code'}
193+
</button>
147194
{(wordWrap.isEnabled || wordWrap.isCodeScrollable) && (
148195
<WordWrapButton
149196
className={styles.codeButton}
150197
onClick={() => wordWrap.toggle()}
151198
isEnabled={wordWrap.isEnabled}
152199
/>
153200
)}
154-
<CopyButton className={styles.codeButton} code={code} />
201+
<CopyButton className={styles.codeButton} code={editableCode} />
155202
{enableExecute && (
156203
<button
157204
onClick={handleExecuteToggle}
@@ -166,7 +213,7 @@ export default function CodeBlockString({
166213

167214
{enableExecute && showExecutionResults && (
168215
<QuestDbSqlRunnerEmbedded
169-
queryToExecute={code}
216+
queryToExecute={editableCode}
170217
questdbUrl={currentQuestDbUrl}
171218
/>
172219
)}

0 commit comments

Comments
 (0)