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

💻 new customize adventure page #5535

Merged
merged 46 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
11e9f1a
basic format
hasan-sh May 15, 2024
cd62a0a
🤖 Automatically update generated files
hasan-sh May 15, 2024
9a2c1c4
get level from options or js object
hasan-sh May 16, 2024
72dc004
remove margin bottom from tags list
hasan-sh May 16, 2024
87f1b5d
WIP: added code support for previewing
hasan-sh May 16, 2024
0939676
Merge branch 'new-customize-adventure' of github.com:hedyorg/hedy int…
hasan-sh May 16, 2024
5f92bda
solution example editor
hasan-sh May 21, 2024
8a2875e
Merge branch 'main' into new-customize-adventure
hasan-sh May 21, 2024
d72dbdb
🤖 Automatically update generated files
hasan-sh May 21, 2024
398ea77
example code
hasan-sh May 21, 2024
ef1f787
Merge branch 'new-customize-adventure' of github.com:hedyorg/hedy int…
hasan-sh May 21, 2024
7740c21
- save one version of the code for each of adventure and solution exa…
hasan-sh May 23, 2024
1540b8b
Merge branch 'main' into new-customize-adventure
hasan-sh May 23, 2024
ab500b7
fix tests
hasan-sh May 23, 2024
46998bc
🤖 Automatically update generated files
hasan-sh May 23, 2024
f7f8126
fix e2e tests
hasan-sh May 23, 2024
6aed27e
Merge branch 'new-customize-adventure' of github.com:hedyorg/hedy int…
hasan-sh May 23, 2024
056f5eb
WIP: correct previewing and content for editor
hasan-sh May 27, 2024
f310210
Merge branch 'main' into new-customize-adventure
hasan-sh Jun 25, 2024
54f7f33
🤖 Automatically update generated files
hasan-sh Jun 25, 2024
9496381
minor changes accroding to feedback
hasan-sh Jun 26, 2024
899a196
translation keys
hasan-sh Jun 26, 2024
7c1dee1
remove unused literal
hasan-sh Jun 27, 2024
d6b12f8
🤖 Automatically update generated files
hasan-sh Jun 27, 2024
4c3f6c6
fix tests, and fixed changed id tags issue!
hasan-sh Jun 27, 2024
965400f
Merge branch 'new-customize-adventure' of github.com:hedyorg/hedy int…
hasan-sh Jun 27, 2024
d2a1efb
fix tests
hasan-sh Jul 1, 2024
caf3410
Merge branch 'main' into new-customize-adventure
hasan-sh Jul 1, 2024
4961a56
🤖 Automatically update generated files
hasan-sh Jul 1, 2024
ff7baae
changes according to #5475
hasan-sh Jul 1, 2024
41f81f2
Merge branch 'main' into new-customize-adventure
hasan-sh Jul 1, 2024
a41c1ba
Merge branch 'new-customize-adventure' of github.com:hedyorg/hedy int…
hasan-sh Jul 1, 2024
e936adf
remove only keyword cypress
hasan-sh Jul 1, 2024
cef3c13
🤖 Automatically update generated files
hasan-sh Jul 1, 2024
30e97c2
Merge branch 'main' into new-customize-adventure
hasan-sh Jul 2, 2024
f55974d
🤖 Automatically update generated files
hasan-sh Jul 2, 2024
80fe8d1
Revert "fix tests, and fixed changed id tags issue!"
hasan-sh Jul 2, 2024
6e92773
data-cy attributes
hasan-sh Jul 2, 2024
973bb04
Merge branch 'new-customize-adventure' of github.com:hedyorg/hedy int…
hasan-sh Jul 2, 2024
ba2e342
new design adventure tabs
Annelein Jul 2, 2024
f680d53
Merge branch 'new-customize-adventure' of https://github.com/hedyorg/…
Annelein Jul 2, 2024
c9a67bf
🤖 Automatically update generated files
Annelein Jul 2, 2024
3dcdf9c
make tips hidden
Annelein Jul 2, 2024
95989e1
fix for cypress test
Annelein Jul 2, 2024
e901726
id to data-cy in cypress tests
Annelein Jul 2, 2024
be8b87e
Merge branch 'main' into new-customize-adventure
mergify[bot] Jul 3, 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
3 changes: 3 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ def load_customized_adventures(level, customizations, into_adventures):
else:
db_row['content'] = safe_format(db_row['content'],
**hedy_content.KEYWORDS.get(g.keyword_lang))
if 'solution_example' in db_row:
db_row['solution_example'] = safe_format(db_row['solution_example'],
**hedy_content.KEYWORDS.get(g.keyword_lang))
except Exception:
# We don't want teacher being able to break the student UI -> pass this adventure
pass
Expand Down
8 changes: 7 additions & 1 deletion messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-04-22 12:26-0400\n"
"POT-Creation-Date: 2024-06-26 16:04+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand Down Expand Up @@ -1589,6 +1589,12 @@ msgstr ""
msgid "social_media"
msgstr ""

