diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f4e1bac3c5..0c2ab8a434 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -137,9 +137,9 @@ jobs: echo "Running tests..." if [[ "x${{ github.event.inputs.ignoreLowerCoverage }}" == "xtrue" ]]; then echo "Lower coverage failures will be ignored." - ./ietf/manage.py test --settings=settings_postgrestest --ignore-lower-coverage + ./ietf/manage.py test --validate-html-harder --settings=settings_test --ignore-lower-coverage else - ./ietf/manage.py test --settings=settings_postgrestest + ./ietf/manage.py test --validate-html-harder --settings=settings_test fi coverage xml diff --git a/.github/workflows/ci-run-tests.yml b/.github/workflows/ci-run-tests.yml index e8e9fe324b..eec60cb641 100644 --- a/.github/workflows/ci-run-tests.yml +++ b/.github/workflows/ci-run-tests.yml @@ -45,7 +45,7 @@ jobs: exit 1 fi echo "Running tests..." - ./ietf/manage.py test --settings=settings_postgrestest + ./ietf/manage.py test --validate-html-harder --settings=settings_test coverage xml - name: Upload Coverage Results to Codecov diff --git a/.pnp.cjs b/.pnp.cjs index bb809ceb11..622e680ac2 100644 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -49,7 +49,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@rollup/pluginutils", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.0.2"],\ ["@twuni/emojify", "npm:1.0.2"],\ ["@vitejs/plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.2.3"],\ - ["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.2.3"],\ + ["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.0"],\ ["bootstrap-icons", "npm:1.10.5"],\ ["browser-fs-access", "npm:0.34.1"],\ ["browserlist", "npm:1.0.1"],\ @@ -3131,10 +3131,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ - ["npm:5.2.3", {\ - "packageLocation": "./.yarn/cache/bootstrap-npm-5.2.3-7458283a23-0211805dec.zip/node_modules/bootstrap/",\ + ["npm:5.3.0", {\ + "packageLocation": "./.yarn/cache/bootstrap-npm-5.3.0-240c38a3b2-29a83cc8ca.zip/node_modules/bootstrap/",\ "packageDependencies": [\ - ["bootstrap", "npm:5.2.3"]\ + ["bootstrap", "npm:5.3.0"]\ ],\ "linkType": "SOFT"\ }],\ @@ -3151,10 +3151,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "HARD"\ }],\ - ["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.2.3", {\ - "packageLocation": "./.yarn/__virtual__/bootstrap-virtual-c4952ffff0/0/cache/bootstrap-npm-5.2.3-7458283a23-0211805dec.zip/node_modules/bootstrap/",\ + ["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.0", {\ + "packageLocation": "./.yarn/__virtual__/bootstrap-virtual-3c63ba6f80/0/cache/bootstrap-npm-5.3.0-240c38a3b2-29a83cc8ca.zip/node_modules/bootstrap/",\ "packageDependencies": [\ - ["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.2.3"],\ + ["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.0"],\ ["@popperjs/core", "npm:2.11.8"],\ ["@types/popperjs__core", null]\ ],\ @@ -7887,7 +7887,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@rollup/pluginutils", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.0.2"],\ ["@twuni/emojify", "npm:1.0.2"],\ ["@vitejs/plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.2.3"],\ - ["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.2.3"],\ + ["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.0"],\ ["bootstrap-icons", "npm:1.10.5"],\ ["browser-fs-access", "npm:0.34.1"],\ ["browserlist", "npm:1.0.1"],\ diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 7e43a30f88..4bd0b99363 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -48,7 +48,7 @@ "args": [ "${workspaceFolder}/ietf/manage.py", "test", - "--settings=settings_postgrestest" + "--settings=settings_test" ], "group": "test", "presentation": { @@ -68,7 +68,7 @@ "args": [ "${workspaceFolder}/ietf/manage.py", "test", - "--settings=settings_postgrestest", + "--settings=settings_test", "--pattern=tests_js.py" ], "group": "test", diff --git a/.yarn/cache/bootstrap-npm-5.2.3-7458283a23-0211805dec.zip b/.yarn/cache/bootstrap-npm-5.2.3-7458283a23-0211805dec.zip deleted file mode 100644 index 24c59290c5..0000000000 Binary files a/.yarn/cache/bootstrap-npm-5.2.3-7458283a23-0211805dec.zip and /dev/null differ diff --git a/.yarn/cache/bootstrap-npm-5.3.0-240c38a3b2-29a83cc8ca.zip b/.yarn/cache/bootstrap-npm-5.3.0-240c38a3b2-29a83cc8ca.zip new file mode 100644 index 0000000000..8099bab24f Binary files /dev/null and b/.yarn/cache/bootstrap-npm-5.3.0-240c38a3b2-29a83cc8ca.zip differ diff --git a/LICENSE b/LICENSE index aaed0ef57d..c180fa3f9f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2008-2022, The IETF Trust +Copyright (c) 2008-2023, The IETF Trust All rights reserved. Redistribution and use in source and binary forms, with or without @@ -26,4 +26,4 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index 7a46bd9cd2..20c9f3e599 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ If VS Code is not available to you, in your clone, type `cd docker; ./run` Once the containers are started, run the tests to make sure your checkout is a good place to start from (all tests should pass - if any fail, ask for help at tools-develop@). Inside the app container's shell type: ```sh -ietf/manage.py test --settings=settings_postgrestest +ietf/manage.py test --settings=settings_test ``` Note that we recently moved the datatracker onto PostgreSQL - you may still find older documentation that suggests testing with settings_sqlitetest. That will no longer work. @@ -228,7 +228,7 @@ before activating a new release. From a datatracker container, run the command: ```sh -./ietf/manage.py test --settings=settings_postgrestest +./ietf/manage.py test --settings=settings_test ``` > You can limit the run to specific tests using the `--pattern` argument. diff --git a/client/App.vue b/client/App.vue index 0664525ca4..2a6c5e6e98 100644 --- a/client/App.vue +++ b/client/App.vue @@ -26,6 +26,21 @@ const siteStore = useSiteStore() const appContainer = ref(null) +// -------------------------------------------------------------------- +// Set user theme +// -------------------------------------------------------------------- + +const desiredTheme = window.localStorage?.getItem('theme') +if (desiredTheme === 'dark') { + siteStore.theme = 'dark' +} else if (desiredTheme === 'light') { + siteStore.theme = 'light' +} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) { + siteStore.theme = 'dark' +} else { + siteStore.theme = 'light' +} + // -------------------------------------------------------------------- // Handle browser resize // -------------------------------------------------------------------- diff --git a/client/agenda/Agenda.vue b/client/agenda/Agenda.vue index 1cd1042f4f..0212fc8cb6 100644 --- a/client/agenda/Agenda.vue +++ b/client/agenda/Agenda.vue @@ -533,6 +533,13 @@ onMounted(() => { color: $blue-700; position: relative; + @at-root .theme-dark & { + border: 1px solid $blue-800; + background: linear-gradient(to top, lighten($blue-900, 2%), lighten($blue-900, 5%)); + color: $blue-100; + box-shadow: inset 0 0 0 1px #000; + } + > button { position: absolute; top: 15px; diff --git a/client/agenda/AgendaDetailsModal.vue b/client/agenda/AgendaDetailsModal.vue index 0a140b8c4e..037e32f9cb 100644 --- a/client/agenda/AgendaDetailsModal.vue +++ b/client/agenda/AgendaDetailsModal.vue @@ -282,6 +282,10 @@ async function fetchSessionMaterials () { .bi { font-size: 20px; color: $indigo; + + @at-root .theme-dark & { + color: $indigo-300; + } } .detail-header { @@ -343,6 +347,11 @@ async function fetchSessionMaterials () { border-radius: 5px; font-weight: 500; + @at-root .theme-dark & { + background-color: $gray-900; + border-color: $gray-700; + } + a { cursor: pointer; @@ -365,6 +374,11 @@ async function fetchSessionMaterials () { margin-top: 12px; border-radius: 5px; + @at-root .theme-dark & { + background-color: $gray-900; + border-color: $gray-700; + } + .bi { color: $blue; } @@ -377,6 +391,10 @@ async function fetchSessionMaterials () { border: none; border-radius: 5px; display: block; + + @at-root .theme-dark & { + background-color: $gray-900; + } } } diff --git a/client/agenda/AgendaFilter.vue b/client/agenda/AgendaFilter.vue index 629096211d..b1f1065708 100644 --- a/client/agenda/AgendaFilter.vue +++ b/client/agenda/AgendaFilter.vue @@ -217,30 +217,58 @@ function toggleFilterGroup (key) { padding: 5px; border-radius: 10px; + @at-root .theme-dark & { + background-color: $gray-800; + } + &:nth-child(2) { background-color: $blue-100; + @at-root .theme-dark & { + background-color: $gray-800; + } + .agenda-personalize-areamain { button { color: $blue-600; + + @at-root .theme-dark & { + color: $blue-100; + } } } .agenda-personalize-groups { background-color: lighten($blue-100, 7%); + + @at-root .theme-dark & { + background-color: $gray-700; + } } } &:nth-child(3) { background-color: $orange-100; + @at-root .theme-dark & { + background-color: $gray-800; + } + .agenda-personalize-areamain { button { color: $orange-600; + + @at-root .theme-dark & { + color: $orange-100; + } } } .agenda-personalize-groups { background-color: lighten($orange-100, 7%); + + @at-root .theme-dark & { + background-color: $gray-700; + } } } @@ -276,6 +304,12 @@ function toggleFilterGroup (key) { transition: background-color .5s ease; position: relative; + @at-root .theme-dark & { + background-color: $gray-600; + border-color: $gray-700; + color: #FFF; + } + > .bi { margin-right: .5rem; } @@ -310,6 +344,10 @@ function toggleFilterGroup (key) { flex: 1; display: flex; flex-wrap: wrap; + + @at-root .theme-dark & { + background-color: $gray-700; + } } &-group { @@ -324,6 +362,12 @@ function toggleFilterGroup (key) { color: $gray-600; margin-right: 0px; + @at-root .theme-dark & { + background-color: $gray-600; + border-color: $gray-700; + color: #FFF; + } + @media screen and (max-width: $bs5-break-sm) { font-size: .9em; } diff --git a/client/agenda/AgendaQuickAccess.vue b/client/agenda/AgendaQuickAccess.vue index ae23edcabb..5952e6de1c 100644 --- a/client/agenda/AgendaQuickAccess.vue +++ b/client/agenda/AgendaQuickAccess.vue @@ -219,6 +219,9 @@ function scrollToNow (ev) { - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ietf/static/images/ietf-logo-white.svg b/ietf/static/images/ietf-logo-white.svg new file mode 100644 index 0000000000..2417f917ce --- /dev/null +++ b/ietf/static/images/ietf-logo-white.svg @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ietf/static/images/irtf-logo-white.svg b/ietf/static/images/irtf-logo-white.svg new file mode 100644 index 0000000000..a67412581e --- /dev/null +++ b/ietf/static/images/irtf-logo-white.svg @@ -0,0 +1,65 @@ + + + + + R + + + + + + diff --git a/ietf/static/images/irtf-logo.svg b/ietf/static/images/irtf-logo.svg index be64890b25..10b2a96816 100644 --- a/ietf/static/images/irtf-logo.svg +++ b/ietf/static/images/irtf-logo.svg @@ -6,7 +6,7 @@ version="1.1" id="svg303" sodipodi:docname="irtf-logo.svg" - inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)" + inkscape:version="1.2.2 (b0a84865, 2022-12-01)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" @@ -24,12 +24,12 @@ inkscape:deskcolor="#d1d1d1" showgrid="false" inkscape:zoom="1.0373737" - inkscape:cx="304.1334" - inkscape:cy="446.80136" + inkscape:cx="303.65142" + inkscape:cy="447.76535" inkscape:window-width="1797" inkscape:window-height="1083" inkscape:window-x="951" - inkscape:window-y="445" + inkscape:window-y="417" inkscape:window-maximized="0" inkscape:current-layer="svg303" /> R -
+
diff --git a/ietf/static/js/password_strength.js b/ietf/static/js/password_strength.js index eaeed2e1c4..4df5c14439 100644 --- a/ietf/static/js/password_strength.js +++ b/ietf/static/js/password_strength.js @@ -30,7 +30,7 @@ widget .find(".label-danger") - .addClass("bg-danger") + .addClass("text-bg-danger") .removeClass("label-danger"); widget @@ -64,13 +64,13 @@ .val()); if (result.score < 3) { - password_strength_bar.removeClass('bg-success') - .addClass('bg-warning'); + password_strength_bar.removeClass('text-bg-success') + .addClass('text-bg-warning'); password_strength_info.find('.badge') .removeClass('d-none'); } else { - password_strength_bar.removeClass('bg-warning') - .addClass('bg-success'); + password_strength_bar.removeClass('text-bg-warning') + .addClass('text-bg-success'); password_strength_info.find('.badge') .addClass('d-none'); } @@ -86,8 +86,8 @@ .html(result.crack_times_display.offline_slow_hashing_1e4_per_second); password_strength_offline_info.removeClass('d-none'); } else { - password_strength_bar.removeClass('bg-success') - .addClass('bg-warning'); + password_strength_bar.removeClass('text-bg-success') + .addClass('text-bg-warning'); password_strength_bar.width('0%') .attr('aria-valuenow', 0); password_strength_info.addClass('d-none'); @@ -186,4 +186,4 @@ // Call the init for backwards compatibility djangoPasswordStrength.init(); -})(jQuery, window, document); \ No newline at end of file +})(jQuery, window, document); diff --git a/ietf/static/js/theme.js b/ietf/static/js/theme.js new file mode 100644 index 0000000000..d244eec288 --- /dev/null +++ b/ietf/static/js/theme.js @@ -0,0 +1,88 @@ +/*! + * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * + * https://github.com/twbs/bootstrap/blob/main/site/static/docs/5.3/assets/js/color-modes.js + */ + +(() => { + 'use strict' + + const getStoredTheme = () => localStorage.getItem('theme') || 'auto' + const setStoredTheme = theme => localStorage.setItem('theme', theme) + + const getPreferredTheme = () => { + const storedTheme = getStoredTheme() + if (storedTheme) { + return storedTheme + } + + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' + } + + const setTheme = theme => { + if (theme === 'auto') { + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.documentElement.setAttribute('data-bs-theme', 'dark') + } else if (window.matchMedia('(prefers-color-scheme: light)').matches) { + document.documentElement.setAttribute('data-bs-theme', 'light') + } + } else { + document.documentElement.setAttribute('data-bs-theme', theme) + } + } + + setTheme(getPreferredTheme()) + + const showActiveTheme = (theme, focus = false) => { + const themeSwitcher = document.querySelector('#bd-theme') + + if (!themeSwitcher) { + return + } + + // Commented-out lines are from the original bs5 js, which uses a more complicated pref dropdown. + // Kept them here for easier future diffing. + const themeSwitcherText = document.querySelector('#bd-theme-text') + // const activeThemeIcon = document.querySelector('.theme-icon-active use') + const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`) + // const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href') + + document.querySelectorAll('[data-bs-theme-value]').forEach(element => { + element.classList.remove('active') + element.setAttribute('aria-pressed', 'false') + }) + + btnToActive.classList.add('active') + btnToActive.setAttribute('aria-pressed', 'true') + // activeThemeIcon.setAttribute('href', svgOfActiveBtn) + // const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})` + // themeSwitcher.setAttribute('aria-label', themeSwitcherLabel) + + if (focus) { + themeSwitcher.focus() + } + } + + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + const storedTheme = getStoredTheme() + if (storedTheme !== 'light' && storedTheme !== 'dark') { + setTheme(getPreferredTheme()) + } + }) + + window.addEventListener('DOMContentLoaded', () => { + showActiveTheme(getPreferredTheme()) + + document.querySelectorAll('[data-bs-theme-value]') + .forEach(toggle => { + toggle.addEventListener('click', () => { + const theme = toggle.getAttribute('data-bs-theme-value') + setStoredTheme(theme) + setTheme(theme) + showActiveTheme(theme, true) + }) + }) + }) +})() diff --git a/ietf/templates/401.html b/ietf/templates/401.html index a88ce940e5..8c06dff9e1 100644 --- a/ietf/templates/401.html +++ b/ietf/templates/401.html @@ -3,9 +3,7 @@ {% load static %} {% block title %}401 Unauthorized{% endblock %} {% block content %} - IETF + {% include "logo.html" with org="ietf" classes="col-2 mb-5" only %}

Authentication Required


diff --git a/ietf/templates/403.html b/ietf/templates/403.html index 155e4ea998..2ea87eb3ad 100644 --- a/ietf/templates/403.html +++ b/ietf/templates/403.html @@ -3,9 +3,7 @@ {% load static %} {% block title %}Error: Restricted Access{% endblock %} {% block content %} - IETF + {% include "logo.html" with org="ietf" classes="col-2 mb-5" only %}

Restricted Access


diff --git a/ietf/templates/404.html b/ietf/templates/404.html index de247c89a1..b21bd5d97b 100644 --- a/ietf/templates/404.html +++ b/ietf/templates/404.html @@ -3,9 +3,7 @@ {% load static %} {% block title %}Error: Page Not Found{% endblock %} {% block content %} - IETF + {% include "logo.html" with org="ietf" classes="col-2 mb-5" only %}

The page you were looking for couldn't be found


diff --git a/ietf/templates/500.html b/ietf/templates/500.html index b7ea01bdde..bd205dad6b 100644 --- a/ietf/templates/500.html +++ b/ietf/templates/500.html @@ -3,9 +3,7 @@ {% load static %} {% block title %}500 Internal Server Error{% endblock %} {% block content %} - IETF + {% include "logo.html" with org="ietf" classes="col-2 mb-5" only %}

Internal Server Error


diff --git a/ietf/templates/base.html b/ietf/templates/base.html index 0d7ddc868f..9e07bad00d 100644 --- a/ietf/templates/base.html +++ b/ietf/templates/base.html @@ -6,7 +6,7 @@ {% origin %} {% load django_bootstrap5 %} {% load django_vite %} - + {% analytical_head_top %} @@ -19,6 +19,8 @@ + {# load this in the head, to prevent flickering #} + @@ -33,11 +35,10 @@ data-group-menu-data-url="{% url 'ietf.group.views.group_menu_data' %}"> {% analytical_body_top %} Skip to main content -