Skip to content

Commit

Permalink
Merge pull request #54 from hcp-uw/ide-fixes
Browse files Browse the repository at this point in the history
Ide fixes
  • Loading branch information
s-fristrom authored Sep 29, 2024
2 parents aaa78c6 + fc4564f commit 7797f1e
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 60 deletions.
15 changes: 7 additions & 8 deletions starter-frontend/src/components/editor/IDEPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,24 @@ export default function IDEPlugin({editor, openIDE, openNewIDE}: PluginRegistrat

if (oldDiv !== null) {
let newDiv = document.createElement("div");
newDiv.className = "ide-div";

let newPre = document.createElement("pre");

let newCode = document.createElement("code");
newCode.className = "ide-code";
newCode.dataset.lang = "0";
newCode.id = "active";
newDiv.appendChild(newCode);

let newBreak = document.createElement("br");
newDiv.appendChild(newBreak);
newPre.appendChild(newCode);
newDiv.appendChild(newPre);

let newButton = document.createElement("button");
newButton.textContent = "Run in IDE";
newButton.addEventListener("click", openIDE);
newButton.className = "run-in-ide-btn";
newDiv.appendChild(newButton);

editor.dom.replace(newDiv, oldDiv);
}
// editor.execCommand('mceInsertContent', false, newCont
// // "<br><code data-language='0' id='active'></code><br><button onClick='openIDE()'>Run in IDE</button><br>"
// );

openNewIDE();
},
Expand Down
21 changes: 16 additions & 5 deletions starter-frontend/src/components/editor/TextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,27 @@ export default function TextEditor({editorRef, initContent, eRoute, setIsLoading
setupEditor && setupEditor(editor);
}, []);