msgid "solution_example"
msgstr ""

msgid "solution_example_explanation"
msgstr ""

msgid "something_went_wrong_keyword_parsing"
msgstr ""

Expand Down
21 changes: 12 additions & 9 deletions static/js/adventure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ declare let window: CustomWindow;

export interface InitializeCustomizeAdventurePage {
readonly page: 'customize-adventure';
readonly level: number;
}

let $editor: ClassicEditor;
let keywordHasAlert: Map<string, boolean> = new Map()

export async function initializeCustomAdventurePage(_options: InitializeCustomizeAdventurePage) {
const editorContainer = document.querySelector('#adventure_editor') as HTMLElement;
const editorContainer = document.querySelector('#adventure-editor') as HTMLElement;
const editorSolutionExampleContainer = document.querySelector('#adventure-solution-editor') as HTMLElement;
// Initialize the editor with the default language
let lang = document.querySelector('#languages_dropdown> .option.selected')!.getAttribute('data-value') as string
const TRADUCTIONS = convert(TRADUCTION_IMPORT) as Map<string, Map<string,string>>;
Expand All @@ -28,6 +30,7 @@ export async function initializeCustomAdventurePage(_options: InitializeCustomiz

if (editorContainer) {
await initializeEditor(lang, editorContainer);
await initializeEditor(lang, editorSolutionExampleContainer, true);
showWarningIfMultipleKeywords(TRADUCTION)
$editor.model.document.on('change:data', () => {
showWarningIfMultipleKeywords(TRADUCTION)
Expand Down Expand Up @@ -107,12 +110,8 @@ function findCoincidences(name: string, TRADUCTION: Map<string, string>) {
return coincidences;
}

function initializeEditor(language: string, editorContainer: HTMLElement): Promise<void> {
function initializeEditor(language: string, editorContainer: HTMLElement, solutionExample=false): Promise<void> {
return new Promise((resolve, reject) => {
if ($editor) {
$editor.destroy();
}

ClassicEditor
.create(editorContainer, {
codeBlock: {
Expand All @@ -123,9 +122,13 @@ function initializeEditor(language: string, editorContainer: HTMLElement): Promi
language,
})
.then(editor => {
window.ckEditor = editor;
$editor = editor;
$editor.model.document.on("change:data", e => autoSave("customize_adventure", e))
if (solutionExample) {
window.ckSolutionEditor = editor;
} else {
window.ckEditor = editor;
$editor = editor;
}
editor.model.document.on("change:data", e => autoSave("customize_adventure", e))
resolve();
})
.catch(error => {
Expand Down
60 changes: 37 additions & 23 deletions static/js/appbundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -103885,7 +103885,8 @@ def note_with_error(value, err):
var $editor;
var keywordHasAlert = new Map();
async function initializeCustomAdventurePage(_options) {
const editorContainer = document.querySelector("#adventure_editor");
const editorContainer = document.querySelector("#adventure-editor");
const editorSolutionExampleContainer = document.querySelector("#adventure-solution-editor");
let lang = document.querySelector("#languages_dropdown> .option.selected").getAttribute("data-value");
const TRADUCTIONS = convert(highlighting_trad_default);
if (!TRADUCTIONS.has(lang)) {
Expand All @@ -103894,6 +103895,7 @@ def note_with_error(value, err):
let TRADUCTION3 = TRADUCTIONS.get(lang);
if (editorContainer) {
await initializeEditor(lang, editorContainer);
await initializeEditor(lang, editorSolutionExampleContainer, true);
showWarningIfMultipleKeywords(TRADUCTION3);
$editor.model.document.on("change:data", () => {
showWarningIfMultipleKeywords(TRADUCTION3);
Expand Down Expand Up @@ -103967,11 +103969,8 @@ def note_with_error(value, err):
}
return coincidences;
}
function initializeEditor(language2, editorContainer) {
function initializeEditor(language2, editorContainer, solutionExample = false) {
return new Promise((resolve2, reject) => {
if ($editor) {
$editor.destroy();
}
import_ckeditor.default.create(editorContainer, {
codeBlock: {
languages: [
Expand All @@ -103980,9 +103979,13 @@ def note_with_error(value, err):
},
language: language2
}).then((editor) => {
window.ckEditor = editor;
$editor = editor;
$editor.model.document.on("change:data", (e) => autoSave("customize_adventure", e));
if (solutionExample) {
window.ckSolutionEditor = editor;
} else {
window.ckEditor = editor;
$editor = editor;
}
editor.model.document.on("change:data", (e) => autoSave("customize_adventure", e));
resolve2();
}).catch((error2) => {
console.error(error2);
Expand Down Expand Up @@ -118469,18 +118472,7 @@ def note_with_error(value, err):
});
});
}
function update_db_adventure(adventure_id) {
const adventure_name = $("#custom_adventure_name").val();
let classes = [];
let levels = [];
document.querySelectorAll("#levels_dropdown > .option.selected").forEach((el3) => {
levels.push(el3.getAttribute("data-value"));
});
document.querySelectorAll("#classes_dropdown > .option.selected").forEach((el3) => {
classes.push(el3.getAttribute("data-value"));
});
const language2 = document.querySelector("#languages_dropdown> .option.selected").getAttribute("data-value");
const content2 = import_dompurify2.default.sanitize(window.ckEditor.getData());
function get_formatted_content(content2, levels, language2) {
const parser19 = new DOMParser();
const html = parser19.parseFromString(content2, "text/html");
const minLevel = Math.min(...levels.map((el3) => Number(el3)));
Expand Down Expand Up @@ -118511,6 +118503,23 @@ def note_with_error(value, err):
}
}
const formatted_content = html.getElementsByTagName("body")[0].outerHTML.replace(/<br>/g, "\n");
return formatted_content;
}
function update_db_adventure(adventure_id) {
const adventure_name = $("#custom_adventure_name").val();
let classes = [];
let levels = [];
document.querySelectorAll("#levels_dropdown > .option.selected").forEach((el3) => {
levels.push(el3.getAttribute("data-value"));
});
document.querySelectorAll("#classes_dropdown > .option.selected").forEach((el3) => {
classes.push(el3.getAttribute("data-value"));
});
const language2 = document.querySelector("#languages_dropdown> .option.selected").getAttribute("data-value");
const content2 = import_dompurify2.default.sanitize(window.ckEditor.getData());
const solutionExampleCode = import_dompurify2.default.sanitize(window.ckSolutionEditor.getData());
const formatted_content = get_formatted_content(content2, levels, language2);
const formatted_solution_code = get_formatted_content(solutionExampleCode, levels, language2);
const agree_public = $("#agree_public").prop("checked");
$.ajax({
type: "POST",
Expand All @@ -118520,6 +118529,7 @@ def note_with_error(value, err):
name: adventure_name,
content: content2,
formatted_content,
formatted_solution_code,
public: agree_public,
language: language2,
classes,
Expand Down Expand Up @@ -121358,16 +121368,20 @@ def note_with_error(value, err):

// static/js/initialize.ts
function initialize(options) {
var _a3;
var _a3, _b;
setClientMessageLanguage(options.lang);
let level3 = options.level;
if (!level3 && ((_a3 = options.javascriptPageOptions) == null ? void 0 : _a3.page) == "customize-adventure") {
level3 = options.javascriptPageOptions.level;
}
initializeApp({
level: options.level,
level: level3,
keywordLanguage: options.keyword_language,
staticRoot: options.staticRoot
});
initializeFormSubmits();
initializeTutorial();
switch ((_a3 = options.javascriptPageOptions) == null ? void 0 : _a3.page) {
switch ((_b = options.javascriptPageOptions) == null ? void 0 : _b.page) {
case "code":
initializeCodePage(options.javascriptPageOptions);
break;
Expand Down
4 changes: 2 additions & 2 deletions static/js/appbundle.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions static/js/custom-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
*/
export interface CustomWindow extends Window {
ckEditor: ClassicEditor;
ckSolutionEditor: ClassicEditor;
}
8 changes: 7 additions & 1 deletion static/js/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,14 @@ type InitializePageOptions =
export function initialize(options: InitializeOptions) {
setClientMessageLanguage(options.lang);

let level = options.level;

if (!level && options.javascriptPageOptions?.page == "customize-adventure") {
level = options.javascriptPageOptions.level
}

initializeApp({
level: options.level,
level: level,
keywordLanguage: options.keyword_language,
staticRoot: options.staticRoot,
});
Expand Down
44 changes: 26 additions & 18 deletions static/js/teachers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,24 +215,7 @@ export function remove_student(class_id: string, student_id: string, prompt: str
});
}

function update_db_adventure(adventure_id: string) {
// Todo TB: It would be nice if we improve this with the formToJSON() function once #3077 is merged
const adventure_name = $('#custom_adventure_name').val();
let classes: string[] = [];
let levels: string[] = []

document.querySelectorAll('#levels_dropdown > .option.selected').forEach((el) => {
levels.push(el.getAttribute("data-value") as string)
})

document.querySelectorAll('#classes_dropdown > .option.selected').forEach((el) => {
classes.push(el.getAttribute("data-value") as string)
})

const language = document.querySelector('#languages_dropdown> .option.selected')!.getAttribute('data-value') as string

const content = DOMPurify.sanitize(window.ckEditor.getData());

function get_formatted_content(content: string, levels: string[], language: string) {
const parser = new DOMParser();
const html = parser.parseFromString(content, 'text/html');
const minLevel = Math.min(...levels.map((el) => Number(el)));
Expand Down Expand Up @@ -268,6 +251,30 @@ function update_db_adventure(adventure_id: string) {
}
// We have to replace <br> for newlines, because the serializer swithces them around
const formatted_content = html.getElementsByTagName('body')[0].outerHTML.replace(/<br>/g, '\n');
return formatted_content
}

function update_db_adventure(adventure_id: string) {
// Todo TB: It would be nice if we improve this with the formToJSON() function once #3077 is merged
const adventure_name = $('#custom_adventure_name').val();
let classes: string[] = [];
let levels: string[] = []

document.querySelectorAll('#levels_dropdown > .option.selected').forEach((el) => {
levels.push(el.getAttribute("data-value") as string)
})

document.querySelectorAll('#classes_dropdown > .option.selected').forEach((el) => {
classes.push(el.getAttribute("data-value") as string)
})

const language = document.querySelector('#languages_dropdown> .option.selected')!.getAttribute('data-value') as string

const content = DOMPurify.sanitize(window.ckEditor.getData());
const solutionExampleCode = DOMPurify.sanitize(window.ckSolutionEditor.getData());

const formatted_content = get_formatted_content(content, levels, language);
const formatted_solution_code = get_formatted_content(solutionExampleCode, levels, language);
const agree_public = $('#agree_public').prop('checked');

$.ajax({
Expand All @@ -278,6 +285,7 @@ function update_db_adventure(adventure_id: string) {
name: adventure_name,
content: content,
formatted_content: formatted_content,
formatted_solution_code: formatted_solution_code,
public: agree_public,
language,
classes,
Expand Down
Loading
Loading