Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.
2 changes: 1 addition & 1 deletion runestone/activecode/activecode.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def setup(app):
TEMPLATE_START = """
<div class="%(divclass)s %(optclass)s">
<div data-component="activecode" id=%(divid)s data-question_label="%(question_label)s">
<div id=%(divid)s_question class="ac_question col-md-12">
<div id=%(divid)s_question class="ac_question">
"""

TEMPLATE_END = """
Expand Down
25 changes: 17 additions & 8 deletions runestone/activecode/css/activecode.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,24 @@
clear: both;
}

.ac_section .clearfix {
position: initial;
}

.unittest-results {
margin-left: 20px;
}

.ac_output {
margin-top: 10px;
margin-bottom: -10px;
display: none;
background-color: inherit;
}
.ac_output pre {
background-color: lightgray;
}

.python_check_results pre {
background-color: #f5f5f5;
}

.ac_caption {
text-align: center;
font-weight: bold;
Expand Down Expand Up @@ -102,10 +103,6 @@
border: 2px solid black;
}

.ac_section > .col-md-12 {
max-width: 100% !important;
}

.full_width ol {
max-width: 100% !important;
}
Expand Down Expand Up @@ -150,3 +147,15 @@
margin-bottom: 10px;
min-height: 0px !important;
}

.codelens {
margin-bottom: 20px;
}

.codecoach {
margin-top: 20px;
}

.ac_section .alert h3:first-child {
margin-top: 0px;
}
3 changes: 0 additions & 3 deletions runestone/activecode/js/acfactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,6 @@ export default class ACFactory {
sid: sid,
graderactive: true,
};
if (language === "htmlmixed") {
addopts["vertical"] = true;
}
newac = ACFactory.createActiveCode(thepre, language, addopts);
var savediv = newac.divid;
newac.divid = savediv;
Expand Down
116 changes: 68 additions & 48 deletions runestone/activecode/js/activecode.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ export class ActiveCode extends RunestoneBase {
this.containerDiv = opts.orig;
this.useRunestoneServices = opts.useRunestoneServices;
this.python3 = true;
this.alignVertical = opts.vertical;
this.origElem = orig;
this.origText = this.origElem.textContent;
this.divid = opts.orig.id;
Expand Down Expand Up @@ -159,7 +158,7 @@ export class ActiveCode extends RunestoneBase {
var linkdiv = document.createElement("div");
linkdiv.id = this.divid.replace(/_/g, "-").toLowerCase(); // :ref: changes _ to - so add this as a target
var codeDiv = document.createElement("div");
$(codeDiv).addClass("ac_code_div col-md-12");
$(codeDiv).addClass("ac_code_div");
this.codeDiv = codeDiv;
this.outerDiv.lang = this.language;
$(this.origElem).replaceWith(this.outerDiv);
Expand Down Expand Up @@ -286,7 +285,6 @@ export class ActiveCode extends RunestoneBase {
var ctrlDiv = document.createElement("div");
var butt;
$(ctrlDiv).addClass("ac_actions");
$(ctrlDiv).addClass("col-md-12");
// Run
butt = document.createElement("button");
$(butt).text($.i18n("msg_activecode_run_code"));
Expand Down Expand Up @@ -703,7 +701,7 @@ export class ActiveCode extends RunestoneBase {
// to hold turtle graphics output. We use a div in case the turtle changes from
// using a canvas to using some other element like svg in the future.
var outDiv = document.createElement("div");
$(outDiv).addClass("ac_output col-md-12");
$(outDiv).addClass("ac_output");
this.outDiv = outDiv;
this.output = document.createElement("pre");
this.output.id = this.divid + "_stdout";
Expand All @@ -723,26 +721,28 @@ export class ActiveCode extends RunestoneBase {
$(this.graphics).addClass("visible-ac-canvas");
}.bind(this)
);
var clearDiv = document.createElement("div");
$(clearDiv).css("clear", "both"); // needed to make parent div resize properly
this.outerDiv.appendChild(clearDiv);

//Anything that wants to add output to coachdiv can do so after the h3
// all those elements will be cleared with each run and coach display will be
// reset to none. Any component that adds content after a run should set display
// to block to ensure visibility
var coachDiv = document.createElement("div");
coachDiv.classList.add("alert", "alert-warning", "codecoach");
$(coachDiv).css("display", "none");
let coachHead = coachDiv.appendChild(document.createElement("h3"));
coachHead.textContent = "Code Coach";
this.outerDiv.appendChild(coachDiv);
this.codecoach = coachDiv;

outDiv.appendChild(this.output);
outDiv.appendChild(this.graphics);
this.outerDiv.appendChild(outDiv);
var lensDiv = document.createElement("div");
lensDiv.classList.add("codelens");
lensDiv.id = `${this.divid}_codelens`;
$(lensDiv).addClass("col-md-12");
$(lensDiv).css("display", "none");
this.codelens = lensDiv;
this.outerDiv.appendChild(lensDiv);
var coachDiv = document.createElement("div");
$(coachDiv).addClass("col-md-12");
$(coachDiv).css("display", "none");
this.codecoach = coachDiv;
this.outerDiv.appendChild(coachDiv);
clearDiv = document.createElement("div");
$(clearDiv).css("clear", "both"); // needed to make parent div resize properly
this.outerDiv.appendChild(clearDiv);
}

disableSaveLoad() {
Expand Down Expand Up @@ -911,38 +911,6 @@ export class ActiveCode extends RunestoneBase {
div_id: this.divid,
});
}
// <iframe id="%(divid)s_codelens" width="800" height="500" style="display:block"src="#">
// </iframe>
showCodeCoach() {
var myIframe;
var srcURL;
var cl;
var div_id = this.divid;
if (this.codecoach === null) {
this.codecoach = document.createElement("div");
this.codecoach.style.display = "block";
}
cl = this.codecoach.firstChild;
if (cl) {
this.codecoach.removeChild(cl);
}
srcURL = eBookConfig.app + "/admin/diffviewer?divid=" + div_id;
myIframe = document.createElement("iframe");
myIframe.setAttribute("id", div_id + "_coach");
myIframe.setAttribute("width", "100%");
myIframe.setAttribute("height", "500px");
myIframe.setAttribute("style", "display:block");
myIframe.style.background = "#fff";
myIframe.style.width = "100%";
myIframe.src = srcURL;
this.codecoach.appendChild(myIframe);
$(this.codecoach).show();
this.logBookEvent({
event: "coach",
act: "view",
div_id: this.divid,
});
}

toggleEditorVisibility() {}

Expand Down Expand Up @@ -1303,6 +1271,51 @@ Yet another is that there is an internal error. The internal error message is:
}
}

async checkPythonSyntax() {
let code = this.editor.getValue();
fetch('/ns/coach/python_check', {
method: 'POST',
body: code
})
.then((response) => {
return response.json();
})
.then((data) => {
if(data.trim() !== '') {
//clean up returned text
let errorLines = data.split("\n");
let codeLines = code.split("\n");
let message = "";
for(let line of errorLines) {
if(line.indexOf(".py:") != -1) {
//old pyflakes returns "file:line:col error"
//new pyflakes returns "file:line:col: error"
//handle either
const cleaner = /[^.]*.py:(\d+):(\d+):? (.*)/i;
let lineParts = line.match(cleaner)
message += "Line " + lineParts[1] + ": " + lineParts[3] + "\n";
message += codeLines[lineParts[1] - 1] + "\n";
message += " ".repeat(lineParts[2] - 1) + "^\n";
} else {
message += line + "\n";
}
}
message = message.slice(0,-1); //remove trailing newline

//Render
let checkDiv = document.createElement("div");
checkDiv.classList.add("python_check_results");
let checkPre = checkDiv.appendChild(document.createElement("pre"));
checkPre.textContent = message;
this.codecoach.append(checkDiv);
$(this.codecoach).css("display", "block");
}
})
.catch(err => {
console.log("Error with ajax python check:", err);
});
}

/* runProg has several async elements to it.
* 1. Skulpt runs the python program asynchronously
* 2. The history is restored asynchronously
Expand All @@ -1328,6 +1341,10 @@ Yet another is that there is an internal error. The internal error message is:
var prog = await this.buildProg(true);
this.saveCode = "True";
$(this.output).text("");

//clear anything after header in codecoach
$(this.codecoach).children().slice(1).remove();

while ($(`#${this.divid}_errinfo`).length > 0) {
$(`#${this.divid}_errinfo`).remove();
}
Expand Down Expand Up @@ -1369,6 +1386,9 @@ Yet another is that there is an internal error. The internal error message is:
queue: false,
});
}
if (this.language == "python" || this.language == "python3") {
this.checkPythonSyntax();
}
try {
await Sk.misceval.asyncToPromise(function () {
return Sk.importMainWithBody("<stdin>", false, prog, true);
Expand Down
13 changes: 0 additions & 13 deletions runestone/activecode/js/activecode_html.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ActiveCode } from "./activecode.js";
export default class HTMLActiveCode extends ActiveCode {
constructor(opts) {
super(opts);
opts.alignVertical = true;
this.code = $("<textarea />").html(this.origElem.innerHTML).text();
$(this.runButton).text("Render");
this.editor.setValue(this.code);
Expand All @@ -14,12 +13,6 @@ export default class HTMLActiveCode extends ActiveCode {
let saveCode = "True";
this.saveCode = await this.manage_scrubber(saveCode);
$(this.output).text("");
if (!this.alignVertical) {
$(this.codeDiv).switchClass("col-md-12", "col-md-6", {
duration: 500,
queue: false,
});
}
$(this.outDiv).show({ duration: 700, queue: false });
prog =
"<script type=text/javascript>window.onerror = function(msg,url,line) {alert(msg+' on line: '+line);};</script>" +
Expand All @@ -28,14 +21,8 @@ export default class HTMLActiveCode extends ActiveCode {
}

createOutput() {
this.alignVertical = true;
var outDiv = document.createElement("div");
$(outDiv).addClass("ac_output");
if (this.alignVertical) {
$(outDiv).addClass("col-md-12");
} else {
$(outDiv).addClass("col-md-5");
}
this.outDiv = outDiv;
this.output = document.createElement("iframe");
$(this.output).css("background-color", "white");
Expand Down
2 changes: 1 addition & 1 deletion runestone/common/js/presenter_mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function codelensListener(duration) {
function configureCodelens() {
let acCodeTitle = document.createElement("h4");
acCodeTitle.textContent = "Active Code Window";
let acCode = $(".ac_code_div").removeClass("col-md-12");
let acCode = $(".ac_code_div");
$(".ac_code_div").addClass("col-md-6");
acCode.prepend(acCodeTitle);

Expand Down
2 changes: 1 addition & 1 deletion runestone/hparsons/hparsons.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def setup(app):
TEMPLATE_START = """
<div class="runestone">
<div data-component="hparsons" id=%(divid)s data-question_label="%(question_label)s" class="alert alert-warning hparsons_section">
<div class="hp_question col-md-12">
<div class="hp_question">
"""

TEMPLATE_END = """
Expand Down
2 changes: 1 addition & 1 deletion runestone/hparsons/js/SQLFeedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default class SQLFeedback extends HParsonsFeedback {

createOutput() {
var outDiv = document.createElement("div");
$(outDiv).addClass("hp_output col-md-12");
$(outDiv).addClass("hp_output");
this.outDiv = outDiv;
this.output = document.createElement("pre");
this.output.id = this.hparsons.divid + "_stdout";
Expand Down
1 change: 0 additions & 1 deletion runestone/hparsons/js/hparsons.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ export default class HParsons extends RunestoneBase {
createControls() {
var ctrlDiv = document.createElement("div");
$(ctrlDiv).addClass("hp_actions");
$(ctrlDiv).addClass("col-md-12");

// Run Button
this.runButton = document.createElement("button");
Expand Down