return (
<div id="editor-area">
<form>
<Editor
initialValue={content}
initialValue={"<div id='placement'></div>" + content}
tinymceScriptSrc={process.env.PUBLIC_URL + '/tinymce/tinymce.min.js'}
id='editor'
licenseKey="gpl"
// @ts-ignore
onInit={(_evt, editor) => {editorRef.current = editor}}
onInit={(_evt, editor) => {editorRef.current = editor;
setupIDEButtons(openIDE, editorRef);
}}
init={{
height: "calc(100vh - 105px)",
width: "auto",
resize: false,
menubar: false,
extended_valid_elements: 'button[className|onClick]',
extended_valid_elements: 'button[class|className|onClick|onclick|classname]',
plugins: [
'advlist', 'autolink', 'lists', 'link', 'image', 'charmap',
'anchor', 'searchreplace', 'visualblocks', 'code', 'fullscreen',
Expand All @@ -58,7 +62,7 @@ export default function TextEditor({editorRef, initContent, eRoute, setIsLoading
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }',
save_onsavecallback: (): void => {
// @ts-ignore
save(setContent, editorRef, eRoute, setIsLoading, setCurrContent)
save(setContent, editorRef, eRoute, setIsLoading, setCurrContent, openIDE)
},
setup,
...init,
Expand All @@ -76,13 +80,14 @@ export default function TextEditor({editorRef, initContent, eRoute, setIsLoading
* TO-DO: Implement.
*/
function save(setContent: React.Dispatch<React.SetStateAction<string>>, editorRef: React.RefObject<TinyMCEEditor>, eRoute: string, setIsLoading: React.Dispatch<React.SetStateAction<boolean>>,
setCurrContent: React.Dispatch<React.SetStateAction<string>>): void {
setCurrContent: React.Dispatch<React.SetStateAction<string>>, openIDE: (this: HTMLButtonElement, ev: MouseEvent) => void): void {
if (editorRef.current !== null) {
const content = editorRef.current.getContent();
setContent(content);
setCurrContent(content);
doSave(content, eRoute, setIsLoading, setContent, setCurrContent);

setupIDEButtons(openIDE, editorRef);
}
}

Expand Down Expand Up @@ -124,3 +129,9 @@ const doSave = async (content: string, route: string, setIsLoading: React.Dispat
console.log(e);
}
}


// @ts-ignore
function setupIDEButtons(openIDE, editorRef): void {
editorRef.current.dom.getRoot().addEventListener("click", openIDE);
}
22 changes: 13 additions & 9 deletions starter-frontend/src/components/ide/CodeEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import React, { ChangeEvent, useState } from "react";
import Editor from "@monaco-editor/react";
import { languageOption } from "./languageOptions";

type CodeEditorProps = {
onChange: (action: string, data: string
// : ChangeEvent<HTMLInputElement>
) => void,
// To-DO: Change to list of options
language: string,
code: string,
// To-do: change to list of options

code: string,

setCode: React.Dispatch<React.SetStateAction<string>>;

language: languageOption,

theme: string
};

export default function CodeEditor( {onChange, language, code, theme}: CodeEditorProps ) {
const [value, setValue] = useState<string>(code || "");
export default function CodeEditor( {onChange, code, setCode, language, theme}: CodeEditorProps ) {
// const [value, setValue] = useState<string>(code || "");

const handleEditorChange = (value: string | undefined) => {
if (typeof value === "undefined") {
throw new Error("Editor value is undefined.");
} else {
setValue(value);
setCode(value);
onChange("code", value);
}
}
Expand All @@ -29,8 +33,8 @@ export default function CodeEditor( {onChange, language, code, theme}: CodeEdito
<Editor
height={`100%`}
width={`100%`}
language={language || "javascript"}
value={value}
language={language.value || "javascript"}
value={code}
theme={theme}
onChange={handleEditorChange}
/>
Expand Down
19 changes: 11 additions & 8 deletions starter-frontend/src/components/ide/IDE.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,28 @@ import { Editor as TinyMCEEditor } from "tinymce";

type IDEProps = {
// Initial code in the IDE
initCode: string,
code: string,

initLang: number,
setCode: React.Dispatch<React.SetStateAction<string>>;

language: languageOption,

setLanguage: React.Dispatch<React.SetStateAction<languageOption>>,

setIsIDEOpen: React.Dispatch<React.SetStateAction<boolean>>,

editorRef: React.RefObject<TinyMCEEditor | null>
}


export default function IDE({initCode, initLang, setIsIDEOpen, editorRef}: IDEProps): JSX.Element {
const [code, setCode] = useState<string>(initCode);
export default function IDE({code, setCode, language, setLanguage, setIsIDEOpen, editorRef}: IDEProps): JSX.Element {
const [customInput, setCustomInput] = useState<string>("");
const [output, setOutput] = useState<boolean>(true);
const [outputDetails, setOutputDetails] = useState<any | null>(null);
const [processing, setProcessing] = useState<boolean | null>(null);
const [language, setLanguage] = useState<languageOption>(languageOptions[initLang]);
const [updated, setUpdated] = useState<boolean>(true);

function onSelectChange(sl: languageOption | null): void {
console.log("Selected option ", sl);
if (sl !== null) {
setLanguage(sl);
setUpdated(false);
Expand Down Expand Up @@ -142,6 +143,7 @@ export default function IDE({initCode, initLang, setIsIDEOpen, editorRef}: IDEPr
const langIndex = languageOptions.findIndex(function(obj){return obj.id == language.id});
newCode.dataset.lang = "" + langIndex;
newCode.id = "active";
newCode.className = "ide-code";
editor.dom.replace(newCode, oldCode);
}

Expand All @@ -153,11 +155,12 @@ export default function IDE({initCode, initLang, setIsIDEOpen, editorRef}: IDEPr

return (
<div className="ide">
<LanguagesDropdown onSelectChange={onSelectChange} />
<LanguagesDropdown onSelectChange={onSelectChange} language={language} />
<CodeEditor
code={code}
setCode={setCode}
onChange={onChange}
language={language?.value}
language={language}
theme="vs-dark"
/>

Expand Down
8 changes: 5 additions & 3 deletions starter-frontend/src/components/ide/LanguagesDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import Select, { SingleValue } from "react-select";
import { languageOptions, languageOption } from "./languageOptions";

type LanguagesDropdownProps = {
onSelectChange: (sl: languageOption | null) => void
onSelectChange: (sl: languageOption | null) => void,
language: languageOption
}

export default function LanguagesDropdown( { onSelectChange }: LanguagesDropdownProps ): JSX.Element {
export default function LanguagesDropdown( { onSelectChange, language }: LanguagesDropdownProps ): JSX.Element {
const customStyles = {
control: (provided, state) => ({
...provided,
Expand Down Expand Up @@ -46,7 +47,8 @@ export default function LanguagesDropdown( { onSelectChange }: LanguagesDropdown
return (
<Select
options={languageOptions}
defaultValue={languageOptions[0]}
defaultValue={language}
value={language}
onChange={(selectedOption) => onSelectChange(selectedOption)}
className="ide-dropdown"
styles={customStyles}
Expand Down
73 changes: 46 additions & 27 deletions starter-frontend/src/pages/editor/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import SavePublicButton from "../../components/editor/SavePublicButton";
import PublicSaveModal from "../../components/editor/PublicSaveModal";
import IDE from "../../components/ide/IDE";
import { Editor as TinyMCEEditor } from 'tinymce';
import { languageOption, languageOptions } from "../../components/ide/languageOptions";

/** Type for storing details about note documents */
export type DetailsData = {
Expand Down Expand Up @@ -49,46 +50,64 @@ export function Note(): JSX.Element {

// IDE
// If IDE is open
// TO-DO CHANGE false
const [isIDEOpen, setIsIDEOpen] = useState<boolean>(false);
// Initial IDE code
const [initIDECode, setInitIDECode] = useState<string>("");
// Initial IDE language
const [initIDELang, setInitIDELang] = useState<number>(0);
// IDE code
const [code, setCode] = useState<string>("");
// IDE language
const [language, setLanguage] = useState<languageOption>(languageOptions[0]);

// ***
const editorRef = useRef<TinyMCEEditor | null>(null);


function openNewIDE(): void {
setInitIDECode("");
setInitIDELang(0);
setCode("");
setLanguage(languageOptions[0]);
setIsIDEOpen(true);
}

function openIDE(this: HTMLButtonElement, _ev: MouseEvent): void {
const parentDiv = this.parentNode;
if (parentDiv !== null) {
const codeBlock = parentDiv.querySelector("code");
if (codeBlock !== null) {
const codeContent = codeBlock.textContent;
if (codeContent === null) {
setInitIDECode("");
} else {
setInitIDECode(codeContent);
}
const language = codeBlock.dataset.lang;
if (language === null) {
setInitIDELang(0);
} else {
setInitIDELang(Number(language));
function openIDE(this: HTMLButtonElement, ev: MouseEvent): void {


// @ts-ignore
if (ev.target !== null && ev.target.className !== null && ev.target.className === "run-in-ide-btn") {
// @ts-ignore
const editor = ev.target.getRootNode();
const oldActive = editor.getElementById("active");
if (oldActive !== null) {
oldActive.setAttribute("id", "");
}


// @ts-ignore
const parentDiv = ev.target.parentNode;
if (parentDiv !== null) {
const codeBlock = parentDiv.querySelector("code");
if (codeBlock !== null) {
codeBlock.id = "active";
const codeContent = codeBlock.textContent;
if (codeContent === null) {
console.log("code null");
setCode("");
} else {
setCode(codeContent);
}
console.log("setting code");
const language = codeBlock.dataset.lang;
if (language === null) {
console.log("language null");
setLanguage(languageOptions[0]);
} else {
setLanguage(languageOptions[Number(language)]);
}
console.log("setting language");

setIsIDEOpen(true);
}

setIsIDEOpen(true);
}
}
}

}


const [currName, setCurrName] = useState<string>("");
Expand Down Expand Up @@ -263,7 +282,7 @@ export function Note(): JSX.Element {
openNewIDE={openNewIDE}/>
{
isIDEOpen &&
<IDE initCode={initIDECode} initLang={initIDELang} setIsIDEOpen={setIsIDEOpen} editorRef={editorRef}/>}
<IDE code={code} setCode={setCode} language={language} setLanguage={setLanguage} setIsIDEOpen={setIsIDEOpen} editorRef={editorRef}/>}
</div>


Expand Down

0 comments on commit 7797f1e

Please sign in to comment.