From 8a055a0d68f8d5e3c44b94149c310edc4fc1a428 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Thu, 11 Aug 2022 19:10:49 +0200 Subject: [PATCH] Update Bootstrap from v4 to v5 --- .../javascripts/bootstrap-dropdown-submenu.js | 2 +- app/assets/javascripts/codeharbor_link.js | 2 +- app/assets/javascripts/editor.js | 11 +- app/assets/javascripts/editor/editor.js.erb | 46 +++-- .../editor/participantsupport.js.erb | 10 +- app/assets/javascripts/editor/turtle.js | 11 +- .../javascripts/exercise_collections.js.erb | 2 +- app/assets/javascripts/exercises.js.erb | 19 +- app/assets/javascripts/forms.js | 2 +- .../pagedown/markdown.editor.js.erb | 24 +-- .../javascripts/pagedown/pagedown.js.erb | 2 +- app/assets/stylesheets/base.css.scss | 15 +- .../bootstrap-dropdown-submenu.css.scss | 4 +- app/assets/stylesheets/editor.css.scss | 8 +- app/assets/stylesheets/exercises.css.scss | 4 +- app/assets/stylesheets/forms.css.scss | 6 - app/helpers/application_helper.rb | 4 +- app/javascript/application.js | 3 +- .../_breadcrumbs_and_title.html.slim | 13 +- app/views/application/_flash.html.slim | 3 +- .../application/_locale_selector.html.slim | 2 +- app/views/application/_navigation.html.slim | 2 +- .../application/_navigation_submenu.html.slim | 2 +- app/views/application/_session.html.slim | 2 +- app/views/code_ocean/files/_form.html.slim | 16 +- app/views/codeharbor_links/_form.html.slim | 14 +- app/views/community_solutions/_form.html.slim | 16 +- app/views/consumers/_form.html.slim | 12 +- app/views/consumers/show.html.slim | 2 +- .../error_template_attributes/_form.html.slim | 14 +- app/views/error_templates/_form.html.slim | 20 +- .../execution_environments/_form.html.slim | 48 ++--- .../execution_environments/index.html.slim | 4 +- .../execution_environments/shell.html.slim | 2 +- .../execution_environments/show.html.slim | 6 +- .../_add_exercise_modal.slim | 2 +- .../exercise_collections/_form.html.slim | 12 +- app/views/exercises/_add_tip_modal.slim | 2 +- app/views/exercises/_code_field.html.slim | 6 +- .../_comment_dialogcontent.html.slim | 6 +- app/views/exercises/_editor.html.slim | 22 ++- .../exercises/_editor_file_tree.html.slim | 53 +++--- app/views/exercises/_editor_output.html.slim | 172 +++++++++--------- app/views/exercises/_export_actions.html.slim | 6 +- app/views/exercises/_file_form.html.slim | 28 +-- app/views/exercises/_form.html.slim | 40 ++-- .../_request_comment_dialogcontent.html.slim | 6 +- app/views/exercises/_tips_content.html.slim | 2 +- .../external_users/statistics.html.slim | 12 +- app/views/exercises/feedback.html.slim | 8 +- app/views/exercises/implement.html.slim | 47 +++-- app/views/exercises/index.html.slim | 19 +- app/views/exercises/show.html.slim | 13 +- .../exercises/study_group_dashboard.html.slim | 6 +- app/views/external_users/index.html.slim | 20 +- app/views/file_templates/_form.html.slim | 12 +- app/views/file_types/_form.html.slim | 16 +- app/views/internal_users/_form.html.slim | 16 +- app/views/internal_users/activate.html.slim | 8 +- .../internal_users/forgot_password.html.slim | 2 +- app/views/internal_users/index.html.slim | 19 +- .../internal_users/reset_password.html.slim | 8 +- app/views/layouts/application.html.slim | 6 +- app/views/proxy_exercises/_form.html.slim | 10 +- app/views/proxy_exercises/index.html.slim | 13 +- app/views/proxy_exercises/show.html.slim | 2 +- .../request_for_comments/index.html.slim | 24 +-- app/views/request_for_comments/show.html.slim | 10 +- app/views/sessions/new.html.slim | 8 +- app/views/shared/_edit_button.html.slim | 2 +- app/views/shared/_form_filters.html.slim | 13 +- app/views/shared/_modal.html.slim | 5 +- .../statistics/activity_history.html.slim | 6 +- app/views/study_groups/_form.html.slim | 6 +- app/views/study_groups/index.html.slim | 13 +- app/views/submissions/index.html.slim | 13 +- app/views/tags/_form.html.slim | 4 +- app/views/tips/_collapsed_card.html.slim | 2 +- app/views/tips/_form.html.slim | 16 +- app/views/tips/_sortable_tip.html.slim | 6 +- .../user_exercise_feedbacks/_form.html.slim | 4 +- package.json | 6 +- spec/helpers/application_helper_spec.rb | 2 +- yarn.lock | 38 ++-- 84 files changed, 559 insertions(+), 566 deletions(-) diff --git a/app/assets/javascripts/bootstrap-dropdown-submenu.js b/app/assets/javascripts/bootstrap-dropdown-submenu.js index 10809c02..38ad3854 100644 --- a/app/assets/javascripts/bootstrap-dropdown-submenu.js +++ b/app/assets/javascripts/bootstrap-dropdown-submenu.js @@ -1,6 +1,6 @@ $(document).on('turbolinks:load', function() { - var subMenusSelector = 'ul.dropdown-menu [data-toggle=dropdown]'; + var subMenusSelector = 'ul.dropdown-menu [data-bs-toggle=dropdown]'; function openSubMenu(event) { if (this.pathname === '/') { diff --git a/app/assets/javascripts/codeharbor_link.js b/app/assets/javascripts/codeharbor_link.js index 4cd49ece..fdf42859 100644 --- a/app/assets/javascripts/codeharbor_link.js +++ b/app/assets/javascripts/codeharbor_link.js @@ -1,5 +1,5 @@ $(document).on('turbolinks:load', function() { - $('[data-toggle="tooltip"]').tooltip(); + $('[data-bs-toggle="tooltip"]').tooltip(); if($.isController('codeharbor_links')) { if ($('.edit_codeharbor_link, .new_codeharbor_link').isPresent()) { diff --git a/app/assets/javascripts/editor.js b/app/assets/javascripts/editor.js index 465e2f49..6dc79b7f 100644 --- a/app/assets/javascripts/editor.js +++ b/app/assets/javascripts/editor.js @@ -15,12 +15,9 @@ $(document).on('turbolinks:load', function(event) { ); if ($('#editor').isPresent() && CodeOceanEditor && event.originalEvent.data.url.includes("/implement")) { - if (CodeOceanEditor.isBrowserSupported()) { - $('#alert').hide(); - // This call will (amon other things) initializeEditors and load the content except for the last line - // It must not be called during page navigation. Otherwise, content will be duplicated! - // Search for insertLines and Turbolinks reload / cache control - CodeOceanEditor.initializeEverything(); - } + // This call will (amon other things) initializeEditors and load the content except for the last line + // It must not be called during page navigation. Otherwise, content will be duplicated! + // Search for insertLines and Turbolinks reload / cache control + CodeOceanEditor.initializeEverything(); } }); diff --git a/app/assets/javascripts/editor/editor.js.erb b/app/assets/javascripts/editor/editor.js.erb index b07341ae..d242e64b 100644 --- a/app/assets/javascripts/editor/editor.js.erb +++ b/app/assets/javascripts/editor/editor.js.erb @@ -78,7 +78,7 @@ var CodeOceanEditor = { if ($('#output-' + index).isPresent()) { return $('#output-' + index); } else { - var element = $('
').attr('id', 'output-' + index);
+            var element = $('
').attr('id', 'output-' + index);
             $('#output').append(element);
             return element;
         }
@@ -235,10 +235,20 @@ var CodeOceanEditor = {
         window.dispatchEvent(new Event('resize'));
     },
 
-    resizeParentOfAceEditor: function (element) {
+    resizeSidebars: function () {
+        $('#content-left-sidebar').height(this.calculateEditorHeight('#content-left-sidebar', false));
+        $('#content-right-sidebar').height(this.calculateEditorHeight('#content-right-sidebar', false));
+    },
+
+    calculateEditorHeight: function (element, considerStatusbar) {
+        let bottom = considerStatusbar ? ($('#statusbar').height() || 0) : 0;
         // calculate needed size: window height - position of top of ACE editor - height of autosave label below editor - 5 for bar margins
-        var windowHeight = window.innerHeight - $(element).offset().top - ($('#statusbar').height() || 0) - 5;
-        $(element).parent().height(windowHeight);
+        return window.innerHeight - $(element).offset().top - bottom - 5;
+    },
+
+    resizeParentOfAceEditor: function (element) {
+        const editorHeight = this.calculateEditorHeight(element, true);
+        $(element).parent().height(editorHeight);
     },
 
     initializeEditors: function (own_solution = false) {
@@ -259,6 +269,7 @@ var CodeOceanEditor = {
             // Resize frame on window size change
             $(window).resize(function () {
                 this.resizeParentOfAceEditor(element);
+                this.resizeSidebars();
             }.bind(this));
 
             var editor = ace.edit(element);
@@ -390,6 +401,7 @@ var CodeOceanEditor = {
             tipButton.on('click', this.handleSideBarToggle.bind(this));
         }
         $('#sidebar').on('transitionend', this.resizeAceEditors.bind(this));
+        $('#sidebar').on('transitionend', this.resizeSidebars.bind(this));
     },
 
     handleSideBarToggle: function () {
@@ -433,12 +445,12 @@ var CodeOceanEditor = {
         button.prop('disabled', true);
         button.on('click', function () {
             $('#rfc_intervention_text').hide()
-            $('#comment-modal').modal('show');
+            new bootstrap.Modal($('#comment-modal')).show();
         });
 
         $('#askForCommentsButton').on('click', this.requestComments.bind(this));
         $('#closeAskForCommentsButton').on('click', function () {
-            $('#comment-modal').modal('hide');
+            bootstrap.Modal.getInstance($('#comment-modal')).hide();
         });
 
         setTimeout(function () {
@@ -475,12 +487,6 @@ var CodeOceanEditor = {
         return this.isActiveFileExecutable() && ['teacher_defined_test', 'user_defined_test', 'teacher_defined_linter'].includes(this.active_frame.data('role'));
     },
 
-    isBrowserSupported: function () {
-        //  websockets are used for run, score and test
-        // Also exclude IE and IE 11
-        return Modernizr.websockets && window.navigator.userAgent.indexOf("MSIE") <= 0 && !navigator.userAgent.match(/Trident\/7\./);
-    },
-
     populateCard: function (card, result, index) {
         card.addClass(this.getCardClass(result));
         card.find('.card-title .filename').text(result.filename);
@@ -778,7 +784,7 @@ var CodeOceanEditor = {
         event.preventDefault();
         this.createSubmission('#create-file', null, function (response) {
             $('#code_ocean_file_context_id').val(response.id);
-            $('#modal-file').modal('show');
+            new bootstrap.Modal($('#modal-file')).show();
         }.bind(this));
     },
 
@@ -786,6 +792,7 @@ var CodeOceanEditor = {
         $('#toggle-sidebar-output').on('click', this.hideOutputBar.bind(this));
         $('#toggle-sidebar-output-collapsed').on('click', this.showOutputBar.bind(this));
         $('#output_sidebar').on('transitionend', this.resizeAceEditors.bind(this));
+        $('#output_sidebar').on('transitionend', this.resizeSidebars.bind(this));
     },
 
     showOutputBar: function () {
@@ -801,7 +808,7 @@ var CodeOceanEditor = {
     },
 
     initializeSideBarTooltips: function () {
-        $('[data-toggle="tooltip"]').tooltip()
+        $('[data-bs-toggle="tooltip"]').tooltip()
     },
 
     initializeDescriptionToggle: function () {
@@ -809,12 +816,13 @@ var CodeOceanEditor = {
         $('a#toggle').on('click', this.toggleDescriptionCard.bind(this));
     },
 
-    toggleDescriptionCard: function () {
+    toggleDescriptionCard: function (event) {
         $('#description-card').toggleClass('description-card-collapsed').toggleClass('description-card');
         $('#description-symbol').toggleClass('fa-chevron-down').toggleClass('fa-chevron-right');
         var toggle = $('a#toggle');
         toggle.text(toggle.text() == toggle.data('hide') ? toggle.data('show') : toggle.data('hide'));
         this.resizeAceEditors();
+        this.resizeSidebars();
         event.preventDefault();
     },
 
@@ -871,7 +879,7 @@ var CodeOceanEditor = {
                             if (editor.data('tips-interventions')) {
                                 const modal = $('#tips-intervention-modal');
                                 modal.find('.modal-footer').html(I18n.t("exercises.implement.intervention.explanation", {duration: Math.round(percentile75 / 60)}));
-                                modal.modal('show');
+                                new bootstrap.Modal(modal).show();
                                 $.ajax({
                                     data: {
                                         intervention_type: 'TipsIntervention'
@@ -883,7 +891,7 @@ var CodeOceanEditor = {
                             } else if (editor.data('break-interventions')) {
                                 const modal = $('#break-intervention-modal');
                                 modal.find('.modal-footer').html(I18n.t("exercises.implement.intervention.explanation", {duration: Math.round(percentile75 / 60)}));
-                                modal.modal('show');
+                                new bootstrap.Modal(modal).show();
                                 $.ajax({
                                     data: {
                                         intervention_type: 'BreakIntervention'
@@ -902,7 +910,7 @@ var CodeOceanEditor = {
                                     modal.on('hidden.bs.modal', function () {
                                         modal.find('.modal-footer').text('');
                                     });
-                                    modal.modal('show');
+                                    new bootstrap.Modal(modal).show();
                                     $.ajax({
                                         data: {
                                             intervention_type: 'QuestionIntervention'
@@ -945,7 +953,6 @@ var CodeOceanEditor = {
         CodeOceanEditor.editors = [];
         this.initializeRegexes();
         this.initializeCodePilot();
-        $('.score, #development-environment').show();
         this.configureEditors();
         this.initializeEditors();
         this.initializeEventHandlers();
@@ -961,6 +968,7 @@ var CodeOceanEditor = {
         this.renderScore();
         this.showFirstFile();
         this.resizeAceEditors();
+        this.resizeSidebars();
         this.initializeDeadlines();
         CodeOceanEditorTips.initializeEventHandlers();
 
diff --git a/app/assets/javascripts/editor/participantsupport.js.erb b/app/assets/javascripts/editor/participantsupport.js.erb
index 77d2138b..db801aeb 100644
--- a/app/assets/javascripts/editor/participantsupport.js.erb
+++ b/app/assets/javascripts/editor/participantsupport.js.erb
@@ -4,7 +4,7 @@ CodeOceanEditorFlowr = {
     '
' + '' + + body.append('' + '<%= I18n.t('exercises.implement.flowr.go_to_question') %>'); body.find('.btn').on('click', CodeOceanEditor.createEventHandler('editor_flowr_click_question', questionUrl)); @@ -112,7 +112,7 @@ CodeOceanEditorCodePilot = { QaApiOutputBuffer: {'stdout': '', 'stderr': ''}, initializeCodePilot: function () { - if ($('#questions-column').isPresent() && (typeof QaApi != 'undefined') && QaApi.isBrowserSupported()) { + if ($('#questions-column').isPresent() && (typeof QaApi != 'undefined')) { $('#editor-column').addClass('col-md-10').removeClass('col-md-12'); $('#questions-column').addClass('col-md-2'); @@ -161,7 +161,7 @@ CodeOceanEditorRequestForComments = { this.createSubmission($('#requestComments'), null, createRequestForComments.bind(this)); - $('#comment-modal').modal('hide'); + bootstrap.Modal.getInstance($('#comment-modal')).hide(); $('#question').val(''); // we disabled the button to prevent that the user spams RFCs, but decided against this now. //var button = $('#requestComments'); diff --git a/app/assets/javascripts/editor/turtle.js b/app/assets/javascripts/editor/turtle.js index e6463ee4..d388f375 100644 --- a/app/assets/javascripts/editor/turtle.js +++ b/app/assets/javascripts/editor/turtle.js @@ -37,15 +37,16 @@ CodeOceanEditorTurtle = { }, showCanvas: function () { - if ($('#turtlediv').isPresent() && this.turtlecanvas.hasClass('d-none')) { - this.turtlecanvas.removeClass('d-none'); + const turtlediv = $('#turtlediv'); + if (turtlediv.isPresent() && turtlediv.hasClass('d-none')) { + turtlediv.removeClass('d-none'); } }, hideCanvas: function () { - const turtlecanvas = $('#turtlecanvas'); - if ($('#turtlediv').isPresent() && !turtlecanvas.hasClass('d-none')) { - turtlecanvas.addClass('d-none'); + const turtlediv = $('#turtlediv'); + if (turtlediv.isPresent() && !turtlediv.hasClass('d-none')) { + turtlediv.addClass('d-none'); } } diff --git a/app/assets/javascripts/exercise_collections.js.erb b/app/assets/javascripts/exercise_collections.js.erb index 6c8602f7..d0aad22e 100644 --- a/app/assets/javascripts/exercise_collections.js.erb +++ b/app/assets/javascripts/exercise_collections.js.erb @@ -187,7 +187,7 @@ $(document).on('turbolinks:load', function() { for (var i = 0; i < selectedExercises.length; i++) { addExercise(selectedExercises[i].value, selectedExercises[i].label); } - $('#add-exercise-modal').modal('hide') + bootstrap.Modal.getInstance($('#add-exercise-modal')).hide(); updateExerciseList(); addExercisesForm.find('select').val('').trigger("chosen:updated"); }); diff --git a/app/assets/javascripts/exercises.js.erb b/app/assets/javascripts/exercises.js.erb index 9a5f0378..a91586dd 100644 --- a/app/assets/javascripts/exercises.js.erb +++ b/app/assets/javascripts/exercises.js.erb @@ -123,7 +123,7 @@ $(document).on('turbolinks:load', function () { var buildCheckboxes = function () { $('tbody tr').each(function (index, element) { var td = $('td.public', element); - var checkbox = $('', { + var checkbox = $('', { checked: td.data('value'), type: 'checkbox' }); @@ -225,9 +225,9 @@ $(document).on('turbolinks:load', function () { const tip = {id: id, title: title} const template = '
' + - '' + tip.title + - '' + - '' + + '' + tip.title + + '' + + '' + '
' + '
'; const tipList = $('#tip-list').append(template); @@ -243,7 +243,7 @@ $(document).on('turbolinks:load', function () { for (let i = 0; i < selectedTips.length; i++) { addTip(selectedTips[i].value, selectedTips[i].label); } - $('#add-tips-modal').modal('hide') + bootstrap.Modal.getInstance($('#add-tips-modal')).hide(); updateTipsJSON(); chosenInputTips.val('').trigger("chosen:updated"); }); @@ -328,10 +328,7 @@ $(document).on('turbolinks:load', function () { var observeExportButtons = function () { $('.export-start').on('click', function (e) { e.preventDefault(); - $('#export-modal').modal({ - height: 250 - }); - $('#export-modal').modal('show'); + new bootstrap.Modal($('#export-modal')).show(); exportExerciseStart($(this).data().exerciseId); }); $('body').on('click', '.export-retry-button', function () { @@ -382,7 +379,7 @@ $(document).on('turbolinks:load', function () { if (response.status == 'success') { $messageDiv.addClass('export-success'); setTimeout((function () { - $('#export-modal').modal('hide'); + bootstrap.Modal.getInstance($('#export-modal')).hide(); $messageDiv.html('').removeClass('export-success'); }), 3000); } else { @@ -396,7 +393,7 @@ $(document).on('turbolinks:load', function () { }; var overrideTextareaTabBehavior = function () { - $('.form-group textarea[name$="[content]"]').on('keydown', function (event) { + $('.mb-3 textarea[name$="[content]"]').on('keydown', function (event) { if (event.which === TAB_KEY_CODE) { event.preventDefault(); insertTabAtCursor($(this)); diff --git a/app/assets/javascripts/forms.js b/app/assets/javascripts/forms.js index 7e469455..2be40eba 100644 --- a/app/assets/javascripts/forms.js +++ b/app/assets/javascripts/forms.js @@ -9,7 +9,7 @@ $(document).on('turbolinks:load', function() { event.preventDefault(); if (!$(this).hasClass('disabled')) { - var parent = $(this).parents('.form-group'); + var parent = $(this).parents('.mb-3'); var original_input = parent.find('.original-input'); var alternative_input = parent.find('.alternative-input'); diff --git a/app/assets/javascripts/pagedown/markdown.editor.js.erb b/app/assets/javascripts/pagedown/markdown.editor.js.erb index 459d7cfa..8330a85c 100644 --- a/app/assets/javascripts/pagedown/markdown.editor.js.erb +++ b/app/assets/javascripts/pagedown/markdown.editor.js.erb @@ -1018,7 +1018,7 @@ text = 'http://' + text; } - $(dialog).modal('hide'); + bootstrap.Modal.getInstance($(dialog)).hide(); callback(text); return false; @@ -1032,7 +1032,7 @@ //