Нет описания

assessment(before change to handsontable).blade.php 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. @extends('layouts.master')
  2. @section('navigation')
  3. @if($role==1)
  4. @include('local.managers.admins._navigation')
  5. @elseif($role==2)
  6. @include('local.managers.sCoords._navigation')
  7. @elseif($role==3)
  8. @include('local.managers.pCoords._navigation')
  9. @else
  10. @include('local.professors._navigation')
  11. @endif
  12. @stop
  13. @section('main')
  14. <!-- View criterion info -->
  15. <div class="modal fade" id="modal-view-criterion">
  16. <div class="modal-dialog modal-lg">
  17. <div class="modal-content">
  18. <div class="modal-header">
  19. <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
  20. <h4 class="modal-title"></h4>
  21. </div>
  22. <div class="modal-body">
  23. <table class="table table-bordered">
  24. <thead>
  25. <th>Beginning (1-2)</th>
  26. <th>In Progress (3-4)</th>
  27. <th>Good (5-6)</th>
  28. <th>Excellent (7-8)</th>
  29. <th>Notes</th>
  30. </thead>
  31. <tbody>
  32. <tr></tr>
  33. </tbody>
  34. </table>
  35. </div>
  36. </div><!-- /.modal-content -->
  37. </div><!-- /.modal-dialog -->
  38. </div><!-- /.modal -->
  39. <div class="row">
  40. <div class="col-md-12">
  41. <div class="well">
  42. <button id="button-language" class="btn btn-default btn-sm pull-right">Change language / Cambiar idioma</button>
  43. <div id="english-instructions">
  44. <h4>Instructions:</h4>
  45. <ol>
  46. <li>Fill in the scores per criterion for each student. You can see the student's final score in the last column.</li>
  47. <li>Click 'Save Assessment' to save your assessment. You can come back later if you need to make any updates.</li>
  48. </ol>
  49. <h4>Notes:</h4>
  50. <ul>
  51. <li>If a particular criterion cannot be assessed for a student, select "N/A" (Not Applicable). This <strong>will not</strong> affect the student's score.</li>
  52. <li>If a particular criterion was assessed but the student did not complete the necessary work, you must select "0". This <strong>will</strong> affect the student's score.</li>
  53. <li>If a student did not complete any work for this activity, select "0" for all columns in that student's row.</li>
  54. <li>If a student dropped the class, select "N/A" (Not Applicable) for all columns in that student's row.</li>
  55. <li>Cells with "0" or "N/A" <strong>will not</strong> be used to determine whether a criterion is achieved. Only scores from 1 to 8 will be considered for this purpose.</li>
  56. </ul>
  57. </div>
  58. <div id="spanish-instructions">
  59. <h4>Instrucciones:</h4>
  60. <ol>
  61. <li>Seleccione la puntuación por criterio para cada estudiante. Puede ver la puntuación final en la última columna.</li>
  62. <li>Oprima 'Save Assessment' para guardar las puntuaciones. Puede volver a esta página luego si desea hacer cambios.</li>
  63. </ol>
  64. <h4>Notas:</h4>
  65. <ul>
  66. <li>Si un criterio particular no puede ser evaluado, seleccione "N/A" (No Aplica). Esto <strong>no</strong> afectará la puntuación final del estudiante.</li>
  67. <li>Si un criterio particular fue evaluado, pero el estudiante no completó el trabajo necesario, debe seleccionar "0". Esto <strong>sí</strong> afectará la puntuación final del estudiante.</li>
  68. <li>Si un estudiante no completó el trabajo para esta actividad, seleccione "0" en todas las columnas de la fila de ese estudiante.</li>
  69. <li>Si un estudiante se dio de baja, seleccione "N/A" (No Aplica) en todas las columnas de la fila de ese estudiante.</li>
  70. <li>Las celdas con "0" o "N/A" <strong>no</strong> serán utilizadas para determinar si un criterio se alcanzó o no. Solamente las puntuaciones del 1 al 8 serán consideradas.</li>
  71. </ul>
  72. </div>
  73. </div>
  74. <p id="course">Course: {{{ $course->code }}} {{{ $course->number }}}</p>
  75. <p id="section">Section: {{{ $course->section }}}</p>
  76. {{ HTML::linkAction('ActivitiesController@show', 'Back to Activity', array($activity->id), array('class'=>'btn btn-default btn-sm pull-right')) }}
  77. <p id="activity" data-activity-id="{{{ $activity->id }}}">Activity: {{{ $activity->name}}} </p>
  78. <p>Passing Criteria: <span id="expected_percentage">{{{ $rubric->expected_percentage }}}% of students must obtain at least </span><span id="expected_points">{{{$rubric->expected_points}}}</span> points </p>
  79. <table id="assessment-table" class="table table-striped">
  80. <thead>
  81. <tr>
  82. <th>Student</th>
  83. @foreach ($rubric_contents as $criterion)
  84. <th class="criterion-field" data-criterion-id="{{{ $criterion->id }}}"><div class="th-box">{{ $criterion->name}}</div></th>
  85. @endforeach
  86. <th>Student Percentage</th>
  87. </tr>
  88. </thead>
  89. <tbody>
  90. <!-- If the activity was assessed, load the assessment. Otherwise load empty sheet -->
  91. @if(sizeof($assessments)!=0)
  92. <!-- For each assessment -->
  93. @foreach ($assessments as $assessment)
  94. <tr class="student-row">
  95. <!-- Fetch student name -->
  96. <td class="student-field" data-student-id="{{ $assessment->student_id }}">
  97. {{{ $assessment->name }}}
  98. </td>
  99. <!-- For each criterion in the rubric, there's a score field -->
  100. @for ($i = 0; $i<sizeof($rubric_contents); $i++)
  101. <td class="score-field">
  102. <select name="" id="" class="form-control">
  103. <!-- Option from 0-8 -->
  104. @for ($j=0; $j<=8; $j++)
  105. <!-- If the decoded scores with index as the assessment id and second index as criterion id equals the loop index, mark it as selected -->
  106. @if( $j == $scores_array[$assessment->id][$rubric_contents[$i]->id])
  107. <option value="{{$j}}" selected="selected">{{ $j }}</option>
  108. @else
  109. <option value="{{$j}}">{{ $j }}</option>
  110. @endif
  111. @endfor
  112. <!-- N/A option -->
  113. @if( $scores_array[$assessment->id][$rubric_contents[$i]->id]=="N/A")
  114. <option value="N/A" selected="selected">N/A</option>
  115. @else
  116. <option value="N/A">N/A</option>
  117. @endif
  118. </select>
  119. </td>
  120. @endfor
  121. <td class="percentage">{{{ $assessment->percentage }}}</td>
  122. </tr>
  123. @endforeach
  124. @else
  125. @foreach ($students as $student)
  126. <tr class="student-row">
  127. <td class="student-field" data-student-id={{ $student->id }}>{{{ $student->name }}}</td>
  128. @for ($i = 0; $i<sizeof($rubric_contents); $i++)
  129. <td class="score-field">
  130. <select name="" id="" class="form-control">
  131. <option value="0">0</option>
  132. <option value="1">1</option>
  133. <option value="2">2</option>
  134. <option value="3">3</option>
  135. <option value="4">4</option>
  136. <option value="5">5</option>
  137. <option value="6">6</option>
  138. <option value="7">7</option>
  139. <option value="8">8</option>
  140. <option value="N/A">N/A</option>
  141. </select>
  142. </td>
  143. @endfor
  144. <td class="percentage"></td>
  145. </tr>
  146. @endforeach
  147. @endif
  148. </tbody>
  149. <tfoot>
  150. <tr>
  151. <td>
  152. <strong>Passed Criteria Percentage </strong>
  153. </td>
  154. @for ($i = 0; $i<sizeof($rubric_contents); $i++)
  155. <td class="total"><strong><span class="total-value"></span>%</strong>
  156. </td>
  157. @endfor
  158. <td></td>
  159. </tr>
  160. </tfoot>
  161. </table>
  162. <div class="text-center">
  163. <button id="button-submit-assessment" class="btn btn-primary btn-lg">Save Assessment</button>
  164. </div>
  165. </div>
  166. </div>
  167. @stop
  168. @section ('javascript')
  169. // --------------------------------------------------------------------------
  170. // Page load
  171. // --------------------------------------------------------------------------
  172. // Enable fixed headers
  173. $('#assessment-table').stickyTableHeaders();
  174. // Hide spanish instructions by default
  175. $('#spanish-instructions').toggle();
  176. $('.total').each(function(index)
  177. {
  178. percentagePerCriterion(index+1);
  179. });
  180. $('.student-row').each(function(index)
  181. {
  182. percentagePerStudent($(this));
  183. });
  184. // --------------------------------------------------------------------------
  185. // Functions
  186. // --------------------------------------------------------------------------
  187. // Calculate average of students that passed a specific criterion
  188. function percentagePerCriterion(columnIndex)
  189. {
  190. // Object to hold the score sum of each criterion
  191. var sum = 0 ;
  192. var total = 0;
  193. columnIndex+=1;
  194. // Iterate through rows of column
  195. $('table tbody tr td:nth-child('+columnIndex+')').each(function( index )
  196. {
  197. var val = parseInt($(this).children('select').find(':selected').val());
  198. /* If N/A or 0 are chosen, they are ignored in the calculation. */
  199. if(Number.isInteger(val) && val!=0)
  200. {
  201. if(val >= parseInt($('#expected_points').text()))
  202. {
  203. sum+=1;
  204. }
  205. total+=1;
  206. }
  207. });
  208. var percentage= (sum/total*100).toFixed(2);
  209. // If no criteria were assessed, set the percentage to 0.
  210. // This is to avoid show NaN%
  211. if(total==0)
  212. percentage="0.00";
  213. $('.total:nth-child('+columnIndex+') span').html(percentage);
  214. }
  215. // Calculate total for a specific student
  216. function percentagePerStudent(row)
  217. {
  218. // Object to hold the score student's total score
  219. var sum = 0 ;
  220. var total = 0;
  221. var percentage = 0;
  222. row.find('td.score-field').each(function(index)
  223. {
  224. var val = parseInt($(this).children('select').find(':selected').val());
  225. if(Number.isInteger(val))
  226. {
  227. sum += val;
  228. total+=1;
  229. }
  230. });
  231. percentage =((sum/(total*8))*100).toFixed(2);
  232. //If percentage is not a number, set it to 0.
  233. if(isNaN(percentage))
  234. percentage="0.00";
  235. row.find('.percentage').html('<strong>'+percentage+'%</strong>');
  236. }
  237. // --------------------------------------------------------------------------
  238. // Events
  239. // --------------------------------------------------------------------------
  240. // When any score changes, calculate percentages
  241. $('select').on('change', function(e)
  242. {
  243. percentagePerCriterion($(this).parent().index());
  244. percentagePerStudent($(this).closest('tr'));
  245. });
  246. // Submit button is clicked
  247. $('#button-submit-assessment').on('click', function(e)
  248. {
  249. var expected_points = parseInt($('#expected_points').text());
  250. var expected_percentage = parseInt($('#expected_percentage').text());
  251. //Prevent page refresh
  252. e.preventDefault();
  253. // Row in the database
  254. var activity_id = $('#activity').data('activity-id');
  255. // Object to hold the score sum of each criterion
  256. var criteriaSumObject = new Object();
  257. // Object to hold % of students that passed each criterion
  258. var CriteriaAchievedPercentage = new Object();
  259. // Object to hold all student evaluations
  260. var studentAssessments = new Array();
  261. // Iterate through all students
  262. $('#assessment-table tbody tr').each(function( index )
  263. {
  264. var ScoresObject = new Object(); // Scores column in database
  265. var CriterionObject = new Object(); // Objects inside ScoresObject
  266. var SingleStudentAssessment = new Object();
  267. SingleStudentAssessment.student_id = $(this).find('.student-field').data('student-id');
  268. // For each criterion, store the score in array
  269. $(this).children('td.score-field').each(function( index )
  270. {
  271. // Table cell with a score
  272. var scoreField = $(this);
  273. // Criterion being evaluated in current iteration
  274. var criterion_id = $('.criterion-field').eq(index).data('criterion-id');
  275. // Score in the cell
  276. var score = scoreField.children('select').find(':selected').val();
  277. // Store the score in the scores Object
  278. ScoresObject[criterion_id]=score;
  279. // Initialize the index for the sum object, if it's undefined
  280. if(typeof(criteriaSumObject[criterion_id]) == 'undefined')
  281. {
  282. criteriaSumObject[criterion_id]=0;
  283. }
  284. // Add to this criterion's total
  285. criteriaSumObject[criterion_id]+=parseInt(score);
  286. });
  287. SingleStudentAssessment.scores = ScoresObject;
  288. SingleStudentAssessment.percentage = $(this).find('.percentage').text();
  289. console.log('student object: '+JSON.stringify(SingleStudentAssessment));
  290. var clone = jQuery.extend({}, SingleStudentAssessment);
  291. studentAssessments.push(clone);
  292. });
  293. console.log('students: '+JSON.stringify(studentAssessments));
  294. console.log('total points per criteria: '+JSON.stringify(criteriaSumObject));
  295. // Iterate through all evaluated criteria, determining which were achieved
  296. // by comparing the completion percentage to the expected percentage
  297. var CriteriaAchievedResults = new Object();
  298. $('.total').each(function(index)
  299. {
  300. var id = $('.criterion-field').eq(index).data('criterion-id');
  301. CriteriaAchievedPercentage[id] = parseFloat($(this).find('span').text());
  302. //Set whether criterion was achieved (1) or not (0)
  303. if(CriteriaAchievedPercentage[id] >= expected_percentage)
  304. {
  305. CriteriaAchievedResults[id]=1;
  306. }
  307. else
  308. {
  309. CriteriaAchievedResults[id]=0;
  310. }
  311. });
  312. console.log('criteria results: '+JSON.stringify(CriteriaAchievedResults));
  313. console.log('criteria percentages: '+JSON.stringify(CriteriaAchievedPercentage));
  314. // Save activity to the database
  315. $.post
  316. (
  317. "{{ URL::action('ActivitiesController@saveAssessment') }}",
  318. {
  319. activity_id: activity_id,
  320. criteria_achieved_percentage: JSON.stringify(CriteriaAchievedPercentage),
  321. criteria_achievement: JSON.stringify(CriteriaAchievedResults),
  322. student_scores: JSON.stringify(studentAssessments),
  323. },
  324. function(data)
  325. {
  326. location.reload();
  327. window.scrollTo(0, 0);
  328. }
  329. );
  330. });
  331. // Language button is clicked
  332. $('#button-language').on('click', function(e)
  333. {
  334. $('#english-instructions').stop().toggle();
  335. $('#spanish-instructions').stop().toggle();
  336. });
  337. // Criterion name is clicked
  338. $('.criterion-field').on('click', function()
  339. {
  340. $.ajax({
  341. type: 'POST',
  342. url: "{{ URL::action('CriteriaController@fetchCriterionWithTrashed') }}",
  343. data: { id: $(this).data('criterion-id') },
  344. success: function(data)
  345. {
  346. $('.modal-title').html(data.name);
  347. $('.modal-body tbody tr').empty();
  348. $('.modal-body tbody tr').append
  349. (
  350. '<td>'+data.description12+'</td>'
  351. +'<td>'+data.description34+'</td>'
  352. +'<td>'+data.description56+'</td>'
  353. +'<td>'+data.description78+'</td>'
  354. );
  355. if(data.notes!=null)
  356. $('.modal-body tbody tr').append('<td>'+data.notes+'</td>');
  357. else
  358. $('.modal-body tbody tr').append('<td></td>');
  359. },
  360. async:true
  361. });
  362. $('#modal-view-criterion').modal();
  363. });
  364. @stop