diff --git a/Gemfile b/Gemfile index c3256083..2077e5ce 100644 --- a/Gemfile +++ b/Gemfile @@ -26,10 +26,6 @@ gem 'sprockets', '~>3.7' gem 'coffee-rails' gem 'coffee-rails-source-maps' gem 'uglifier' -gem 'jquery-rails' # needed for general jQuery stuff -gem 'jquery-ui-rails' # needed specifically for drag-and-drop ability -gem 'jquery-tablesorter' # needed to allow re-sortable tables -gem 'cocoon' # used for dynamically generating nested forms gem 'rubyzip' # used for reading submitted zip files @@ -38,9 +34,7 @@ gem 'bootstrap-sass', '>= 3.4.1' gem 'sassc-rails' gem 'bootstrap-sass-extras' gem 'bootstrap3-datetimepicker-rails' # for the datetime widget -gem 'bootstrap-toggle-rails' # for toggle buttons instead of checkboxes -gem 'momentjs-rails', '>= 2.9.0' # needed for human-friendly textual dates gem 'font-awesome-rails' gem 'addressable' diff --git a/Gemfile.lock b/Gemfile.lock index 64ffacf9..b5cf134f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -92,7 +92,6 @@ GEM sassc (>= 2.0.0) bootstrap-sass-extras (0.1.0) rails (>= 3.1.0) - bootstrap-toggle-rails (2.2.1.0) bootstrap3-datetimepicker-rails (4.17.47) momentjs-rails (>= 2.8.1) builder (3.2.4) @@ -113,7 +112,6 @@ GEM json childprocess (4.1.0) chronic (0.10.2) - cocoon (1.2.15) coderay (1.1.3) coffee-rails (5.0.0) coffee-script (>= 2.2.0) @@ -164,14 +162,6 @@ GEM headless (2.3.1) i18n (1.10.0) concurrent-ruby (~> 1.0) - jquery-rails (4.4.0) - rails-dom-testing (>= 1, < 3) - railties (>= 4.2.0) - thor (>= 0.14, < 2.0) - jquery-tablesorter (1.27.2) - railties (>= 3.2) - jquery-ui-rails (6.0.1) - railties (>= 3.2.16) json (2.6.1) kramdown (2.4.0) rexml @@ -179,7 +169,7 @@ GEM kramdown (~> 2.0) launchy (2.5.0) addressable (~> 2.7) - libv8 (3.16.14.19) + libv8 (3.16.14.19-x86_64-linux) listen (3.7.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) @@ -192,7 +182,6 @@ GEM matrix (0.4.2) method_source (1.0.0) mini_mime (1.1.2) - mini_portile2 (2.8.0) minitest (5.15.0) minitest-reporters (1.5.0) ansi @@ -221,8 +210,7 @@ GEM net-protocol timeout nio4r (2.5.8) - nokogiri (1.13.5) - mini_portile2 (~> 2.8.0) + nokogiri (1.13.5-x86_64-linux) racc (~> 1.4) orm_adapter (0.5.0) passenger (6.0.13) @@ -358,7 +346,7 @@ GEM rubyzip (>= 1.0.0) PLATFORMS - ruby + x86_64-linux DEPENDENCIES activerecord-import @@ -370,12 +358,10 @@ DEPENDENCIES bootsnap (>= 1.1.0) bootstrap-sass (>= 3.4.1) bootstrap-sass-extras - bootstrap-toggle-rails bootstrap3-datetimepicker-rails bundler-audit capybara capybara-webkit - cocoon coffee-rails coffee-rails-source-maps daemons @@ -389,15 +375,11 @@ DEPENDENCIES font-awesome-rails headless i18n - jquery-rails - jquery-tablesorter - jquery-ui-rails kramdown kramdown-parser-gfm launchy listen minitest-reporters - momentjs-rails (>= 2.9.0) net-http passenger (>= 5.0.25) pg diff --git a/app/assets/javascripts/0startup.js.coffee b/app/assets/javascripts/0startup.js.coffee deleted file mode 100644 index 1e5e5096..00000000 --- a/app/assets/javascripts/0startup.js.coffee +++ /dev/null @@ -1,6 +0,0 @@ - -window.run_on_page = (name, func) -> - $(() -> - if name == window.current_page_name - func() - ) diff --git a/app/assets/javascripts/assignments.js b/app/assets/javascripts/assignments.js deleted file mode 100644 index 044ad413..00000000 --- a/app/assets/javascripts/assignments.js +++ /dev/null @@ -1,306 +0,0 @@ -(function() { - function renderComments(lineComments) { - $(".file-pane").each(function(index) { - var theseComments = lineComments[index] || {}; - if (theseComments["noCommentsFor"]) return; - // Standard text-files get line comments - $(this).find(".CodeMirror").each(function(_, cm) { - renderLineComments(cm.CodeMirror, theseComments); - }); - // Nonstandard files (jars, overly-large files) get page comments - $(this).find(".pageContainer").each(function(pageNum, pageContainer) { - renderPageComments(pageNum + 1, pageContainer, theseComments); - }); - // Pdfs get page and region comments - $(this).find("div[id^='pdf_']").each(function(_, pdfDiv) { - var pageRendered = []; - $(pdfDiv).pdfViewer({ - pageContainerReady: function(_, details) { - renderPageComments(details.pageNum, details.pageContainer, theseComments); - }, - pageReady: function(_, details) { - if (pageRendered[details.pageNum]) return; - pageRendered[details.pageNum] = true; - renderRegionComments(details.pageNum, details.container.regionComments, theseComments); - } - }); - }); - }); - } - window.renderComments = renderComments; - function renderLineComments(cm, theseComments) { - cm.operation(function() { - Object.keys(theseComments).forEach(function(gradeId, _) { - var commentsByGrade = theseComments[gradeId] || {}; - var type = commentsByGrade.type; - Object.keys(commentsByGrade).forEach(function(line, _) { - if (line === "type") return; - var commentsOnLine = commentsByGrade[line] || {}; - commentsOnLine.forEach(function(comment, _) { - renderLineComment(cm, gradeId, type, line, comment); - }); - }); - }); - }); - } - function renderPageComments(pageNum, pageContainer, theseComments) { - var pageComments = $(pageContainer).find(".pageComments"); - Object.keys(theseComments).forEach(function(gradeId, _) { - var commentsByGrade = theseComments[gradeId] || {}; - var type = commentsByGrade.type; - var commentsForPage = commentsByGrade[pageNum] || []; - commentsForPage.forEach(function(comment, _) { - if (!comment.info) { - renderPageComment(pageComments[0], gradeId, type, pageNum, comment); - } - }); - }); - } - function renderRegionComments(pageNum, regionComments, theseComments) { - Object.keys(theseComments).forEach(function(gradeId, _) { - var commentsByGrade = theseComments[gradeId] || {}; - var type = commentsByGrade.type; - var commentsForPage = commentsByGrade[pageNum] || []; - commentsForPage.forEach(function(comment, _) { - if (comment.info) { - renderRegionComment(regionComments[0], gradeId, type, pageNum, comment); - } - }); - }); - } - - function renderPageComment(pc, gradeId, type, line, comment) { - var widget = $("
").lineCommentView({ - gradeId, - type, - line, - severity: comment.severity, - label: comment.label, - author: comment.author, - deduction: comment.deduction, - title: comment.title, - comment: comment.comment, - suppressed: comment.suppressed - }); - $(pc).append(widget); - } - window.renderPageComment = renderPageComment; - function renderRegionComment(rc, gradeId, type, line, comment) { - var pdfViewer = $(rc).closest(".pdfDisplay").pdfViewer("instance"); - var $page = $(rc).find(".page"); - var infoJson; - if (comment.info) { - try { - infoJson = JSON.parse(comment.info); - } catch(e) { - infoJson = undefined; - } - } - if (infoJson && infoJson.type === "area") { - pdfViewer.createAreaComment($page, false, { - gradeId, - left: infoJson.left, - top: infoJson.top, - width: infoJson.width, - height: infoJson.height, - dimensions: infoJson.dimensions, - type, - line, - label: comment.label, - id: comment.id, - severity: comment.severity, - label: comment.label, - author: comment.author, - deduction: comment.deduction, - title: comment.title, - comment: comment.comment, - suppressed: comment.suppressed - }); - } - } - window.renderRegionComment = renderRegionComment; - - function renderLineComment(cm, gradeId, type, line, comment) { - var widget = $("
").lineCommentView({ - gradeId, - type, - line, - severity: comment.severity, - label: comment.label, - author: comment.author, - deduction: comment.deduction, - title: comment.title, - comment: comment.comment, - suppressed: comment.suppressed - }); - cm.addLineWidget(parseInt(line) - 1, widget[0], {coverGutter: false, noHScroll: true}); - } - window.renderLineComment = renderLineComment; - - function init_datetime() { - $('.datetime-picker').datetimepicker({ - sideBySide: true, - format: "YYYY/MM/DD h:mm A", - defaultDate: undefined - }); - } - - var max_grader_order; - const extraCreditWarning = "This assignment is already marked as extra-credit. Only mark this grader as extra credit if you truly mean to have extra credit on top of extra credit."; - function on_add_grader(evt, el) { - el.find(".spinner").each(function(_ii, div) { - activateSpinner(div); - }); - var newToggles = el.find("input[data-toggle='toggle']"); - newToggles.bootstrapToggle(); - newToggles = newToggles.parent("div[data-toggle='toggle']"); - newToggles.attr('title', extraCreditWarning); - newToggles.tooltip(); - if ($("input[data-toggle='toggle'][name='assignment[extra_credit]']").prop('checked')) { - newToggles.tooltip('enable'); - } else { - newToggles.tooltip('disable'); - } - el.find("input[name$='[order]']").val(++max_grader_order); - el.find(".file-picker").each(function(index) { activate_file_picker($(this)); }); - form_tabs_init_all(el); - } - - function on_add_interlock(evt, el) { - var relAssignment = el.find("select[name$='[related_assignment_id]']"); - el.find("select[name$='[constraint]']").change(function(){ - if (this.value == "check_section_toggles") { - $(relAssignment).hide(); - } else { - $(relAssignment).show(); - } - }); - } - - - function form_init() { - init_datetime(); - - max_grader_order = - Math.max(0, - Math.max.apply(null, - $("input[name$='[order]']").map(function() { return $(this).val() }).toArray())); - - $('.graders-list').on('cocoon:after-insert', on_add_grader); - $('.interlocks-list').on('cocoon:after-insert', on_add_interlock); - - $('.spinner').each(function (_ii, div) { - activateSpinner(div); - if ($(div).find("input").prop("disabled")) { - disableSpinner(div); - } - }); - - $("#files-graders").sortable({ - placeholder: "ui-state-highlight", - update: function(e, ui) { - var orders = $("#files-graders input[name$='[order]']"); - orders.each(function(index, item) { - $(item).val(++max_grader_order); - }); - } - }); - - $("input[name='assignment[extra_credit]']").change(function() { - var newToggles = $(".graders-list .tab-pane").map(function(_, e) { return $(e).data("bn.detached-tab"); }); - newToggles = $.map(newToggles, function(kids) { return $.map(kids, function(k) { return k; }); }); - newToggles = $(newToggles).find("div[data-toggle='toggle']"); - debugger - if ($(this).prop('checked')) { - newToggles.tooltip('enable'); - newToggles.find("input[data-toggle='toggle']").bootstrapToggle('off'); - } else { - newToggles.tooltip('disable'); - } - }); - - $("form").submit(function(e) { - var graderTypeInputs = - $("li.grader").filter(function(index) { - return $(this).find("input[id^='assignment_graders_'][id$='_destroy'][value='1']").length == 0; - }).find("input[id$='_type']"); - debugger - var graderTypes = graderTypeInputs.map(function() { return $(this).val().replace(/^.*_/, ""); }); - var asHash = Object.create(null); - graderTypes.map(function() { asHash[this] = (asHash[this] || 0) + 1; }); - var prompt = ""; - for (var type in asHash) { - if (asHash[type] > 1) { - prompt += "\t" + asHash[type] + " of " + type + "\n"; - } - } - if (prompt !== "") { - if (!confirm("Are you sure you intended to have multiple graders of the same type?\n" + prompt)) { - e.preventDefault(); - return false; - } - } - return true; - }); - - $(".file-picker").each(function(index) { activate_file_picker($(this)); }); - } - - run_on_page("assignments/new", form_init); - run_on_page("assignments/create", form_init); - run_on_page("assignments/edit", form_init); - run_on_page("assignments/update", form_init); -})(); - -/* -run_on_page "assignments/show", () -> - inputs = [] - by_user = {} - - find_inputs = () -> - inputs = $(".grade-entry-box") - - by_user = {} - inputs.each (ii, box) -> - user_id = $(box).data("user-id") - by_user[user_id] = ii - - focus_row = (row_number) -> - next = inputs[row_number] - if next - $(next).focus() - - - handle_arrow_keys = (event) -> - user_id = $(event.target).data("user-id") - row_number = by_user[user_id] - - switch $.keyDecoder.parse(event) - when "Up" - focus_row(row_number - 1) - - when "Down" - focus_row(row_number + 1) - - handle_form_send = (event) -> - box = $(event.target).find(".grade-entry-box")[0] - user_id = $(box).data("user-id") - - row_number = by_user[user_id] - focus_row(row_number + 1) - - setup_handlers = () -> - find_inputs() - - $(".grade-entry-box").off "keyup", handle_arrow_keys - $(".grade-entry-box").on "keyup", handle_arrow_keys - - $(".sub-form").off "ajax:send", handle_form_send - $(".sub-form").on "ajax:send", handle_form_send - - $(document).ajaxComplete () -> - $('#ajax-status').text("ajax-status: done") - setup_handlers() - - setup_handlers() -*/ diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee deleted file mode 100644 index 76156794..00000000 --- a/app/assets/javascripts/main.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/javascripts/nicEditorIcons.gif b/app/assets/javascripts/nicEditorIcons.gif deleted file mode 100644 index 4fc2a6db..00000000 Binary files a/app/assets/javascripts/nicEditorIcons.gif and /dev/null differ diff --git a/app/assets/javascripts/reg_requests.js.coffee b/app/assets/javascripts/reg_requests.js.coffee deleted file mode 100644 index 76156794..00000000 --- a/app/assets/javascripts/reg_requests.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/javascripts/sandboxes.coffee b/app/assets/javascripts/sandboxes.coffee deleted file mode 100644 index 24f83d18..00000000 --- a/app/assets/javascripts/sandboxes.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/settings.js.coffee b/app/assets/javascripts/settings.js.coffee deleted file mode 100644 index 24f83d18..00000000 --- a/app/assets/javascripts/settings.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/teamsets.js.coffee b/app/assets/javascripts/teamsets.js.coffee deleted file mode 100644 index 80cd0b78..00000000 --- a/app/assets/javascripts/teamsets.js.coffee +++ /dev/null @@ -1,30 +0,0 @@ -setup_form = () -> - $('.add-user-btn').click (e) -> - row = $(e.target).closest('tr.user') - opt = $("") - .attr("value", row.data().id) - .text(row.data().name) - $('#users').append(opt) - row.hide() - - $('.remove-users-btn').click (e) -> - $('#users option').filter((_,e) -> e.selected).each (i, opt) -> - opt.selected = false - $(opt).detach() - $("#users [data-id='#{opt.value}']").show() - - $('#submit-btn').click (ev) -> - $('#users option').each (i, opt) -> - opt.selected = true - - $("#existingTS").on("change", () -> - $(".teamset-div").addClass("hidden") - $("#ts_" + $(this).val()).removeClass("hidden") - ).change() - - - -run_on_page "teamsets/create", setup_form -run_on_page "teamsets/new", setup_form -run_on_page "teamsets/edit", setup_form -run_on_page "teamsets/bulk_enter", setup_form diff --git a/app/assets/javascripts/terms.js.coffee b/app/assets/javascripts/terms.js.coffee deleted file mode 100644 index 76156794..00000000 --- a/app/assets/javascripts/terms.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 8eebbd24..e1f4e3c7 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -1,10 +1,3 @@ -//= require codemirror/lib/codemirror -//= require codemirror/theme/mdn-like -//= require jquery-tablesorter/theme.bootstrap_2 -//= require jquery-ui/resizable -//= require bootstrap-toggle -//= require pdfjs-dist/web/pdf_viewer - // Import the bootstrap overrides *before* bootstrap. @import "bootstrap-overrides"; @@ -12,8 +5,6 @@ @import "bootstrap-sprockets"; @import "bootstrap"; @import "font-awesome"; -@import "bootstrap-datetimepicker"; -@import "bootstrap-treeview"; // Internal stylesheets. @import "footer"; diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 7c3021d7..53399228 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -15,4 +15,67 @@ // const images = require.context('../images', true) // const imagePath = (name) => images(name, true) -console.log('Hello World from Webpacker') +import 'tablesorter'; +import 'tablesorter/dist/css/theme.bootstrap_2.min.css' + +import 'jquery-ujs'; + +import 'bootstrap-toggle'; + +import '@nathanvda/cocoon'; + +import 'codemirror/lib/codemirror'; +import 'codemirror/lib/codemirror.css'; +import 'codemirror/theme/mdn-like.css'; +import 'codemirror/addon/runmode/runmode'; +import 'codemirror/addon/selection/active-line'; +import 'codemirror/mode/clike/clike'; +import 'codemirror/mode/mllike/mllike'; +import 'codemirror/mode/haskell/haskell'; +import 'codemirror/mode/haskell-literate/haskell-literate'; +import 'codemirror/mode/ebnf/ebnf'; +import 'codemirror/mode/javascript/javascript'; +import 'codemirror/mode/markdown/markdown'; +import 'codemirror/mode/scheme/scheme'; +import 'codemirror/mode/commonlisp/commonlisp'; +import 'codemirror/mode/python/python'; +import 'codemirror/mode/css/css'; +import 'codemirror/mode/stex/stex'; +import 'codemirror/mode/xml/xml'; +import 'codemirror/mode/yaml/yaml'; +import 'codemirror/mode/htmlmixed/htmlmixed'; + + +$(function() { + +// require('../src/pdf_render'); + +require('jquery-ui/ui/widgets/tooltip'); +require('../src/0startup'); +require('../src/application'); +require('../src/assignments') +require('../src/bootstrap.treeview'); +require('../src/courses'); +require('../src/form-tabs'); +require('../src/grades'); +require('../src/jquery.matchHeight'); +require('../src/jquery.keyDecoder'); +require('../src/makefile-mode'); +require('../src/submissions'); +require('../src/teamsets'); + +}) + +// import '../src/pdf_render'; +// import '../src/0startup'; +// import '../src/application'; +// import '../src/assignments'; +// import '../src/bootstrap.treeview'; +// import '../src/courses'; +// import '../src/form-tabs'; +// import '../src/grades'; +// import '../src/jquery.matchHeight'; +// import '../src/jquery.keyDecoder'; +// import '../src/makefile-mode'; +// import '../src/submissions'; +// import '../src/teamsets'; diff --git a/app/javascript/packs/dompurify.js b/app/javascript/packs/dompurify.js new file mode 100644 index 00000000..cd8c5fcf --- /dev/null +++ b/app/javascript/packs/dompurify.js @@ -0,0 +1,3 @@ +import dompurify from 'dompurify/dist/purify.min.js'; + +window.DOMPurify = dompurify; diff --git a/app/javascript/packs/globals.js b/app/javascript/packs/globals.js new file mode 100644 index 00000000..02e77442 --- /dev/null +++ b/app/javascript/packs/globals.js @@ -0,0 +1,16 @@ +import $ from 'jquery'; +global.jQuery = $; +global.$ = $; + + + +import moment from 'moment'; +global.moment = moment; + +import 'jquery-ui'; +import 'jquery-ui/ui/widgets/draggable'; +import 'jquery-ui/ui/widgets/resizable'; +// TODO: import 'jquery-ui/ui/the'; resizable.css?? +import 'jquery-ui/ui/widgets/sortable'; +import 'jquery-ui/ui/widgets/selectable'; +import 'jquery-ui/ui/widgets/tooltip'; diff --git a/app/javascript/packs/pdfjs.js b/app/javascript/packs/pdfjs.js new file mode 100644 index 00000000..5dca7232 --- /dev/null +++ b/app/javascript/packs/pdfjs.js @@ -0,0 +1,2 @@ +import "pdfjs-dist/build/pdf.min.js"; +import "pdfjs-dist/web/pdf_viewer.js"; diff --git a/app/javascript/src/0startup.js b/app/javascript/src/0startup.js new file mode 100644 index 00000000..41c66686 --- /dev/null +++ b/app/javascript/src/0startup.js @@ -0,0 +1,11 @@ + +(function() { + window.run_on_page = function(name, func) { + return $(function() { + if (name === window.current_page_name) { + return func(); + } + }); + }; + +}).call(this); diff --git a/app/assets/javascripts/application.js b/app/javascript/src/application.js similarity index 86% rename from app/assets/javascripts/application.js rename to app/javascript/src/application.js index 43b38087..bf6dd47e 100644 --- a/app/assets/javascripts/application.js +++ b/app/javascript/src/application.js @@ -1,50 +1,6 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, -// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// the compiled file. -// -// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD -// GO AFTER THE REQUIRES BELOW. -// -//= require jquery -//= require jquery-ui/widgets/draggable -//= require jquery-ui/widgets/resizable -//= require jquery-ui/widgets/sortable -//= require jquery-ui/widgets/selectable -//= require jquery_ujs -//= require jquery.matchHeight -//= require jquery-tablesorter -//= require jquery.keyDecoder -//= require cocoon -//= require moment -//= require bootstrap-sprockets +// TODO: finish removing all of these //= require bootstrap-datetimepicker -//= require bootstrap.treeview -//= require bootstrap-toggle -//= require codemirror/lib/codemirror -//= require codemirror/addon/runmode/runmode -//= require codemirror/addon/selection/active-line -//= require codemirror/mode/clike/clike -//= require codemirror/mode/mllike/mllike -//= require codemirror/mode/haskell/haskell -//= require codemirror/mode/haskell-literate/haskell-literate -//= require codemirror/mode/ebnf/ebnf -//= require codemirror/mode/javascript/javascript -//= require codemirror/mode/markdown/markdown -//= require codemirror/mode/scheme/scheme -//= require codemirror/mode/commonlisp/commonlisp -//= require codemirror/mode/python/python -//= require codemirror/mode/css/css -//= require codemirror/mode/stex/stex -//= require codemirror/mode/xml/xml -//= require codemirror/mode/yaml/yaml -//= require codemirror/mode/htmlmixed/htmlmixed //= require pyret-codemirror-mode/mode/pyret -//= require_tree . function enableShowUsernames(elts) { @@ -189,12 +145,15 @@ function activate_file_picker($e) { }); } +import $ from 'jquery'; +import t from 'tablesorter'; +$.tablesorter = t; $.tablesorter.addParser({ id: 'dates', is: function(_) { return false; }, - format: function(_, _, cell, _) { + format: function(_a, _b, cell, _) { return $(cell).find("span.local-time").data("iso-date"); }, parsed: false, @@ -210,11 +169,13 @@ $(function() { $(this).attr("title", makeFriendlyDate($(this).attr("title"), true)); }); $('[data-toggle="tooltip"]').each(function(elt) { - $(this).tooltip({ + console.log("am running", this, $(this).tooltip); + var ret = $(this).tooltip({ animated: 'fade', placement: $(this).data("placement") || 'right', html: true }); + console.log(ret); }); $("input.numeric").on("keydown", validateNumericInput); diff --git a/app/javascript/src/assignments.js b/app/javascript/src/assignments.js new file mode 100644 index 00000000..9d819d9a --- /dev/null +++ b/app/javascript/src/assignments.js @@ -0,0 +1,252 @@ +export function renderComments(lineComments) { + $(".file-pane").each(function(index) { + var theseComments = lineComments[index] || {}; + if (theseComments["noCommentsFor"]) return; + // Standard text-files get line comments + $(this).find(".CodeMirror").each(function(_, cm) { + renderLineComments(cm.CodeMirror, theseComments); + }); + // Nonstandard files (jars, overly-large files) get page comments + $(this).find(".pageContainer").each(function(pageNum, pageContainer) { + renderPageComments(pageNum + 1, pageContainer, theseComments); + }); + // Pdfs get page and region comments + $(this).find("div[id^='pdf_']").each(function(_, pdfDiv) { + var pageRendered = []; + $(pdfDiv).pdfViewer({ + pageContainerReady: function(_, details) { + renderPageComments(details.pageNum, details.pageContainer, theseComments); + }, + pageReady: function(_, details) { + if (pageRendered[details.pageNum]) return; + pageRendered[details.pageNum] = true; + renderRegionComments(details.pageNum, details.container.regionComments, theseComments); + } + }); + }); + }); +} +window.renderComments = renderComments; + +export function renderLineComments(cm, theseComments) { + cm.operation(function() { + Object.keys(theseComments).forEach(function(gradeId, _) { + var commentsByGrade = theseComments[gradeId] || {}; + var type = commentsByGrade.type; + Object.keys(commentsByGrade).forEach(function(line, _) { + if (line === "type") return; + var commentsOnLine = commentsByGrade[line] || {}; + commentsOnLine.forEach(function(comment, _) { + renderLineComment(cm, gradeId, type, line, comment); + }); + }); + }); + }); +} + +export function renderPageComments(pageNum, pageContainer, theseComments) { + var pageComments = $(pageContainer).find(".pageComments"); + Object.keys(theseComments).forEach(function(gradeId, _) { + var commentsByGrade = theseComments[gradeId] || {}; + var type = commentsByGrade.type; + var commentsForPage = commentsByGrade[pageNum] || []; + commentsForPage.forEach(function(comment, _) { + if (!comment.info) { + renderPageComment(pageComments[0], gradeId, type, pageNum, comment); + } + }); + }); +} + +export function renderRegionComments(pageNum, regionComments, theseComments) { + Object.keys(theseComments).forEach(function(gradeId, _) { + var commentsByGrade = theseComments[gradeId] || {}; + var type = commentsByGrade.type; + var commentsForPage = commentsByGrade[pageNum] || []; + commentsForPage.forEach(function(comment, _) { + if (comment.info) { + renderRegionComment(regionComments[0], gradeId, type, pageNum, comment); + } + }); + }); +} + +export function renderPageComment(pc, gradeId, type, line, comment) { + var widget = $("
").lineCommentView({ + gradeId, + type, + line, + severity: comment.severity, + label: comment.label, + author: comment.author, + deduction: comment.deduction, + title: comment.title, + comment: comment.comment, + suppressed: comment.suppressed + }); + $(pc).append(widget); +} + +export function renderRegionComment(rc, gradeId, type, line, comment) { + var pdfViewer = $(rc).closest(".pdfDisplay").pdfViewer("instance"); + var $page = $(rc).find(".page"); + var infoJson; + if (comment.info) { + try { + infoJson = JSON.parse(comment.info); + } catch(e) { + infoJson = undefined; + } + } + if (infoJson && infoJson.type === "area") { + pdfViewer.createAreaComment($page, false, { + gradeId, + left: infoJson.left, + top: infoJson.top, + width: infoJson.width, + height: infoJson.height, + dimensions: infoJson.dimensions, + type, + line, + label: comment.label, + id: comment.id, + severity: comment.severity, + label: comment.label, + author: comment.author, + deduction: comment.deduction, + title: comment.title, + comment: comment.comment, + suppressed: comment.suppressed + }); + } +} + +export function renderLineComment(cm, gradeId, type, line, comment) { + var widget = $("
").lineCommentView({ + gradeId, + type, + line, + severity: comment.severity, + label: comment.label, + author: comment.author, + deduction: comment.deduction, + title: comment.title, + comment: comment.comment, + suppressed: comment.suppressed + }); + cm.addLineWidget(parseInt(line) - 1, widget[0], {coverGutter: false, noHScroll: true}); +} + +function init_datetime() { + $('.datetime-picker').datetimepicker({ + sideBySide: true, + format: "YYYY/MM/DD h:mm A", + defaultDate: undefined + }); +} + +var max_grader_order; +const extraCreditWarning = "This assignment is already marked as extra-credit. Only mark this grader as extra credit if you truly mean to have extra credit on top of extra credit."; +function on_add_grader(evt, el) { + el.find(".spinner").each(function(_ii, div) { + activateSpinner(div); + }); + var newToggles = el.find("input[data-toggle='toggle']"); + newToggles.bootstrapToggle(); + newToggles = newToggles.parent("div[data-toggle='toggle']"); + newToggles.attr('title', extraCreditWarning); + newToggles.tooltip(); + if ($("input[data-toggle='toggle'][name='assignment[extra_credit]']").prop('checked')) { + newToggles.tooltip('enable'); + } else { + newToggles.tooltip('disable'); + } + el.find("input[name$='[order]']").val(++max_grader_order); + el.find(".file-picker").each(function(index) { activate_file_picker($(this)); }); + form_tabs_init_all(el); +} + +function on_add_interlock(evt, el) { + var relAssignment = el.find("select[name$='[related_assignment_id]']"); + el.find("select[name$='[constraint]']").change(function(){ + if (this.value == "check_section_toggles") { + $(relAssignment).hide(); + } else { + $(relAssignment).show(); + } + }); +} + + +function form_init() { + init_datetime(); + + max_grader_order = + Math.max(0, + Math.max.apply(null, + $("input[name$='[order]']").map(function() { return $(this).val() }).toArray())); + + $('.graders-list').on('cocoon:after-insert', on_add_grader); + $('.interlocks-list').on('cocoon:after-insert', on_add_interlock); + + $('.spinner').each(function (_ii, div) { + activateSpinner(div); + if ($(div).find("input").prop("disabled")) { + disableSpinner(div); + } + }); + + $("#files-graders").sortable({ + placeholder: "ui-state-highlight", + update: function(e, ui) { + var orders = $("#files-graders input[name$='[order]']"); + orders.each(function(index, item) { + $(item).val(++max_grader_order); + }); + } + }); + + $("input[name='assignment[extra_credit]']").change(function() { + var newToggles = $(".graders-list .tab-pane").map(function(_, e) { return $(e).data("bn.detached-tab"); }); + newToggles = $.map(newToggles, function(kids) { return $.map(kids, function(k) { return k; }); }); + newToggles = $(newToggles).find("div[data-toggle='toggle']"); + debugger + if ($(this).prop('checked')) { + newToggles.tooltip('enable'); + newToggles.find("input[data-toggle='toggle']").bootstrapToggle('off'); + } else { + newToggles.tooltip('disable'); + } + }); + + $("form").submit(function(e) { + var graderTypeInputs = + $("li.grader").filter(function(index) { + return $(this).find("input[id^='assignment_graders_'][id$='_destroy'][value='1']").length == 0; + }).find("input[id$='_type']"); + debugger + var graderTypes = graderTypeInputs.map(function() { return $(this).val().replace(/^.*_/, ""); }); + var asHash = Object.create(null); + graderTypes.map(function() { asHash[this] = (asHash[this] || 0) + 1; }); + var prompt = ""; + for (var type in asHash) { + if (asHash[type] > 1) { + prompt += "\t" + asHash[type] + " of " + type + "\n"; + } + } + if (prompt !== "") { + if (!confirm("Are you sure you intended to have multiple graders of the same type?\n" + prompt)) { + e.preventDefault(); + return false; + } + } + return true; + }); + + $(".file-picker").each(function(index) { activate_file_picker($(this)); }); +} + +run_on_page("assignments/new", form_init); +run_on_page("assignments/create", form_init); +run_on_page("assignments/edit", form_init); +run_on_page("assignments/update", form_init); diff --git a/app/assets/javascripts/bootstrap.treeview.js b/app/javascript/src/bootstrap.treeview.js similarity index 100% rename from app/assets/javascripts/bootstrap.treeview.js rename to app/javascript/src/bootstrap.treeview.js diff --git a/app/assets/javascripts/courses.js b/app/javascript/src/courses.js similarity index 100% rename from app/assets/javascripts/courses.js rename to app/javascript/src/courses.js diff --git a/app/assets/javascripts/form-tabs.js b/app/javascript/src/form-tabs.js similarity index 100% rename from app/assets/javascripts/form-tabs.js rename to app/javascript/src/form-tabs.js diff --git a/app/assets/javascripts/grades.js b/app/javascript/src/grades.js similarity index 100% rename from app/assets/javascripts/grades.js rename to app/javascript/src/grades.js diff --git a/vendor/assets/javascripts/jquery.keyDecoder.js b/app/javascript/src/jquery.keyDecoder.js similarity index 100% rename from vendor/assets/javascripts/jquery.keyDecoder.js rename to app/javascript/src/jquery.keyDecoder.js diff --git a/app/assets/javascripts/jquery.matchHeight.js b/app/javascript/src/jquery.matchHeight.js similarity index 100% rename from app/assets/javascripts/jquery.matchHeight.js rename to app/javascript/src/jquery.matchHeight.js diff --git a/app/assets/javascripts/makefile-mode.js b/app/javascript/src/makefile-mode.js similarity index 92% rename from app/assets/javascripts/makefile-mode.js rename to app/javascript/src/makefile-mode.js index ca475fb2..5ff74d8c 100644 --- a/app/assets/javascripts/makefile-mode.js +++ b/app/javascript/src/makefile-mode.js @@ -2,16 +2,10 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: http://codemirror.net/LICENSE -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { "use strict"; +import CodeMirror from 'codemirror'; + CodeMirror.defineMode('makefile', function() { var words = {}; @@ -141,5 +135,3 @@ CodeMirror.defineMode('makefile', function() { }); CodeMirror.defineMIME('text/x-makefile', 'makefile'); - -}); diff --git a/app/javascript/src/pdf_render.js b/app/javascript/src/pdf_render.js new file mode 100644 index 00000000..35a0d536 --- /dev/null +++ b/app/javascript/src/pdf_render.js @@ -0,0 +1,341 @@ +const pdfjsLib = require('pdfjs-dist'); +const worker = require('pdfjs-dist/build/pdf.worker'); +pdfjsLib.GlobalWorkerOptions.workerSrc = worker; + + +var CSS_UNITS = 96/72; +var eventBus = new pdfjsViewer.EventBus(); +$(document.body).prepend($("#selectionWrapperWrapper").detach()); +function encodePath(str) { + return str.split('/').map(encodeURIComponent).join('/'); +} +window.jQuery.widget("bn.pdfViewer", { + options: { }, + _create: function() { + var thiz = this; + var $div = this.element; + var $pages = $div.find("div.pdfPages"); + //////////////////////////////////////// + //////////////////// Rendering + //////////////////////////////////////// + pdfjsLib.getDocument(encodePath($div.data("rendered"))).promise.then(createPages); + function createPages(pdf) { + // Page numbers are 1-based + $pages.data("pdf", pdf); + var promises = [] + for (var i = 1; i <= pdf.numPages; i++) { + var pageContainer = $("
").addClass("pageContainer"); + var pageComments = $("
").addClass("pageComments"); + var regionComments = $("
").addClass("regionComments") + $pages.append(pageContainer.append(pageComments).append(regionComments)); + thiz._trigger("pageContainerReady", null, { + pageNum: i, + pdfViewer: thiz, + pageContainer, pageComments, regionComments + }); + promises.push(pdf.getPage(i)); + } + $pages.data("pdfPages", Promise.all(promises)); + return enqueueAllPages(); + } + this.pagesToRender = {promise: Promise.resolve, worklist: [], scale: ""}; + function enqueueAllPages(force) { + return $pages.data("pdfPages").then(function(pages) { + var renderScale = $div.find("#scaleSelect").val(); + if (!force && renderScale === thiz.pagesToRender.scale) { + return thiz.pagesToRender.promise; + } + thiz.pagesToRender.worklist.forEach((item) => {if (item) { item.skip = true; }}); + var $allContainers = $pages.find("div.pageContainer").map(function(index, c) { + return { + index, + outerContainer: c, + pageComments: $(c).find("div.pageComments"), + regionComments: $(c).find("div.regionComments")//.data("index", index) + }; + }); + // console.log("AllPages: " + $allContainers.length + ", pageCount: " + pages.length); + var worklist = []; + // Page numbers are 1-based, but forEach() is 0-based + pages.forEach(function(page, pageNum) { + worklist.push({ + pdfViewer: thiz, + pageData: page, + pageNum: pageNum + 1, + renderScale, + numPages: pages.length, + container: $allContainers[pageNum]}); + }); + var $loading = $div.find("div.loadingBar"); + var $progress = $loading.find("div.progress"); + $progress.addClass("indeterminate"); + $loading.removeClass("hidden").show(); + thiz.pagesToRender = {promise: renderPages(worklist, $loading, $progress, 0), + worklist: worklist, + scale: renderScale}; + return thiz.pagesToRender.promise; + }); + } + function renderPages(worklist, $loading, $progress, curIndex) { + if (curIndex == worklist.length) { + worklist.length = 0; + $loading.addClass("hidden"); + $loading.css({"width": "0%"}) + $progress.removeClass("indeterminate"); + return Promise.resolve(); + } else { + var workItem = worklist[curIndex]; + worklist[curIndex] = undefined; + if (workItem.skip) { + // console.log("Skipping " + workItem.pageNum + " at " + workItem.renderScale); + return renderPages(worklist, $loading, $progress, curIndex + 1); + } else { + var comments = workItem.container.regionComments.find("div.Region").detach(); + workItem.container.regionComments.find("div.page").remove(); + var pct = 100 * (workItem.pageNum / workItem.numPages); + $progress.addClass("indeterminate"); + $loading.removeClass("hidden").css({width: "" + Math.floor(pct) + "%"}).show(); + return renderPage(workItem.pageData, workItem.pageNum, workItem.container, workItem.renderScale) + .then(() => { + // console.log("Rendering " + workItem.pageNum + " at " + workItem.renderScale); + workItem.container.regionComments.find("div.page") + .append(comments); + if (thiz.options.editable) { + workItem.container.regionComments.find("div.page") + .off("click.page").on("click.page", (e, ui) => thiz._clickPage(e, ui, $(e.currentTarget))) + .selectable({stop: (e, ui) => thiz._stopCommentRegion(e, ui), + start: (e, ui) => thiz._startCommentRegion(e, ui), + delay: 1, + appendTo: $("#translateWrapper")[0]}) + .selectable("enable"); + } + comments.each((index, c) => { + $(c).areaComment("instance").reinit(); + }); + thiz._trigger("pageReady", null, workItem); + return renderPages(worklist, $loading, $progress, curIndex + 1); + }); + } + } + } + function renderPage(pdfPage, pageNum, container, renderScale) { + // Creating the page view with default parameters. + var width; + var fontSize = Number.parseFloat($pages.css('font-size')); + var viewport = pdfPage.getViewport({scale: 1}); + var containerHScale, containerVScale; + if ($pages.is(":visible")) { + containerHScale = ($pages.width() - 3 * fontSize) / viewport.width; + containerVScale = ($pages.height() - 3 * fontSize) / viewport.height; + } else { + // If the PDF isn't currently visible, force its nearest invisible parent to be visible + // long enough to compute dimensions + var lastHidden = $pages.parentsUntil(":visible").last(); + var hiddenStyle = lastHidden.attr("style"); + lastHidden.show(); + containerHScale = ($pages.width() - 3 * fontSize) / viewport.width; + containerVScale = ($pages.height() - 3 * fontSize) / viewport.height; + if (hiddenStyle) + lastHidden.attr("style", hiddenStyle); + else + lastHidden.removeAttr("style"); + } + switch(renderScale) { + case 'page-actual': width = 1; break; + case 'page-width': width = containerHScale / CSS_UNITS; break; + case 'page-fit': width = Math.min(containerHScale, containerVScale) / CSS_UNITS; break; + case 'auto': + if (containerHScale > containerVScale) + width = Math.min(containerHScale, containerVScale) / CSS_UNITS; + else + width = containerHScale / CSS_UNITS; + break; + default: + width = Number.parseFloat(renderScale); + break; + } + var pdfPageView = new pdfjsViewer.PDFPageView({ + container: container.regionComments[0], + id: pageNum, + scale: width, + defaultViewport: viewport, + renderer: 'canvas', + eventBus: eventBus, + // // We can enable text/annotations layers, if needed + // textLayerFactory: new pdfjsViewer.DefaultTextLayerFactory(), + // annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory(), + }); + // Associates the actual page with the view, and drawing it + pdfPageView.setPdfPage(pdfPage); + return pdfPageView.draw(); + } + //////////////////////////////////////// + //////////////////// Zooming + //////////////////////////////////////// + $div.find("#zoomOut").click(function(e) { + var $scale = $div.find("#scaleSelect"); + var $options = $scale.find("option"); + var newIndex = Math.max($scale[0].selectedIndex - 1, 0); + $scale.val($options[newIndex].value).change(); + e.stopImmediatePropagation(); + return false; + }); + $div.find("#zoomIn").click(function(e) { + var $scale = $div.find("#scaleSelect"); + var $options = $scale.find("option"); + var newIndex = Math.min($scale[0].selectedIndex + 1, $options.length - 1); + $scale.val($scale.find("option")[newIndex].value).change(); + e.stopImmediatePropagation(); + return false; + }); + $div.find("#scaleSelect").change(enqueueAllPages); + var resizer; + $(window).resize(function(e) { + if (e.target !== window) return; + if (resizer) { window.clearTimeout(resizer); resizer = undefined; } + if ($pages.data("pdfPages")) { + resizer = setTimeout(() => enqueueAllPages(true), 100); + } + }); + //////////////////////////////////////// + //////////////////// Downloading + //////////////////////////////////////// + var clickingDownload = false; + $div.find("#new_window").click(function(e) { + window.open(encodePath($div.data("source")), "_blank"); + e.stopPropagation(); + }); + $div.find("#download").click(function(e) { + // console.log("Clicking on button"); + var dm = new pdfjsViewer.DownloadManager({}); + dm.downloadUrl(encodePath($div.data("source")), $div.data("alt")); + e.stopPropagation(); + }); + }, + + //////////////////////////////////////// + //////////////////// PDF Commenting + //////////////////////////////////////// + createAreaComment: function($page, editable, options) { + var $final = $("
"); + $page.append($final); + var combinedOptions = $.extend({}, options, { + change: function(e, details) { + // console.log("areaComment " + details.widget.id() + " change details:", details); + if (details.newSeverity) + $final.removeClass(details.oldSeverity).addClass(details.newSeverity); + if (options.change) + options.change.call(this, e, details); + } + }); + return $final.areaComment({ + container: "parent", + editable: editable, + left: options.left, + top: options.top, + width: options.width, + height: options.height, + dimensions: options.dimensions, + gradeId: options.gradeId, + severity: options.severity, + commentEditor: combinedOptions + }); + }, + _onMove: function(e, ui) { + var $selHelper = $(".ui-selectable-helper"); + if ($selHelper.width() > 20 && $selHelper.height() > 20) { + $selHelper.addClass("big-enough"); + } else { + $selHelper.removeClass("big-enough"); + } + }, + _startCommentRegion: function(e, ui) { + var $div = this.element; + var offsetDiv = $div.offset(); + $("#selectionWrapperWrapper").css({ + overflow: "hidden", + position: "absolute", + top: offsetDiv.top, + left: offsetDiv.left, + width: $div.width(), + height: $div.height(), + "z-index": 999 + }).removeClass("hidden").on("mousemove", (e, ui) => this._onMove(e, ui)); + var offsetTarget = $(e.target).offset(); + $("#selectionWrapper").css({ + overflow: "hidden", + position: "absolute", + border: "1px solid rgba(255, 255, 0, 0.5)", + top: offsetTarget.top - offsetDiv.top, + left: offsetTarget.left - offsetDiv.left, + width: e.target.offsetWidth, + height: e.target.offsetHeight, + }); + $("#translateWrapper").css({ + top: -offsetTarget.top, + left: -offsetTarget.left, + position: "relative" + }); + }, + _stopCommentRegion: function(e, ui) { + var $region = $(e.target).selectable("instance").helper; + if ($region.hasClass("big-enough")) { + this._selectArea(e, ui, $region); + } else { + this._clickPage(e, ui, $(e.target)); + } + $("#selectionWrapperWrapper").off("mousemove").addClass("hidden"); + }, + _clickPage: function(e, ui, $page) { + var details = { + pdfViewer: this, + page: $page, + regionComments: $page.closest(".regionComments"), + pageComments: $page.closest(".regionComments").prev(".pageComments"), + pageNum: $page.data("page-number") + }; + this._trigger("pageClicked", e, details); + e.stopImmediatePropagation(); + return false; + }, + _selectArea: function(e, ui, $region) { + var $page = $(e.target); + var pageWidth = $page[0].offsetWidth; + var pageHeight = $page[0].offsetHeight; + var offset = $page.offset(); + var leftPx = $region[0].offsetLeft - offset.left; + var topPx = $region[0].offsetTop - offset.top; + var widthPx = $region[0].offsetWidth; + var heightPx = $region[0].offsetHeight; + if (leftPx < 0) { + widthPx += leftPx; leftPx = 0; + } else if (leftPx + widthPx >= pageWidth) { + widthPx = pageWidth - leftPx; + } + if (topPx < 0) { + heightPx += topPx; topPx = 0; + } else if (topPx + heightPx >= pageHeight) { + heightPx = pageHeight - topPx; + } + var left = leftPx / pageWidth; + var top = topPx / pageHeight; + var width = widthPx / pageWidth; + var height = heightPx / pageHeight; + var details = { + pdfViewer: this, + page: $page, + regionComments: $page.closest(".regionComments"), + selection: $region, + left: left, + top: top, + width: width, + height: height, + pageWidth: pageWidth, + pageheight: pageHeight, + pageNum: $page.data("page-number") + }; + this._trigger("pageAreaSelected", e, details); + e.stopImmediatePropagation(); + return false; + } +}); diff --git a/app/assets/javascripts/submissions.js b/app/javascript/src/submissions.js similarity index 100% rename from app/assets/javascripts/submissions.js rename to app/javascript/src/submissions.js diff --git a/app/javascript/src/teamsets.js b/app/javascript/src/teamsets.js new file mode 100644 index 00000000..73bae76e --- /dev/null +++ b/app/javascript/src/teamsets.js @@ -0,0 +1,40 @@ +(function() { + var setup_form; + + setup_form = function() { + $('.add-user-btn').click(function(e) { + var opt, row; + row = $(e.target).closest('tr.user'); + opt = $("").attr("value", row.data().id).text(row.data().name); + $('#users').append(opt); + return row.hide(); + }); + $('.remove-users-btn').click(function(e) { + return $('#users option').filter(function(_, e) { + return e.selected; + }).each(function(i, opt) { + opt.selected = false; + $(opt).detach(); + return $("#users [data-id='" + opt.value + "']").show(); + }); + }); + $('#submit-btn').click(function(ev) { + return $('#users option').each(function(i, opt) { + return opt.selected = true; + }); + }); + return $("#existingTS").on("change", function() { + $(".teamset-div").addClass("hidden"); + return $("#ts_" + $(this).val()).removeClass("hidden"); + }).change(); + }; + + run_on_page("teamsets/create", setup_form); + + run_on_page("teamsets/new", setup_form); + + run_on_page("teamsets/edit", setup_form); + + run_on_page("teamsets/bulk_enter", setup_form); + +}).call(this); diff --git a/app/views/grades/_enter_comments.js.erb b/app/views/grades/_enter_comments.js.erb index 26153418..c0c7ec7a 100644 --- a/app/views/grades/_enter_comments.js.erb +++ b/app/views/grades/_enter_comments.js.erb @@ -306,6 +306,7 @@ $(function() { manualComments[i] = lineComments[i][gradeId] || {}; delete lineComments[i][gradeId]; } + console.log(window.renderComments); renderComments(lineComments); function loadPageComments(pdfViewer, index, pageNum, pageComments, page) { // Page numbers are 1-based diff --git a/app/views/grades/edit_CodereviewGrader.html.erb b/app/views/grades/edit_CodereviewGrader.html.erb index 74c23f92..0ef9f12a 100644 --- a/app/views/grades/edit_CodereviewGrader.html.erb +++ b/app/views/grades/edit_CodereviewGrader.html.erb @@ -1,7 +1,7 @@ <% @page_title = @grader.display_type %> <% cur_reg = current_user.registration_for(@course) %> <% content_for :wide_content_before do %> -<%= javascript_include_tag "dompurify/dist/purify.min.js" %> +<%= javascript_pack_tag "dompurify" %> diff --git a/app/views/grades/edit_ManualGrader.html.erb b/app/views/grades/edit_ManualGrader.html.erb index b34efab2..f73097b8 100644 --- a/app/views/grades/edit_ManualGrader.html.erb +++ b/app/views/grades/edit_ManualGrader.html.erb @@ -1,7 +1,7 @@ <% @page_title = @grader.display_type %> <% cur_reg = current_user.registration_for(@course) %> <% content_for :wide_content_before do %> -<%= javascript_include_tag "dompurify/dist/purify.min.js" %> +<%= javascript_pack_tag "dompurify" %> diff --git a/app/views/grades/edit_QuestionsGrader.html.erb b/app/views/grades/edit_QuestionsGrader.html.erb index 2cfb5b02..850182bb 100644 --- a/app/views/grades/edit_QuestionsGrader.html.erb +++ b/app/views/grades/edit_QuestionsGrader.html.erb @@ -1,7 +1,7 @@ <% @page_title = @grader.display_type %> <% cur_reg = current_user.registration_for(@course) %> <% content_for :wide_content_before do %> -<%= javascript_include_tag "dompurify/dist/purify.min.js" %> +<%= javascript_pack_tag "dompurify" %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 8b1fee38..692baf9a 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -15,7 +15,8 @@ <%= stylesheet_link_tag "application", :media => "all" %> - <%= javascript_include_tag "application" %> + <%= javascript_pack_tag "globals" %> + <%= javascript_pack_tag "application" %> diff --git a/app/views/layouts/errors.html.erb b/app/views/layouts/errors.html.erb index fbe13b9f..fdba474c 100644 --- a/app/views/layouts/errors.html.erb +++ b/app/views/layouts/errors.html.erb @@ -15,7 +15,7 @@ <%= stylesheet_link_tag "application", :media => "all" %> - <%= javascript_include_tag "application" %> + <%= javascript_pack_tag "application" %> style="background-color: <%= @bgcolor %>;"<% end %>> diff --git a/app/views/submissions/_codereview_details.html.erb b/app/views/submissions/_codereview_details.html.erb index c7a4660b..730a68fd 100644 --- a/app/views/submissions/_codereview_details.html.erb +++ b/app/views/submissions/_codereview_details.html.erb @@ -1,5 +1,5 @@ <% content_for :wide_content do %> -<%= javascript_include_tag "dompurify/dist/purify.min.js" %> +<%= javascript_pack_tag "dompurify" %> diff --git a/app/views/submissions/_files.html.erb b/app/views/submissions/_files.html.erb index d8459cd5..9552d16f 100644 --- a/app/views/submissions/_files.html.erb +++ b/app/views/submissions/_files.html.erb @@ -1,6 +1,5 @@ <% @@MAX_LINES = 10000 %> -<%= javascript_include_tag "pdfjs-dist/build/pdf.min.js" %> -<%= javascript_include_tag "pdfjs-dist/web/pdf_viewer.js" %> +<%= javascript_pack_tag "pdfjs" %>