Skip to content

Commit

Permalink
Merge branch 'main' into enhance/papyros-run-button
Browse files Browse the repository at this point in the history
  • Loading branch information
jorg-vr committed Feb 13, 2024
2 parents 56acbfd + bcb1b9f commit 15d431a
Show file tree
Hide file tree
Showing 51 changed files with 234 additions and 7,829 deletions.
181 changes: 91 additions & 90 deletions app/assets/javascripts/coding_scratchpad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const CODE_EDITOR_PARENT_ID = "scratchpad-editor-wrapper";
const PANEL_PARENT_ID = "scratchpad-panel-wrapper";
const CODE_OUTPUT_PARENT_ID = "scratchpad-output-wrapper";
const CODE_INPUT_PARENT_ID = "scratchpad-input-wrapper";
const OFFCANVAS_ID = "scratchpad-offcanvas";
export const OFFCANVAS_ID = "scratchpad-offcanvas";
const SHOW_OFFCANVAS_BUTTON_ID = "scratchpad-offcanvas-show-btn";
const CODE_COPY_BUTTON_ID = "scratchpad-code-copy-btn";
const CLOSE_BUTTON_ID = "scratchpad-offcanvas-close-btn";
Expand All @@ -21,99 +21,80 @@ const CODE_TRACE_PARENT_ID = "scratchpad-trace-wrapper";
const TRACE_TAB_ID = "scratchpad-trace-tab";
const DESCRIPTION_TAB_ID = "scratchpad-description-tab";

