@extends('layouts.master') @section('navigation') @if(Auth::user()->role==1) @include('local.managers.admins._navigation') @elseif(Auth::user()->role==2) @include('local.managers.sCoords._navigation') @elseif(Auth::user()->role==3) @include('local.managers.pCoords._navigation') @endif @stop @section('main') <!-- Update Rubric Modal --> <div class="modal fade" id="modal-confirm-update"> <div class="modal-dialog modal-sm"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title">Update Rubric</h4> </div> <div class="modal-body"> <p>Speak to any coordinators and/or professors in your School or Program that may be affected when you update this rubric. Professors that have already used this rubric will keep a copy of it as they used it, not an updated one.</p> <p>Do you want to update this rubric?</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">No</button> <button id="button-update-rubric" class="btn btn-primary save">Update</button> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> <!-- Delete Rubric Modal --> <div class="modal fade" id="modal-confirm-delete"> <div class="modal-dialog modal-sm"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title">Delete Rubric</h4> </div> <div class="modal-body"> <p>Please note: By deleting this rubric, it will no longer be available to your school's or program's professors. However, professors that have already used it will keep a copy in their activities. Speak to any coordinators and/or professors in your School or Program that may be affected.</p> <p>Are you sure you want to delete this rubric?</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">No</button> <button id="button-delete-rubric" class="btn btn-primary">Delete</button> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> <div class="row"> <div class="col-md-12"> <div class="panel panel-default"> <div class="panel-heading"> <span class="glyphicon glyphicon-triangle-bottom"></span> General Information </div> <div class="panel-body"> <form> <div class="form-group"> <label>Select a template, or create your own rubric</label> <select id="select-template" class="form-control"> <option data-template-id="0">Custom</option> @foreach ($templates as $template) @if($template->school_id==NULL && $template->program_id==NULL) <option data-template-id="{{ $template->id }}" data-template-program-id="{{ $template->program_id }}" data-admin="1" > {{{ $template->name }}} </option> @elseif($template->school_id!=NULL && $template->program_id==NULL) <option data-template-id="{{ $template->id }}" data-template-program-id="{{ $template->program_id }}" > {{{ $template->name }}} </option> @else <option data-template-id="{{ $template->id }}" data-template-program-id="{{ $template->program_id }}" class="bg-success" > {{{ $template->name }}} </option> @endif @endforeach </select> </div> <!-- If user is admin s/he can pick which schools can view the rubric --> @if(Auth::user()->role==1) <div class="form-group"> <label>Select the School this rubric will be visible from</label> <select id="select-school" class="form-control"> <option data-school-id="0">All</option> @foreach ($schools as $school) <option data-school-id="{{ $school->id }}"> {{ $school->name }} </option> @endforeach </select> </div> @endif <!-- If user is admin or school coordinator, s/he can pick which programs --> @if(Auth::user()->role==1 || Auth::user()->role==2) <div class="form-group"> <label>Select the Program this rubric belongs to</label> <select id="select-program" class="form-control"> <option data-program-id="0">All</option> @foreach ($programs as $program) <option data-program-id="{{ $program->id }}" data-program-program-id="{{ $program->program_id }}" > {{ $program->name }} </option> @endforeach </select> </div> @endif </form> <label for="">Select the lower bound for passing criteria</label> <form class="form-inline"> <div class="form-group"> <!-- Select percentage. If there is a rubric, select the saved value --> <select id="expected_percentage" class="form-control"> @for($i = 50; $i <= 100; $i++) @if($i==70) <option selected="selected" value="{{ $i }}">{{ $i }}</option> @else <option value="{{ $i }}">{{ $i }}</option> @endif @endfor </select> % of all students must score at least <!-- Select points. If there is a rubric, select the saved value --> <select id="expected_points" class="form-control"> @for($i = 5; $i <= 8; $i++) @if($i==5) <option selected="selected" value="{{ $i }}">{{ $i }}</option> @else <option value="{{ $i }}">{{ $i }}</option> @endif @endfor </select> point(s) in a criterion for it to pass. </div> </form> <br> <form> <div class="form-group"> <label>Select Status (you can change this later)</label> <div class="radio"> <label> <input type="radio" name="is_visible" id="is_visible0" value="0" checked> This rubric is <strong>not complete</strong> yet and will not be available to professors. </label> </div> <div class="radio"> <label> <input type="radio" name="is_visible" id="is_visible1" value="1"> This rubric is <strong>complete</strong> and will be available to professors. </label> </div> </div> </form> <div> <p class="small">Note: You can hide or show this section by clicking on its heading. You may want to hide it to have more space. </p> </div> </div> </div> <div class="well"> <form> <div class="form-group"> <label>Select a Learning Outcome</label> <select id="select-outcome" class="form-control"> @foreach ($outcomes as $outcome) <option data-outcome-id="{{ $outcome->id }}">{{ $outcome->name }}</option> @endforeach </select> </div> @if(Auth::user()->role != '1') <label>Filter Criteria</label> <div class="form-group"> <label class="radio-inline"> <input type="radio" checked name="criteria-filter" id="criteria-all" value="all"> All Criteria </label> <label class="radio-inline"> <input type="radio" name="criteria-filter" id="criteria-school" value="school"> Criteria from my School </label> @if(Auth::user()->role == '3') <label class="radio-inline"> <input type="radio" name="criteria-filter" id="criteria-program" value="program"> Criteria from my Program(s) </label> @endif </div> @endif <div class="form-group"> <label>Select a Criterion</label><span id="updated-text" class="text-success small"> updated</span> <select id="select-criterion" class="form-control"> </select> </div> <button id="button-add-criterion" class="btn btn-md btn-primary center-block"> <span class="glyphicon glyphicon-plus"></span> Add Criterion to Rubric</button> </form> </div> </div> </div> <div id="rubric-container" class="row"> <div class="col-md-12"> <table class="table table-striped table-condensed"> <thead><tr><th colspan="6 "><input id="rubric-name" type="text" class="form-control input-lg" placeholder="Rubric Name"></th></tr></thead> <thead> <tr> <th></th> <th>Criterion</th> <th>Beginning (1-2)</th> <th>In Progress (3-4)</th> <th>Good (5-6)</th> <th>Excellent (7-8)</th> <th></th> </tr> </thead> <tbody> </tbody> </table> <div id="copyright-info"> <hr> <p class="small"><strong>Copyright Information</strong></p> <ul id="copyright-list" class="list-unstyled small"> </ul> <hr> </div> <div class="text-center"> <div class="btn-group" role="group" aria-label="..."> <button id="button-create-rubric" class="btn btn-lg btn-primary save"> <span class="glyphicon glyphicon-floppy-disk"></span> Create </button> <button id="button-confirm-update-rubric" data-toggle="modal" data-target="#modal-confirm-update" class="btn btn-lg btn-primary"> <span class="glyphicon glyphicon-pencil"></span> Update </button> <button id="button-confirm-delete-rubric" data-toggle="modal" data-target="#modal-confirm-delete" class="btn btn-lg btn-primary"> <span class="glyphicon glyphicon-remove"></span> Delete </button> <button id="button-print-rubric" class="btn btn-lg btn-primary"><span class="glyphicon glyphicon-print"></span> Print <span class="small">(saved version)</span></button> </div> </div> </div> </div> @stop @section('included-js') <!-- jQuery Sortable Tables --> <script src="{{ asset('vendor/jQuerySortable/jquery-sortable-min.js') }}"></script> <!-- X-Editable js --> <script src="{{ asset('vendor/xeditable/bootstrap-editable.min.js') }}"></script> @stop @section('javascript') // -------------------------------------------------------------------------- // Page load // -------------------------------------------------------------------------- $('#updated-text').hide(); // Enable/disable program selection depending on school selection if user is // admin if({{Auth::user()->role}}==1) toggleProgramSelect($('#select-school')); // Fetch criteria of first outcome fetchCriteria($('#select-outcome')); // Hide table $('#rubric-container').hide(); // Disable Update and Delete Buttons by default $('#button-confirm-update-rubric').prop('disabled', true); $('#button-confirm-delete-rubric').prop('disabled', true); $('#button-print-rubric').prop('disabled', true); // Sortable rows $('.table').sortable({ handle: 'span.glyphicon.glyphicon-move', containerSelector: 'table', itemPath: '> tbody', itemSelector: 'tr', placeholder: '<tr class="placeholder"><th><span class="glyphicon glyphicon-arrow-right"></span></th></tr>' }); // -------------------------------------------------------------------------- // Functions // -------------------------------------------------------------------------- // Fetch criteria associated to a specific learning outcome function fetchCriteria(outcome) { $.post ( "{{ URL::route('fetchCriteria') }}", { id: outcome.find(':selected').data('outcome-id'), filter: $('input[name=criteria-filter]:checked').val() }, function(data) { $('#select-criterion').empty(); // Append criteria data.forEach( function (arrayItem) { $('#select-criterion') .append('<option data-criterion-id="'+arrayItem.id+'" >'+arrayItem.name+'</option>'); }); // If there are no criteria assigned to the selected outcome, disable the // input and the button used to add criteria. if(!$('#select-criterion').children().length) { $('#select-criterion').prop('disabled', true); $('#button-add-criterion').prop('disabled', true); } // Otherwise, enable both the input and the button else { $('#select-criterion').prop('disabled', false); $('#button-add-criterion').prop('disabled', false); } $('#updated-text').fadeIn('slow').fadeOut('slow'); } ); } // Add a new criterion to the rubric function addCriterion() { // Show the rubric container if(!$('tbody').children().length) { $('#rubric-container').show(); } // Get the selected criterion's id var id= parseInt($('#select-criterion').find(':selected').data('criterion-id')); // Check for duplicates var duplicates=false; $('tbody tr').each(function() { if ($(this).data('criterion-id') == id) { duplicates=true; } }); // If there are any, display an error if(duplicates) { $('#js-error-row').show(); $('#js-error-row').find('#error-message').text('Error: The selected criterion was already added.'); return; } // Otherwise, hide the error container else { $('#js-error-row').hide(); } // Fetch information of the criterion selected $.post ( "{{ URL::route('fetchCriterion') }}", { id: id}, function(data) { // Append the fetched data var str ='<tr data-assoc-outcome-id="'+data.outcome_id+'"' +'data-criterion-id="'+data.id+'" data-criterion-copyright="'+data.copyright+'" data-criterion-notes="'+data.notes+'"><th><span class="glyphicon glyphicon-move"></span></th><td>'; if(data.notes) { str+='<span><em data-toggle="tooltip" data-placement="top" title="'+data.notes+'">'+data.name+'</em></span><sup></sup>'; } else { str+='<span>'+data.name+'</span><sup></sup>'; } str+='</td><td class="editable" data-type="textarea">'+data.description12+'</td>' +'<td class="editable" data-type="textarea">'+data.description34+'</td>' +'<td class="editable" data-type="textarea">'+data.description56+'</td>' +'<td class="editable" data-type="textarea">'+data.description78+'</td>' +'<th><span class="glyphicon glyphicon-remove icon-btn" aria-hidden="true"></span></th></tr>'; $('table tbody').append(str); // Build copyright list buildCopyrightList(); // Enable X-Edtable on this new row $('.editable').editable({ unsavedclass: null, rows: 4 }); // Turn on tooltips again (because content is dynamic) $('[data-toggle="tooltip"]').tooltip(); // Sortable rows $('.table').sortable({ handle: 'span.glyphicon.glyphicon-move', containerSelector: 'table', itemPath: '> tbody', itemSelector: 'tr', placeholder: '<tr class="placeholder"><th><span class="glyphicon glyphicon-arrow-right"></span></th></tr>' }); } ); } // Fetch single criterion function fetchCriterion(criterion) { $.post ( "{{ URL::route('fetchCriterion') }}", { id: outcome.find(':selected').data('outcome-id')}, function(data) { $('#select-criterion').empty(); data.forEach( function (arrayItem) { $('#select-criterion') .append('<option data-criterion-id="'+arrayItem.id+'" >'+arrayItem.name+'</option>'); }); $('#select-criterion').append('<option data-criterion-id="0">Custom</option>'); } ); } // Build list from copyright info in rubric function buildCopyrightList() { // Empty the copyright list $('#copyright-list').empty(); $('tbody tr').each(function( index ) { var criterion = $(this); // If there's copyright info if(criterion.data('criterion-copyright')!=null) { var copyright = criterion.data('criterion-copyright'); // If there is anything in the copyright list if($('#copyright-list li').length>0) { // Check copyright list for the same copyright text var found = false; $('#copyright-list li').each(function() { // If found, give the string its number if(copyright==$(this).find('span').text()) { copyrightNumber = Number.parseInt($(this).find('sup').text()); criterion.children('td:nth-child(1)').find('sup').text(copyrightNumber); found =true; //to break return false; } }); // Otherwise, give it the next number and append a new item to the // list if(!found) { var copyrightNumber = $('#copyright-list li').length+1; criterion.children('td:nth-child(1)').find('sup').text(copyrightNumber); $('#copyright-list').append('<li><sup>'+copyrightNumber+' </sup><span>'+copyright+'<span></li>'); } } // Otherwise, give it number 1 and append it else { criterion.children('td:nth-child(1)').find('sup').text('1'); $('#copyright-list').append('<li><sup>1 </sup><span>'+copyright+'<span></li>'); } } }); if($('#copyright-info li').length>0) { $('#copyright-info').show(); } else { $('#copyright-info').hide(); } } // Fetch programs associated to a specific school function fetchPrograms(school) { $.ajax({ type: 'POST', url: "{{ URL::action('ProgramsController@fetch') }}", data: { id: school.find(':selected').data('school-id')}, success: function(data) { $('#select-program').empty(); $('#select-program').append('<option data-program-id="0">All</option>'); data.forEach( function (program) { $('#select-program') .append('<option data-program-id="'+program.id+'" >'+program.name+'</option>'); }); }, async:false }); if($('#select-school').find(':selected').data('school-id')!=0) $('#select-program').prop('disabled', false); else $('#select-program').prop('disabled', true); } // Load a template. This function is different from the one for professors function loadTemplate() { $.post ( "{{ URL::to('loadTemplate') }}", { id: $('#select-template').find(':selected').data('template-id')}, function(data) { // Show the container and empty all rows $('#rubric-container').show(); $('tbody').empty(); //Set the name of the rubric $('#rubric-name').val(data.name); // Set school id to 0, then to the saved value if it exists $('#select-school option[data-school-id="0"]').prop('selected', true); $('#select-school option[data-school-id="'+data.school_id+'"]').prop('selected', true); // Fetch programs associated to that school fetchPrograms($('#select-school')); // Set program id to 0, then to the saved value if it exists $('#select-program option[data-program-id="0"]').prop('selected', true); $('#select-program option[data-program-id="'+data.program_id+'"]').prop('selected', true); // Set expected values $('#expected_percentage option[value="'+data.expected_percentage+'"]').prop('selected', true); $('#expected_points option[value="'+data.expected_points+'"]').prop('selected', true); // Set visibility var is_visible = JSON.parse(data.is_visible); if(is_visible) { $('#is_visible0').prop('checked', false); $('#is_visible1').prop('checked', true); } else { $('#is_visible1').prop('checked', false); $('#is_visible0').prop('checked', true); } // Set the contents of the rubric var contents = JSON.parse(data.contents); contents.forEach(function (data) { // Append the fetched data var str ='<tr data-assoc-outcome-id="'+data.outcome_id+'"' +'data-criterion-id="'+data.id+'" data-criterion-copyright="'+data.copyright+'" data-criterion-notes="'+data.notes+'"><th><span class="glyphicon glyphicon-move"></span></th><td>'; if(data.notes) { str+='<span><em data-toggle="tooltip" data-placement="top" title="'+data.notes+'">'+data.name+'</em></span><sup></sup>'; } else { str+='<span>'+data.name+'</span><sup></sup>'; } str+='</td><td class="editable" data-type="textarea">'+data.description12+'</td>' +'<td class="editable" data-type="textarea">'+data.description34+'</td>' +'<td class="editable" data-type="textarea">'+data.description56+'</td>' +'<td class="editable" data-type="textarea">'+data.description78+'</td>' +'<th><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></th></tr>'; $('table tbody').append(str); // Build copyright list buildCopyrightList(); // Enable X-Edtable on this new row $('.editable').editable({ unsavedclass: null, rows: 4 }); // Turn on tooltips again (because content is dynamic) $('[data-toggle="tooltip"]').tooltip(); }); // Sortable rows $('.table').sortable({ handle: 'span.glyphicon.glyphicon-move', containerSelector: 'table', itemPath: '> tbody', itemSelector: 'tr', placeholder: '<tr class="placeholder"><th><span class="glyphicon glyphicon-arrow-right"></span></th></tr>' }); // Build Copyright List buildCopyrightList(); } ); } // Checks whether the user wants to save a rubric with a name that already exists function nameExists() { var duplicates = false; $('#select-template option').each(function() { var optionName = $(this).text().trim(); if($('#rubric-name').val().trim()===optionName) { duplicates = true; } }); return duplicates; } //Enable disable program select function toggleProgramSelect(school) { if(school.find(':selected').data('school-id')<1) { $('#select-program option[data-program-id="0"]').prop('selected', true); $('#select-program').prop('disabled', true); } else { fetchPrograms(school); $('#select-program').prop('disabled', false); } } // -------------------------------------------------------------------------- // Events // -------------------------------------------------------------------------- // Toggle visibility for accordion panels $('.panel-heading').on('click', function() { if($(this).find('.glyphicon').hasClass('glyphicon-triangle-right')) { $(this).find('.glyphicon').removeClass('glyphicon-triangle-right'); $(this).find('.glyphicon').addClass('glyphicon-triangle-bottom'); } else if($(this).find('.glyphicon').hasClass('glyphicon-triangle-bottom')) { $(this).find('.glyphicon').removeClass('glyphicon-triangle-bottom'); $(this).find('.glyphicon').addClass('glyphicon-triangle-right'); } $(this).siblings('.panel-body').stop().slideToggle(); }); // When trying to change the template, ask the user to confirm and reset the // rubric if s/he does $('#select-template').on('change', function() { // If changing to custom template, reset if($('#select-template').find(':selected').data('template-id')=='0') { $('#rubric-container').hide(); $('#rubric-name').val(''); $('tbody').empty(); // Disable delete, update and print buttons $('#button-confirm-delete-rubric').prop('disabled', true); $('#button-confirm-update-rubric').prop('disabled', true); $('#button-print-rubric').prop('disabled', true); } // Otherwise, load the selected template else { loadTemplate(); //If user is admin, or the templates id matches user's, or the template // id's school matches user, allow editing var selected = $('#select-template').find(':selected'); var program = '{{ Auth::user()->program_id }}'; if( {{ Auth::user()->role }}==1 || ({{ Auth::user()->role }}==2 && selected.data('admin')!=1) || ({{ Auth::user()->role }}==3 && selected.data('template-program-id')== program && selected.data('admin')!=1 ) ) { $('#button-confirm-delete-rubric').prop('disabled', false); $('#button-confirm-update-rubric').prop('disabled', false); } else { // Disable update and edit $('#button-confirm-delete-rubric').prop('disabled', true); $('#button-confirm-update-rubric').prop('disabled', true); } // Enable print button $('#button-print-rubric').prop('disabled', false); } }); // When a school changes, update its programs. If all is selected, disable $('#select-school').on('change', function() { toggleProgramSelect($(this)); }); // When a learning outcome changes, update its criteria $('#select-outcome, input[name=criteria-filter]').on('change', function() { fetchCriteria($('#select-outcome')); }); // When the add button is clicked $('#button-add-criterion').on('click', function(e) { //Prevent page refresh e.preventDefault(); //Add new criterion addCriterion(); }); // When the create or update buttons are clicked (.save) $('.save').on('click', function(e) { //Prevent page refresh e.preventDefault(); // Empty field validation var emptyFields=false; $('td').each(function() { if ($(this).text() == "" || $(this).text() == "Empty") { emptyFields=true; } }); // If any fields are empty, display error if(emptyFields || $.trim($('#rubric-name').val())=='') { $('#js-error-row').show(); $('#js-error-row').find('#error-message').text('Error: Please fill all the fields. Make sure your rubric has a name.'); return; } else { $('#js-error-row').hide(); } // Check whether a rubric with the written name already exists if($(this).attr('id')=='button-create-rubric' && nameExists()) { $('#js-error-row').show(); $('#js-error-row').find('#error-message').text('Error: A template with that name already exists.'); return; } else { $('#js-error-row').hide(); } var criterionObject = new Object(); var criteriaArray = new Array(); // For each criterion in the rubric, get its value and put it into an array $('tbody tr').each(function( index ) { criterionObject.id = $(this).data('criterion-id'); criterionObject.outcome_id = $(this).data('assoc-outcome-id'); criterionObject.name = $(this).children('td:nth-child(2)').find('span').text(); criterionObject.description12 = $(this).children('td:nth-child(3)').text(); criterionObject.description34 = $(this).children('td:nth-child(4)').text(); criterionObject.description56 = $(this).children('td:nth-child(5)').text(); criterionObject.description78 = $(this).children('td:nth-child(6)').text(); criterionObject.copyright = $(this).data('criterion-copyright'); criterionObject.notes = $(this).data('criterion-notes'); // Clone the object and push it into the array var clone = jQuery.extend({}, criterionObject); criteriaArray.push(clone); //console.log(JSON.stringify(clone)); }); //console.log('school', $('#select-school').find(':selected').data('school-id') ); //console.log('program', $('#select-program').find(':selected').data('program-id') ); if($(this).attr('id')=='button-create-rubric') { // Create $.post ( "{{ URL::to('saveTemplate') }}", { name: $('#rubric-name').val(), contents: JSON.stringify(criteriaArray), school_id: $('#select-school').find(':selected').data('school-id'), program_id: $('#select-program').find(':selected').data('program-id'), expected_percentage: $('#expected_percentage').find(':selected').val(), expected_points: $('#expected_points').find(':selected').val(), is_visible: $('input[name=is_visible]:checked').val() }, function(data) { location.reload(true); } ); } else { console.log('school', $('#select-school').find(':selected').data('school-id') ); console.log('program', $('#select-program').find(':selected').data('program-id') ); // Update database $.post ( "{{ URL::to('updateTemplate') }}", { id: $('#select-template').find(':selected').data('template-id'), name: $('#rubric-name').val(), contents: JSON.stringify(criteriaArray), school_id: $('#select-school').find(':selected').data('school-id'), program_id: $('#select-program').find(':selected').data('program-id'), expected_percentage: $('#expected_percentage').find(':selected').val(), expected_points: $('#expected_points').find(':selected').val(), is_visible: $('input[name=is_visible]:checked').val() }, function(data) { location.reload(true); } ); } }); // When the confirm delete button is clicked $('#button-delete-rubric').on('click', function(e) { $('#modal-confirm-delete').modal('hide'); // Delete from database $.post ( "{{ URL::to('deleteTemplate') }}", { id: $('#select-template').find(':selected').data('template-id') }, function(data) { location.reload(); } ); }); // Remove a criterion and hide the table if it was the only one $('table').on('click', '.glyphicon-remove', function(e) { $(this).closest('tr').remove(); if(!$('tbody').children().length) { $('#rubric-container').hide(); } buildCopyrightList(); }); // When print button is clicked, redirect to print page $('#button-print-rubric').on('click', function(e) { e.preventDefault(); window.location = "printRubric/"+$('#select-template').find(':selected').data('template-id'); }); @stop