Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UI] Switch read only editors to code mirror #4924

Merged
merged 25 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
de6ae55
switch read only editors to code mirror
jpelay Dec 18, 2023
f97ba3e
Merge branch 'main' of github.com:hedyorg/hedy into read-only-editors
jpelay Dec 20, 2023
8c05af4
fixing button placement
jpelay Dec 20, 2023
da92544
set up parsons
jpelay Dec 21, 2023
341ff01
not every pre node has a child code node
jpelay Dec 22, 2023
ef3d54c
Use sortable JS for parsons and improve general functionality
jpelay Dec 22, 2023
d954a43
allow parsons to grow or shrink
jpelay Dec 22, 2023
6364f6f
initialize translations
jpelay Dec 22, 2023
ac28ce3
switch for read only editors
jpelay Dec 22, 2023
613962f
fix cheatsheet imports
jpelay Dec 22, 2023
73b5372
fix debugger tests
jpelay Dec 22, 2023
112dc3b
initialize translations before creating editors
jpelay Dec 22, 2023
b532a8a
fix editor page tests
jpelay Dec 22, 2023
7d1b3a1
fix keyword language switcher tests
jpelay Dec 22, 2023
7bf80b9
fix run code button tess
jpelay Dec 22, 2023
66de6a0
fix syntax highlighting test
jpelay Dec 22, 2023
e4cf29f
fix to text tabs button tests
jpelay Dec 22, 2023
7d08c68
fuix try button and programs pages tests
jpelay Dec 22, 2023
edfe5cd
js fiñes
jpelay Dec 22, 2023
0ba487a
remove call to ace script in html files
jpelay Dec 23, 2023
78f104c
remove calls to ace related scripts
jpelay Dec 27, 2023
9a67e70
fix preview button
jpelay Dec 27, 2023
e3100bc
fix minimum height
jpelay Dec 29, 2023
4543434
Merge branch 'main' into read-only-editors
jpelay Jan 2, 2024
43416d2
Merge branch 'main' into read-only-editors
mergify[bot] Jan 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"@types/dompurify": "^2.3.3",
"@types/jqueryui": "^1.12.16",
"autoprefixer": "^10.4.2",
"chai-colors": "^1.0.1",
"chart.js": "^3.6.2",
"codemirror": "^6.0.1",
"dompurify": "^2.3.5",
Expand Down
94 changes: 42 additions & 52 deletions static/js/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MessageKey } from './message-translations';
import { turtle_prefix, pygame_prefix, normal_prefix } from './pythonPrefixes'
import { Achievement, Adventure, isServerSaveInfo, ServerSaveInfo } from './types';
import { startIntroTutorial } from './tutorials/tutorial';
import { loadParsonsExercise } from './parsons';
import { get_parsons_code, initializeParsons, loadParsonsExercise } from './parsons';
import { checkNow, onElementBecomesVisible } from './browser-helpers/on-element-becomes-visible';
import { incrementDebugLine, initializeDebugger, load_variables, startDebug } from './debugging';
import { localDelete, localLoad, localSave } from './local';
Expand All @@ -16,7 +16,6 @@ import { postJson } from './comm';
import { LocalSaveWarning } from './local-save-warning';
import { HedyEditor, EditorType } from './editor';
import { stopDebug } from "./debugging";
import { HedyAceEditorCreator } from './ace-editor';
import { HedyCodeMirrorEditorCreator } from './cm-editor';
import { initializeTranslation } from './lezer-parsers/tokens';

Expand All @@ -26,7 +25,6 @@ export let theModalEditor: HedyEditor;
export let theGlobalSourcemap: { [x: string]: any; };
export const theLocalSaveWarning = new LocalSaveWarning();
const editorCreator: HedyCodeMirrorEditorCreator = new HedyCodeMirrorEditorCreator();
const aceEditorCreator: HedyAceEditorCreator = new HedyAceEditorCreator();
let last_code: string;

