From 83ec739433c185221b4fed7d77bbda5b0c9fcc8b Mon Sep 17 00:00:00 2001 From: Emmanuel Schanzer Date: Tue, 8 Oct 2024 08:31:34 -0400 Subject: [PATCH] allow for descendent implementations (#35) --- actions/ImplementationActions.php | 114 ++++++++++++++++++++++++ actions/common.php | 4 +- js/scripts.js | 2 +- js/validate.js | 2 +- views/Implementation.php | 140 +++++++++++++++++++++++------- views/Implementations.php | 7 +- views/common.php | 2 +- 7 files changed, 233 insertions(+), 38 deletions(-) create mode 100644 actions/ImplementationActions.php diff --git a/actions/ImplementationActions.php b/actions/ImplementationActions.php new file mode 100644 index 0000000..f4c2042 --- /dev/null +++ b/actions/ImplementationActions.php @@ -0,0 +1,114 @@ +query($sql); + if($result){ + $id = $mysqli->insert_id; + // attempts to update a record with identical data result in NO INSERT, so we need + // to detect this and return the original id instead (quotes removed) + echo $id? $id : $values[0]; + } else { + echo "ERROR: Sorry $sql. ". $mysqli->error; + } + $mysqli->close(); + } + + + function duplicateImplementation($data) { + $mysqli = openDB_Connection(); + try { + $mysqli->begin_transaction(); + $sql = "INSERT INTO Implementations ( + implementation_id, + person_id, + course_name, + subject, + grade_level, + computer_access, + start, + curriculum, + model, + module_theme, + when_teaching, + dataset_selection, + lesson_list, + num_students, + demographics_json, + exams, + standards, + status, + parent_impl_id + ) + SELECT + NULL AS implementation_id, + person_id, + CONCAT('(Copy) ', course_name) AS course_name, + subject, + grade_level, + computer_access, + start, + curriculum, + model, + module_theme, + when_teaching, + dataset_selection, + lesson_list, + num_students, + demographics_json, + exams, + standards, + status, + ".$data['implementation_id']." AS parent_id + FROM Implementations WHERE implementation_id=".$data['implementation_id']; + + $result = $mysqli->query($sql); + $new_implementation_id; + if($result) { + $new_implementation_id = $mysqli->insert_id; + } else { + echo "ERROR when duplicating the implementation: Sorry $sql. ". $mysqli->error; + } + $mysqli->commit(); + } catch (mysqli_sql_exception $exception) { + $mysqli->rollback(); + throw $exception; + } + $mysqli->close(); + echo $new_implementation_id; + } + +?> \ No newline at end of file diff --git a/actions/common.php b/actions/common.php index ddd7b9d..c981643 100644 --- a/actions/common.php +++ b/actions/common.php @@ -62,12 +62,14 @@ function openDB_Connection() { } function genericInsertOrUpdate($table, $data) { - $mysqli = openDB_Connection(); + $mysqli = openDB_Connection(); $columns = array_keys($data); $values = array_values($data); + for( $i = 0; $i < count($values); $i++ ){ $values[$i] = quoteOrNull(mysqli_real_escape_string( $mysqli, $values[$i] )); } + $updateFields = implode(", ", array_map( function($column,$value) { return $column."=".$value; }, $columns, $values diff --git a/js/scripts.js b/js/scripts.js index 24eac93..24b3e7c 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -163,7 +163,7 @@ function updateRequest(e, callback) { if(!formObject) return false; console.log('validated!', formObject); const data = JSON.stringify(formObject); - + // append method and JSON-formatted string to post address const target = event.target; target.action += '?method=update&data='+data; diff --git a/js/validate.js b/js/validate.js index 1312bb8..3c58064 100644 --- a/js/validate.js +++ b/js/validate.js @@ -125,7 +125,7 @@ function validate(elt, type, value){ const numb = '0123456789.'; const date = numb+'/.-'; -const sym = '#\'\"\,\!\?\$/:-\(\)\[\]\|\.\\\n=+-’'; +const sym = '\;#\'\"\,\!\?\$/:-\(\)\[\]\|\.\\\n=+-’'; const numbsym = numb+sym; const lwr = 'abcdefghijklmnopqrstuvwxyz.- '; const upr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.- '; diff --git a/views/Implementation.php b/views/Implementation.php index e64cca4..3bd0eac 100644 --- a/views/Implementation.php +++ b/views/Implementation.php @@ -22,6 +22,7 @@ width: 75px; } .chart { width: 200px; height: 200px; float: right; } + #parent_course_name { border: none; border-bottom: solid 1px black; pointer-events: none; } query($sql); $data = (!$result || ($result->num_rows !== 1))? false : $result->fetch_array(MYSQLI_ASSOC); $mysqli->close(); @@ -69,7 +71,7 @@ function deleteImplementationRq(){ // if the request is successful, execute the callback request.onreadystatechange = function() { if (request.readyState == 4 && request.status == 200) { - deleteEventRp(request.responseText); + deleteImplementationRp(request.responseText); } }; const data = JSON.stringify({implementation_id:id}); @@ -77,21 +79,37 @@ function deleteImplementationRq(){ request.send(); } } - function deleteEventRp( rsp ){ - const urlValue = baseURL + `/views/Classes.php`; + function deleteImplementationRp( rsp ){ + const urlValue = baseURL + `/views/Implementations.php`; window.location = urlValue; } + function duplicateImplementationRq(e) { + const id = document.getElementById('implementation_id').value; + if(confirm("Are you sure you want to duplicate Implementation ID# " + id + "?")){ + var request = new XMLHttpRequest(); + // if the request is successful, execute the callback + request.onreadystatechange = function() { + if (request.readyState == 4 && request.status == 200) { + window.location = "Implementation.php?implementation_id="+request.responseText; + } + }; + const data = JSON.stringify({implementation_id:id}); + request.open('POST', "../actions/ImplementationActions.php?method=duplicateImplementation&data="+data); + request.send(); + } + } + function drawCharts() { drawGenderChart(); drawEthnicityChart() } function drawGenderChart() { - const num_students = Number(document.getElementById('num_students').value); - const pct_girls = Number(document.getElementById('pct_girls').value); - const pct_non_binary= Number(document.getElementById('pct_non_binary').value); - const pct_boys = 1 - (pct_girls + pct_non_binary); + const num_students = Number(document.getElementById('num_students').value) / 100; + const pct_girls = Number(document.getElementById('pct_girls').value) / 100; + const pct_non_binary= Number(document.getElementById('pct_non_binary').value) / 100; + const pct_boys = 1 - (pct_girls + pct_non_binary) / 100; const data = google.visualization.arrayToDataTable([ ['Gender', '#Students', {type:'string', role:'tooltip'}], ['Boys', pct_boys, String(Math.round(num_students * pct_boys)) + " male students"], @@ -109,12 +127,12 @@ function drawGenderChart() { } function drawEthnicityChart() { - const num_students = Number(document.getElementById('num_students').value); - const pct_black = Number(document.getElementById('pct_black').value); - const pct_latino = Number(document.getElementById('pct_latino').value); - const pct_asian = Number(document.getElementById('pct_asian').value); - const pct_islander = Number(document.getElementById('pct_islander').value); - const pct_white = (1 - (pct_black + pct_latino + pct_asian + pct_islander)); + const num_students = Number(document.getElementById('num_students').value) / 100; + const pct_black = Number(document.getElementById('pct_black').value) / 100; + const pct_latino = Number(document.getElementById('pct_latino').value) / 100; + const pct_asian = Number(document.getElementById('pct_asian').value) / 100; + const pct_islander = Number(document.getElementById('pct_islander').value) / 100; + const pct_white = (1 - (pct_black + pct_latino + pct_asian + pct_islander)) / 100; const data = google.visualization.arrayToDataTable([ ['Ethnicty', '#Students', {type:'string', role:'tooltip'}], ['White', pct_white, String(Math.round(num_students * pct_white)) + " white students"], @@ -142,13 +160,30 @@ function drawEthnicityChart() {

+
-
+"> + implementation_id=".$_REQUEST["implementation_id"].". Submitting this form will create a new DB entry with a new implementation_id."; + } + ?> + + + + + + + + + + + +
Class Implementation - " /> @@ -157,15 +192,26 @@ function drawEthnicityChart() { " - type="text" size="80" maxlength="70" required="yes"/> + type="text" size="50" maxlength="70" required="yes"/> + + + " /> + + + + + + + + - " style="border-bottom:solid 1px black; width: 300px; display: inline-block;"> + " style="border-bottom:solid 1px black; width: 200px; display: inline-block;"> - +
@@ -195,6 +241,7 @@ function drawEthnicityChart() { +
@@ -205,7 +252,6 @@ function drawEthnicityChart() { -
" + value="" type="number" size="4" maxlength="3"/> @@ -283,7 +329,7 @@ function drawEthnicityChart() { " + value="" onchange="drawCharts()" type="number" size="4" maxlength="3"/> @@ -292,7 +338,7 @@ function drawEthnicityChart() { " + value="" onchange="drawCharts()" type="number" size="4" maxlength="3"/> @@ -302,7 +348,7 @@ function drawEthnicityChart() { " + value="" onchange="drawCharts()" type="number" size="4" maxlength="3"/> @@ -311,7 +357,7 @@ function drawEthnicityChart() { " + value="" onchange="drawCharts()" type="number" size="4" maxlength="3"/> @@ -320,7 +366,7 @@ function drawEthnicityChart() { " + value="" onchange="drawCharts()" type="number" size="4" maxlength="3"/> @@ -329,7 +375,7 @@ function drawEthnicityChart() { " + value="" onchange="drawCharts()" type="number" size="4" maxlength="3"/> @@ -343,5 +389,37 @@ function drawEthnicityChart() { \ No newline at end of file diff --git a/views/Implementations.php b/views/Implementations.php index 28ef837..b94acc8 100644 --- a/views/Implementations.php +++ b/views/Implementations.php @@ -83,7 +83,7 @@ function addPerson() { window.location = 'Person.php'; } SUM(CASE WHEN status LIKE 'Not implementing yet, but will this school year' then 1 else 0 end) AS this_year, SUM(CASE WHEN status LIKE 'Will not implement this school year, but will next year' then 1 else 0 end) AS next_year, SUM(CASE WHEN status LIKE 'Will not implement' then 1 else 0 end) AS not_implementing, - SUM(CASE WHEN status LIKE 'Unknown' then 1 else 0 end) AS unknown + SUM(CASE WHEN status LIKE 'Initial Plan' then 1 else 0 end) AS initial_plan FROM Implementations AS I GROUP BY X"; @@ -139,14 +139,15 @@ function drawCharts() { chart = new google.visualization.PieChart(document.getElementById('curriculumChart')); chart.draw(curriculum, options); - const { implementing, this_year, next_year, not_implementing, unknown } = data; + const { implementing, this_year, next_year, not_implementing, initial_plan } = data; + console.log(data); const status = google.visualization.arrayToDataTable([ ['Curriculum', '%Classes', {type:'string', role:'tooltip'}], ['Implementing', implementing, String( implementing ) + " Implementing"], ['Not implementing yet, but will this school year', this_year, String( this_year ) + " Will Implement this Year"], ['Will not implement this school year, but will next year', next_year, String( next_year ) + " Will Implement Next Year"], ['Will not implement', not_implementing, String( not_implementing ) + " Not Implementing"], - ['Unknown', unknown, String( unknown ) + " Unknown"], + ['Initial Plan', initial_plan, String( initial_plan ) + " Initial Plan"], ]); options = { title: 'Implementation Status', legend: 'none' }; chart = new google.visualization.PieChart(document.getElementById('statusChart')); diff --git a/views/common.php b/views/common.php index 262b418..7c9e1a9 100644 --- a/views/common.php +++ b/views/common.php @@ -98,7 +98,7 @@ function openDB_Connection() { $modelOpts = ["Dedicated Course","Dedicated Unit Within Existing Course","Lessons Sprinkled Throughout Course"]; -$implStatusOpts = ["Implementing","Not implementing yet, but will this school year","Will not implement this school year, but will next year","Will not implement","Unknown"]; +$implStatusOpts = ["Initial Plan", "Implementing","Not implementing yet, but will this school year","Will not implement this school year, but will next year","Will not implement","Initial Plan"]; $eventTypeOpts = ["Presentation","Coaching","Training","Meetup","Panel","AYW"];