Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit 68e3db1

Browse files
committed
🍻 Oh GOD now it is truly migrated
1 parent 8353958 commit 68e3db1

3 files changed

Lines changed: 192 additions & 8 deletions

File tree

runestone/hparsons/hparsons.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def setup(app):
4848

4949
TEMPLATE_START = """
5050
<div class="%(divclass)s">
51-
<div data-component="activecode" id=%(divid)s data-question_label="%(question_label)s">
51+
<div data-component="hparsons" id=%(divid)s data-question_label="%(question_label)s">
5252
<div id=%(divid)s_question class="ac_question col-md-12">
5353
"""
5454

runestone/hparsons/js/hparsons-sql.js

Lines changed: 190 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Handsontable from "handsontable";
2-
import 'handsontable/dist/handsontable.full.css';
2+
// import 'handsontable/dist/handsontable.full.css';
33
import initSqlJs from "sql.js/dist/sql-wasm.js";
44
import RunestoneBase from "../../common/js/runestonebase.js";
55

@@ -13,8 +13,8 @@ import "codemirror/mode/javascript/javascript.js";
1313
import "codemirror/mode/sql/sql.js";
1414
import "codemirror/mode/clike/clike.js";
1515
import "codemirror/mode/octave/octave.js";
16-
import "./../css/activecode.css";
17-
import "codemirror/lib/codemirror.css";
16+
// import "./../../activecode/css/activecode.css";
17+
// import "codemirror/lib/codemirror.css";
1818

1919
// copied from activecode
2020
// Used by Skulpt.
@@ -24,9 +24,14 @@ window.vegaEmbed = embed;
2424

2525
var allDburls = {};
2626

