From 5cc85ba13958953256bb60686a3b69433a9939c4 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Mon, 28 Aug 2023 20:57:12 +0200 Subject: [PATCH 01/22] update bootstrap5 to 5.3.1 --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index df71416248b0..1a84fdc62d12 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "bootstrap-switch": "3.3.2", "bootstrap-timepicker": "0.5.1", "bootstrap3-typeahead": "bassjobsen/Bootstrap-3-Typeahead#~3.1.1", - "bootstrap5": "npm:bootstrap@5.2.3", + "bootstrap5": "npm:bootstrap@5.3.1", "calendars": "kbwood/calendars#2.1.2", "clipboard": "1.5.15", "crypto-js": "4.0.0", diff --git a/yarn.lock b/yarn.lock index 3e17d7f9fe63..e3a38d7ece17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -806,10 +806,10 @@ bootstrap3-typeahead@bassjobsen/Bootstrap-3-Typeahead#~3.1.1: version "3.1.1" resolved "https://codeload.github.com/bassjobsen/Bootstrap-3-Typeahead/tar.gz/c65c829fe8411f6eadb88415d09c1e85bb4603d0" -"bootstrap5@npm:bootstrap@5.2.3": - version "5.2.3" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.3.tgz#54739f4414de121b9785c5da3c87b37ff008322b" - integrity sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ== +"bootstrap5@npm:bootstrap@5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.1.tgz#8ca07040ad15d7f75891d1504cf14c5dedfb1cfe" + integrity sha512-jzwza3Yagduci2x0rr9MeFSORjcHpt0lRZukZPZQJT1Dth5qzV7XcgGqYzi39KGAVYR8QEDVoO0ubFKOxzMG+g== bootstrap@3.4.1, bootstrap@^3.3: version "3.4.1" @@ -5725,7 +5725,7 @@ wide-align@^1.1.5: dependencies: string-width "^1.0.2 || 2 || 3 || 4" -word-wrap@^1.2.3, "word-wrap@npm:@aashutoshrathi/word-wrap@1.2.5", word-wrap@~1.2.3: +word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.5" resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.5.tgz#383aeebd5c176c320d6364fb869669559bbdbac9" integrity sha512-plhoNEfSVdHMKXQyAxvH0Zyv3/4NL8r6pwgMQdmHR2vBUXn2t74PN2pBRppqKUa6RMT0yldyvOHG5Dbjwy2mBQ== From cb1e48383778e7682075e6c226246afc810f013c Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Mon, 28 Aug 2023 20:57:49 +0200 Subject: [PATCH 02/22] fix scss with missing file after bootstrap5 upgrade --- corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq.scss b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq.scss index b2917bf269c2..e10e55aa5819 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq.scss +++ b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq.scss @@ -3,6 +3,7 @@ @import "functions"; @import "commcarehq/variables"; // This comes before Bootstrap 5 variables to override the defaults @import "variables"; +@import "variables-dark"; @import "commcarehq/variables_bootstrap3"; // Variables specific to B3-era Stylesheet @import "maps"; @import "mixins"; From e3fe84ce385b0b5ce09bebbedcedcdbb3ce837c7 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Mon, 28 Aug 2023 20:59:20 +0200 Subject: [PATCH 03/22] make sure bootstrap5 bundle is included for popper --- .../hqwebapp/templates/hqwebapp/includes/core_libraries.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corehq/apps/hqwebapp/templates/hqwebapp/includes/core_libraries.html b/corehq/apps/hqwebapp/templates/hqwebapp/includes/core_libraries.html index 3660ddb7f883..194274f0f7ac 100644 --- a/corehq/apps/hqwebapp/templates/hqwebapp/includes/core_libraries.html +++ b/corehq/apps/hqwebapp/templates/hqwebapp/includes/core_libraries.html @@ -68,7 +68,7 @@ otherwise the two tooltip widgets and two button widgets conflict. {% endcomment %} {% if use_bootstrap5 %} - + {% else %} {% endif %} From d981f822aa43859788ca0ad4c684314523b5402c Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Mon, 28 Aug 2023 21:00:31 +0200 Subject: [PATCH 04/22] bootstrap5 bundle actually included in core_libraries now for non requirejs pages --- corehq/apps/hqwebapp/templates/hqwebapp/base.html | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/corehq/apps/hqwebapp/templates/hqwebapp/base.html b/corehq/apps/hqwebapp/templates/hqwebapp/base.html index 069734eef272..ba80c3fb76a9 100644 --- a/corehq/apps/hqwebapp/templates/hqwebapp/base.html +++ b/corehq/apps/hqwebapp/templates/hqwebapp/base.html @@ -281,11 +281,7 @@ {# javascript below this line #} - {% if use_bootstrap5 %} - - {% else %} - {% include "hqwebapp/partials/requirejs.html" with BASE_MAIN=True %} - {% endif %} + {% include "hqwebapp/partials/requirejs.html" with BASE_MAIN=True %} {# DO NOT COMPRESS #} From cd0112de6a3016c3387c45d6a77f8cbbf7db3d4b Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Mon, 28 Aug 2023 21:01:53 +0200 Subject: [PATCH 05/22] update base.html to include bootstrap5 or 3 versions of file based on is_bootstrap5 context variable --- .../hqwebapp/templates/hqwebapp/base.html | 87 ++++++++++++++----- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/corehq/apps/hqwebapp/templates/hqwebapp/base.html b/corehq/apps/hqwebapp/templates/hqwebapp/base.html index ba80c3fb76a9..663e8d346d56 100644 --- a/corehq/apps/hqwebapp/templates/hqwebapp/base.html +++ b/corehq/apps/hqwebapp/templates/hqwebapp/base.html @@ -184,7 +184,11 @@ {% block modals %}{% endblock %} {% if show_mobile_ux_warning %} - {% include "hqwebapp/partials/bootstrap3/mobile_ux_warning.html" %} + {% if use_bootstrap5 %} + {% include "hqwebapp/partials/bootstrap5/mobile_ux_warning.html" %} + {% else %} + {% include "hqwebapp/partials/bootstrap3/mobile_ux_warning.html" %} + {% endif %} {% endif %} {# Report Issue #} @@ -208,7 +212,11 @@ {% if EULA_COMPLIANCE %} {% if request.couch_user and not request.couch_user.is_eula_signed %} {% registerurl 'agree_to_eula' %} - {% include 'hqwebapp/includes/bootstrap3/modal_eula.html' %} + {% if use_bootstrap5 %} + {% include 'hqwebapp/includes/bootstrap5/modal_eula.html' %} + {% else %} + {% include 'hqwebapp/includes/bootstrap3/modal_eula.html' %} + {% endif %} {% endif %} {% endif %} @@ -219,7 +227,11 @@ {% registerurl 'submit_hubspot_cta_form' %} {# 30 Day Trial #} - {% include 'hqwebapp/includes/bootstrap3/modal_30_day_trial.html' %} + {% if use_bootstrap5 %} + {% include 'hqwebapp/includes/bootstrap5/modal_30_day_trial.html' %} + {% else %} + {% include 'hqwebapp/includes/bootstrap3/modal_30_day_trial.html' %} + {% endif %} {% block additional_initial_page_data %} {% comment %} @@ -287,16 +299,29 @@ {# HQ Specific Libraries #} {% if not requirejs_main %} - {% compress js %} - - - - - - - - - {% endcompress %} + {% if use_bootstrap5 %} + {% compress js %} + + + + + + + + + {% endcompress %} + {% else %} + {% compress js %} + + + + + + + + + {% endcompress %} + {% endif %} {% endif %} {# JavaScript Display Logic Libaries #} @@ -383,22 +408,42 @@ {% endif %} {% if is_demo_visible %} - {% include "hqwebapp/partials/bootstrap3/get_demo_modals.html" %} + {% if use_bootstrap5 %} + {% include "hqwebapp/partials/bootstrap5/get_demo_modals.html" %} + {% else %} + {% include "hqwebapp/partials/bootstrap3/get_demo_modals.html" %} + {% endif %} {% endif %} {# Knockout component templates #} - {% include 'hqwebapp/partials/bootstrap3/ko_pagination.html' %} - {% include 'hqwebapp/partials/bootstrap3/ko_inline_edit.html' %} - {% include 'hqwebapp/partials/bootstrap3/ko_search_box.html' %} - {% include 'hqwebapp/partials/bootstrap3/ko_select_toggle.html' %} - {% include 'hqwebapp/partials/bootstrap3/ko_feedback.html' %} + {% if use_bootstrap5 %} + {% include 'hqwebapp/partials/bootstrap5/ko_pagination.html' %} + {% include 'hqwebapp/partials/bootstrap5/ko_inline_edit.html' %} + {% include 'hqwebapp/partials/bootstrap5/ko_search_box.html' %} + {% include 'hqwebapp/partials/bootstrap5/ko_select_toggle.html' %} + {% include 'hqwebapp/partials/bootstrap5/ko_feedback.html' %} + {% else %} + {% include 'hqwebapp/partials/bootstrap3/ko_pagination.html' %} + {% include 'hqwebapp/partials/bootstrap3/ko_inline_edit.html' %} + {% include 'hqwebapp/partials/bootstrap3/ko_search_box.html' %} + {% include 'hqwebapp/partials/bootstrap3/ko_select_toggle.html' %} + {% include 'hqwebapp/partials/bootstrap3/ko_feedback.html' %} + {% endif %} {% if show_overdue_invoice_modal and not requirejs_main %} - + {% if use_bootstrap5 %} + + {% else %} + + {% endif %} {% endif %} {% if show_prepaid_modal and not requirejs_main %} - + {% if use_bootstrap5 %} + + {% else %} + + {% endif %} {% endif %} {% if show_status_page %} From 07b3fd474e139d81c809edcf10ec3fc95c2a3794 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Mon, 28 Aug 2023 21:02:30 +0200 Subject: [PATCH 06/22] override grid container widths to match existing style --- .../static/hqwebapp/scss/commcarehq/_variables.scss | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_variables.scss b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_variables.scss index b92f181c310c..aa2607b71bf8 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_variables.scss +++ b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_variables.scss @@ -1,3 +1,14 @@ +// Grid Containers +// we will want to adapt the defaults in a full redesign +$container-max-widths: ( + sm: 540px, + md: 720px, + lg: 960px, + xl: 1140px, + xxl: 1160px +); + + // Typography Overrides $font-family-sans-serif: "Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; $font-size-base: .75rem; // approx 12px From ff89521741c950d685f60d2fd8a837fb1924d1c2 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Mon, 28 Aug 2023 21:03:26 +0200 Subject: [PATCH 07/22] small tweaks to bootstrap5 hq layout to better mirror current bootstrap 3 styling --- .../hqwebapp/scss/commcarehq/_containers.scss | 4 ++++ .../static/hqwebapp/scss/commcarehq/_dropdown.scss | 13 +++++++++---- .../static/hqwebapp/scss/commcarehq/_nav.scss | 1 + .../static/hqwebapp/scss/commcarehq/_navbar.scss | 11 ++++++++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_containers.scss b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_containers.scss index 590f2710cfe6..af4272472f0f 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_containers.scss +++ b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_containers.scss @@ -1,3 +1,7 @@ +html, body { + height: 100%; +} + .hq-container { min-height: 100%; height: auto !important; diff --git a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_dropdown.scss b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_dropdown.scss index 2a731ff34179..3f88bd53d541 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_dropdown.scss +++ b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_dropdown.scss @@ -24,7 +24,7 @@ border-color: transparent; border-style: solid; border-width: 5px 0 5px 5px; - border-left-color: darken($dropdown-bg, 20%); + border-left-color: darken($body-bg, 20%); margin-right: -5px; margin-top: 3.3px; color: $dropdown-link-color; @@ -72,14 +72,19 @@ margin-top: 5px; } - .dropdown-menu .dropdown-divider { - margin-top: 0px; - margin-bottom: 0px; + .navbar-nav > li > a.dropdown-toggle-with-icon { + padding-top: 22px !important; + padding-bottom: 17px !important; } .nav-settings-bar .dropdown-toggle-with-icon.nav-link::after { display: none; } + + .dropdown-toggle::after { + vertical-align: 2.48px; + margin-left: 2px; + } } @media (max-width: map-get($grid-breakpoints, "lg")) { diff --git a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_nav.scss b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_nav.scss index 8365af7fad40..ee48ecfccf07 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_nav.scss +++ b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_nav.scss @@ -54,6 +54,7 @@ .nav-main-icon { font-size: 1.7em; line-height: 0.7em; + color: $gray-light; } .text-hq-nav-header { diff --git a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_navbar.scss b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_navbar.scss index 9ab13848b2c2..66f0da7d7297 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_navbar.scss +++ b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_navbar.scss @@ -6,9 +6,12 @@ min-height: $navbar-height; .navbar-brand { + padding-top: 11px; line-height: 17px; - height: $navbar-height - 4px; + height: $navbar-height - 6px; display: inline-block; + margin-left: -1px; + margin-right: 3px; // Standard HQ logo // Custom domain logos use an actual image @@ -30,8 +33,9 @@ } &.navbar-expand-lg .navbar-nav .nav-link { - padding: 21px 15px; + padding: 21px 15px 20px; line-height: 19.5px; + color: $gray-light; } &.navbar-expand-lg .navbar-nav li:not(.active) > .nav-link:focus, @@ -64,6 +68,7 @@ .nav-settings-bar { margin-left: auto; order: 2; + padding-right: 8px; } @media(max-width: 1057px) { @@ -131,7 +136,7 @@ .dimagi-logo svg { height: 22px; width: 50px; - top: 3px; + top: 2px; position: relative; display: inline-block; } From 3641ae051d21b0948a82129f2f05415d03e706d2 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Mon, 28 Aug 2023 21:03:48 +0200 Subject: [PATCH 08/22] re-add support for page-header for now until we do redesign --- .../hqwebapp/static/hqwebapp/scss/commcarehq/_type.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_type.scss b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_type.scss index ecd1d6fbab2d..3e07104eeabc 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_type.scss +++ b/corehq/apps/hqwebapp/static/hqwebapp/scss/commcarehq/_type.scss @@ -90,3 +90,10 @@ code { a { cursor: pointer; } + +// we should eventually get rid of this as bootstrap5+ doesn't natively support +.page-header { + padding-bottom: 7.5px; + margin: 34px 0 17px; + border-bottom: 1px solid #eeeeee; +} \ No newline at end of file From 3f9d0cb81824bc7c38f3f5bede36e065e525f4b3 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:04:37 +0200 Subject: [PATCH 09/22] ensure bootstrap5_loader points to bootstrap global in non-requirejs pages --- corehq/apps/hqwebapp/static/hqwebapp/js/hqModules.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/js/hqModules.js b/corehq/apps/hqwebapp/static/hqwebapp/js/hqModules.js index b918a6e1bbb2..ce45af74f2d7 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/js/hqModules.js +++ b/corehq/apps/hqwebapp/static/hqwebapp/js/hqModules.js @@ -69,6 +69,9 @@ function hqDefine(path, dependencies, moduleAccessor) { 'hqwebapp/js/lib/modernizr': 'Modernizr', 'sinon/pkg/sinon': 'sinon', }; + if (window.USE_BOOTSTRAP5) { + thirdPartyGlobals['hqwebapp/js/bootstrap5_loader'] = 'bootstrap'; + } var args = []; for (var i = 0; i < dependencies.length; i++) { var dependency = dependencies[i]; From 0546fd82f684c848f2802f57e53c6a5d60b37ef7 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:05:39 +0200 Subject: [PATCH 10/22] update reference to bootstrap5 version of hq.helpers in bootstrap5/alert_user --- .../apps/hqwebapp/static/hqwebapp/js/bootstrap5/alert_user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/alert_user.js b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/alert_user.js index b63241c36e7b..228a62a76224 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/alert_user.js +++ b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/alert_user.js @@ -16,7 +16,7 @@ hqDefine("hqwebapp/js/bootstrap5/alert_user", [ "jquery", "knockout", - "hqwebapp/js/bootstrap3/hq.helpers", + "hqwebapp/js/bootstrap5/hq.helpers", ], function ( $, From 223d0995d2d55ddbfb84dcda11a357ebd11cd3ce Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:07:03 +0200 Subject: [PATCH 11/22] ensure core_libraries loads bootstrap 3 or bootstrap 5 versions of javascript files for non requirejs page --- .../hqwebapp/includes/core_libraries.html | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/corehq/apps/hqwebapp/templates/hqwebapp/includes/core_libraries.html b/corehq/apps/hqwebapp/templates/hqwebapp/includes/core_libraries.html index 194274f0f7ac..3fe88adccc5f 100644 --- a/corehq/apps/hqwebapp/templates/hqwebapp/includes/core_libraries.html +++ b/corehq/apps/hqwebapp/templates/hqwebapp/includes/core_libraries.html @@ -103,29 +103,48 @@ {# already minified #} {% if hq %} + {% if use_bootstrap5 %} {% compress js %} - - - - - - - - - + + + + + + + + + {% endcompress %} + {% else %} + {% compress js %} + + + + + + + + + + {% endcompress %} + {% endif %} {% endif %} {% endif %} {% if hq %} - {% if use_bootstrap5 %} + {% if use_bootstrap5 %} + {% compress js %} - {% else %} - - {% endif %} + + + + {% endcompress %} + {% else %} {% compress js %} + {% endcompress %} + {% endif %} {% endif %} From 1e4b88688bbf9bf58a73eff436a3f0a5fbcc538f Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:18:41 +0200 Subject: [PATCH 12/22] removing this popover override as popover has been completely rewritten and tip() is no longer relevant either. will fix if we run into issues during migration, but this block of code throws an error in bootstrap 5 pages --- .../hqwebapp/js/bootstrap5/hq.helpers.js | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq.helpers.js b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq.helpers.js index c5efcee20af2..245af1df0ce8 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq.helpers.js +++ b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq.helpers.js @@ -59,19 +59,6 @@ hqDefine("hqwebapp/js/bootstrap5/hq.helpers", [ return false; // let default handler run }; - var oldHide = $.fn.popover.Constructor.prototype.hide; - - $.fn.popover.Constructor.prototype.hide = function () { - if (this.options.trigger === "hover" && this.tip().is(":hover")) { - var that = this; - setTimeout(function () { - return that.hide.apply(that, arguments); - }, that.options.delay.hide); - return; - } - oldHide.apply(this, arguments); - }; - $.fn.hqHelp = function () { var self = this; self.each(function (i) { @@ -103,6 +90,11 @@ hqDefine("hqwebapp/js/bootstrap5/hq.helpers", [ }); }; + $.fn.changeButtonState = function (state) { + $(this).text($(this).data(state + '-text')); + return this; + }; + $.fn.addSpinnerToButton = function () { $(this).find("i").addClass("hide"); $(this).prepend(' '); From 9071342a18c219f2ca72866387cee36008a1a7fa Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:20:51 +0200 Subject: [PATCH 13/22] whitespace changes for readability --- .../hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js index a803cafda6ee..7cd7bf8f6797 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js +++ b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js @@ -1,5 +1,7 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ - "jquery", "jquery-form/dist/jquery.form.min", "hqwebapp/js/bootstrap5/hq.helpers", + "jquery", + "jquery-form/dist/jquery.form.min", + "hqwebapp/js/bootstrap5/hq.helpers", ], function ($) { $(function () { var $hqwebappBugReportModal = $('#modalReportIssue'), From 9b50cec0fdca4ceed76231ede2e04f9480c4bc70 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:23:42 +0200 Subject: [PATCH 14/22] modernize hq-bug-report a little bit before we do the bootstrap relevant changes --- .../hqwebapp/js/bootstrap5/hq-bug-report.js | 125 +++++++++--------- 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js index 7cd7bf8f6797..65288a356a73 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js +++ b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js @@ -3,49 +3,52 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ "jquery-form/dist/jquery.form.min", "hqwebapp/js/bootstrap5/hq.helpers", ], function ($) { + 'use strict'; $(function () { - var $hqwebappBugReportModal = $('#modalReportIssue'), - $hqwebappBugReportForm = $('#hqwebapp-bugReportForm'), - $hqwebappBugReportSubmit = $('#bug-report-submit'), - $hqwebappBugReportCancel = $('#bug-report-cancel'), - $ccFormGroup = $("#bug-report-cc-form-group"), - $emailFormGroup = $("#bug-report-email-form-group"), - $issueSubjectFormGroup = $("#bug-report-subject-form-group"), - isBugReportSubmitting = false; + let self = {}; - var resetForm = function () { - $hqwebappBugReportForm.find("button[type='submit']").button('reset'); - $hqwebappBugReportForm.resetForm(); - $hqwebappBugReportCancel.enableButton(); - $hqwebappBugReportSubmit.button('reset'); - $ccFormGroup.removeClass('has-error has-feedback'); - $ccFormGroup.find(".label-danger").addClass('hide'); - $emailFormGroup.removeClass('has-error has-feedback'); - $emailFormGroup.find(".label-danger").addClass('hide'); + self.$hqwebappBugReportModal = $('#modalReportIssue'); + self.$hqwebappBugReportForm = $('#hqwebapp-bugReportForm'); + self.$hqwebappBugReportSubmit = $('#bug-report-submit'); + self.$hqwebappBugReportCancel = $('#bug-report-cancel'); + self.$ccFormGroup = $("#bug-report-cc-form-group"); + self.$emailFormGroup = $("#bug-report-email-form-group"); + self.$issueSubjectFormGroup = $("#bug-report-subject-form-group"); + self.isBugReportSubmitting = false; + + self.resetForm = function () { + self.$hqwebappBugReportForm.find("button[type='submit']").button('reset'); + self.$hqwebappBugReportForm.resetForm(); + self.$hqwebappBugReportCancel.enableButton(); + self.$hqwebappBugReportSubmit.button('reset'); + self.$ccFormGroup.removeClass('has-error has-feedback'); + self.$ccFormGroup.find(".label-danger").addClass('hide'); + self.$emailFormGroup.removeClass('has-error has-feedback'); + self.$emailFormGroup.find(".label-danger").addClass('hide'); }; - $hqwebappBugReportModal.on('shown.bs.modal', function () { + self.$hqwebappBugReportModal.on('shown.bs.modal', function () { $("input#bug-report-subject").focus(); }); - $hqwebappBugReportForm.submit(function () { - var isDescriptionEmpty = !$("#bug-report-subject").val() && !$("#bug-report-message").val(); + self.$hqwebappBugReportForm.submit(function (e) { + let isDescriptionEmpty = !$("#bug-report-subject").val() && !$("#bug-report-message").val(); if (isDescriptionEmpty) { - highlightInvalidField($issueSubjectFormGroup); + self.highlightInvalidField(self.$issueSubjectFormGroup); } - var emailAddress = $(this).find("input[name='email']").val(); - if (emailAddress && !IsValidEmail(emailAddress)) { - highlightInvalidField($emailFormGroup); + let emailAddress = $(this).find("input[name='email']").val(); + if (emailAddress && !self.isValidEmail(emailAddress)) { + self.highlightInvalidField(self.$emailFormGroup); return false; } - var emailAddresses = $(this).find("input[name='cc']").val(); + let emailAddresses = $(this).find("input[name='cc']").val(); emailAddresses = emailAddresses.replace(/ /g, "").split(","); - for (var index in emailAddresses) { - var email = emailAddresses[index]; - if (email && !IsValidEmail(email)) { - highlightInvalidField($ccFormGroup); + for (let index in emailAddresses) { + let email = emailAddresses[index]; + if (email && !self.isValidEmail(email)) { + self.highlightInvalidField(self.$ccFormGroup); return false; } } @@ -53,57 +56,61 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ return false; } - if (!isBugReportSubmitting && $hqwebappBugReportSubmit.text() === $hqwebappBugReportSubmit.data("success-text")) { - $hqwebappBugReportModal.modal("hide"); - } else if (!isBugReportSubmitting) { - $hqwebappBugReportCancel.disableButtonNoSpinner(); - $hqwebappBugReportSubmit.button('loading'); + if (!self.isBugReportSubmitting && self.$hqwebappBugReportSubmit.text() === + self.$hqwebappBugReportSubmit.data("success-text")) { + self.$hqwebappBugReportModal.modal('hide'); + } else if (!self.isBugReportSubmitting) { + self.$hqwebappBugReportCancel.disableButtonNoSpinner(); + self.$hqwebappBugReportSubmit.button('loading'); $(this).ajaxSubmit({ type: "POST", url: $(this).attr('action'), - beforeSerialize: hqwebappBugReportBeforeSerialize, - beforeSubmit: hqwebappBugReportBeforeSubmit, - success: hqwebappBugReportSucccess, - error: hqwebappBugReportError, + beforeSerialize: self.hqwebappBugReportBeforeSerialize, + beforeSubmit: self.hqwebappBugReportBeforeSubmit, + success: self.hqwebappBugReportSuccess, + error: self.hqwebappBugReportError, }); } return false; }); - function IsValidEmail(email) { - var regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; + self.isValidEmail = function (email) { + let regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; return regex.test(email); - } + }; - function hqwebappBugReportBeforeSerialize($form) { + self.hqwebappBugReportBeforeSerialize = function ($form) { $form.find("#bug-report-url").val(location.href); - } + }; - function hqwebappBugReportBeforeSubmit() { - isBugReportSubmitting = true; - } + self.hqwebappBugReportBeforeSubmit = function () { + self.isBugReportSubmitting = true; + }; - function hqwebappBugReportSucccess() { - isBugReportSubmitting = false; - $hqwebappBugReportForm.find("button[type='submit']").button('success').removeClass('btn-danger').addClass('btn-primary'); - $hqwebappBugReportModal.one('hidden.bs.modal', function () { - resetForm(); + self.hqwebappBugReportSuccess = function () { + self.isBugReportSubmitting = false; + self.$hqwebappBugReportModal.one('hidden.bs.modal', function () { + self.resetForm(); }); - } + self.$hqwebappBugReportForm.find("button[type='submit']") + .button('success') + .removeClass('btn-danger').addClass('btn-primary'); + }; - function hqwebappBugReportError() { - isBugReportSubmitting = false; - $hqwebappBugReportForm.find("button[type='submit']").button('error').removeClass('btn-primary').addClass('btn-danger'); - $hqwebappBugReportCancel.enableButton(); - } + self.hqwebappBugReportError = function () { + self.isBugReportSubmitting = false; + self.$hqwebappBugReportForm.find("button[type='submit']").button('error') + .removeClass('btn-primary').addClass('btn-danger'); + self.$hqwebappBugReportCancel.enableButton(); + }; - function highlightInvalidField($element) { + self.highlightInvalidField = function ($element) { $element.addClass('has-error has-feedback'); $element.find(".label-danger").removeClass('hide'); $element.find("input").focus(function () { $element.removeClass("has-error has-feedback"); $element.find(".label-danger").addClass('hide'); }); - } + }; }); }); From 2e67d0a8d8b40bb35cab6f2e3d45e657388747a3 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:26:23 +0200 Subject: [PATCH 15/22] update .button( to .changeButtonState( --- .../static/hqwebapp/js/bootstrap5/hq-bug-report.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js index 65288a356a73..46d2220e9743 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js +++ b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js @@ -17,10 +17,10 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ self.isBugReportSubmitting = false; self.resetForm = function () { - self.$hqwebappBugReportForm.find("button[type='submit']").button('reset'); + self.$hqwebappBugReportForm.find("button[type='submit']").changeButtonState('reset'); self.$hqwebappBugReportForm.resetForm(); self.$hqwebappBugReportCancel.enableButton(); - self.$hqwebappBugReportSubmit.button('reset'); + self.$hqwebappBugReportSubmit.changeButtonState('reset'); self.$ccFormGroup.removeClass('has-error has-feedback'); self.$ccFormGroup.find(".label-danger").addClass('hide'); self.$emailFormGroup.removeClass('has-error has-feedback'); @@ -61,7 +61,7 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ self.$hqwebappBugReportModal.modal('hide'); } else if (!self.isBugReportSubmitting) { self.$hqwebappBugReportCancel.disableButtonNoSpinner(); - self.$hqwebappBugReportSubmit.button('loading'); + self.$hqwebappBugReportSubmit.changeButtonState('loading'); $(this).ajaxSubmit({ type: "POST", url: $(this).attr('action'), @@ -93,13 +93,13 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ self.resetForm(); }); self.$hqwebappBugReportForm.find("button[type='submit']") - .button('success') + .changeButtonState('success') .removeClass('btn-danger').addClass('btn-primary'); }; self.hqwebappBugReportError = function () { self.isBugReportSubmitting = false; - self.$hqwebappBugReportForm.find("button[type='submit']").button('error') + self.$hqwebappBugReportForm.find("button[type='submit']").changeButtonState('error') .removeClass('btn-primary').addClass('btn-danger'); self.$hqwebappBugReportCancel.enableButton(); }; From 0c5ed92db95b156caf047b1ba93efdef663557b3 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:27:18 +0200 Subject: [PATCH 16/22] update bootstrap 5 modal js usage --- .../static/hqwebapp/js/bootstrap5/hq-bug-report.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js index 46d2220e9743..50d96a100f98 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js +++ b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js @@ -1,13 +1,15 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ "jquery", + "hqwebapp/js/bootstrap5_loader", "jquery-form/dist/jquery.form.min", "hqwebapp/js/bootstrap5/hq.helpers", -], function ($) { +], function ($, bootstrap) { 'use strict'; $(function () { let self = {}; - self.$hqwebappBugReportModal = $('#modalReportIssue'); + self.$bugReportModalElement = $('#modalReportIssue'); + self.bugReportModal = new bootstrap.Modal(self.$bugReportModalElement); self.$hqwebappBugReportForm = $('#hqwebapp-bugReportForm'); self.$hqwebappBugReportSubmit = $('#bug-report-submit'); self.$hqwebappBugReportCancel = $('#bug-report-cancel'); @@ -27,7 +29,7 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ self.$emailFormGroup.find(".label-danger").addClass('hide'); }; - self.$hqwebappBugReportModal.on('shown.bs.modal', function () { + self.$bugReportModalElement.on('shown.bs.modal', function () { $("input#bug-report-subject").focus(); }); @@ -58,7 +60,7 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ if (!self.isBugReportSubmitting && self.$hqwebappBugReportSubmit.text() === self.$hqwebappBugReportSubmit.data("success-text")) { - self.$hqwebappBugReportModal.modal('hide'); + self.bugReportModal.hide(); } else if (!self.isBugReportSubmitting) { self.$hqwebappBugReportCancel.disableButtonNoSpinner(); self.$hqwebappBugReportSubmit.changeButtonState('loading'); @@ -89,7 +91,7 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ self.hqwebappBugReportSuccess = function () { self.isBugReportSubmitting = false; - self.$hqwebappBugReportModal.one('hidden.bs.modal', function () { + self.$bugReportModalElement.one('hidden.bs.modal', function () { self.resetForm(); }); self.$hqwebappBugReportForm.find("button[type='submit']") From 7eb74a70111c9321a66be19093913d96251530b7 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:28:03 +0200 Subject: [PATCH 17/22] prevent form from submitting and posting to action url if anything in this submit function throws an error --- .../hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js index 50d96a100f98..778d7485c6d9 100644 --- a/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js +++ b/corehq/apps/hqwebapp/static/hqwebapp/js/bootstrap5/hq-bug-report.js @@ -34,6 +34,8 @@ hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ }); self.$hqwebappBugReportForm.submit(function (e) { + e.preventDefault(); + let isDescriptionEmpty = !$("#bug-report-subject").val() && !$("#bug-report-message").val(); if (isDescriptionEmpty) { self.highlightInvalidField(self.$issueSubjectFormGroup); From 07843c8c588fb2f5559d82718c2fe1a6829e31b9 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:28:28 +0200 Subject: [PATCH 18/22] migrate license pages to bootstrap 5 --- corehq/apps/hqwebapp/views.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/corehq/apps/hqwebapp/views.py b/corehq/apps/hqwebapp/views.py index c7b980972f2c..b2ad3becb4b2 100644 --- a/corehq/apps/hqwebapp/views.py +++ b/corehq/apps/hqwebapp/views.py @@ -76,7 +76,7 @@ DEPLOY_IN_PROGRESS_FLAG, ) from corehq.apps.hqadmin.service_checks import CHECKS, run_checks -from corehq.apps.hqwebapp.decorators import waf_allow +from corehq.apps.hqwebapp.decorators import waf_allow, use_bootstrap5 from corehq.apps.hqwebapp.doc_info import get_doc_info from corehq.apps.hqwebapp.doc_lookup import lookup_doc_id from corehq.apps.hqwebapp.encoders import LazyEncoder @@ -89,6 +89,7 @@ from corehq.apps.hqwebapp.models import HQOauthApplication from corehq.apps.hqwebapp.login_utils import get_custom_login_page from corehq.apps.hqwebapp.utils import get_environment_friendly_name +from corehq.apps.hqwebapp.utils.bootstrap import get_bootstrap_version from corehq.apps.locations.permissions import location_safe from corehq.apps.sms.event_handlers import handle_email_messaging_subevent from corehq.apps.users.event_handlers import handle_email_invite_message @@ -841,14 +842,16 @@ def render_static(request, template, page_name): """ Takes an html file and renders it Commcare HQ's styling """ - return render(request, "hqwebapp/bootstrap3/blank.html", + return render(request, f"hqwebapp/{get_bootstrap_version()}/blank.html", {'tmpl': template, 'page_name': page_name}) +@use_bootstrap5 def apache_license(request): return render_static(request, "apache_license.html", _("Apache License")) +@use_bootstrap5 def bsd_license(request): return render_static(request, "bsd_license.html", _("BSD License")) From 2a50add12bacb5cfcf2d09d61ff68d430c6acc59 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:28:46 +0200 Subject: [PATCH 19/22] update bootstrap 5 migration js guide for modal usage --- .../utils/bootstrap/changes_guide/js-modal.txt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/corehq/apps/hqwebapp/utils/bootstrap/changes_guide/js-modal.txt b/corehq/apps/hqwebapp/utils/bootstrap/changes_guide/js-modal.txt index cec01970d492..cc70e7ef4402 100644 --- a/corehq/apps/hqwebapp/utils/bootstrap/changes_guide/js-modal.txt +++ b/corehq/apps/hqwebapp/utils/bootstrap/changes_guide/js-modal.txt @@ -1,9 +1,22 @@ The `modal` plugin has been restructured since the removal of jQuery. There is now a new way of triggering modal events and interacting with modals in javascript. +For instance, if we wanted to hide a modal with id `#bugReport` before, we would now do the +following... -Please feel free to update this help text as you find common replacements/restructuring -for our usage of this plugin. Thanks! +previously +``` +$('#bugReport').modal('hide'); +``` + +now +``` +const bugReportModal = new bootstrap.Modal($('#bugReport')); +bugReportModal.hide(); +``` + +Hint: make sure to list `hqwebapp/js/bootstrap5_loader` as a js dependency in the file where +bootstrap is referenced. Old docs: https://getbootstrap.com/docs/3.4/javascript/#modals New docs: https://getbootstrap.com/docs/5.3/components/modal/#via-javascript From 4ada7db7f13fc669195aa515600d347dd1fb7d06 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Tue, 29 Aug 2023 21:35:16 +0200 Subject: [PATCH 20/22] build bootstrap 5 migration diffs --- .../hqwebapp/alert_user.js.diff.txt | 8 +- .../hqwebapp/hq-bug-report.js.diff.txt | 183 +++++++++++++++++- .../hqwebapp/hq.helpers.js.diff.txt | 32 +++ .../dropdowns._dropdown.style.diff.txt | 15 +- ...cludes_variables._variables.style.diff.txt | 23 ++- .../layouts._containers.style.diff.txt | 8 +- .../imports/navs._nav.style.diff.txt | 10 +- .../imports/typography._type.style.diff.txt | 11 ++ .../style-imports.commcarehq.style.diff.txt | 3 +- 9 files changed, 271 insertions(+), 22 deletions(-) diff --git a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/alert_user.js.diff.txt b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/alert_user.js.diff.txt index 564ea8a604fb..522b85780c7b 100644 --- a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/alert_user.js.diff.txt +++ b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/alert_user.js.diff.txt @@ -1,6 +1,6 @@ --- +++ -@@ -13,7 +13,7 @@ +@@ -13,10 +13,10 @@ (success < info < warning < danger). fadeOut: Set to 'true' to have the message automatically removed from the UI after 5s. */ @@ -8,4 +8,8 @@ +hqDefine("hqwebapp/js/bootstrap5/alert_user", [ "jquery", "knockout", - "hqwebapp/js/bootstrap3/hq.helpers", +- "hqwebapp/js/bootstrap3/hq.helpers", ++ "hqwebapp/js/bootstrap5/hq.helpers", + ], + function ( + $, diff --git a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/hq-bug-report.js.diff.txt b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/hq-bug-report.js.diff.txt index c31613200580..1754533dd38c 100644 --- a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/hq-bug-report.js.diff.txt +++ b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/hq-bug-report.js.diff.txt @@ -1,10 +1,185 @@ --- +++ -@@ -1,5 +1,5 @@ +@@ -1,49 +1,58 @@ -hqDefine('hqwebapp/js/bootstrap3/hq-bug-report', [ - "jquery", "jquery-form/dist/jquery.form.min", "hqwebapp/js/bootstrap3/hq.helpers", +-], function ($) { +hqDefine('hqwebapp/js/bootstrap5/hq-bug-report', [ -+ "jquery", "jquery-form/dist/jquery.form.min", "hqwebapp/js/bootstrap5/hq.helpers", - ], function ($) { ++ "jquery", ++ "hqwebapp/js/bootstrap5_loader", ++ "jquery-form/dist/jquery.form.min", ++ "hqwebapp/js/bootstrap5/hq.helpers", ++], function ($, bootstrap) { ++ 'use strict'; $(function () { - var $hqwebappBugReportModal = $('#modalReportIssue'), +- var $hqwebappBugReportModal = $('#modalReportIssue'), +- $hqwebappBugReportForm = $('#hqwebapp-bugReportForm'), +- $hqwebappBugReportSubmit = $('#bug-report-submit'), +- $hqwebappBugReportCancel = $('#bug-report-cancel'), +- $ccFormGroup = $("#bug-report-cc-form-group"), +- $emailFormGroup = $("#bug-report-email-form-group"), +- $issueSubjectFormGroup = $("#bug-report-subject-form-group"), +- isBugReportSubmitting = false; ++ let self = {}; + +- var resetForm = function () { +- $hqwebappBugReportForm.find("button[type='submit']").button('reset'); +- $hqwebappBugReportForm.resetForm(); +- $hqwebappBugReportCancel.enableButton(); +- $hqwebappBugReportSubmit.button('reset'); +- $ccFormGroup.removeClass('has-error has-feedback'); +- $ccFormGroup.find(".label-danger").addClass('hide'); +- $emailFormGroup.removeClass('has-error has-feedback'); +- $emailFormGroup.find(".label-danger").addClass('hide'); ++ self.$bugReportModalElement = $('#modalReportIssue'); ++ self.bugReportModal = new bootstrap.Modal(self.$bugReportModalElement); ++ self.$hqwebappBugReportForm = $('#hqwebapp-bugReportForm'); ++ self.$hqwebappBugReportSubmit = $('#bug-report-submit'); ++ self.$hqwebappBugReportCancel = $('#bug-report-cancel'); ++ self.$ccFormGroup = $("#bug-report-cc-form-group"); ++ self.$emailFormGroup = $("#bug-report-email-form-group"); ++ self.$issueSubjectFormGroup = $("#bug-report-subject-form-group"); ++ self.isBugReportSubmitting = false; ++ ++ self.resetForm = function () { ++ self.$hqwebappBugReportForm.find("button[type='submit']").changeButtonState('reset'); ++ self.$hqwebappBugReportForm.resetForm(); ++ self.$hqwebappBugReportCancel.enableButton(); ++ self.$hqwebappBugReportSubmit.changeButtonState('reset'); ++ self.$ccFormGroup.removeClass('has-error has-feedback'); ++ self.$ccFormGroup.find(".label-danger").addClass('hide'); ++ self.$emailFormGroup.removeClass('has-error has-feedback'); ++ self.$emailFormGroup.find(".label-danger").addClass('hide'); + }; + +- $hqwebappBugReportModal.on('shown.bs.modal', function () { ++ self.$bugReportModalElement.on('shown.bs.modal', function () { + $("input#bug-report-subject").focus(); + }); + +- $hqwebappBugReportForm.submit(function () { +- var isDescriptionEmpty = !$("#bug-report-subject").val() && !$("#bug-report-message").val(); ++ self.$hqwebappBugReportForm.submit(function (e) { ++ e.preventDefault(); ++ ++ let isDescriptionEmpty = !$("#bug-report-subject").val() && !$("#bug-report-message").val(); + if (isDescriptionEmpty) { +- highlightInvalidField($issueSubjectFormGroup); ++ self.highlightInvalidField(self.$issueSubjectFormGroup); + } + +- var emailAddress = $(this).find("input[name='email']").val(); +- if (emailAddress && !IsValidEmail(emailAddress)) { +- highlightInvalidField($emailFormGroup); ++ let emailAddress = $(this).find("input[name='email']").val(); ++ if (emailAddress && !self.isValidEmail(emailAddress)) { ++ self.highlightInvalidField(self.$emailFormGroup); + return false; + } + +- var emailAddresses = $(this).find("input[name='cc']").val(); ++ let emailAddresses = $(this).find("input[name='cc']").val(); + emailAddresses = emailAddresses.replace(/ /g, "").split(","); +- for (var index in emailAddresses) { +- var email = emailAddresses[index]; +- if (email && !IsValidEmail(email)) { +- highlightInvalidField($ccFormGroup); ++ for (let index in emailAddresses) { ++ let email = emailAddresses[index]; ++ if (email && !self.isValidEmail(email)) { ++ self.highlightInvalidField(self.$ccFormGroup); + return false; + } + } +@@ -51,57 +60,61 @@ + return false; + } + +- if (!isBugReportSubmitting && $hqwebappBugReportSubmit.text() === $hqwebappBugReportSubmit.data("success-text")) { +- $hqwebappBugReportModal.modal("hide"); +- } else if (!isBugReportSubmitting) { +- $hqwebappBugReportCancel.disableButtonNoSpinner(); +- $hqwebappBugReportSubmit.button('loading'); ++ if (!self.isBugReportSubmitting && self.$hqwebappBugReportSubmit.text() === ++ self.$hqwebappBugReportSubmit.data("success-text")) { ++ self.bugReportModal.hide(); ++ } else if (!self.isBugReportSubmitting) { ++ self.$hqwebappBugReportCancel.disableButtonNoSpinner(); ++ self.$hqwebappBugReportSubmit.changeButtonState('loading'); + $(this).ajaxSubmit({ + type: "POST", + url: $(this).attr('action'), +- beforeSerialize: hqwebappBugReportBeforeSerialize, +- beforeSubmit: hqwebappBugReportBeforeSubmit, +- success: hqwebappBugReportSucccess, +- error: hqwebappBugReportError, ++ beforeSerialize: self.hqwebappBugReportBeforeSerialize, ++ beforeSubmit: self.hqwebappBugReportBeforeSubmit, ++ success: self.hqwebappBugReportSuccess, ++ error: self.hqwebappBugReportError, + }); + } + return false; + }); + +- function IsValidEmail(email) { +- var regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; ++ self.isValidEmail = function (email) { ++ let regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; + return regex.test(email); +- } ++ }; + +- function hqwebappBugReportBeforeSerialize($form) { ++ self.hqwebappBugReportBeforeSerialize = function ($form) { + $form.find("#bug-report-url").val(location.href); +- } ++ }; + +- function hqwebappBugReportBeforeSubmit() { +- isBugReportSubmitting = true; +- } ++ self.hqwebappBugReportBeforeSubmit = function () { ++ self.isBugReportSubmitting = true; ++ }; + +- function hqwebappBugReportSucccess() { +- isBugReportSubmitting = false; +- $hqwebappBugReportForm.find("button[type='submit']").button('success').removeClass('btn-danger').addClass('btn-primary'); +- $hqwebappBugReportModal.one('hidden.bs.modal', function () { +- resetForm(); ++ self.hqwebappBugReportSuccess = function () { ++ self.isBugReportSubmitting = false; ++ self.$bugReportModalElement.one('hidden.bs.modal', function () { ++ self.resetForm(); + }); +- } ++ self.$hqwebappBugReportForm.find("button[type='submit']") ++ .changeButtonState('success') ++ .removeClass('btn-danger').addClass('btn-primary'); ++ }; + +- function hqwebappBugReportError() { +- isBugReportSubmitting = false; +- $hqwebappBugReportForm.find("button[type='submit']").button('error').removeClass('btn-primary').addClass('btn-danger'); +- $hqwebappBugReportCancel.enableButton(); +- } ++ self.hqwebappBugReportError = function () { ++ self.isBugReportSubmitting = false; ++ self.$hqwebappBugReportForm.find("button[type='submit']").changeButtonState('error') ++ .removeClass('btn-primary').addClass('btn-danger'); ++ self.$hqwebappBugReportCancel.enableButton(); ++ }; + +- function highlightInvalidField($element) { ++ self.highlightInvalidField = function ($element) { + $element.addClass('has-error has-feedback'); + $element.find(".label-danger").removeClass('hide'); + $element.find("input").focus(function () { + $element.removeClass("has-error has-feedback"); + $element.find(".label-danger").addClass('hide'); + }); +- } ++ }; + }); + }); diff --git a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/hq.helpers.js.diff.txt b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/hq.helpers.js.diff.txt index 28b7decbbf5d..709ba772458e 100644 --- a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/hq.helpers.js.diff.txt +++ b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/javascript/hqwebapp/hq.helpers.js.diff.txt @@ -6,3 +6,35 @@ 'jquery', 'knockout', 'underscore', +@@ -59,19 +59,6 @@ + return false; // let default handler run + }; + +- var oldHide = $.fn.popover.Constructor.prototype.hide; +- +- $.fn.popover.Constructor.prototype.hide = function () { +- if (this.options.trigger === "hover" && this.tip().is(":hover")) { +- var that = this; +- setTimeout(function () { +- return that.hide.apply(that, arguments); +- }, that.options.delay.hide); +- return; +- } +- oldHide.apply(this, arguments); +- }; +- + $.fn.hqHelp = function () { + var self = this; + self.each(function (i) { +@@ -101,6 +88,11 @@ + event.preventDefault(); + }); + }); ++ }; ++ ++ $.fn.changeButtonState = function (state) { ++ $(this).text($(this).data(state + '-text')); ++ return this; + }; + + $.fn.addSpinnerToButton = function () { diff --git a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/dropdowns._dropdown.style.diff.txt b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/dropdowns._dropdown.style.diff.txt index de9c8d33f5a6..58a1f6dc6658 100644 --- a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/dropdowns._dropdown.style.diff.txt +++ b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/dropdowns._dropdown.style.diff.txt @@ -1,6 +1,6 @@ --- +++ -@@ -24,97 +24,69 @@ +@@ -24,97 +24,74 @@ border-color: transparent; border-style: solid; border-width: 5px 0 5px 5px; @@ -9,7 +9,7 @@ - margin-top: 3px; - color: @dropdown-link-color; - line-height: @line-height-base; -+ border-left-color: darken($dropdown-bg, 20%); ++ border-left-color: darken($body-bg, 20%); + margin-right: -5px; + margin-top: 3.3px; + color: $dropdown-link-color; @@ -96,14 +96,19 @@ + margin-top: 5px; + } + -+ .dropdown-menu .dropdown-divider { -+ margin-top: 0px; -+ margin-bottom: 0px; ++ .navbar-nav > li > a.dropdown-toggle-with-icon { ++ padding-top: 22px !important; ++ padding-bottom: 17px !important; + } + + .nav-settings-bar .dropdown-toggle-with-icon.nav-link::after { + display: none; + } ++ ++ .dropdown-toggle::after { ++ vertical-align: 2.48px; ++ margin-left: 2px; ++ } +} + +@media (max-width: map-get($grid-breakpoints, "lg")) { diff --git a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/includes_variables._variables.style.diff.txt b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/includes_variables._variables.style.diff.txt index 8ca48ddd6439..e5c1030bbe39 100644 --- a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/includes_variables._variables.style.diff.txt +++ b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/includes_variables._variables.style.diff.txt @@ -1,18 +1,29 @@ --- +++ -@@ -1,119 +1,111 @@ +@@ -1,119 +1,122 @@ -@import "@{b3-import-variables}"; -+// Typography Overrides -+$font-family-sans-serif: "Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; -+$font-size-base: .75rem; // approx 12px ++// Grid Containers ++// we will want to adapt the defaults in a full redesign ++$container-max-widths: ( ++ sm: 540px, ++ md: 720px, ++ lg: 960px, ++ xl: 1140px, ++ xxl: 1160px ++); -// Nunito Sans is used on dimagi.com and embedded in hqwebapp/base.html -@font-family-sans-serif: "Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; -+// Links -+$link-decoration: none; -@font-size-base: 12px; -@icon-font-path: "../../bootstrap/fonts/"; ++// Typography Overrides ++$font-family-sans-serif: "Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; ++$font-size-base: .75rem; // approx 12px ++ ++// Links ++$link-decoration: none; ++ +// Form Overrides +$input-border-radius-lg: 5px; + diff --git a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/layouts._containers.style.diff.txt b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/layouts._containers.style.diff.txt index 955db4aff434..931797da4f89 100644 --- a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/layouts._containers.style.diff.txt +++ b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/layouts._containers.style.diff.txt @@ -1,10 +1,12 @@ --- +++ -@@ -1,32 +1,11 @@ +@@ -1,32 +1,15 @@ -body, html { - height: 100%; --} -- ++html, body { ++ height: 100%; + } + .hq-container { min-height: 100%; height: auto !important; diff --git a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/navs._nav.style.diff.txt b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/navs._nav.style.diff.txt index e7d3dc762f45..befd5207acde 100644 --- a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/navs._nav.style.diff.txt +++ b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/navs._nav.style.diff.txt @@ -36,7 +36,15 @@ } .nav-input { padding: 3px 20px; -@@ -68,7 +68,7 @@ +@@ -54,6 +54,7 @@ + .nav-main-icon { + font-size: 1.7em; + line-height: 0.7em; ++ color: $gray-light; + } + + .text-hq-nav-header { +@@ -68,7 +69,7 @@ } .nav > li > a { diff --git a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/typography._type.style.diff.txt b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/typography._type.style.diff.txt index 18d3c742bfa4..011dab19e956 100644 --- a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/typography._type.style.diff.txt +++ b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/imports/typography._type.style.diff.txt @@ -28,3 +28,14 @@ } .no-border { +@@ -89,3 +90,10 @@ + a { + cursor: pointer; + } ++ ++// we should eventually get rid of this as bootstrap5+ doesn't natively support ++.page-header { ++ padding-bottom: 7.5px; ++ margin: 34px 0 17px; ++ border-bottom: 1px solid #eeeeee; ++} \ No newline at end of file diff --git a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/style-imports.commcarehq.style.diff.txt b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/style-imports.commcarehq.style.diff.txt index 6b4ac2ab3b82..a6e9e037cb48 100644 --- a/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/style-imports.commcarehq.style.diff.txt +++ b/corehq/apps/hqwebapp/tests/data/bootstrap5_diffs/stylesheets/style-imports.commcarehq.style.diff.txt @@ -1,6 +1,6 @@ --- +++ -@@ -1,43 +1,93 @@ +@@ -1,43 +1,94 @@ -@import "_hq/includes/variables.less"; -@import "_hq/includes/mixins.less"; @@ -48,6 +48,7 @@ +@import "functions"; +@import "commcarehq/variables"; // This comes before Bootstrap 5 variables to override the defaults +@import "variables"; ++@import "variables-dark"; +@import "commcarehq/variables_bootstrap3"; // Variables specific to B3-era Stylesheet +@import "maps"; +@import "mixins"; From 432dcd317caba07db40a090f5dbfd3ce74596876 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Wed, 30 Aug 2023 15:03:59 +0200 Subject: [PATCH 21/22] update expected core libraries template to fix test and match changes --- .../rendered/javascript_libraries_hq_bootstrap5.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/corehq/apps/hqwebapp/templatetags/tests/rendered/javascript_libraries_hq_bootstrap5.html b/corehq/apps/hqwebapp/templatetags/tests/rendered/javascript_libraries_hq_bootstrap5.html index 27c9e69e8fb2..af54c8c15cee 100644 --- a/corehq/apps/hqwebapp/templatetags/tests/rendered/javascript_libraries_hq_bootstrap5.html +++ b/corehq/apps/hqwebapp/templatetags/tests/rendered/javascript_libraries_hq_bootstrap5.html @@ -8,7 +8,7 @@ - + @@ -27,16 +27,16 @@ - + - - + + - - + + From c8b4e31c0f81cccc6d08f581b90a0bd4d38dfe89 Mon Sep 17 00:00:00 2001 From: Biyeun Buczyk Date: Wed, 30 Aug 2023 18:01:17 +0200 Subject: [PATCH 22/22] fix test from updated copy --- .../tests/utils/test_bootstrap_changes.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/corehq/apps/hqwebapp/tests/utils/test_bootstrap_changes.py b/corehq/apps/hqwebapp/tests/utils/test_bootstrap_changes.py index 1eac08a7cfa5..6eb781272804 100644 --- a/corehq/apps/hqwebapp/tests/utils/test_bootstrap_changes.py +++ b/corehq/apps/hqwebapp/tests/utils/test_bootstrap_changes.py @@ -64,12 +64,16 @@ def test_flag_changed_javascript_plugins_bootstrap5(): flags = flag_changed_javascript_plugins( line, get_spec('bootstrap_3_to_5') ) - eq(flags, ['The `modal` plugin has been restructured since the removal of jQuery.\n\n' - 'There is now a new way of triggering modal events and interacting with ' - 'modals in javascript.\n\nPlease feel free to update this help text as ' - 'you find common replacements/restructuring\nfor our usage of this plugin. ' - 'Thanks!\n\nOld docs: https://getbootstrap.com/docs/3.4/javascript/#modals\n' - 'New docs: https://getbootstrap.com/docs/5.3/components/modal/#via-javascript\n']) + eq(flags, ["The `modal` plugin has been restructured since the removal of jQuery.\n\n" + "There is now a new way of triggering modal events and interacting with " + "modals in javascript.\nFor instance, if we wanted to hide a modal with " + "id `#bugReport` before, we would now do the\nfollowing...\n\npreviously" + "\n```\n$('#bugReport').modal('hide');\n```\n\nnow\n```\nconst bugReportModal" + " = new bootstrap.Modal($('#bugReport'));\nbugReportModal.hide();\n```\n\n" + "Hint: make sure to list `hqwebapp/js/bootstrap5_loader` as a js dependency " + "in the file where\nbootstrap is referenced.\n\nOld docs: " + "https://getbootstrap.com/docs/3.4/javascript/#modals\nNew docs: " + "https://getbootstrap.com/docs/5.3/components/modal/#via-javascript\n"]) def test_flag_extended_changed_javascript_plugins_bootstrap5():