From 10b582101eb1aec45dd0d3ed741b9f4ec50922d2 Mon Sep 17 00:00:00 2001 From: jorg-vr Date: Mon, 11 Dec 2023 10:17:19 +0100 Subject: [PATCH] Add frontend to papyros --- package.json | 1 + src/BackendEvent.ts | 3 ++- src/BackendManager.ts | 2 +- src/CodeRunner.ts | 47 +++++++++++++++++++++--------------- src/Papyros.ts | 54 +++++++++++++++++++++++++++++------------- yarn.lock | 55 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 124 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index b221686f..fda42177 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@codemirror/state": "^6.3.2", "@codemirror/theme-one-dark": "^6.1.2", "@codemirror/view": "^6.22.1", + "@dodona/trace-component": "1.0.0-beta.5", "@lezer/common": "^1.1.0", "comlink": "^4.4.1", "comsync": "^0.0.9", diff --git a/src/BackendEvent.ts b/src/BackendEvent.ts index 4c8da8de..2bd49fa0 100644 --- a/src/BackendEvent.ts +++ b/src/BackendEvent.ts @@ -9,7 +9,8 @@ export enum BackendEventType { Sleep = "sleep", Error = "error", Interrupt = "interrupt", - Loading = "loading" + Loading = "loading", + Trace = "trace" } /** * All possible types for ease of iteration diff --git a/src/BackendManager.ts b/src/BackendManager.ts index 8d4061cd..879167cd 100644 --- a/src/BackendManager.ts +++ b/src/BackendManager.ts @@ -101,7 +101,7 @@ export abstract class BackendManager { if (e.type === BackendEventType.Start) { BackendManager.halted = false; } - if (!BackendManager.halted && this.subscriberMap.has(e.type)) { + if ((!BackendManager.halted || e.type === BackendEventType.Trace) && this.subscriberMap.has(e.type)) { this.subscriberMap.get(e.type)!.forEach(cb => cb(e)); } } diff --git a/src/CodeRunner.ts b/src/CodeRunner.ts index de7222c8..82747897 100644 --- a/src/CodeRunner.ts +++ b/src/CodeRunner.ts @@ -1,26 +1,31 @@ -import { proxy } from "comlink"; -import { SyncClient } from "comsync"; -import { Backend } from "./Backend"; -import { BackendEvent, BackendEventType } from "./BackendEvent"; -import { BackendManager } from "./BackendManager"; -import { CodeEditor } from "./editor/CodeEditor"; +import {proxy} from "comlink"; +import {SyncClient} from "comsync"; +import {Backend} from "./Backend"; +import {BackendEvent, BackendEventType} from "./BackendEvent"; +import {BackendManager} from "./BackendManager"; +import {CodeEditor} from "./editor/CodeEditor"; import { addPapyrosPrefix, - APPLICATION_STATE_TEXT_ID, CODE_BUTTONS_WRAPPER_ID, DEFAULT_EDITOR_DELAY, RUN_BTN_ID, - STATE_SPINNER_ID, STOP_BTN_ID + APPLICATION_STATE_TEXT_ID, + CODE_BUTTONS_WRAPPER_ID, + DEFAULT_EDITOR_DELAY, + RUN_BTN_ID, + STATE_SPINNER_ID, + STOP_BTN_ID } from "./Constants"; -import { InputManager, InputManagerRenderOptions, InputMode } from "./InputManager"; -import { ProgrammingLanguage } from "./ProgrammingLanguage"; -import { renderSpinningCircle } from "./util/HTMLShapes"; +import {InputManager, InputManagerRenderOptions, InputMode} from "./InputManager"; +import {ProgrammingLanguage} from "./ProgrammingLanguage"; +import {renderSpinningCircle} from "./util/HTMLShapes"; +import {addListener, downloadResults, getElement, parseData, t} from "./util/Util"; import { - addListener, getElement, - t, downloadResults, parseData -} from "./util/Util"; -import { - RenderOptions, renderWithOptions, - renderButton, ButtonOptions, Renderable, appendClasses + appendClasses, + ButtonOptions, + Renderable, + renderButton, + RenderOptions, + renderWithOptions } from "./util/Rendering"; -import { OutputManager } from "./OutputManager"; +import {OutputManager} from "./OutputManager"; interface DynamicButton { id: string; @@ -384,7 +389,11 @@ export class CodeRunner extends Renderable { await backend.call( backend.workerProxy.runCode, code, mode ); - console.log("Run finished", await backend.workerProxy.getTraceback()); + BackendManager.publish({ + type: BackendEventType.Trace, + data: await backend.workerProxy.getTraceback(), + contentType: "text/json" + }); } catch (error: any) { if (error.type === "InterruptError") { // Error signaling forceful interrupt diff --git a/src/Papyros.ts b/src/Papyros.ts index 0bd0602a..c5991024 100644 --- a/src/Papyros.ts +++ b/src/Papyros.ts @@ -1,32 +1,44 @@ /* eslint-disable max-len */ import I18n from "i18n-js"; import { - EDITOR_WRAPPER_ID, PROGRAMMING_LANGUAGE_SELECT_ID, - LOCALE_SELECT_ID, INPUT_AREA_WRAPPER_ID, EXAMPLE_SELECT_ID, - PANEL_WRAPPER_ID, DARK_MODE_TOGGLE_ID, - MAIN_APP_ID, OUTPUT_AREA_WRAPPER_ID + DARK_MODE_TOGGLE_ID, + EDITOR_WRAPPER_ID, + EXAMPLE_SELECT_ID, + INPUT_AREA_WRAPPER_ID, + LOCALE_SELECT_ID, + MAIN_APP_ID, + OUTPUT_AREA_WRAPPER_ID, + PANEL_WRAPPER_ID, + PROGRAMMING_LANGUAGE_SELECT_ID } from "./Constants"; -import { InputManagerRenderOptions, InputMode } from "./InputManager"; -import { ProgrammingLanguage } from "./ProgrammingLanguage"; +import {InputManagerRenderOptions, InputMode} from "./InputManager"; +import {ProgrammingLanguage} from "./ProgrammingLanguage"; +import {addListener, cleanCurrentUrl, getElement, getLocales, loadTranslations, removeSelection, t} from "./util/Util"; +import {CodeRunner, RunState} from "./CodeRunner"; +import {getCodeForExample, getExampleNames} from "./examples/Examples"; +import {AtomicsChannelOptions, makeChannel, ServiceWorkerChannelOptions} from "sync-message"; +import {BackendManager} from "./BackendManager"; import { - t, loadTranslations, getLocales, - removeSelection, - addListener, getElement, cleanCurrentUrl -} from "./util/Util"; -import { RunState, CodeRunner } from "./CodeRunner"; -import { getCodeForExample, getExampleNames } from "./examples/Examples"; -import { AtomicsChannelOptions, makeChannel, ServiceWorkerChannelOptions } from "sync-message"; -import { BackendManager } from "./BackendManager"; -import { - RenderOptions, renderWithOptions, renderSelect, renderSelectOptions, - ButtonOptions, Renderable, renderLabel, appendClasses + appendClasses, + ButtonOptions, + Renderable, + renderLabel, + RenderOptions, + renderSelect, + renderSelectOptions, + renderWithOptions } from "./util/Rendering"; +import "@dodona/trace-component/dist/components/TraceComponent"; +import { BackendEventType } from "./BackendEvent"; +import { TraceComponent } from "@dodona/trace-component/dist/components/TraceComponent"; const LANGUAGE_MAP = new Map([ ["python", ProgrammingLanguage.Python], ["javascript", ProgrammingLanguage.JavaScript] ]); +const TRACE_COMPONENT_ID = "trace-component"; + /** * Configuration options for this instance of Papyros */ @@ -289,6 +301,10 @@ export class Papyros extends Renderable { ${renderLabel(t("Papyros.input"), renderOptions.inputOptions!.parentElementId)}
+ +
+ +
@@ -320,6 +336,10 @@ export class Papyros extends Renderable { addListener(DARK_MODE_TOGGLE_ID, () => { this.setDarkMode(!renderOptions.darkMode); }, "click"); + const traceComponent = getElement(TRACE_COMPONENT_ID) as TraceComponent; + BackendManager.subscribe(BackendEventType.Trace, e => { + traceComponent.trace = JSON.parse(e.data).trace; + }); } this.codeRunner.render({ statusPanelOptions: renderOptions.statusPanelOptions!, diff --git a/yarn.lock b/yarn.lock index b48e716b..e34e0b68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -504,6 +504,14 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== +"@dodona/trace-component@1.0.0-beta.5": + version "1.0.0-beta.5" + resolved "https://registry.yarnpkg.com/@dodona/trace-component/-/trace-component-1.0.0-beta.5.tgz#5631f6a169ce6cf62c1a2ab94a55ebfb1f1dc1d3" + integrity sha512-P/tjMKAGyHjV0fAnR5nzpz21frqXKQ2fKJ8PKJYWTHIoicVPY2LqOMalVEltLy5LkzT3s9238EVN473GqmJ4TQ== + dependencies: + "@jsplumb/browser-ui" "^6.2.10" + lit "^3.0.0" + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -803,6 +811,11 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jsplumb/browser-ui@^6.2.10": + version "6.2.10" + resolved "https://registry.yarnpkg.com/@jsplumb/browser-ui/-/browser-ui-6.2.10.tgz#86b85ed42110563d2816e3712677cdbbbf33366f" + integrity sha512-trk++mK5q6hceJL79teemzcilJ+8DrZT/lMK0+B80AtHqZHr0YwMCf+so2JBb2Z/MDZ0fUEU9MbELY6OPhhs5g== + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -843,6 +856,18 @@ "@lezer/highlight" "^1.0.0" "@lezer/lr" "^1.0.0" +"@lit-labs/ssr-dom-shim@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.2.tgz#d693d972974a354034454ec1317eb6afd0b00312" + integrity sha512-jnOD+/+dSrfTWYfSXBXlo5l5f0q1UuJo3tkbMDCYA2lKUYq79jaxqtGEvnRoh049nt1vdo1+45RinipU6FGY2g== + +"@lit/reactive-element@^2.0.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-2.0.2.tgz#779ae9d265407daaf7737cb892df5ec2a86e22a0" + integrity sha512-SVOwLAWUQg3Ji1egtOt1UiFe4zdDpnWHyc5qctSceJ5XIu0Uc76YmGpIjZgx9YJ0XtdW0Jm507sDvjOu+HnB8w== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.1.2" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1157,6 +1182,11 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== +"@types/trusted-types@^2.0.2": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" + integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== + "@types/ws@^8.5.5": version "8.5.10" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" @@ -3800,6 +3830,31 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +lit-element@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-4.0.2.tgz#1a519896d5ab7c7be7a8729f400499e38779c093" + integrity sha512-/W6WQZUa5VEXwC7H9tbtDMdSs9aWil3Ou8hU6z2cOKWbsm/tXPAcsoaHVEtrDo0zcOIE5GF6QgU55tlGL2Nihg== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.1.2" + "@lit/reactive-element" "^2.0.0" + lit-html "^3.1.0" + +lit-html@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-3.1.0.tgz#a7b93dd682073f2e2029656f4e9cd91e8034c196" + integrity sha512-FwAjq3iNsaO6SOZXEIpeROlJLUlrbyMkn4iuv4f4u1H40Jw8wkeR/OUXZUHUoiYabGk8Y4Y0F/rgq+R4MrOLmA== + dependencies: + "@types/trusted-types" "^2.0.2" + +lit@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lit/-/lit-3.1.0.tgz#76429b85dc1f5169fed499a0f7e89e2e619010c9" + integrity sha512-rzo/hmUqX8zmOdamDAeydfjsGXbbdtAFqMhmocnh2j9aDYqbu0fjXygjCa0T99Od9VQ/2itwaGrjZz/ZELVl7w== + dependencies: + "@lit/reactive-element" "^2.0.0" + lit-element "^4.0.0" + lit-html "^3.1.0" + loader-runner@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"