function initCodingScratchpad(programmingLanguage: ProgrammingLanguage): void {
if (Papyros.supportsProgrammingLanguage(programmingLanguage)) {
let papyros: Papyros | undefined = undefined;
let editor: EditorView | undefined = undefined;
const closeButton = document.getElementById(CLOSE_BUTTON_ID);
const showButton = document.getElementById(SHOW_OFFCANVAS_BUTTON_ID);
showButton.addEventListener("click", async function () {
if (!papyros) { // Only create Papyros once per session, but only when required
// Papyros registers a service worker on a specific path
// We used to do this on a different path
// So we need to unregister old serviceworkers manually as these won't get overwritten
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (const registration of registrations) {
if (registration.scope !== document.location.origin + "/") {
registration.unregister();
}
}
});

papyros = new Papyros(
{
programmingLanguage: Papyros.toProgrammingLanguage(programmingLanguage),
standAlone: false,
locale: i18n.locale(),
inputMode: InputMode.Interactive,
channelOptions: {
serviceWorkerName: "inputServiceWorker.js"
}
});

// Render once new button is added
papyros.render({
codeEditorOptions: {
parentElementId: CODE_EDITOR_PARENT_ID
},
statusPanelOptions: {
parentElementId: PANEL_PARENT_ID
},
outputOptions: {
parentElementId: CODE_OUTPUT_PARENT_ID
},
inputOptions: {
parentElementId: CODE_INPUT_PARENT_ID,
inputStyling: {
// Allows 4 lines of input
maxHeight: "10vh"
}
},
traceOptions: {
parentElementId: CODE_TRACE_PARENT_ID
},
darkMode: themeState.theme === "dark"
});
editor ||= window.dodona.editor;
if (editor) {
// Shortcut to copy code to editor
papyros.addButton(
{
id: CODE_COPY_BUTTON_ID,
buttonText: i18n.t("js.coding_scratchpad.copy_to_submit"),
classNames: "btn-secondary",
icon: "<i class=\"mdi mdi-clipboard-arrow-left-outline\"></i>"
},
() => {
setCode(editor, papyros.getCode());
closeButton.click();
// Open submit panel if possible
document.getElementById(SUBMIT_TAB_ID)?.click();
}
);
let papyros: Papyros | undefined;
let editor: EditorView | undefined;
export async function initPapyros(programmingLanguage: ProgrammingLanguage): Promise<Papyros> {
if (!papyros) { // Only create Papyros once per session, but only when required
// Papyros registers a service worker on a specific path
// We used to do this on a different path
// So we need to unregister old serviceworkers manually as these won't get overwritten
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (const registration of registrations) {
if (registration.scope !== document.location.origin + "/") {
registration.unregister();
}
await papyros.launch();

papyros.codeRunner.editor.reconfigure([CodeEditor.STYLE, syntaxHighlighting(rougeStyle, {
fallback: true
})]);
}
});
// Ask user to choose after offcanvas is shown
document.getElementById(OFFCANVAS_ID).addEventListener("shown.bs.offcanvas", () => {
editor ||= window.dodona.editor;
if (editor) { // Start with code from the editor, if there is any
const editorCode = editor.state.doc.toString();
const currentCode = papyros.getCode();
if (!currentCode || // Papyros empty
// Neither code areas are empty, but they differ
(editorCode && currentCode !== editorCode &&
// and user chooses to overwrite current code with editor value
confirm(i18n.t("js.coding_scratchpad.overwrite_code")))) {
papyros.setCode(editorCode);

papyros = new Papyros(
{
programmingLanguage: Papyros.toProgrammingLanguage(programmingLanguage),
standAlone: false,
locale: i18n.locale(),
inputMode: InputMode.Interactive,
channelOptions: {
root: "/",
serviceWorkerName: "inputServiceWorker.js"
}
}
});

// Render once new button is added
papyros.render({
codeEditorOptions: {
parentElementId: CODE_EDITOR_PARENT_ID
},
statusPanelOptions: {
parentElementId: PANEL_PARENT_ID
},
outputOptions: {
parentElementId: CODE_OUTPUT_PARENT_ID
},
inputOptions: {
parentElementId: CODE_INPUT_PARENT_ID,
inputStyling: {
// Allows 4 lines of input
maxHeight: "10vh"
}
},
traceOptions: {
parentElementId: CODE_TRACE_PARENT_ID
},
darkMode: themeState.theme === "dark"
});
editor ||= window.dodona.editor;
if (editor) {
// Shortcut to copy code to editor
papyros.addButton(
{
id: CODE_COPY_BUTTON_ID,
buttonText: i18n.t("js.coding_scratchpad.copy_to_submit"),
classNames: "btn-secondary",
icon: "<i class=\"mdi mdi-clipboard-arrow-left-outline\"></i>"
},
() => {
setCode(editor, papyros.getCode());
const closeButton = document.getElementById(CLOSE_BUTTON_ID);
closeButton.click();
// Open submit panel if possible
document.getElementById(SUBMIT_TAB_ID)?.click();
}
);
}
await papyros.launch();

papyros.codeRunner.editor.reconfigure([CodeEditor.STYLE, syntaxHighlighting(rougeStyle, {
fallback: true
})]);

// Hide Trace tab when a new run is started
BackendManager.subscribe(BackendEventType.Start, () => {
Expand All @@ -138,6 +119,26 @@ function initCodingScratchpad(programmingLanguage: ProgrammingLanguage): void {
}
});
}
return papyros;
}

export { initCodingScratchpad };
export function initCodingScratchpad(programmingLanguage: ProgrammingLanguage): void {
if (Papyros.supportsProgrammingLanguage(programmingLanguage)) {
const showButton = document.getElementById(SHOW_OFFCANVAS_BUTTON_ID);
showButton.addEventListener("click", async () => {
const papyros = await initPapyros(programmingLanguage);
editor ||= window.dodona.editor;
if (editor) { // Start with code from the editor, if there is any
const editorCode = editor.state.doc.toString();
const currentCode = papyros.getCode();
if (!currentCode || // Papyros empty
// Neither code areas are empty, but they differ
(editorCode && currentCode !== editorCode &&
// and user chooses to overwrite current code with editor value
confirm(i18n.t("js.coding_scratchpad.overwrite_code")))) {
papyros.setCode(editorCode);
}
}
});
}
}
6 changes: 6 additions & 0 deletions app/assets/javascripts/favorite_course_buttons.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Toast } from "./toast";
import { fetch, getParentByClassName } from "utilities";
import { i18n } from "i18n/i18n";
import { SeriesIcon } from "components/series_icon";

function initFavoriteButtons(doc: Document | HTMLElement = document): void {
function init(): void {
Expand Down Expand Up @@ -44,6 +45,11 @@ function initFavoriteButtons(doc: Document | HTMLElement = document): void {
cloneFavButton.setAttribute("title", i18n.t("js.unfavorite-course-do"));
new bootstrap.Tooltip(cloneFavButton); // is enabled by default
cloneFavButton.addEventListener("click", toggleFavorite);
// hack to fix double rendering of content of lit element 'd-series-icon'
clone.querySelectorAll("d-series-icon").forEach((el: SeriesIcon) => {
el.replaceChildren();
el.requestUpdate();
});
} else {
new Toast(i18n.t("js.favorite-course-failed"));
}
Expand Down
2 changes: 0 additions & 2 deletions app/assets/javascripts/i18n/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,6 @@
"timeseries_desc": "This graph shows on which moments the students submitted the most solutions.",
"timeseries_title": "Submissions over time",
"total": "total",
"tutor-failed": "Something went wrong while loading the online python tutor",
"unfavorite-course-do": "Unfavorite",
"unfavorite-course-failed": "Unfavoriting course failed",
"unfavorite-course-succeeded": "Unfavorited course",
Expand Down Expand Up @@ -953,7 +952,6 @@
"timeseries_desc": "Deze grafiek toont op welke momenten het meest aan een bepaalde oefening werd gewerkt.",
"timeseries_title": "Ingediende oplossingen over tijd",
"total": "totaal aantal",
"tutor-failed": "Er ging iets fout bij het laden van de online python tutor",
"unfavorite-course-do": "Verwijder uit favorieten",
"unfavorite-course-failed": "Cursus uit favorieten verwijderen mislukt",
"unfavorite-course-succeeded": "Cursus verwijderd uit favorieten",
Expand Down
10 changes: 1 addition & 9 deletions app/assets/javascripts/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ import { Modal } from "bootstrap";
import { render, TemplateResult } from "lit";


function showInfoModal(title: TemplateResult | string, content: TemplateResult | string, options?: {allowFullscreen: boolean}): void {
const button = document.querySelector("#info-modal .modal-header #fullscreen-button") as HTMLElement;

if (options?.allowFullscreen) {
button.style.display = "inline";
} else {
button.style.display = "none";
}

function showInfoModal(title: TemplateResult | string, content: TemplateResult | string): void {
render(title, document.querySelector("#info-modal .modal-title") as HTMLElement);
render(content, document.querySelector("#info-modal .modal-body") as HTMLElement);

Expand Down
Loading

0 comments on commit 15d431a

Please sign in to comment.