27+
export var hpList;
28+
// Dictionary that contains all instances of horizontal Parsons problem objects
29+
if (hpList === undefined) hpList = {};
30+
2731
export default class SQLHParons extends RunestoneBase {
2832
constructor(opts) {
2933
super(opts);
34+
console.log('hparsons sql constructor')
3035
// copied from activecode
3136
var suffStart;
3237
var orig = $(opts.orig).find("textarea")[0];
@@ -182,6 +187,155 @@ export default class SQLHParons extends RunestoneBase {
182187
}
183188
});
184189
}
190+
191+
// copied from activecode
192+
async runButtonHandler() {
193+
// Disable the run button until the run is finished.
194+
this.runButton.disabled = true;
195+
try {
196+
await this.runProg();
197+
} catch (e) {
198+
console.log(`there was an error ${e} running the code`);
199+
}
200+
if (this.logResults) {
201+
this.logCurrentAnswer();
202+
}
203+
this.renderFeedback();
204+
// The run is finished; re-enable the button.
205+
this.runButton.disabled = false;
206+
}
207+
208+
// copied from activecode
209+
addHistoryButton(ctrlDiv) {
210+
let butt = document.createElement("button");
211+
$(butt).text($.i18n("msg_activecode_load_history"));
212+
$(butt).addClass("btn btn-default");
213+
$(butt).attr("type", "button");
214+
ctrlDiv.appendChild(butt);
215+
this.histButton = butt;
216+
$(butt).click(this.addHistoryScrubber.bind(this));
217+
if (this.graderactive) {
218+
this.addHistoryScrubber(true);
219+
}
220+
}
221+
222+
// copied from activecode
223+
// _`addHistoryScrubber`
224+
// ---------------------
225+
// Activecode -- If the code has not changed wrt the scrubber position value then don't save the code or reposition the scrubber
226+
// -- still call runlog, but add a parameter to not save the code
227+
// add an initial load history button
228+
// if there is no edit then there is no append to_save (True/False)
229+
async addHistoryScrubber(pos_last) {
230+
let response;
231+
var reqData = {
232+
acid: this.divid,
233+
};
234+
if (this.sid !== undefined) {
235+
reqData["sid"] = this.sid;
236+
}
237+
console.log("before get hist");
238+
if (
239+
eBookConfig.practice_mode ||
240+
(this.isTimed && !this.assessmentTaken)
241+
) {
242+
// If this is timed and already taken we should restore history info
243+
this.renderScrubber();
244+
} else {
245+
let request = new Request(`${eBookConfig.new_server_prefix}/assessment/gethist`, {
246+
method: "POST",
247+
headers: this.jsonHeaders,
248+
body: JSON.stringify(reqData),
249+
});
250+
try {
251+
response = await fetch(request);
252+
let data = await response.json();
253+
if (!response.ok) {
254+
throw new Error(`Failed to get the history data: ${data.detail}`);
255+
}
256+
data = data.detail;
257+
if (data.history !== undefined) {
258+
this.history = this.history.concat(data.history);
259+
for (let t in data.timestamps) {
260+
this.timestamps.push(
261+
new Date(data.timestamps[t]).toLocaleString()
262+
);
263+
}
264+
}
265+
} catch (e) {
266+
console.log(`unable to fetch history: ${e}`);
267+
}
268+
this.renderScrubber(pos_last);
269+
}
270+
return "success";
271+
}
272+
273+
renderScrubber(pos_last) {
274+
console.log("making a new scrubber");
275+
var scrubberDiv = document.createElement("div");
276+
$(scrubberDiv).css("display", "inline-block");
277+
$(scrubberDiv).css("margin-left", "10px");
278+
$(scrubberDiv).css("margin-right", "10px");
279+
$(scrubberDiv).css({
280+
"min-width": "200px",
281+
"max-width": "300px",
282+
});
283+
var scrubber = document.createElement("div");
284+
this.timestampP = document.createElement("span");
285+
this.slideit = function () {
286+
this.editor.setValue(this.history[$(scrubber).slider("value")]);
287+
var curVal = this.timestamps[$(scrubber).slider("value")];
288+
let pos = $(scrubber).slider("value");
289+
let outOf = this.history.length;
290+
$(this.timestampP).text(`${curVal} - ${pos + 1} of ${outOf}`);
291+
this.logBookEvent({
292+
event: "activecode",
293+
act: "slide:" + curVal,
294+
div_id: this.divid,
295+
});
296+
};
297+
$(scrubber).slider({
298+
max: this.history.length - 1,
299+
value: this.history.length - 1,
300+
});
301+
$(scrubber).css("margin", "10px");
302+
$(scrubber).on("slide", this.slideit.bind(this));
303+
$(scrubber).on("slidechange", this.slideit.bind(this));
304+
scrubberDiv.appendChild(scrubber);
305+
scrubberDiv.appendChild(this.timestampP);
306+
// If there is a deadline set then position the scrubber at the last submission
307+
// prior to the deadline
308+
if (this.deadline) {
309+
let i = 0;
310+
let done = false;
311+
while (i < this.history.length && !done) {
312+
if (new Date(this.timestamps[i]) > this.deadline) {
313+
done = true;
314+
} else {
315+
i += 1;
316+
}
317+
}
318+
i = i - 1;
319+
scrubber.value = Math.max(i, 0);
320+
this.editor.setValue(this.history[scrubber.value]);
321+
$(scrubber).slider("value", scrubber.value);
322+
} else if (pos_last) {
323+
scrubber.value = this.history.length - 1;
324+
this.editor.setValue(this.history[scrubber.value]);
325+
} else {
326+
scrubber.value = 0;
327+
}
328+
let pos = $(scrubber).slider("value");
329+
let outOf = this.history.length;
330+
let ts = this.timestamps[$(scrubber).slider("value")];
331+
$(this.timestampP).text(`${ts} - ${pos + 1} of ${outOf}`);
332+
$(this.histButton).remove();
333+
this.histButton = null;
334+
this.historyScrubber = scrubber;
335+
$(scrubberDiv).insertAfter(this.runButton);
336+
} // end definition of helper
337+
338+
185339
// copied from activecode
186340
createEditor(index) {
187341
this.outerDiv = document.createElement("div");
@@ -344,7 +498,8 @@ export default class SQLHParons extends RunestoneBase {
344498
$(butt).addClass("btn btn-success run-button");
345499
ctrlDiv.appendChild(butt);
346500
this.runButton = butt;
347-
console.log("adding click function for run");
501+
console.log(butt);
502+
console.log("adding click function for run in sql");
348503
this.runButton.onclick = this.runButtonHandler.bind(this);
349504
$(butt).attr("type", "button");
350505

@@ -527,12 +682,41 @@ export default class SQLHParons extends RunestoneBase {
527682
return Promise.resolve("done");
528683
}
529684

685+
// copied from anctivecode
686+
async buildProg(useSuffix) {
687+
// assemble code from prefix, suffix, and editor for running.
688+
var pretext;
689+
var prog = this.editor.getValue() + "\n";
690+
if (this.prefix) {
691+
prog = this.prefix + prog;
692+
}
693+
this.pretext = "";
694+
this.pretextLines = 0;
695+
this.progLines = prog.match(/\n/g).length + 1;
696+
if (this.includes) {
697+
// iterate over the includes, in-order prepending to prog
698+
pretext = "";
699+
for (var x = 0; x < this.includes.length; x++) {
700+
let iCode = await this.getIncludedCode(this.includes[x]);
701+
pretext = pretext + iCode + "\n";
702+
}
703+
this.pretext = pretext;
704+
if (this.pretext) {
705+
this.pretextLines = (this.pretext.match(/\n/g) || "").length;
706+
}
707+
prog = pretext + prog;
708+
}
709+
if (useSuffix && this.suffix) {
710+
prog = prog + this.suffix;
711+
}
712+
return Promise.resolve(prog);
713+
}
530714
async logCurrentAnswer(sid) {
531715
let data = {
532716
div_id: this.divid,
533717
code: this.editor.getValue(),
534718
language: this.language,
535-
errinfo: this.results[this.results.length - 1].status,
719+
// errinfo: this.results[this.results.length - 1].status,
536720
to_save: this.saveCode,
537721
prefix: this.pretext,
538722
suffix: this.suffix,
@@ -679,7 +863,7 @@ function createTable(tableData, container, maxHeight) {
679863
== execute our code on them ==
680864
=================================*/
681865
$(document).bind("runestone:login-complete", function () {
682-
$("[data-component=sqlhparsons]").each(function () {
866+
$("[data-component=hparsons]").each(function () {
683867
if ($(this).closest("[data-component=timedAssessment]").length == 0) {
684868
// If this element exists within a timed component, don't render it here
685869
// try {

webpack.index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ const module_map = {
7070
khanex: () => import("./runestone/khanex/js/khanex.js"),
7171
lp_build: () => import("./runestone/lp/js/lp.js"),
7272
multiplechoice: () => import("./runestone/mchoice/js/timedmc.js"),
73-
hparsons: () => import("./runestone/hparsons/js/hparsons.js"),
73+
hparsons: () => import("./runestone/hparsons/js/hparsons-sql.js"),
7474
parsons: () => import("./runestone/parsons/js/timedparsons.js"),
7575
poll: () => import("./runestone/poll/js/poll.js"),
7676
quizly: () => import("./runestone/quizly/js/quizly.js"),

0 commit comments

Comments
 (0)