diff --git a/.gitignore b/.gitignore index 1451b1f2fc..b9a688073b 100644 --- a/.gitignore +++ b/.gitignore @@ -101,7 +101,6 @@ lms/static/certificates/css/ cms/static/css/ common/static/common/js/vendor/ common/static/common/css/vendor/ -common/static/common/media/ common/static/bundles webpack-stats.json diff --git a/common/static/common/templates/gradebook/_gradebook_modal_table.underscore b/common/static/common/templates/gradebook/_gradebook_modal_table.underscore deleted file mode 100644 index 1683463d86..0000000000 --- a/common/static/common/templates/gradebook/_gradebook_modal_table.underscore +++ /dev/null @@ -1,42 +0,0 @@ - \ No newline at end of file diff --git a/common/static/common/templates/gradebook/_gradebook_table.underscore b/common/static/common/templates/gradebook/_gradebook_table.underscore deleted file mode 100644 index 0031b761b8..0000000000 --- a/common/static/common/templates/gradebook/_gradebook_table.underscore +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - <% var sections = studentsData[0].section_breakdown; %> - <% _.each(sections, function(section, i){ %> - <% var tooltip = section.detail; %> - - <% //The next two if statements are going to parse the section details for tooltip %> - <% if (_.str.include(tooltip, '=')) { %> - <% tooltip = tooltip.substring(0, tooltip.indexOf('=')); %> - <% } %> - - <% if (_.str.include(tooltip, '-')) { %> - <% tooltip = tooltip.substring(0, tooltip.indexOf('-')); %> - <% } %> - - <% var category = (section.category || '').replace(/[\W_]+/g, ''); %> - <% var chapterName = (section.chapter_name || '').replace(/[\W_]+/g, ''); %> - <% - var moduleId = ''; - studentsData.every(function(student) { - moduleId = student.section_breakdown[i].module_id; - return _.contains(['', 'None'], moduleId); - }); - %> - - - <% }) %> - - - - - - <% _.each(studentsData, function(student){ %> - - - - <% _.each(student.section_breakdown, function(section){ %> - <% var category = (section.category || '').replace(/[\W_]+/g, ''); %> - <% var chapterName = (section.chapter_name || '').replace(/[\W_]+/g, ''); %> - - <% }) %> - - - - <% }) %> - -
<%- strLib.userHeading %> -
<%- section.label %>
- <% if (!(section.is_average || section.is_ag)) { %> - - <% } %> -
<%- strLib.total %>
<%- student.full_name || student.username %> - <%- (section.grade_description || '') %> - - <%- (student.percent * 100).toFixed(2) %>% -
- -
\ No newline at end of file diff --git a/common/static/common/templates/gradebook/_grading_policies.underscore b/common/static/common/templates/gradebook/_grading_policies.underscore deleted file mode 100644 index aac455ac08..0000000000 --- a/common/static/common/templates/gradebook/_grading_policies.underscore +++ /dev/null @@ -1,4 +0,0 @@ -<% _.each(gradingPolicies, function(policy){ %> - <% var value = policy.replace(/[\W_]+/g, ''); %> - -<% }) %> \ No newline at end of file diff --git a/common/static/css/vendor/fixedColumns.dataTables.min.css b/common/static/css/vendor/fixedColumns.dataTables.min.css deleted file mode 100644 index 71e801b53e..0000000000 --- a/common/static/css/vendor/fixedColumns.dataTables.min.css +++ /dev/null @@ -1 +0,0 @@ -table.DTFC_Cloned thead,table.DTFC_Cloned tfoot{background-color:white}div.DTFC_Blocker{background-color:white}div.DTFC_LeftWrapper table.dataTable,div.DTFC_RightWrapper table.dataTable{margin-bottom:0;z-index:2}div.DTFC_LeftWrapper table.dataTable.no-footer,div.DTFC_RightWrapper table.dataTable.no-footer{border-bottom:none} diff --git a/lms/djangoapps/instructor/views/api_urls.py b/lms/djangoapps/instructor/views/api_urls.py index fb9b7a208a..674c9419eb 100644 --- a/lms/djangoapps/instructor/views/api_urls.py +++ b/lms/djangoapps/instructor/views/api_urls.py @@ -4,7 +4,7 @@ Instructor API endpoint urls. from django.conf.urls import url -from lms.djangoapps.instructor.views import api, gradebook_api, writable_gradebook_api +from lms.djangoapps.instructor.views import api, gradebook_api urlpatterns = [ url(r'^students_update_enrollment$', api.students_update_enrollment, name='students_update_enrollment'), @@ -74,7 +74,6 @@ urlpatterns = [ # spoc gradebook url(r'^gradebook$', gradebook_api.spoc_gradebook, name='spoc_gradebook'), - url(r'^writable_gradebook$', writable_gradebook_api.writable_gradebook, name='writable_gradebook'), url(r'^gradebook/(?P[0-9]+)$', gradebook_api.spoc_gradebook, name='spoc_gradebook'), diff --git a/lms/djangoapps/instructor/views/writable_gradebook_api.py b/lms/djangoapps/instructor/views/writable_gradebook_api.py deleted file mode 100644 index 989da8fdb4..0000000000 --- a/lms/djangoapps/instructor/views/writable_gradebook_api.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -Grade book view for instructor and pagination work (for grade book) -which is currently use by ccx and instructor apps. -""" -from django.db import transaction -from django.http import HttpResponseNotFound -from django.views.decorators.cache import cache_control -from opaque_keys.edx.keys import CourseKey - -from edxmako.shortcuts import render_to_response -from lms.djangoapps.courseware.courses import get_course_with_access -from lms.djangoapps.grades.config.waffle import waffle_flags, WRITABLE_GRADEBOOK -from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory -from lms.djangoapps.instructor.views.api import require_level - - -@transaction.non_atomic_requests -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') -def writable_gradebook(request, course_id): - """ - Show the writable gradebook for this course: - - Only displayed to course staff - """ - course_key = CourseKey.from_string(course_id) - if not waffle_flags()[WRITABLE_GRADEBOOK].is_enabled(course_key): - return HttpResponseNotFound() - - course = get_course_with_access(request.user, 'load', course_key) - - course_grade = CourseGradeFactory().read(request.user, course) - courseware_summary = course_grade.chapter_grades.values() - course_sections = [] - - for chapter in courseware_summary: - chapter_name = chapter['display_name'] - for section in chapter['sections']: - if section.problem_scores and section.graded and chapter_name not in course_sections: - course_sections.append(chapter_name) - - return render_to_response('courseware/writable_gradebook.html', { - 'number_of_students': 2, - 'course': course, - 'course_id': course_key, - 'course_sections': course_sections, - # Checked above - 'staff_access': True, - 'ordered_grades': sorted(course.grade_cutoffs.items(), key=lambda i: i[1], reverse=True), - }) diff --git a/lms/static/js/jquery.writable_gradebook.js b/lms/static/js/jquery.writable_gradebook.js deleted file mode 100644 index 73b94a3ae0..0000000000 --- a/lms/static/js/jquery.writable_gradebook.js +++ /dev/null @@ -1,110 +0,0 @@ -var Gradebook = function($element, $gradeTableWrapper) { - "use strict"; - var $body = $('body'); - var $grades = $element.find('#gradebook-table-container'); - var $gradeTable = $gradeTableWrapper.find('#student-grades-table'); - var $search = $element.find('.student-search-field'); - var $leftShadow = $('
'); - var $rightShadow = $('
'); - var tableHeight = $gradeTable.height(); - var maxScroll = $gradeTable.width() - $grades.width(); - - var mouseOrigin; - var tableOrigin; - - var startDrag = function(e) { - mouseOrigin = e.pageX; - tableOrigin = $gradeTable.position().left; - $body.addClass('no-select'); - $body.bind('mousemove', onDragTable); - $body.bind('mouseup', stopDrag); - }; - - /** - * - Called when the user drags the gradetable - * - Calculates targetLeft, which is the desired position - * of the grade table relative to its leftmost position, using: - * - the new x position of the user's mouse pointer; - * - the gradebook's current x position, and; - * - the value of maxScroll (gradetable width - container width). - * - Updates the position and appearance of the gradetable. - */ - var onDragTable = function(e) { - var offset = e.pageX - mouseOrigin; - var targetLeft = clamp(tableOrigin + offset, maxScroll, 0); - updateHorizontalPosition(targetLeft); - setShadows(targetLeft); - }; - - var stopDrag = function() { - $body.removeClass('no-select'); - $body.unbind('mousemove', onDragTable); - $body.unbind('mouseup', stopDrag); - }; - - var setShadows = function(left) { - var padding = 30; - - var leftPercent = clamp(-left / padding, 0, 1); - $leftShadow.css('opacity', leftPercent); - - var rightPercent = clamp((maxScroll + left) / padding, 0, 1); - $rightShadow.css('opacity', rightPercent); - }; - - var clamp = function(val, min, max) { - if(val > max) { return max; } - if(val < min) { return min; } - return val; - }; - - /** - * - Called when the browser window is resized. - * - Recalculates maxScroll (gradetable width - container width). - * - Calculates targetLeft, which is the desired position - * of the grade table relative to its leftmost position, using: - * - the gradebook's current x position, and: - * - the new value of maxScroll - * - Updates the position and appearance of the gradetable. - */ - var onResizeTable = function() { - maxScroll = $gradeTable.width() - $grades.width(); - var targetLeft = clamp($gradeTable.position().left, maxScroll, 0); - updateHorizontalPosition(targetLeft); - setShadows(targetLeft); - }; - - /** - * - Called on table drag and on window (table) resize. - * - Takes a integer value for the desired (pixel) offset from the left - * (zero/origin) position of the grade table. - * - Uses that value to position the table relative to its leftmost - * possible position within its container. - * - * @param {Number} left - The desired pixel offset from left of the - * desired position. If the value is 0, the gradebook should be moved - * all the way to the left side relative to its parent container. - */ - var updateHorizontalPosition = function(left) { - $grades.scrollLeft(left); - }; - - var highlightRow = function() { - $element.find('.highlight').removeClass('highlight'); - - var index = $(this).index(); - $gradeTable.find('tr').eq(index + 1).addClass('highlight'); - }; - - var filter = function() { - var term = $(this).val(); - if(term.length > 0) { - $gradeTable.find('tbody tr').hide(); - } else { - $gradeTable.find('tbody tr').show(); - } - }; -}; - - - diff --git a/lms/static/js/writable_gradebook.js b/lms/static/js/writable_gradebook.js deleted file mode 100644 index 66595a21ce..0000000000 --- a/lms/static/js/writable_gradebook.js +++ /dev/null @@ -1,590 +0,0 @@ -function _templateLoader(templateName, staticPath, callback, errorCallback) { - var templateURL = staticPath + '/common/templates/gradebook/' + templateName + '.underscore'; - - $.ajax({ - url: templateURL, - method: 'GET', - dataType: 'html', - success: function (data) { - callback(data); - }, - error: function (errorMessage) { - console.log(errorMessage); - errorCallback('Error has occurred while rendering table.'); - } - }); -} - -function courseXblockUpdater(courseID, dataToSend, visibilityData, callback, errorCallback) { - var cleanData = _.map(dataToSend, function (data) { - return { - user_id: data.user_id, - usage_id: data.block_id, - grade: { - earned_all_override: data.grade || 0, - possible_all_override: data.max_grade || 0, - earned_graded_override: data.grade || 0, - possible_graded_override: data.max_grade || 0 - } - }; - }); - - var postUrl = '/api/grades/v1/gradebook/' + courseID + '/bulk-update'; - $('') - $.ajax({ - url: postUrl, - method: 'POST', - contentType: 'application/json; charset=utf-8', - dataType: 'json', - data: JSON.stringify(cleanData), - success: function (data) { - callback(data); - }, - error: function (errorMessage) { - console.log(errorMessage); - errorCallback('Error has occurred while updating grades.'); - } - }); -} - -function getEdxUserInfoAsObject() { - var edxCookie = $.cookie('prod-edx-user-info') || $.cookie('stage-edx-user-info') || $.cookie('edx-user-info'); - return JSON.parse(edxCookie.replace(/\\054/g, ',').replace(/^"(.*)"$/, '$1').replace(/\\"/g, '"')); - -} - -$(document).ready(function() { - var dataTable, - $gradebookWrapper = $('.gradebook-content'), - $courseSectionFilter = $gradebookWrapper.find('#course-sections'), - $errorMessageContainer = $gradebookWrapper.find('#error-message'), - $filtersWrapper = $gradebookWrapper.find('#filters-container'), - $gradebookNotification = $gradebookWrapper.find('#gradebook-notification'), - $gradesTableWrapper = $gradebookWrapper.find('#gradebook-table-container'), - $gradingPolicyFilter = $filtersWrapper.find('#grading-policy'), - adjustedGradesData = {}, - courseID = $gradebookWrapper.attr('data-course-id'), - edxUserInfo = getEdxUserInfoAsObject(), - gradeBookData = [], - gradeOverrideObject = {}, - isFetchingComplete = false, - isFetchingSuccessful = true, - isManualGrading = false, - modalDataTable, - module_list = {'users': {}}, - renderAllGradebook = true, - sectionBlockId = '', - staticPath = $gradebookWrapper.attr('data-static-path'), - userAdjustedGrades = {}, - userAutoGrades = {}, - createMainDataTable = function(studentsDataLength) { - const $gradebookErrorMessageContainer = $gradebookWrapper.find('#gradebook-table-empty-message'); - const $studentGradesTable = $gradesTableWrapper.find('#student-grades-table'); - const options = { - fixedColumns: true, - language: { - zeroRecords: '' - }, - paging: studentsDataLength > 10, - scrollX: true - }; - dataTable = initializeDataTable($studentGradesTable, options, studentsDataLength); - setUpDataTableSearch($studentGradesTable, $gradebookErrorMessageContainer); - $studentGradesTable.on('draw.dt', displayGrades); - }, - createModalTable = function(studentsDataLength) { - const $gradeOverrideModalTable = $gradesTableWrapper.find('#grade-override-modal-table'); - const $modalErrorMessageContainer = $gradesTableWrapper.find('#modal-table-empty-message'); - const options = { - columnDefs: [{ - orderable: false, - targets: 1 - }], - language: { - zeroRecords: '' - }, - paging: studentsDataLength > 10 - }; - modalDataTable = initializeDataTable($gradeOverrideModalTable, options, studentsDataLength); - setUpDataTableSearch($gradeOverrideModalTable, $modalErrorMessageContainer); - }, - destroyDataTable = function($table) { - if ($.fn.DataTable.isDataTable($table)) { - $table.DataTable().destroy(); - $table.unbind(); - } - }, - displayError = function(message) { - $errorMessageContainer.text(message); - $errorMessageContainer.toggleClass('hidden'); - }, - displayAbsoluteGrade = function($cell) { - var $input = $cell.find('input'), - title = $cell.attr('title'); - - if (title !== 'Total' && title !== 'Current grade' && $input.length) { - $input.prop('disabled', false); - $input.val($cell.attr('data-score-earned')); - return; - } - - $cell.text($cell.attr('data-score-absolute')); - }, - displayGrades = function() { - var display = $('#table-data-view-percent').is(':checked') ? displayPercentGrade : displayAbsoluteGrade; - - $('#save-grade-field').hide(); - - $('.data-score-container-class').each(function() { - display($(this)); - }); - }, - displayPercentGrade = function($cell) { - var $input = $cell.find('input'), - title = $cell.attr('title'); - - if (title !== 'Total' && $input.length){ - $input.prop('disabled', true); - $input.val($cell.attr('data-score-percent')); - return; - } - - $cell.text($cell.attr('data-score-percent')); - }, - fetchGrades = function(get_url) { - $.ajax({ - type: 'GET', - url: get_url, - contentType: 'application/json; charset=utf-8', - success: onPageFetched, - failure: function(errMsg) { - isFetchingComplete = true; - isFetchingSuccessful = false; - console.log(errMsg); - displayError('Error has occurred while fetching grades.'); - } - }); - }, - filterGradebook = function() { - var gradingPolicy = $gradingPolicyFilter.val(), - courseSection = $courseSectionFilter.val(), - filterClasses = '.user-data'; - if (gradingPolicy && courseSection) - filterClasses += ',.' + gradingPolicy + '.' + courseSection; - else if (gradingPolicy || courseSection) - filterClasses += ',.' + (gradingPolicy || courseSection); - else - filterClasses = ''; - - dataTable.columns(':not(' + filterClasses + ')').visible(false, false); - dataTable.columns(filterClasses).visible(true, false); - dataTable.columns.adjust().draw(false); - }, - initializeDataTable = function($table, options, studentsDataLength) { - $table.on('length.dt', function(_, _, tableLength) { - // If the provided data is longer than the table length selected - // display the paggination buttons, otherwise hide them. - $(this).parents('.dataTables_wrapper') - .find('.dataTables_paginate') - .toggleClass('hidden', studentsDataLength <= tableLength); - }); - - return $table.DataTable(options); - }, - onFinishedFetchingGrades = function(response) { - isFetchingComplete = true; - isFetchingSuccessful = true; - if (renderAllGradebook) - $filtersWrapper.toggleClass('hidden'); - $gradebookNotification.toggleClass('hidden'); - gradeBookData = gradeBookData.concat(response.results); - gradeBookData = gradeBookData.map(data => { - data.section_breakdown = data.section_breakdown.filter(b => b.chapter_name !== 'holding section') - return data; - }); - renderGradebook(gradeBookData); - }, - onPageFetched = function(response) { - if (response.next) { - gradeBookData = gradeBookData.concat(response.results); - return fetchGrades(response.next); - } - onFinishedFetchingGrades(response); - }, - renderGradingPolicyFilters = function(studentsData) { - _templateLoader('_grading_policies', staticPath, function(template) { - var $tpl = edx.HtmlUtils.template(template)({ - gradingPolicies: Object.keys(studentsData[0].aggregates) - }).toString(); - $('#grading-policy').append($tpl); - $('#grading-policy').append(edx.HtmlUtils.ensureHtml(displayError).toString()); - }, displayError); - }, - renderGradebook = function(studentsData) { - if (renderAllGradebook) - renderGradingPolicyFilters(studentsData); - renderGradebookTable(studentsData); - }, - renderGradebookTable = function(studentsData) { - _templateLoader('_gradebook_table', staticPath, function(template) { - var $tpl = edx.HtmlUtils.template(template)({ - studentsData: studentsData, - strLib: { - userHeading: gettext('Username'), - total: gettext('Total') - } - }).toString(); - $gradesTableWrapper.append($tpl); - createMainDataTable(studentsData.length); - ShowBlockIdEventBinder(); - filterGradebook(); - }, displayError); - renderAllGradebook = true; - }, - startFetchingGrades = function() { - $gradebookNotification.toggleClass('hidden'); - fetchGrades('api/grades/v1/gradebook/' + courseID + '/'); - }; - - $gradingPolicyFilter.change(function() { filterGradebook(); }); - $courseSectionFilter.change(function() { filterGradebook(); }); - - function renderModalTemplateData(template) { - var blockID = $(gradeOverrideObject).attr('data-block-id'); - var studentsData = []; - var tpl = edx.HtmlUtils.template(template); - - gradeBookData.map(function(userData){ - var gradeData = userData.section_breakdown.filter(function(sectionData){ - return (sectionData.module_id === blockID); - }); - - if (!_.isEmpty(gradeData)) { - var auto_grade = parseFloat(gradeData[0].auto_grade); - var score_earned = parseFloat(gradeData[0].score_earned); - var score_possible = parseFloat(gradeData[0].score_possible); - var username = userData.username; - - if (! (isNaN(score_earned) || isNaN(score_possible))) { - if (! isNaN(auto_grade)) { - userAutoGrades[username] = auto_grade + '/' + score_possible; - userAdjustedGrades[username] = score_earned + '/' + score_possible; - } - else - userAutoGrades[username] = score_earned + '/' + score_possible; - - studentsData.push(userData); - } - } - }); - - edx.HtmlUtils.setHtml( - $('#grade-override-modal'), - tpl({ - studentsData: studentsData, - strLib: { - heading: gettext("The Assignment name is:"), - publishGrades: gettext("Publish grades"), - noMatch: gettext("No matching records found"), - studentNameHeading: gettext("Student Name"), - save: gettext("Save"), - cancel: gettext("Cancel") - } - }) - ); - createModalTable(studentsData.length); - fillModalTemplate(); - } - - function fillModalTemplate() { - var $modal = $('.grade-override-modal'); - var $adjustedGradeHeader = $modal.find('#adjusted-grade-header'); - var $manualGradeVisibilityWrapper = $modal.find('#manual-grade-visibility'); - var $saveGradeOverrideButton = $modal.find('.grade-override-modal-save'); - var $tableWrapper = $modal.find('.grade-override-table-wrapper'); - var assignmentName = $(gradeOverrideObject).attr('data-assignment-name'); - var blockID = $(gradeOverrideObject).attr('data-block-id'); - var dataPublished = $(gradeOverrideObject).attr('data-published') || false; - sectionBlockId = $(gradeOverrideObject).attr('data-section-block-id'); - gradesPublished = JSON.parse(dataPublished); - isManualGrading = JSON.parse($(gradeOverrideObject).attr('data-manual-grading')); - $modal.find('.assignment-name-placeholder').text(assignmentName); - $modal.find('.block-id-placeholder').text(blockID); - $modal.find('.grade-override-info-container').hide(); - $adjustedGradeHeader.text(isManualGrading ? 'Manual grade' : 'Grade'); - - $manualGradeVisibilityWrapper.toggle(isManualGrading); - $saveGradeOverrideButton.attr('data-manual-grading', isManualGrading); - $manualGradeVisibilityWrapper.attr('data-visibility', gradesPublished); - $('input[name=grades-published]').prop('checked', gradesPublished); - - $tableWrapper.attr('data-manual-grading', isManualGrading); - $tableWrapper.show(); - $modal.find('#modal-table-empty-message').hide(); - $saveGradeOverrideButton.show().prop('disabled', true); - modalDataTable.$('tr').each(function(){ - $(this).attr('data-block-id', blockID); - var $adjustedGradePlaceholder = $(this).find('td.user-adjusted-grade'); - var username = $adjustedGradePlaceholder.attr('data-username'); - - if (username in userAutoGrades) { - var autoEarnedGrade = userAutoGrades[username].split('/')[0], - autoPossibleGrade = userAutoGrades[username].split('/')[1]; - $adjustedGradePlaceholder.attr('data-score-earned', autoEarnedGrade); - $adjustedGradePlaceholder.attr('data-score-possible', autoPossibleGrade); - - if (username in userAdjustedGrades) { - var adjustedGrade = userAdjustedGrades[username].split('/')[0]; - $adjustedGradePlaceholder.attr('data-score-earned', adjustedGrade); - $adjustedGradePlaceholder.attr('data-sort', adjustedGrade); - $adjustedGradePlaceholder.addClass('has-adjusted-score'); - } - else if (isManualGrading) { - $adjustedGradePlaceholder.attr('data-sort', autoEarnedGrade); - } - else { - $adjustedGradePlaceholder.attr('data-sort', autoEarnedGrade); - } - $adjustedGradePlaceholder.find('input').val($adjustedGradePlaceholder.attr('data-score-earned')); - $adjustedGradePlaceholder.find('span').text($adjustedGradePlaceholder.attr('data-score-possible')); - } - else - $(this).hide(); - }); - $modal.show(); - } - - /* Autograde override modal window manipulation */ - $(document).on('click', '.grade-override', function() { - gradeOverrideObject = this; - _templateLoader('_gradebook_modal_table', staticPath, renderModalTemplateData, displayError); - }); - - function setUpDataTableSearch($table, $tableEmptyMessage) { - $table.on('search.dt', function () { - if (!$table.DataTable().page.info().recordsDisplay) { - $tableEmptyMessage.show(); - } - else { - $tableEmptyMessage.hide(); - } - }); - } - - $(document).on('click', '.grade-override-modal-close', function(){ - gradebookOverrideModalReset(); - }); - - function gradebookOverrideModalReset() { - var $modal = $('.grade-override-modal'); - adjustedGradesData = {}; - userAdjustedGrades = {}; - userAutoGrades = {}; - - $modal.hide(); - $modal.find('.grade-override-table-wrapper').find('tr').show(); - $modal.find('#manual-grade-visibility').hide(); - $modal.find('.grade-override-message').removeClass('error').empty().hide(); - $modal.find('table').find('input').removeClass('score-visited').removeClass('error'); - $modal.find('table').find('textarea').removeClass('score-visited').removeClass('error'); - $modal.find('#modal-table-empty-message').hide(); - destroyDataTable($('#grade-override-modal-table')); - } - - /* Block ID modal window manipulation */ - function ShowBlockIdEventBinder() { - $('.eye-icon.block-id-info').on('click', function(e){ - e.stopPropagation(); - $('.block-id-modal').find('.block-id-placeholder').empty(); - $('.block-id-modal').find('.block-id-placeholder').text($(this).data('block-id')); - $('.block-id-modal').find('.display-name-placeholder').text($(this).data('display-name')); - $('.block-id-modal').show(); - }); - } - - function HasUserMadeChanges() { - var areScoresModified = $('.score-visited').length > 0; - var originalGradeVisibility = $('#manual-grade-visibility').attr('data-visibility'); - var currentGradeVisibility = JSON.stringify($('input[name=grades-published]').prop('checked')); - - return areScoresModified || originalGradeVisibility !== currentGradeVisibility; - } - - function ToggleSaveButton(shouldDisable) { - var $modalSaveButton = $('.grade-override-modal').find('.grade-override-modal-save'); - $modalSaveButton.prop('disabled', shouldDisable); - } - - $(document).on('keyup focus', '.user-adjusted-grade input', function(){ - var $cell = $(this).parents('td'), - previousGrade = $cell.attr('data-score-earned'); - adjustedGrade = $(this).val(); - - $cell.attr('data-sort', adjustedGrade); - - if (previousGrade != adjustedGrade) - $(this).addClass('score-visited'); - else - $(this).removeClass('score-visited'); - - ToggleSaveButton(!HasUserMadeChanges()); - - modalDataTable.rows().invalidate(); - }); - - $(document).on('change', 'input[name=grades-published]', function() { - ToggleSaveButton(!HasUserMadeChanges()); - }); - - function collectOverrideGradebookData() { - var $modal = $('.grade-override-modal'); - var $table = $modal.find('table').dataTable(); - $table.$('tr').each(function(){ - var $row = $(this); - var $gradeCell = $row.find('.user-adjusted-grade'); - var $grade = $gradeCell.find('input'); - var username = $gradeCell.attr('data-username'); - var grade; - - if ($grade.hasClass('score-visited')) - adjustedGradesData[username] = { - 'block_id' : $row.attr('data-block-id'), - 'max_grade' : $gradeCell.attr('data-score-possible'), - 'state' : { 'username': edxUserInfo.username}, - 'user_id' : $row.attr('data-user-id') - }; - - if (username in adjustedGradesData) { - grade = $grade.val().trim(); - - adjustedGradesData[username].grade = grade; - adjustedGradesData[username].remove_adjusted_grade = true; - adjustedGradesData[username].section_block_id = sectionBlockId; - } - }); - } - - function setInfoMessage(messageText){ - var $messageField = $('.grade-override-modal').find('.grade-override-info-container'); - if(messageText) { - $messageField.text(messageText); - $messageField.show(); - } - else { - $messageField.empty(); - $messageField.hide(); - } - } - - $(document).on('click', '.grade-override-modal-save', function() { - var visibilityData = {}; - if (isManualGrading) { - visibilityData = { - 'block_id': $('.block-id-placeholder').html(), - 'visibility': JSON.stringify($('input[name=grades-published]').prop('checked')), - } - } - collectOverrideGradebookData(); - if (Object.keys(adjustedGradesData).length === 0 && !isManualGrading) - return; - var validStatus = ValidateAdjustedGradesData(); - if (validStatus) { - setInfoMessage(gettext('Update in progress, please wait...')); - courseXblockUpdater( - courseID, - adjustedGradesData, - visibilityData, - function(data){ - gradebookOverrideModalReset(); - setInfoMessage(); - renderAllGradebook = false; - gradeBookData = []; - $gradesTableWrapper.empty(); - startFetchingGrades(); - }, function(data){ - console.log(data); - } - ); - } - }); - - function ValidateAdjustedGradesData() { - var isValid = true; - var $table = $('.grade-override-modal').find('table'); - var $messageField = $('.grade-override-modal').find('.grade-override-message'); - $messageField.empty(); - _.each(adjustedGradesData, function(data, username){ - adjustedGradesData[username].errors = []; - var userAdjustedGradeSelector = '*[data-username="' + username + '"].user-adjusted-grade'; - var $adjustedGradePlaceholder = $table.find(userAdjustedGradeSelector).find('input'); - // Is it a valid number - if (isNaN(data.grade)) { - isValid = false; - $adjustedGradePlaceholder.addClass('error'); - adjustedGradesData[username].errors.push('Adjusted grade must be an integer number'); - } - - // Is it within range - var floatGrade = parseFloat(data.grade); - var errorMessage; - if (floatGrade < 0 || floatGrade > parseFloat(data.max_grade)) { - errorMessage = 'Adjusted grade must be within range [0 - ' + data.max_grade + ']'; - isValid = false; - $adjustedGradePlaceholder.addClass('error'); - adjustedGradesData[username].errors.push(errorMessage); - } - - for (var i = 0; i < adjustedGradesData[username].errors.length; i++) { - $separator = $('
'); - $errorMessage = edx.HtmlUtils.joinHtml('Error for user ', username, ': ', adjustedGradesData[username].errors[i]).toString(); - $messageField.append($errorMessage); - $messageField.append($separator); - } - - if (adjustedGradesData[username].errors.length === 0) { - $adjustedGradePlaceholder.removeClass('error'); - delete adjustedGradesData[username].errors; - } - }); - - if (! isValid) { - $messageField.addClass('error'); - $messageField.show(); - } - - return isValid; - } - - $(document).on('change', '#table-data-view-percent', displayGrades); - - $(document).on('change', '#table-data-view-absolute', displayGrades); - - $('.data-score-container-class').each(function(){ - var title = $(this).attr('title'); - if (title !== 'Total' && title !== 'Current grade') - if ($(this).find('input').length) - $(this).find('input').prop('disabled', false); - else - $(this).text($(this).attr('data-score-absolute')); - }); - - $(document).on('change', '#save-grade-field textarea', function(){ - var editor = $('#save-grade-field'), - studentID = editor.attr('data-student-id'), - blockID = editor.attr('data-block-id'), - module_key = studentID + blockID; - - if (!module_list.users[module_key]) - module_list.users[module_key] = { - 'user_id': studentID, - 'grade': parseFloat(editor.attr('data-new-score')).toFixed(2), - 'max_grade': parseFloat(editor.attr('data-score-possible')).toFixed(2), - 'course_id': courseID, - 'block_id': blockID, - 'state': {} - }; - }); - - if ($gradebookWrapper.attr('data-number-of-students') > 0) - startFetchingGrades(); -}); \ No newline at end of file diff --git a/lms/static/sass/_build-course.scss b/lms/static/sass/_build-course.scss index cc1d2421d8..641198aa56 100644 --- a/lms/static/sass/_build-course.scss +++ b/lms/static/sass/_build-course.scss @@ -56,7 +56,6 @@ @import "course/gradebook"; @import "course/instructor/instructor_2"; @import "course/instructor/email"; -@import "course/instructor/writable_gradebook"; @import "xmodule/descriptors/css/module-styles.scss"; // course - ccx_coach diff --git a/lms/static/sass/course/instructor/_writable_gradebook.scss b/lms/static/sass/course/instructor/_writable_gradebook.scss deleted file mode 100644 index a95130af61..0000000000 --- a/lms/static/sass/course/instructor/_writable_gradebook.scss +++ /dev/null @@ -1,109 +0,0 @@ -@mixin table-filter-input { - border: 1px $gray solid; - background-color: $white; - border-radius: 4px; -} - -.gradebook-content { - - .dataTables_filter { - input { - @include table-filter-input; - } - } - - .gradebook-filter { - select { - @include table-filter-input; - } - } - - .view-container { - padding-bottom: 30px; - .filter-title { - margin-right: 5px; - } - input { - margin: 0px 2px; - } - } - - .gradebook-filter { - margin: 10px 0px; - } - - - .dataTables_wrapper { - #student-grades-table{ - margin:0; - } - .dataTables_info { - float: none; - width: 100%; - text-align: center; - } - } - .grade-override-modal { - left: 0px; - top: 50%; - background: $white; - border: 1px $gray solid; - width: 100%; - .modal-content { - background-color: $white; - p{ - padding: 5px; - } - .block-id-placeholder { - font-size: $small-font-size; - } - .grade-override-message { - padding: 5px; - margin: 0px 5px; - background-color: $uxpl-gray-background; - color: $error-color; - } - .user-adjusted-grade input { - max-width: 50px; - height: 18px; - padding: 5px 2px; - } - .user-grade-comment textarea { - max-width: 150px; - } - .grade-override-menu-buttons { - padding: 10px; - } - .grade-override-info-container{ - margin: 10px; - font-size: $small-font-size; - } - } - } - - - @media (min-width: $bp-screen-md) { - .view-container { - .report-download-link { - float: right; - } - } - .grade-override-modal { - left: 22px; - top: 40%; - } - } - - @media (min-width: $bp-screen-xl) { - .view-container { - .report-download-link { - float: right; - } - } - .grade-override-modal { - left: 10%; - top: 30%; - max-width: 1100px; - } - } -} \ No newline at end of file diff --git a/lms/templates/courseware/writable_gradebook.html b/lms/templates/courseware/writable_gradebook.html deleted file mode 100644 index 5962d1c3e0..0000000000 --- a/lms/templates/courseware/writable_gradebook.html +++ /dev/null @@ -1,92 +0,0 @@ -<%page expression_filter="h"/> -<%inherit file="/main.html" /> -<%namespace name='static' file='/static_content.html'/> -<%! -import re -from django.utils.translation import ugettext as _ -from django.core.urlresolvers import reverse -%> - -<%block name="js_extra"> - - - - - - - - - -<%block name="headextra"> - - - <%static:css group='style-course-vendor'/> - <%static:css group='style-course'/> - - -<%include file="/courseware/course_navigation.html" args="active_page=''" /> - -<%def name="get_page_url(page_size)"> - ${page_url}?offset=${page['offset']}&pagesize=${page_size} - - -<%def name="format_class(name)">${re.sub(r'[^a-zA-Z0-9]', '', name)} - -
-
-
-

${_("Gradebook")}

- - - - %if number_of_students > 0: - - - - -
- ${_("No matching records found")} -
-
-
- %else: - ${_("There are no students enrolled in this course.")} - %endif -
-
-
\ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 49b2a7b1f5..1aded5cca0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2925,31 +2925,6 @@ "whatwg-url": "6.5.0" } }, - "datatables": { - "version": "1.10.18", - "resolved": "https://registry.npmjs.org/datatables/-/datatables-1.10.18.tgz", - "integrity": "sha512-ntatMgS9NN6UMpwbmO+QkYJuKlVeMA2Mi0Gu/QxyIh+dW7ZjLSDhPT2tWlzjpIWEkDYgieDzS9Nu7bdQCW0sbQ==", - "requires": { - "jquery": "2.2.4" - } - }, - "datatables.net": { - "version": "1.10.19", - "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.19.tgz", - "integrity": "sha512-+ljXcI6Pj3PTGy5pesp3E5Dr3x3AV45EZe0o1r0gKENN2gafBKXodVnk2ypKwl2tTmivjxbkiqoWnipTefyBTA==", - "requires": { - "jquery": "2.2.4" - } - }, - "datatables.net-fixedcolumns": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/datatables.net-fixedcolumns/-/datatables.net-fixedcolumns-3.2.6.tgz", - "integrity": "sha512-PtEs2tllcHRVZj7fwmAQBWGJ5URRQZpDG2pJsh5jusvnRje3w1+KueMZm60iCtfOkIlUn+/j2+MghxLx/8yfKQ==", - "requires": { - "datatables.net": "1.10.19", - "jquery": "2.2.4" - } - }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", diff --git a/package.json b/package.json index 95402ac4e3..36636c41f6 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,6 @@ "hls.js": "0.9.0", "imports-loader": "0.7.1", "jquery": "2.2.4", - "datatables": "1.10.18", - "datatables.net-fixedcolumns": "3.2.6", "jquery-migrate": "1.4.1", "jquery.scrollto": "2.1.2", "js-cookie": "2.2.0", diff --git a/pavelib/assets.py b/pavelib/assets.py index 662d25558e..490966e60b 100644 --- a/pavelib/assets.py +++ b/pavelib/assets.py @@ -54,9 +54,6 @@ NPM_INSTALLED_LIBRARIES = [ 'backbone.paginator/lib/backbone.paginator.js', 'backbone/backbone.js', 'bootstrap/dist/js/bootstrap.bundle.js', - 'datatables/media', - 'datatables.net/js/jquery.dataTables.js', - 'datatables.net-fixedcolumns/js/dataTables.fixedColumns.min.js', 'hls.js/dist/hls.js', 'jquery-migrate/dist/jquery-migrate.js', 'jquery.scrollto/jquery.scrollTo.js', @@ -82,8 +79,6 @@ NPM_INSTALLED_DEVELOPER_LIBRARIES = [ NPM_JS_VENDOR_DIRECTORY = path('common/static/common/js/vendor') NPM_CSS_VENDOR_DIRECTORY = path("common/static/common/css/vendor") NPM_CSS_DIRECTORY = path("common/static/common/css") -NPM_MEDIA_DIRECTORY = path("common/static/common/media") -NPM_MEDIA_VENDOR_DIRECTORY = path("common/static/common/media/vendor") # system specific lookup path additions, add sass dirs if one system depends on the sass files for other systems SASS_LOOKUP_DEPENDENCIES = { @@ -606,8 +601,6 @@ def process_npm_assets(): if library.endswith('.css') or library.endswith('.css.map'): vendor_dir = NPM_CSS_VENDOR_DIRECTORY - elif library.endswith('/media'): - vendor_dir = NPM_MEDIA_VENDOR_DIRECTORY else: vendor_dir = NPM_JS_VENDOR_DIRECTORY if os.path.exists(library_path): @@ -638,8 +631,6 @@ def process_npm_assets(): NPM_JS_VENDOR_DIRECTORY.mkdir_p() NPM_CSS_DIRECTORY.mkdir_p() NPM_CSS_VENDOR_DIRECTORY.mkdir_p() - NPM_MEDIA_DIRECTORY.mkdir_p() - NPM_MEDIA_VENDOR_DIRECTORY.mkdir_p() # Copy each file to the vendor directory, overwriting any existing file. print("Copying vendor files into static directory")