/**
Expand All @@ -43,7 +41,7 @@ let askPromptOpen = false;
let theAdventures: Record<string, Adventure> = {};
export let theLevel: number = 0;
export let theLanguage: string = '';
let theKeywordLanguage: string = 'en';
export let theKeywordLanguage: string = 'en';
let theStaticRoot: string = '';
let currentTab: string;
let theUserIsLoggedIn: boolean;
Expand Down Expand Up @@ -136,7 +134,6 @@ export function initializeApp(options: InitializeAppOptions) {
initializeSyntaxHighlighter({
keywordLanguage: options.keywordLanguage,
});
initializeHighlightedCodeBlocks(document.body);
initializeCopyToClipboard();

// Close the dropdown menu if the user clicks outside of it
Expand Down Expand Up @@ -367,27 +364,45 @@ export function initializeViewProgramPage(options: InitializeViewProgramPageOpti

export function initializeHighlightedCodeBlocks(where: Element) {
const dir = $("body").attr("dir");

initializeParsons();
if (theLevel) {
initializeTranslation({
keywordLanguage: theKeywordLanguage,
level: theLevel
})
}
// Any code blocks we find inside 'turn-pre-into-ace' get turned into
// read-only editors (for syntax highlighting)
for (const container of $(where).find('.turn-pre-into-ace').get()) {
for (const preview of $(container).find('pre').get()) {
$(preview)
.addClass('text-lg rounded overflow-x-hidden')
.addClass('relative text-lg rounded overflow-x-hidden')
// We set the language of the editor to the current keyword_language -> needed when copying to main editor
.attr('lang', theKeywordLanguage);

// Only turn into an editor if the editor scrolls into view
// Otherwise, the teacher manual Frequent Mistakes page is SUPER SLOW to load.
onElementBecomesVisible(preview, () => {
const codeNode = preview.querySelector('code')
let code: string;
// In case it has a child <code> node
if(codeNode) {
codeNode.hidden = true
code = codeNode.innerText
} else {
code = preview.textContent || "";
preview.textContent = "";
}

// Create this example editor
const exampleEditor = aceEditorCreator.initializeReadOnlyEditor(preview, dir);
const exampleEditor = editorCreator.initializeReadOnlyEditor(preview, dir);
// Strip trailing newline, it renders better
exampleEditor.contents = exampleEditor.contents.trimRight();
exampleEditor.contents = code;
exampleEditor.contents = exampleEditor.contents.trimEnd();
// And add an overlay button to the editor if requested via a show-copy-button class, either
// on the <pre> itself OR on the element that has the '.turn-pre-into-ace' class.
if ($(preview).hasClass('show-copy-button') || $(container).hasClass('show-copy-button')) {
const buttonContainer = $('<div>').addClass('absolute ltr:-right-1 rtl:left-2 w-16').css({top: 5}).appendTo(preview);
const buttonContainer = $('<div>').addClass('absolute ltr:right-0 rtl:left-0 top-0 mx-1 mt-1').appendTo(preview);
let symbol = "⇥";
if (dir === "rtl") {
symbol = "⇤";
Expand All @@ -401,9 +416,13 @@ export function initializeHighlightedCodeBlocks(where: Element) {
clearOutput();
});
}

const levelStr = $(preview).attr('level');
if (levelStr) {
const lang = $(preview).attr('lang');
if (levelStr && lang) {
initializeTranslation({
keywordLanguage: lang,
level: parseInt(levelStr, 10),
})
exampleEditor.setHighlighterForLevel(parseInt(levelStr, 10));
}
});
Expand Down Expand Up @@ -1448,7 +1467,7 @@ export function showVariableView() {
}
}

async function store_parsons_attempt(order: Array<string>, correct: boolean) {
export async function store_parsons_attempt(order: Array<string>, correct: boolean) {
try {
await postJsonWithAchievements('/store_parsons_order', {
level: theLevel,
Expand All @@ -1462,44 +1481,6 @@ async function store_parsons_attempt(order: Array<string>, correct: boolean) {
};
}

// Todo: As the parsons functionality will rapidly increase, we should probably all store this in a dedicated file (?)
function get_parsons_code() {
let code = "";
let count = 1;
let order = new Array();
let mistake = false;

$('.compiler-parsons-box').each(function() {
// We are only interested in the visible code lines
if ($(this).parent().is(':visible')) {
// When the value is 0 there is no code box in the expected spot
let text = $(this).attr('code') || "";
if (text.length > 1) {
// Also add a newline as we removed this from the YAML structure
code += text + "\n";
}
$(this).parents().removeClass('border-black');
let index = $(this).attr('index') || 999;
if (index == count) {
$(this).parents().addClass('border-green-500');
} else {
mistake = true;
$(this).parents().addClass('border-red-500');
}
order.push(index);
count += 1;
}
});
// Before returning the code we want to a-sync store the attempt in the database
// We only have to set the order and level, rest is handled by the back-end
store_parsons_attempt(order, !mistake);
if (mistake) {
return "";
}

return code.replace(/ +$/mg, '');
}

export function get_active_and_trimmed_code() {
theGlobalEditor.trimTrailingSpace();
const storage = window.localStorage;
Expand Down Expand Up @@ -1603,6 +1584,8 @@ export function toggleDevelopersMode(event='click', enforceDevMode: boolean) {
// (Driving from HTML attributes is more flexible on what gets resized, and avoids duplicating
// size literals between HTML and JavaScript).
$('#adventures').toggle(!enable);
// Parsons dont need a fixed height
if (currentTab === 'parsons') return
$('[data-devmodeheight]').each((_, el) => {
const heights = $(el).data('devmodeheight').split(',') as string[];
$(el).css('height', heights[enable ? 1 : 0]);
Expand Down Expand Up @@ -1912,10 +1895,17 @@ function reconfigurePageBasedOnTab() {
resetWindow();

updatePageElements();

if (currentTab === 'parsons') {
loadParsonsExercise(theLevel, 1);
// remove the fixed height from the editor
document.getElementById('code_editor')!.style.height = '100%'
document.getElementById('code_output')!.style.height = '100%'
return;
} else {
$('[data-devmodeheight]').each((_, el) => {
const heights = $(el).data('devmodeheight').split(',') as string[];
$(el).css('height', heights[0]);
});
}

const adventure = theAdventures[currentTab];
Expand Down
88 changes: 44 additions & 44 deletions static/js/appbundle.js

Large diffs are not rendered by default.

Loading