diff --git a/app/assets/javascripts/simple_code.js b/app/assets/javascripts/simple_code.js
index 18a89d2f..e3cca305 100644
--- a/app/assets/javascripts/simple_code.js
+++ b/app/assets/javascripts/simple_code.js
@@ -6,6 +6,8 @@ $(document).ready(function(){
Sk.canvas = "studentCanvas";
$.getJSON('/data/simple_code.json', function(response) {
data = response;
+ var externalIdElement = document.getElementById("exercise-data");
+ var externalId = externalIdElement.getAttribute("data-external-id");
var initial = data[index]['initial'];
var initialArray = initial.split('\n');
var config = data[index]['parsonsConfig'];
diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb
index c226384e..f92cc231 100644
--- a/app/controllers/exercises_controller.rb
+++ b/app/controllers/exercises_controller.rb
@@ -3,6 +3,7 @@ class ExercisesController < ApplicationController
require 'oauth/request_proxy/rack_request'
require 'zip'
require 'tempfile'
+ require 'json'
load_and_authorize_resource
@@ -225,7 +226,50 @@ def edit
end
session[:return_to] = @return_to
end
+ # -------------------------------------------------------------
+ def edit_parsons
+ step = params[:step]
+ full_name = "parsons_s#{step}"
+ puts "full_name = #{full_name}"
+ @exercise = Exercise.where('name LIKE ?', "%#{full_name}%").first
+ json_file_path = Rails.root.join('public', 'data', 'simple_code.json')
+ if File.exist?(json_file_path)
+ file_content = File.read(json_file_path)
+ json_content = JSON.parse(file_content)
+ @step_data = json_content["s#{step}"]
+ else
+ @step_data = {}
+ end
+ end
+ # -------------------------------------------------------------
+ def update_parsons
+ step = params[:step]
+ json_data = params[:step_json_data] # Ensure this matches the name attribute from the form
+ Rails.logger.debug "Received JSON data: #{json_data}"
+
+ json_file_path = Rails.root.join('public', 'data', 'simple_code.json')
+
+ unless File.exist?(json_file_path)
+ redirect_to edit_parsons_exercise_path(step: step), alert: 'JSON file not found.'
+ return
+ end
+
+ begin
+ content = JSON.parse(File.read(json_file_path))
+ updated_data = JSON.parse(json_data)
+ if content["s#{step}"].present?
+ content["s#{step}"] = updated_data
+ File.write(json_file_path, JSON.pretty_generate(content))
+ redirect_to edit_parsons_exercise_path(step: step), notice: 'Parsons updated successfully.'
+ else
+ redirect_to edit_parsons_exercise_path(step: step), alert: "Step not found in JSON."
+ end
+ rescue JSON::ParserError => e
+ Rails.logger.debug e.inspect # Log the error for inspection
+ redirect_to edit_parsons_exercise_path(step: step), alert: "Failed to parse JSON: #{e.message}"
+ end
+ end
# -------------------------------------------------------------
# POST /exercises
diff --git a/app/views/exercises/_exercise.html.haml b/app/views/exercises/_exercise.html.haml
index 2ea70a4f..f18b9e3b 100644
--- a/app/views/exercises/_exercise.html.haml
+++ b/app/views/exercises/_exercise.html.haml
@@ -95,9 +95,14 @@
= link_to exercise.display_name, show_exercise_path(step: "s#{step}")
- else
= link_to exercise.display_name, exercise_practice_path(exercise)
-
+ - is_parsons = exercise.name.downcase.include?('parsons')
- if [ 'show', 'index', 'search' ].include?(action_name) && (current_user.andand.can? :edit, exercise)
- .right= button_link 'Edit', edit_exercise_path(exercise), class: 'btn btn-primary btn-sm'
+ .right
+ - if is_parsons
+ - step = exercise.name.downcase.match(/parsons_s(\d+)/)[1]
+ = button_link 'Edit', edit_parsons_exercise_path(step: step), class: 'btn btn-primary btn-sm'
+ - else
+ = button_link 'Edit', edit_exercise_path(exercise), class: 'btn btn-primary btn-sm'
- if !new_workout
.summary
diff --git a/app/views/exercises/edit_parsons.html.haml b/app/views/exercises/edit_parsons.html.haml
new file mode 100644
index 00000000..28f28b75
--- /dev/null
+++ b/app/views/exercises/edit_parsons.html.haml
@@ -0,0 +1,29 @@
+- if !@lti_launch
+ = render partial: 'layouts/breadcrumb'
+
+%h1
+ Edit Parsons:
+ - if @exercise
+ = link_to @exercise.display_name, exercise_practice_path(@exercise)
+ - else
+ %span Error: Exercise not found.
+
+
+%h2
+ Edit JSON Data for Step: #{params[:step]}
+= form_tag update_parsons_exercise_path(step: params[:step]), method: :post do
+ %fieldset
+ .field
+ = label_tag :step_json_data, "Step JSON Data"
+ = text_area_tag :step_json_data, JSON.pretty_generate(@step_data), class: 'json-editor', rows: 20, cols: 80
+ .actions
+ = submit_tag "Save JSON Changes", class: 'btn btn-primary'
+
+:css
+ .json-editor {
+ font-family: monospace;
+ background-color: #f9f9f9;
+ border: 1px solid #ccc;
+ width: 100%;
+ margin-top: 5px;
+ }
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 533051e9..5a5b2231 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -67,6 +67,8 @@
get 'exercises/download_attempt_data' =>
'exercises#download_attempt_data', as: :download_exercise_attempt_data
get '/gym/exercises/Jsparson/exercise/simple/:step', to: 'exercises#show_exercise', as: 'show_exercise'
+ get '/exercises/Jsparson/exercise/simple/:step/parsons_edit', to: 'exercises#edit_parsons', as: 'edit_parsons_exercise'
+ post '/exercises/Jsparson/exercise/simple/:step/update_parsons', to: 'exercises#update_parsons', as: 'update_parsons_exercise'
# At the bottom, so the routes above take precedence over existing ids
resources :exercises
diff --git a/public/data/simple_code.json b/public/data/simple_code.json
index 3abcbb85..7c5e4ad3 100644
--- a/public/data/simple_code.json
+++ b/public/data/simple_code.json
@@ -1,95 +1,94 @@
{
- "s3":{
- "initial": "IF $$toggle::a::b$$ $$toggle::<::>::<>$$ b THEN\n min := a\nELSE\n min := b\nENDIF",
- "parsonsConfig": {
- "max_wrong_lines": 1,
- "vartests": [
- {
- "initcode": "min = None\na = 0\nb = 2",
- "code": "",
- "message": "Testing with a = 0 ja b = 2",
- "variables": {
- "min": 0
- }
- },
- {
- "initcode": "min = None\na = 7\nb = 4\n",
- "code": "",
- "message": "Testing with a = 7 ja b = 4",
- "variables": {
- "min": 4
- }
- }
- ],
- "executable_code": "if $$toggle$$ $$toggle::<::>::!=$$ b:\nmin = a\nelse:\nmin = b\npass",
- "programmingLang": "pseudo"
+ "s3": {
+ "initial": "IF $$toggle::a::b$$ $$toggle::<::>::<>$$ b THEN\n min := a\nELSE\n min := b\nENDIF",
+ "parsonsConfig": {
+ "max_wrong_lines": 1,
+ "vartests": [
+ {
+ "initcode": "min = None\na = 1\nb = 2",
+ "code": "",
+ "message": "Testing with a = 1 ja b = 2",
+ "variables": {
+ "min": 1
+ }
},
- "title": "Find minimum",
- "instructions": "Construct a function by drag& dropping and reordering lines from the left to the right.The constructed function should set the value of variable min to be the smaller of variables a and b.",
- "order": 0
+ {
+ "initcode": "min = None\na = 7\nb = 4\n",
+ "code": "",
+ "message": "Testing with a = 7 ja b = 4",
+ "variables": {
+ "min": 4
+ }
+ }
+ ],
+ "executable_code": "if $$toggle$$ $$toggle::<::>::!=$$ b:\nmin = a\nelse:\nmin = b\npass",
+ "programmingLang": "pseudo"
},
- "s4":{
- "initial": "$$toggle::x::y::tmp$$ = $$toggle::x::y::tmp$$\n$$toggle::x::y::tmp$$ = $$toggle::x::y::tmp$$\n$$toggle::x::y::tmp$$ = $$toggle::x::y::tmp$$",
- "parsonsConfig": {
- "max_wrong_lines": 1,
- "vartests": [
- {
- "initcode": "x = 0\ny=2",
- "code": "",
- "message": "Testing with initial variable values x = 0 and y = 2",
- "variables": {
- "x": 2
- }
- },
- {
- "initcode": "x = 3\ny=4\n",
- "code": "",
- "message": "Testing with initial variable values x = 3 and y = 4",
- "variables": {
- "x": 4,
- "y": 3
- }
- }
- ],
- "executable_code": "tmp = x\nx = y\ny = tmp\npass" ,
- "programmingLang": "pseudo"
+ "title": "Find minimum",
+ "instructions": "Construct a function by drag& dropping and reordering lines from the left to the right.The constructed function should set the value of variable min to be the smaller of variables a and b.",
+ "order": 0
+ },
+ "s4": {
+ "initial": "$$toggle::x::y::tmp$$ = $$toggle::x::y::tmp$$\n$$toggle::x::y::tmp$$ = $$toggle::x::y::tmp$$\n$$toggle::x::y::tmp$$ = $$toggle::x::y::tmp$$",
+ "parsonsConfig": {
+ "max_wrong_lines": 1,
+ "vartests": [
+ {
+ "initcode": "x = 0\ny=2",
+ "code": "",
+ "message": "Testing with initial variable values x = 0 and y = 2",
+ "variables": {
+ "x": 2
+ }
},
- "title": "Variable Swap",
- "instructions": "Construct a program that swaps the values of variables x
and y
using the helper variable tmp
. You can change the names of the variables",
- "order": 1
+ {
+ "initcode": "x = 3\ny=4\n",
+ "code": "",
+ "message": "Testing with initial variable values x = 3 and y = 4",
+ "variables": {
+ "x": 4,
+ "y": 3
+ }
+ }
+ ],
+ "executable_code": "tmp = x\nx = y\ny = tmp\npass",
+ "programmingLang": "pseudo"
},
- "s5":{
- "initial": "for (int i=0;i<3;i++) {\nSystem.out.print(\"I \");\nSystem.out.print(\"am \");\nSystem.out.print(\"a Java program \");\n}",
- "parsonsConfig": {
- "max_wrong_lines": 1,
- "vartests": [
- {
- "initcode": "output = ''",
- "code": "",
- "message": "Testing...",
- "variables": {
- "output": "I am a Java program I am a Java program I am a Java program "
- }
- }
- ],
- "executable_code": "for x in range(3):\noutput += 'I '\noutput += 'am '\noutput += 'a Java program '\npass\n",
- "programmingLang": "java"
- },
- "title": "Print message with loop",
- "instructions": "Construct code by reordering and indenting the lines.",
- "order": 2
+ "title": "Variable Swap",
+ "instructions": "Construct a program that swaps the values of variables x
and y
using the helper variable tmp
. You can change the names of the variables",
+ "order": 1
+ },
+ "s5": {
+ "initial": "for (int i=0;i<3;i++) {\nSystem.out.print(\"I \");\nSystem.out.print(\"am \");\nSystem.out.print(\"a Java program \");\n}",
+ "parsonsConfig": {
+ "max_wrong_lines": 1,
+ "vartests": [
+ {
+ "initcode": "output = ''",
+ "code": "",
+ "message": "Testing...",
+ "variables": {
+ "output": "I am a Java program I am a Java program I am a Java program "
+ }
+ }
+ ],
+ "executable_code": "for x in range(3):\noutput += 'I '\noutput += 'am '\noutput += 'a Java program '\npass\n",
+ "programmingLang": "java"
},
- "s6":{
- "initial": "REPEAT 3 TIMES\nforward(100)\nleft(120)\nENDREPEAT",
- "parsonsConfig": {
- "max_wrong_lines": 1,
- "turtleModelCode":"modelTurtle.forward(100)\nmodelTurtle.left(120)\nmodelTurtle.forward(100)\nmodelTurtle.left(120)\nmodelTurtle.forward(100)\nmodelTurtle.left(120)",
- "executable_code": "for i in range(0,3):\nmyTurtle.forward(100)\nmyTurtle.left(120)\npass",
- "programmingLang": "pseudo"
- },
- "title": "draw triangle",
- "instructions": "Construct a program by drag&dropping and reordering lines from the left to the right.The constructed program should draw a triangle like shown below.",
- "order": 3
- }
-
+ "title": "Print message with loop",
+ "instructions": "Construct code by reordering and indenting the lines.",
+ "order": 2
+ },
+ "s6": {
+ "initial": "REPEAT 3 TIMES\nforward(100)\nleft(120)\nENDREPEAT",
+ "parsonsConfig": {
+ "max_wrong_lines": 1,
+ "turtleModelCode": "modelTurtle.forward(100)\nmodelTurtle.left(120)\nmodelTurtle.forward(100)\nmodelTurtle.left(120)\nmodelTurtle.forward(100)\nmodelTurtle.left(120)",
+ "executable_code": "for i in range(0,3):\nmyTurtle.forward(100)\nmyTurtle.left(120)\npass",
+ "programmingLang": "pseudo"
+ },
+ "title": "draw triangle",
+ "instructions": "Construct a program by drag&dropping and reordering lines from the left to the right.The constructed program should draw a triangle like shown below.",
+ "order": 3
+ }
}
\ No newline at end of file