Skip to content

Commit

Permalink
Merge pull request #151 from flatironinstitute/create-templates-in-sc…
Browse files Browse the repository at this point in the history
…ript-editors

Create templates in script editors
  • Loading branch information
WardBrian authored Jul 25, 2024
2 parents 4c5b456 + 7d507e5 commit 4943eb8
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 10 deletions.
2 changes: 1 addition & 1 deletion gui/src/app/FileEditor/StanFileEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ const StanFileEditor: FunctionComponent<Props> = ({
readOnly={!isCompiling ? readOnly : true}
toolbarItems={toolbarItems}
codeMarkers={stancErrorsToCodeMarkers(stancErrors)}
hintTextOnEmpty="Begin editing or select an example from the left panel"
contentOnEmpty="Begin editing or select an example from the left panel"
/>
{window}
</Splitter>
Expand Down
20 changes: 12 additions & 8 deletions gui/src/app/FileEditor/TextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type Props = {
toolbarItems?: ToolbarItem[];
label: string;
codeMarkers?: CodeMarker[];
hintTextOnEmpty?: string;
contentOnEmpty?: string | HTMLSpanElement;
};

export type ToolbarItem =
Expand Down Expand Up @@ -55,7 +55,7 @@ const TextEditor: FunctionComponent<Props> = ({
language,
label,
codeMarkers,
hintTextOnEmpty,
contentOnEmpty,
}) => {
const handleChange = useCallback(
(value: string | undefined) => {
Expand Down Expand Up @@ -104,16 +104,16 @@ const TextEditor: FunctionComponent<Props> = ({

useEffect(() => {
if (!editorInstance) return;
if (!hintTextOnEmpty) return;
if (!contentOnEmpty) return;
if (text || editedText) {
return;
}
const contentWidget = createHintTextContentWidget(hintTextOnEmpty);
const contentWidget = createHintTextContentWidget(contentOnEmpty);
editorInstance.addContentWidget(contentWidget);
return () => {
editorInstance.removeContentWidget(contentWidget);
};
}, [text, editorInstance, editedText, hintTextOnEmpty]);
}, [text, editorInstance, editedText, contentOnEmpty]);

/////////////////////////////////////////////////

Expand Down Expand Up @@ -242,14 +242,18 @@ const NotSelectable: FunctionComponent<PropsWithChildren> = ({ children }) => {
return <div className="NotSelectable">{children}</div>;
};

const createHintTextContentWidget = (hintText: string) => {
const createHintTextContentWidget = (content: string | HTMLSpanElement) => {
return {
getDomNode: () => {
const node = document.createElement("div");
node.style.width = "max-content";
node.style.pointerEvents = "none";
node.className = "EditorHintText";
node.textContent = hintText;
const spanElement =
typeof content === "string" ? document.createElement("span") : content;
if (typeof content === "string") {
spanElement.textContent = content;
}
node.appendChild(spanElement);
return node;
},
getId: () => "hintText",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ const DataPyFileEditor: FunctionComponent<Props> = ({
[fileContent, editedFileContent, handleRun, status, handleHelp],
);

const contentOnEmpty = useMemo(() => {
const spanElement = document.createElement("span");
const t1 = document.createTextNode(
"Define a dictionary called data to update the data.json. ",
);
const a1 = document.createElement("a");
a1.onclick = () => {
setEditedFileContent(dataPyTemplate);
};
a1.textContent = "Click here to generate an example";
spanElement.appendChild(t1);
spanElement.appendChild(a1);
return spanElement;
}, [setEditedFileContent]);

return (
<TextEditor
language="python"
Expand All @@ -97,8 +112,13 @@ const DataPyFileEditor: FunctionComponent<Props> = ({
onSetEditedText={setEditedFileContent}
readOnly={readOnly}
toolbarItems={toolbarItems}
contentOnEmpty={contentOnEmpty}
/>
);
};

const dataPyTemplate = `data = {
"a": [1, 2, 3]
}`;

export default DataPyFileEditor;
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,21 @@ if (typeof(data) != "list") {
[fileContent, editedFileContent, handleRun, status, handleHelp],
);

const contentOnEmpty = useMemo(() => {
const spanElement = document.createElement("span");
const t1 = document.createTextNode(
"Define a list called data to update the data.json. ",
);
const a1 = document.createElement("a");
a1.onclick = () => {
setEditedFileContent(dataRTemplate);
};
a1.textContent = "Click here to generate an example";
spanElement.appendChild(t1);
spanElement.appendChild(a1);
return spanElement;
}, [setEditedFileContent]);

return (
<TextEditor
language="r"
Expand All @@ -133,8 +148,13 @@ if (typeof(data) != "list") {
onSetEditedText={setEditedFileContent}
readOnly={readOnly}
toolbarItems={toolbarItems}
contentOnEmpty={contentOnEmpty}
/>
);
};

const dataRTemplate = `data <- list(
a = c(1, 2, 3)
)`;

export default DataRFileEditor;
32 changes: 32 additions & 0 deletions gui/src/app/pyodide/AnalysisPyFileEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,21 @@ const AnalysisPyFileEditor: FunctionComponent<Props> = ({
return ret;
}, [fileContent, editedFileContent, imagesRef, hasData, status, handleRun]);

const contentOnEmpty = useMemo(() => {
const spanElement = document.createElement("span");
const t1 = document.createTextNode(
"Use the draws object to access the samples. ",
);
const a1 = document.createElement("a");
a1.onclick = () => {
setEditedFileContent(analysisPyTemplate);
};
a1.textContent = "Click here to generate an example";
spanElement.appendChild(t1);
spanElement.appendChild(a1);
return spanElement;
}, [setEditedFileContent]);

return (
<TextEditor
language="python"
Expand All @@ -168,10 +183,27 @@ const AnalysisPyFileEditor: FunctionComponent<Props> = ({
onSetEditedText={setEditedFileContent}
readOnly={readOnly}
toolbarItems={toolbarItems}
contentOnEmpty={contentOnEmpty}
/>
);
};

const analysisPyTemplate = `import matplotlib.pyplot as plt
# Print the draws object
print(draws)
# Print parameter names
print(draws.parameter_names)
# plot the lp parameter
samples = draws.get("lp__")
print(samples.shape)
plt.hist(samples.ravel(), bins=30)
plt.title("lp__")
plt.show()
`;

type ConsoleOutType = "stdout" | "stderr";

export const writeConsoleOutToDiv = (
Expand Down
9 changes: 8 additions & 1 deletion gui/src/localStyles.css
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,11 @@ span.EditorTitle {
.EditorHintText {
font-style: italic;
color: #aaa;
}
pointer-events: none;
}

.EditorHintText a {
color: gray;
text-decoration: underline;
pointer-events: all;
}

0 comments on commit 4943eb8

Please sign in to comment.