From e9de3248c0e9b854ce80477ea0ad5d0e15805618 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 29 Dec 2024 03:11:45 +0530 Subject: [PATCH] Ignorar la carpeta venv en Git --- .gitignore | 1 + home/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 121 bytes home/__pycache__/ac_soap.cpython-39.pyc | Bin 0 -> 1753 bytes home/__pycache__/admin.cpython-39.pyc | Bin 0 -> 7625 bytes home/__pycache__/apps.cpython-39.pyc | Bin 0 -> 394 bytes .../context_processors.cpython-39.pyc | Bin 0 -> 1493 bytes .../__pycache__/library_correo.cpython-39.pyc | Bin 0 -> 1089 bytes home/__pycache__/middleware.cpython-39.pyc | Bin 0 -> 1200 bytes home/__pycache__/models.cpython-39.pyc | Bin 0 -> 13190 bytes home/__pycache__/pagos_stripe.cpython-39.pyc | Bin 0 -> 816 bytes home/__pycache__/urls.cpython-39.pyc | Bin 0 -> 4608 bytes home/__pycache__/views.cpython-39.pyc | Bin 0 -> 60521 bytes .../zone_definitions.cpython-39.pyc | Bin 0 -> 252717 bytes home/admin.py | 7 +- home/middleware.py | 28 + home/migrations/0007_maintenancemode.py | 20 + .../__pycache__/0001_initial.cpython-39.pyc | Bin 0 -> 2979 bytes ...treward_claimed_by_and_more.cpython-39.pyc | Bin 0 -> 1258 bytes ...lter_accountactivation_salt.cpython-39.pyc | Bin 0 -> 627 bytes ...untactivation_salt_and_more.cpython-39.pyc | Bin 0 -> 650 bytes .../0005_securitytoken.cpython-39.pyc | Bin 0 -> 847 bytes ...ice_customizeprice_and_more.cpython-39.pyc | Bin 0 -> 3755 bytes .../0007_maintenancemode.cpython-39.pyc | Bin 0 -> 709 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 132 bytes home/models.py | 6 + home/templates/maintenance/maintenance.html | 9 + home/templates/partials/maintenance.html | 16 + home/urls.py | 1 + home/views.py | 3 + novawow/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 124 bytes novawow/__pycache__/middleware.cpython-39.pyc | Bin 0 -> 1197 bytes novawow/__pycache__/settings.cpython-39.pyc | Bin 0 -> 4696 bytes novawow/__pycache__/urls.cpython-39.pyc | Bin 0 -> 577 bytes novawow/__pycache__/views.cpython-39.pyc | Bin 0 -> 300 bytes novawow/__pycache__/wsgi.cpython-39.pyc | Bin 0 -> 527 bytes novawow/middleware.py | 34 - novawow/settings.py | 7 +- novawow/urls.py | 3 - requirements.txt | 15 + static/admin/css/autocomplete.css | 275 + static/admin/css/base.css | 1145 ++ static/admin/css/changelists.css | 328 + static/admin/css/dark_mode.css | 137 + static/admin/css/dashboard.css | 29 + static/admin/css/forms.css | 534 + static/admin/css/login.css | 61 + static/admin/css/nav_sidebar.css | 144 + static/admin/css/responsive.css | 999 ++ static/admin/css/responsive_rtl.css | 84 + static/admin/css/rtl.css | 298 + .../css/vendor/select2/LICENSE-SELECT2.md | 21 + static/admin/css/vendor/select2/select2.css | 481 + .../admin/css/vendor/select2/select2.min.css | 1 + static/admin/css/widgets.css | 604 + static/admin/img/LICENSE | 20 + static/admin/img/README.txt | 7 + static/admin/img/calendar-icons.svg | 14 + static/admin/img/gis/move_vertex_off.svg | 1 + static/admin/img/gis/move_vertex_on.svg | 1 + static/admin/img/icon-addlink.svg | 3 + static/admin/img/icon-alert.svg | 3 + static/admin/img/icon-calendar.svg | 9 + static/admin/img/icon-changelink.svg | 3 + static/admin/img/icon-clock.svg | 9 + static/admin/img/icon-deletelink.svg | 3 + static/admin/img/icon-no.svg | 3 + static/admin/img/icon-unknown-alt.svg | 3 + static/admin/img/icon-unknown.svg | 3 + static/admin/img/icon-viewlink.svg | 3 + static/admin/img/icon-yes.svg | 3 + static/admin/img/inline-delete.svg | 3 + static/admin/img/search.svg | 3 + static/admin/img/selector-icons.svg | 34 + static/admin/img/sorting-icons.svg | 19 + static/admin/img/tooltag-add.svg | 3 + static/admin/img/tooltag-arrowright.svg | 3 + static/admin/js/SelectBox.js | 116 + static/admin/js/SelectFilter2.js | 283 + static/admin/js/actions.js | 201 + static/admin/js/admin/DateTimeShortcuts.js | 408 + static/admin/js/admin/RelatedObjectLookups.js | 238 + static/admin/js/autocomplete.js | 33 + static/admin/js/calendar.js | 221 + static/admin/js/cancel.js | 29 + static/admin/js/change_form.js | 16 + static/admin/js/collapse.js | 43 + static/admin/js/core.js | 170 + static/admin/js/filters.js | 30 + static/admin/js/inlines.js | 359 + static/admin/js/jquery.init.js | 8 + static/admin/js/nav_sidebar.js | 79 + static/admin/js/popup_response.js | 16 + static/admin/js/prepopulate.js | 43 + static/admin/js/prepopulate_init.js | 15 + static/admin/js/theme.js | 56 + static/admin/js/urlify.js | 169 + static/admin/js/vendor/jquery/LICENSE.txt | 20 + static/admin/js/vendor/jquery/jquery.js | 10965 ++++++++++++++++ static/admin/js/vendor/jquery/jquery.min.js | 2 + static/admin/js/vendor/select2/LICENSE.md | 21 + static/admin/js/vendor/select2/i18n/af.js | 3 + static/admin/js/vendor/select2/i18n/ar.js | 3 + static/admin/js/vendor/select2/i18n/az.js | 3 + static/admin/js/vendor/select2/i18n/bg.js | 3 + static/admin/js/vendor/select2/i18n/bn.js | 3 + static/admin/js/vendor/select2/i18n/bs.js | 3 + static/admin/js/vendor/select2/i18n/ca.js | 3 + static/admin/js/vendor/select2/i18n/cs.js | 3 + static/admin/js/vendor/select2/i18n/da.js | 3 + static/admin/js/vendor/select2/i18n/de.js | 3 + static/admin/js/vendor/select2/i18n/dsb.js | 3 + static/admin/js/vendor/select2/i18n/el.js | 3 + static/admin/js/vendor/select2/i18n/en.js | 3 + static/admin/js/vendor/select2/i18n/es.js | 3 + static/admin/js/vendor/select2/i18n/et.js | 3 + static/admin/js/vendor/select2/i18n/eu.js | 3 + static/admin/js/vendor/select2/i18n/fa.js | 3 + static/admin/js/vendor/select2/i18n/fi.js | 3 + static/admin/js/vendor/select2/i18n/fr.js | 3 + static/admin/js/vendor/select2/i18n/gl.js | 3 + static/admin/js/vendor/select2/i18n/he.js | 3 + static/admin/js/vendor/select2/i18n/hi.js | 3 + static/admin/js/vendor/select2/i18n/hr.js | 3 + static/admin/js/vendor/select2/i18n/hsb.js | 3 + static/admin/js/vendor/select2/i18n/hu.js | 3 + static/admin/js/vendor/select2/i18n/hy.js | 3 + static/admin/js/vendor/select2/i18n/id.js | 3 + static/admin/js/vendor/select2/i18n/is.js | 3 + static/admin/js/vendor/select2/i18n/it.js | 3 + static/admin/js/vendor/select2/i18n/ja.js | 3 + static/admin/js/vendor/select2/i18n/ka.js | 3 + static/admin/js/vendor/select2/i18n/km.js | 3 + static/admin/js/vendor/select2/i18n/ko.js | 3 + static/admin/js/vendor/select2/i18n/lt.js | 3 + static/admin/js/vendor/select2/i18n/lv.js | 3 + static/admin/js/vendor/select2/i18n/mk.js | 3 + static/admin/js/vendor/select2/i18n/ms.js | 3 + static/admin/js/vendor/select2/i18n/nb.js | 3 + static/admin/js/vendor/select2/i18n/ne.js | 3 + static/admin/js/vendor/select2/i18n/nl.js | 3 + static/admin/js/vendor/select2/i18n/pl.js | 3 + static/admin/js/vendor/select2/i18n/ps.js | 3 + static/admin/js/vendor/select2/i18n/pt-BR.js | 3 + static/admin/js/vendor/select2/i18n/pt.js | 3 + static/admin/js/vendor/select2/i18n/ro.js | 3 + static/admin/js/vendor/select2/i18n/ru.js | 3 + static/admin/js/vendor/select2/i18n/sk.js | 3 + static/admin/js/vendor/select2/i18n/sl.js | 3 + static/admin/js/vendor/select2/i18n/sq.js | 3 + .../admin/js/vendor/select2/i18n/sr-Cyrl.js | 3 + static/admin/js/vendor/select2/i18n/sr.js | 3 + static/admin/js/vendor/select2/i18n/sv.js | 3 + static/admin/js/vendor/select2/i18n/th.js | 3 + static/admin/js/vendor/select2/i18n/tk.js | 3 + static/admin/js/vendor/select2/i18n/tr.js | 3 + static/admin/js/vendor/select2/i18n/uk.js | 3 + static/admin/js/vendor/select2/i18n/vi.js | 3 + static/admin/js/vendor/select2/i18n/zh-CN.js | 3 + static/admin/js/vendor/select2/i18n/zh-TW.js | 3 + .../admin/js/vendor/select2/select2.full.js | 6820 ++++++++++ .../js/vendor/select2/select2.full.min.js | 2 + static/admin/js/vendor/xregexp/LICENSE.txt | 21 + static/admin/js/vendor/xregexp/xregexp.js | 4652 +++++++ static/admin/js/vendor/xregexp/xregexp.min.js | 160 + .../android-chrome-192x192.png | Bin {home/static => static}/apple-touch-icon.png | Bin {home/static => static}/browserconfig.xml | 0 static/django_ckeditor_5/app.js | 186 + static/django_ckeditor_5/dist/bundle.js | 3 + .../dist/bundle.js.LICENSE.txt | 25 + static/django_ckeditor_5/dist/bundle.js.map | 1 + static/django_ckeditor_5/dist/styles.css | 114 + static/django_ckeditor_5/dist/styles.css.map | 1 + .../django_ckeditor_5/dist/translations/af.js | 1 + .../django_ckeditor_5/dist/translations/ar.js | 1 + .../dist/translations/ast.js | 1 + .../django_ckeditor_5/dist/translations/az.js | 1 + .../django_ckeditor_5/dist/translations/bg.js | 1 + .../django_ckeditor_5/dist/translations/bn.js | 1 + .../django_ckeditor_5/dist/translations/bs.js | 1 + .../django_ckeditor_5/dist/translations/ca.js | 1 + .../django_ckeditor_5/dist/translations/cs.js | 1 + .../django_ckeditor_5/dist/translations/da.js | 1 + .../dist/translations/de-ch.js | 1 + .../django_ckeditor_5/dist/translations/de.js | 1 + .../django_ckeditor_5/dist/translations/el.js | 1 + .../dist/translations/en-au.js | 1 + .../dist/translations/en-gb.js | 1 + .../django_ckeditor_5/dist/translations/eo.js | 1 + .../dist/translations/es-co.js | 1 + .../django_ckeditor_5/dist/translations/es.js | 1 + .../django_ckeditor_5/dist/translations/et.js | 1 + .../django_ckeditor_5/dist/translations/eu.js | 1 + .../django_ckeditor_5/dist/translations/fa.js | 1 + .../django_ckeditor_5/dist/translations/fi.js | 1 + .../django_ckeditor_5/dist/translations/fr.js | 1 + .../django_ckeditor_5/dist/translations/gl.js | 1 + .../django_ckeditor_5/dist/translations/gu.js | 1 + .../django_ckeditor_5/dist/translations/he.js | 1 + .../django_ckeditor_5/dist/translations/hi.js | 1 + .../django_ckeditor_5/dist/translations/hr.js | 1 + .../django_ckeditor_5/dist/translations/hu.js | 1 + .../django_ckeditor_5/dist/translations/hy.js | 1 + .../django_ckeditor_5/dist/translations/id.js | 1 + .../django_ckeditor_5/dist/translations/it.js | 1 + .../django_ckeditor_5/dist/translations/ja.js | 1 + .../django_ckeditor_5/dist/translations/jv.js | 1 + .../django_ckeditor_5/dist/translations/kk.js | 1 + .../django_ckeditor_5/dist/translations/km.js | 1 + .../django_ckeditor_5/dist/translations/kn.js | 1 + .../django_ckeditor_5/dist/translations/ko.js | 1 + .../django_ckeditor_5/dist/translations/ku.js | 1 + .../django_ckeditor_5/dist/translations/lt.js | 1 + .../django_ckeditor_5/dist/translations/lv.js | 1 + .../django_ckeditor_5/dist/translations/ms.js | 1 + .../django_ckeditor_5/dist/translations/nb.js | 1 + .../django_ckeditor_5/dist/translations/ne.js | 1 + .../django_ckeditor_5/dist/translations/nl.js | 1 + .../django_ckeditor_5/dist/translations/no.js | 1 + .../django_ckeditor_5/dist/translations/oc.js | 1 + .../django_ckeditor_5/dist/translations/pl.js | 1 + .../dist/translations/pt-br.js | 1 + .../django_ckeditor_5/dist/translations/pt.js | 1 + .../django_ckeditor_5/dist/translations/ro.js | 1 + .../django_ckeditor_5/dist/translations/ru.js | 1 + .../django_ckeditor_5/dist/translations/si.js | 1 + .../django_ckeditor_5/dist/translations/sk.js | 1 + .../django_ckeditor_5/dist/translations/sl.js | 1 + .../django_ckeditor_5/dist/translations/sq.js | 1 + .../dist/translations/sr-latn.js | 1 + .../django_ckeditor_5/dist/translations/sr.js | 1 + .../django_ckeditor_5/dist/translations/sv.js | 1 + .../django_ckeditor_5/dist/translations/th.js | 1 + .../django_ckeditor_5/dist/translations/ti.js | 1 + .../django_ckeditor_5/dist/translations/tk.js | 1 + .../django_ckeditor_5/dist/translations/tr.js | 1 + .../django_ckeditor_5/dist/translations/tt.js | 1 + .../django_ckeditor_5/dist/translations/ug.js | 1 + .../django_ckeditor_5/dist/translations/uk.js | 1 + .../django_ckeditor_5/dist/translations/ur.js | 1 + .../django_ckeditor_5/dist/translations/uz.js | 1 + .../django_ckeditor_5/dist/translations/vi.js | 1 + .../dist/translations/zh-cn.js | 1 + .../django_ckeditor_5/dist/translations/zh.js | 1 + static/django_ckeditor_5/src/ckeditor.js | 114 + .../django_ckeditor_5/src/override-django.css | 47 + .../css/jquery.autocomplete.css | 38 + static/django_extensions/img/indicator.gif | Bin 0 -> 1553 bytes .../django_extensions/js/jquery.ajaxQueue.js | 116 + .../js/jquery.autocomplete.js | 1152 ++ .../django_extensions/js/jquery.bgiframe.js | 39 + {home/static => static}/favicon-16x16.png | Bin {home/static => static}/favicon-194x194.png | Bin {home/static => static}/favicon-32x32.png | Bin {home/static => static}/favicon.ico | Bin {home/static => static}/mstile-144x144.png | Bin .../nw-themes/nw-ryu/nw-css/novawow-style.css | 0 .../nw-ryu/nw-font/FuturaEF-Book.woff | Bin .../nw-images/nw-avatars/default-avatar.webp | Bin .../nw-classes/death-knight-chest.webp | Bin .../nw-classes/death-knight-medium.jpg | Bin .../nw-images/nw-classes/druid-chest.webp | Bin .../nw-images/nw-classes/druid-medium.jpg | Bin .../nw-images/nw-classes/hunter-chest.webp | Bin .../nw-images/nw-classes/hunter-medium.jpg | Bin .../nw-images/nw-classes/mage-chest.webp | Bin .../nw-images/nw-classes/mage-medium.jpg | Bin .../nw-images/nw-classes/paladin-chest.webp | Bin .../nw-images/nw-classes/paladin-medium.jpg | Bin .../nw-images/nw-classes/priest-chest.webp | Bin .../nw-images/nw-classes/priest-medium.jpg | Bin .../nw-images/nw-classes/rogue-chest.webp | Bin .../nw-images/nw-classes/rogue-medium.jpg | Bin .../nw-images/nw-classes/shaman-chest.webp | Bin .../nw-images/nw-classes/shaman-medium.jpg | Bin .../nw-images/nw-classes/warlock-chest.webp | Bin .../nw-images/nw-classes/warlock-medium.jpg | Bin .../nw-images/nw-classes/warrior-chest.webp | Bin .../nw-images/nw-classes/warrior-medium.jpg | Bin .../nw-classes/wow-death-knight.webp | Bin .../nw-ryu/nw-images/nw-classes/wow-druid.png | Bin .../nw-images/nw-classes/wow-hunter.webp | Bin .../nw-ryu/nw-images/nw-classes/wow-mage.webp | Bin .../nw-images/nw-classes/wow-paladin.webp | Bin .../nw-images/nw-classes/wow-priest.webp | Bin .../nw-images/nw-classes/wow-rogue.webp | Bin .../nw-images/nw-classes/wow-shaman.webp | Bin .../nw-images/nw-classes/wow-warlock.webp | Bin .../nw-images/nw-classes/wow-warrior.webp | Bin .../nw-ryu/nw-images/nw-country-flags/ar.webp | Bin .../nw-ryu/nw-images/nw-country-flags/bo.webp | Bin .../nw-ryu/nw-images/nw-country-flags/cl.webp | Bin .../nw-ryu/nw-images/nw-country-flags/co.webp | Bin .../nw-ryu/nw-images/nw-country-flags/cr.webp | Bin .../nw-ryu/nw-images/nw-country-flags/ec.webp | Bin .../nw-ryu/nw-images/nw-country-flags/gt.webp | Bin .../nw-ryu/nw-images/nw-country-flags/mx.png | Bin .../nw-ryu/nw-images/nw-country-flags/pa.png | Bin .../nw-ryu/nw-images/nw-country-flags/pe.webp | Bin .../nw-ryu/nw-images/nw-country-flags/py.webp | Bin .../nw-ryu/nw-images/nw-country-flags/uy.webp | Bin .../nw-general/account-settings.webp | Bin .../nw-general/novawow-maintenance.webp | Bin 0 -> 562812 bytes .../nw-images/nw-general/nw-divider-mini.webp | Bin .../nw-images/nw-general/nw-divider.png | Bin .../nw-images/nw-icons/account-icons.webp | Bin .../nw-icons/achievement-level-80.jpg | Bin .../nw-images/nw-icons/alliance-icon.jpg | Bin .../nw-icons/alliance-no-border.webp | Bin .../nw-icons/death-knight-medium.jpg | Bin .../nw-images/nw-icons/druid-medium.jpg | Bin .../nw-ryu/nw-images/nw-icons/horde-icon.jpg | Bin .../nw-images/nw-icons/horde-no-border.webp | Bin .../nw-images/nw-icons/hunter-medium.jpg | Bin .../nw-ryu/nw-images/nw-icons/mage-medium.jpg | Bin .../nw-images/nw-icons/money-copper.gif | Bin .../nw-ryu/nw-images/nw-icons/money-gold.gif | Bin .../nw-images/nw-icons/money-silver.webp | Bin .../nw-images/nw-icons/paladin-medium.jpg | Bin .../nw-images/nw-icons/priest-medium.jpg | Bin .../nw-ryu/nw-images/nw-icons/refresh.webp | Bin .../nw-images/nw-icons/rogue-medium.jpg | Bin .../nw-images/nw-icons/shaman-medium.jpg | Bin .../nw-images/nw-icons/warlock-medium.jpg | Bin .../nw-images/nw-icons/warrior-medium.jpg | Bin .../nw-images/nw-logos/bancolombia-logo.webp | Bin .../nw-images/nw-logos/discord-logo.webp | Bin .../nw-images/nw-logos/dlocalgo-logo.webp | Bin .../nw-ryu/nw-images/nw-logos/facebook.png | Bin .../nw-ryu/nw-images/nw-logos/nequi-logo.webp | Bin .../novawow-main-logo-transparent.webp | Bin .../nw-ryu/nw-images/nw-logos/nw-logo.webp | Bin .../nw-images/nw-logos/nw-long-logo.webp | Bin .../nw-images/nw-logos/oficina-peru.png | Bin .../nw-images/nw-logos/paypal-logo.webp | Bin .../nw-images/nw-logos/paypal-p-logo.webp | Bin .../nw-ryu/nw-images/nw-logos/plin-peru.webp | Bin .../nw-images/nw-logos/skrill-logo-small.webp | Bin .../nw-images/nw-logos/skrill-logo.webp | Bin .../nw-ryu/nw-images/nw-logos/twitch.png | Bin .../nw-images/nw-logos/whatsapp-logo.webp | Bin .../nw-ryu/nw-images/nw-logos/yape-peru.png | Bin .../nw-ryu/nw-images/nw-logos/youtube.webp | Bin .../nw-images/nw-mails/facebook-logo-gray.png | Bin .../nw-mails/instagram-logo-gray.png | Bin .../nw-images/nw-mails/nw-mail-body.jpg | Bin .../nw-images/nw-mails/nw-mail-footer.jpg | Bin .../nw-images/nw-mails/nw-mail-logo.webp | Bin .../nw-images/nw-mails/twitter-logo-gray.png | Bin .../nw-images/nw-mails/youtube-logo-gray.png | Bin .../nw-races/big-blood-elf-female.webp | Bin .../nw-races/big-blood-elf-male.webp | Bin .../nw-races/big-draenei-female.webp | Bin .../nw-images/nw-races/big-draenei-male.webp | Bin .../nw-images/nw-races/big-dwarf-female.webp | Bin .../nw-images/nw-races/big-dwarf-male.webp | Bin .../nw-images/nw-races/big-gnome-female.webp | Bin .../nw-images/nw-races/big-gnome-male.webp | Bin .../nw-images/nw-races/big-human-female.webp | Bin .../nw-images/nw-races/big-human-male.webp | Bin .../nw-races/big-night-elf-female.webp | Bin .../nw-races/big-night-elf-male.webp | Bin .../nw-images/nw-races/big-orc-female.webp | Bin .../nw-images/nw-races/big-orc-male.webp | Bin .../nw-images/nw-races/big-tauren-female.webp | Bin .../nw-images/nw-races/big-tauren-male.webp | Bin .../nw-images/nw-races/big-troll-female.webp | Bin .../nw-images/nw-races/big-troll-male.webp | Bin .../nw-images/nw-races/big-undead-female.webp | Bin .../nw-images/nw-races/big-undead-male.webp | Bin .../nw-images/nw-ranks/10_Proficient.svg | 0 .../nw-images/nw-ranks/11_Experienced.svg | 0 .../nw-ryu/nw-images/nw-ranks/12_Mentor.svg | 0 .../nw-ryu/nw-images/nw-ranks/13_Veteran.svg | 0 .../nw-images/nw-ranks/14_GrandMaster.svg | 0 .../nw-ryu/nw-images/nw-ranks/1_Newbie.svg | 0 .../nw-ryu/nw-images/nw-ranks/2_Rookie.svg | 0 .../nw-images/nw-ranks/3_Apprentice.svg | 0 .../nw-ryu/nw-images/nw-ranks/4_Explorer.svg | 0 .../nw-images/nw-ranks/5_Contributor.svg | 0 .../nw-images/nw-ranks/6_Enthusiast.svg | 0 .../nw-images/nw-ranks/7_Collaborator.svg | 0 .../nw-ryu/nw-images/nw-ranks/8_Regular.svg | 0 .../nw-images/nw-ranks/9_RisingStar.svg | 0 .../nw-images/nw-vote-sites/arenatop100.webp | Bin .../nw-images/nw-vote-sites/gtop100.jpg | Bin .../nw-images/nw-vote-sites/top100arena.jpg | Bin .../nw-ryu/nw-images/nw-vote-sites/topg.webp | Bin .../nw-js-handlers/change_email_response.js | 0 .../nw-js-handlers/change_faction_response.js | 0 .../change_password_response.js | 0 .../nw-js-handlers/change_race_response.js | 0 .../nw-js-handlers/customize_response.js | 0 .../nw-ryu/nw-js-handlers/gold_response.js | 0 .../nw-js-handlers/level_up_response.js | 0 .../nw-ryu/nw-js-handlers/login_response.js | 0 .../nw-js-handlers/my_account_response.js | 0 .../nw-ryu/nw-js-handlers/recruit-response.js | 0 .../nw-ryu/nw-js-handlers/register.js | 0 .../nw-js-handlers/rename_guild_response.js | 0 .../nw-ryu/nw-js-handlers/rename_response.js | 0 .../nw-ryu/nw-js-handlers/revive_response.js | 0 .../nw-js-handlers/security_token_response.js | 0 .../nw-ryu/nw-js-handlers/store_response.js | 0 .../nw-js-handlers/trade_points_response.js | 0 .../transfer_character_response.js | 0 .../nw-ryu/nw-js-handlers/unstuck_response.js | 0 .../nw-js-handlers/vote_points_response.js | 0 .../nw-themes/nw-ryu/nw-js/nw-scripts.js | 0 .../nw-themes/nw-ryu/nw-js/power.js | 0 .../nw-themes/nw-ryu/nw-videos/nw-logo.mp4 | Bin {home/static => static}/safari-pinned-tab.svg | 0 {home/static => static}/site.webmanifest | 0 413 files changed, 32683 insertions(+), 41 deletions(-) create mode 100644 .gitignore create mode 100644 home/__pycache__/__init__.cpython-39.pyc create mode 100644 home/__pycache__/ac_soap.cpython-39.pyc create mode 100644 home/__pycache__/admin.cpython-39.pyc create mode 100644 home/__pycache__/apps.cpython-39.pyc create mode 100644 home/__pycache__/context_processors.cpython-39.pyc create mode 100644 home/__pycache__/library_correo.cpython-39.pyc create mode 100644 home/__pycache__/middleware.cpython-39.pyc create mode 100644 home/__pycache__/models.cpython-39.pyc create mode 100644 home/__pycache__/pagos_stripe.cpython-39.pyc create mode 100644 home/__pycache__/urls.cpython-39.pyc create mode 100644 home/__pycache__/views.cpython-39.pyc create mode 100644 home/__pycache__/zone_definitions.cpython-39.pyc create mode 100644 home/middleware.py create mode 100644 home/migrations/0007_maintenancemode.py create mode 100644 home/migrations/__pycache__/0001_initial.cpython-39.pyc create mode 100644 home/migrations/__pycache__/0002_accountactivation_remove_recruitreward_claimed_by_and_more.cpython-39.pyc create mode 100644 home/migrations/__pycache__/0003_alter_accountactivation_salt.cpython-39.pyc create mode 100644 home/migrations/__pycache__/0004_alter_accountactivation_salt_and_more.cpython-39.pyc create mode 100644 home/migrations/__pycache__/0005_securitytoken.cpython-39.pyc create mode 100644 home/migrations/__pycache__/0006_changefactionprice_changeraceprice_customizeprice_and_more.cpython-39.pyc create mode 100644 home/migrations/__pycache__/0007_maintenancemode.cpython-39.pyc create mode 100644 home/migrations/__pycache__/__init__.cpython-39.pyc create mode 100644 home/templates/maintenance/maintenance.html create mode 100644 home/templates/partials/maintenance.html create mode 100644 novawow/__pycache__/__init__.cpython-39.pyc create mode 100644 novawow/__pycache__/middleware.cpython-39.pyc create mode 100644 novawow/__pycache__/settings.cpython-39.pyc create mode 100644 novawow/__pycache__/urls.cpython-39.pyc create mode 100644 novawow/__pycache__/views.cpython-39.pyc create mode 100644 novawow/__pycache__/wsgi.cpython-39.pyc delete mode 100644 novawow/middleware.py create mode 100644 requirements.txt create mode 100644 static/admin/css/autocomplete.css create mode 100644 static/admin/css/base.css create mode 100644 static/admin/css/changelists.css create mode 100644 static/admin/css/dark_mode.css create mode 100644 static/admin/css/dashboard.css create mode 100644 static/admin/css/forms.css create mode 100644 static/admin/css/login.css create mode 100644 static/admin/css/nav_sidebar.css create mode 100644 static/admin/css/responsive.css create mode 100644 static/admin/css/responsive_rtl.css create mode 100644 static/admin/css/rtl.css create mode 100644 static/admin/css/vendor/select2/LICENSE-SELECT2.md create mode 100644 static/admin/css/vendor/select2/select2.css create mode 100644 static/admin/css/vendor/select2/select2.min.css create mode 100644 static/admin/css/widgets.css create mode 100644 static/admin/img/LICENSE create mode 100644 static/admin/img/README.txt create mode 100644 static/admin/img/calendar-icons.svg create mode 100644 static/admin/img/gis/move_vertex_off.svg create mode 100644 static/admin/img/gis/move_vertex_on.svg create mode 100644 static/admin/img/icon-addlink.svg create mode 100644 static/admin/img/icon-alert.svg create mode 100644 static/admin/img/icon-calendar.svg create mode 100644 static/admin/img/icon-changelink.svg create mode 100644 static/admin/img/icon-clock.svg create mode 100644 static/admin/img/icon-deletelink.svg create mode 100644 static/admin/img/icon-no.svg create mode 100644 static/admin/img/icon-unknown-alt.svg create mode 100644 static/admin/img/icon-unknown.svg create mode 100644 static/admin/img/icon-viewlink.svg create mode 100644 static/admin/img/icon-yes.svg create mode 100644 static/admin/img/inline-delete.svg create mode 100644 static/admin/img/search.svg create mode 100644 static/admin/img/selector-icons.svg create mode 100644 static/admin/img/sorting-icons.svg create mode 100644 static/admin/img/tooltag-add.svg create mode 100644 static/admin/img/tooltag-arrowright.svg create mode 100644 static/admin/js/SelectBox.js create mode 100644 static/admin/js/SelectFilter2.js create mode 100644 static/admin/js/actions.js create mode 100644 static/admin/js/admin/DateTimeShortcuts.js create mode 100644 static/admin/js/admin/RelatedObjectLookups.js create mode 100644 static/admin/js/autocomplete.js create mode 100644 static/admin/js/calendar.js create mode 100644 static/admin/js/cancel.js create mode 100644 static/admin/js/change_form.js create mode 100644 static/admin/js/collapse.js create mode 100644 static/admin/js/core.js create mode 100644 static/admin/js/filters.js create mode 100644 static/admin/js/inlines.js create mode 100644 static/admin/js/jquery.init.js create mode 100644 static/admin/js/nav_sidebar.js create mode 100644 static/admin/js/popup_response.js create mode 100644 static/admin/js/prepopulate.js create mode 100644 static/admin/js/prepopulate_init.js create mode 100644 static/admin/js/theme.js create mode 100644 static/admin/js/urlify.js create mode 100644 static/admin/js/vendor/jquery/LICENSE.txt create mode 100644 static/admin/js/vendor/jquery/jquery.js create mode 100644 static/admin/js/vendor/jquery/jquery.min.js create mode 100644 static/admin/js/vendor/select2/LICENSE.md create mode 100644 static/admin/js/vendor/select2/i18n/af.js create mode 100644 static/admin/js/vendor/select2/i18n/ar.js create mode 100644 static/admin/js/vendor/select2/i18n/az.js create mode 100644 static/admin/js/vendor/select2/i18n/bg.js create mode 100644 static/admin/js/vendor/select2/i18n/bn.js create mode 100644 static/admin/js/vendor/select2/i18n/bs.js create mode 100644 static/admin/js/vendor/select2/i18n/ca.js create mode 100644 static/admin/js/vendor/select2/i18n/cs.js create mode 100644 static/admin/js/vendor/select2/i18n/da.js create mode 100644 static/admin/js/vendor/select2/i18n/de.js create mode 100644 static/admin/js/vendor/select2/i18n/dsb.js create mode 100644 static/admin/js/vendor/select2/i18n/el.js create mode 100644 static/admin/js/vendor/select2/i18n/en.js create mode 100644 static/admin/js/vendor/select2/i18n/es.js create mode 100644 static/admin/js/vendor/select2/i18n/et.js create mode 100644 static/admin/js/vendor/select2/i18n/eu.js create mode 100644 static/admin/js/vendor/select2/i18n/fa.js create mode 100644 static/admin/js/vendor/select2/i18n/fi.js create mode 100644 static/admin/js/vendor/select2/i18n/fr.js create mode 100644 static/admin/js/vendor/select2/i18n/gl.js create mode 100644 static/admin/js/vendor/select2/i18n/he.js create mode 100644 static/admin/js/vendor/select2/i18n/hi.js create mode 100644 static/admin/js/vendor/select2/i18n/hr.js create mode 100644 static/admin/js/vendor/select2/i18n/hsb.js create mode 100644 static/admin/js/vendor/select2/i18n/hu.js create mode 100644 static/admin/js/vendor/select2/i18n/hy.js create mode 100644 static/admin/js/vendor/select2/i18n/id.js create mode 100644 static/admin/js/vendor/select2/i18n/is.js create mode 100644 static/admin/js/vendor/select2/i18n/it.js create mode 100644 static/admin/js/vendor/select2/i18n/ja.js create mode 100644 static/admin/js/vendor/select2/i18n/ka.js create mode 100644 static/admin/js/vendor/select2/i18n/km.js create mode 100644 static/admin/js/vendor/select2/i18n/ko.js create mode 100644 static/admin/js/vendor/select2/i18n/lt.js create mode 100644 static/admin/js/vendor/select2/i18n/lv.js create mode 100644 static/admin/js/vendor/select2/i18n/mk.js create mode 100644 static/admin/js/vendor/select2/i18n/ms.js create mode 100644 static/admin/js/vendor/select2/i18n/nb.js create mode 100644 static/admin/js/vendor/select2/i18n/ne.js create mode 100644 static/admin/js/vendor/select2/i18n/nl.js create mode 100644 static/admin/js/vendor/select2/i18n/pl.js create mode 100644 static/admin/js/vendor/select2/i18n/ps.js create mode 100644 static/admin/js/vendor/select2/i18n/pt-BR.js create mode 100644 static/admin/js/vendor/select2/i18n/pt.js create mode 100644 static/admin/js/vendor/select2/i18n/ro.js create mode 100644 static/admin/js/vendor/select2/i18n/ru.js create mode 100644 static/admin/js/vendor/select2/i18n/sk.js create mode 100644 static/admin/js/vendor/select2/i18n/sl.js create mode 100644 static/admin/js/vendor/select2/i18n/sq.js create mode 100644 static/admin/js/vendor/select2/i18n/sr-Cyrl.js create mode 100644 static/admin/js/vendor/select2/i18n/sr.js create mode 100644 static/admin/js/vendor/select2/i18n/sv.js create mode 100644 static/admin/js/vendor/select2/i18n/th.js create mode 100644 static/admin/js/vendor/select2/i18n/tk.js create mode 100644 static/admin/js/vendor/select2/i18n/tr.js create mode 100644 static/admin/js/vendor/select2/i18n/uk.js create mode 100644 static/admin/js/vendor/select2/i18n/vi.js create mode 100644 static/admin/js/vendor/select2/i18n/zh-CN.js create mode 100644 static/admin/js/vendor/select2/i18n/zh-TW.js create mode 100644 static/admin/js/vendor/select2/select2.full.js create mode 100644 static/admin/js/vendor/select2/select2.full.min.js create mode 100644 static/admin/js/vendor/xregexp/LICENSE.txt create mode 100644 static/admin/js/vendor/xregexp/xregexp.js create mode 100644 static/admin/js/vendor/xregexp/xregexp.min.js rename {home/static => static}/android-chrome-192x192.png (100%) rename {home/static => static}/apple-touch-icon.png (100%) rename {home/static => static}/browserconfig.xml (100%) create mode 100644 static/django_ckeditor_5/app.js create mode 100644 static/django_ckeditor_5/dist/bundle.js create mode 100644 static/django_ckeditor_5/dist/bundle.js.LICENSE.txt create mode 100644 static/django_ckeditor_5/dist/bundle.js.map create mode 100644 static/django_ckeditor_5/dist/styles.css create mode 100644 static/django_ckeditor_5/dist/styles.css.map create mode 100644 static/django_ckeditor_5/dist/translations/af.js create mode 100644 static/django_ckeditor_5/dist/translations/ar.js create mode 100644 static/django_ckeditor_5/dist/translations/ast.js create mode 100644 static/django_ckeditor_5/dist/translations/az.js create mode 100644 static/django_ckeditor_5/dist/translations/bg.js create mode 100644 static/django_ckeditor_5/dist/translations/bn.js create mode 100644 static/django_ckeditor_5/dist/translations/bs.js create mode 100644 static/django_ckeditor_5/dist/translations/ca.js create mode 100644 static/django_ckeditor_5/dist/translations/cs.js create mode 100644 static/django_ckeditor_5/dist/translations/da.js create mode 100644 static/django_ckeditor_5/dist/translations/de-ch.js create mode 100644 static/django_ckeditor_5/dist/translations/de.js create mode 100644 static/django_ckeditor_5/dist/translations/el.js create mode 100644 static/django_ckeditor_5/dist/translations/en-au.js create mode 100644 static/django_ckeditor_5/dist/translations/en-gb.js create mode 100644 static/django_ckeditor_5/dist/translations/eo.js create mode 100644 static/django_ckeditor_5/dist/translations/es-co.js create mode 100644 static/django_ckeditor_5/dist/translations/es.js create mode 100644 static/django_ckeditor_5/dist/translations/et.js create mode 100644 static/django_ckeditor_5/dist/translations/eu.js create mode 100644 static/django_ckeditor_5/dist/translations/fa.js create mode 100644 static/django_ckeditor_5/dist/translations/fi.js create mode 100644 static/django_ckeditor_5/dist/translations/fr.js create mode 100644 static/django_ckeditor_5/dist/translations/gl.js create mode 100644 static/django_ckeditor_5/dist/translations/gu.js create mode 100644 static/django_ckeditor_5/dist/translations/he.js create mode 100644 static/django_ckeditor_5/dist/translations/hi.js create mode 100644 static/django_ckeditor_5/dist/translations/hr.js create mode 100644 static/django_ckeditor_5/dist/translations/hu.js create mode 100644 static/django_ckeditor_5/dist/translations/hy.js create mode 100644 static/django_ckeditor_5/dist/translations/id.js create mode 100644 static/django_ckeditor_5/dist/translations/it.js create mode 100644 static/django_ckeditor_5/dist/translations/ja.js create mode 100644 static/django_ckeditor_5/dist/translations/jv.js create mode 100644 static/django_ckeditor_5/dist/translations/kk.js create mode 100644 static/django_ckeditor_5/dist/translations/km.js create mode 100644 static/django_ckeditor_5/dist/translations/kn.js create mode 100644 static/django_ckeditor_5/dist/translations/ko.js create mode 100644 static/django_ckeditor_5/dist/translations/ku.js create mode 100644 static/django_ckeditor_5/dist/translations/lt.js create mode 100644 static/django_ckeditor_5/dist/translations/lv.js create mode 100644 static/django_ckeditor_5/dist/translations/ms.js create mode 100644 static/django_ckeditor_5/dist/translations/nb.js create mode 100644 static/django_ckeditor_5/dist/translations/ne.js create mode 100644 static/django_ckeditor_5/dist/translations/nl.js create mode 100644 static/django_ckeditor_5/dist/translations/no.js create mode 100644 static/django_ckeditor_5/dist/translations/oc.js create mode 100644 static/django_ckeditor_5/dist/translations/pl.js create mode 100644 static/django_ckeditor_5/dist/translations/pt-br.js create mode 100644 static/django_ckeditor_5/dist/translations/pt.js create mode 100644 static/django_ckeditor_5/dist/translations/ro.js create mode 100644 static/django_ckeditor_5/dist/translations/ru.js create mode 100644 static/django_ckeditor_5/dist/translations/si.js create mode 100644 static/django_ckeditor_5/dist/translations/sk.js create mode 100644 static/django_ckeditor_5/dist/translations/sl.js create mode 100644 static/django_ckeditor_5/dist/translations/sq.js create mode 100644 static/django_ckeditor_5/dist/translations/sr-latn.js create mode 100644 static/django_ckeditor_5/dist/translations/sr.js create mode 100644 static/django_ckeditor_5/dist/translations/sv.js create mode 100644 static/django_ckeditor_5/dist/translations/th.js create mode 100644 static/django_ckeditor_5/dist/translations/ti.js create mode 100644 static/django_ckeditor_5/dist/translations/tk.js create mode 100644 static/django_ckeditor_5/dist/translations/tr.js create mode 100644 static/django_ckeditor_5/dist/translations/tt.js create mode 100644 static/django_ckeditor_5/dist/translations/ug.js create mode 100644 static/django_ckeditor_5/dist/translations/uk.js create mode 100644 static/django_ckeditor_5/dist/translations/ur.js create mode 100644 static/django_ckeditor_5/dist/translations/uz.js create mode 100644 static/django_ckeditor_5/dist/translations/vi.js create mode 100644 static/django_ckeditor_5/dist/translations/zh-cn.js create mode 100644 static/django_ckeditor_5/dist/translations/zh.js create mode 100644 static/django_ckeditor_5/src/ckeditor.js create mode 100644 static/django_ckeditor_5/src/override-django.css create mode 100644 static/django_extensions/css/jquery.autocomplete.css create mode 100644 static/django_extensions/img/indicator.gif create mode 100644 static/django_extensions/js/jquery.ajaxQueue.js create mode 100644 static/django_extensions/js/jquery.autocomplete.js create mode 100644 static/django_extensions/js/jquery.bgiframe.js rename {home/static => static}/favicon-16x16.png (100%) rename {home/static => static}/favicon-194x194.png (100%) rename {home/static => static}/favicon-32x32.png (100%) rename {home/static => static}/favicon.ico (100%) rename {home/static => static}/mstile-144x144.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-css/novawow-style.css (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-font/FuturaEF-Book.woff (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-avatars/default-avatar.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/death-knight-chest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/death-knight-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/druid-chest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/druid-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/hunter-chest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/hunter-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/mage-chest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/mage-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/paladin-chest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/paladin-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/priest-chest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/priest-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/rogue-chest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/rogue-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/shaman-chest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/shaman-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/warlock-chest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/warlock-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/warrior-chest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/warrior-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/wow-death-knight.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/wow-druid.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/wow-hunter.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/wow-mage.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/wow-paladin.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/wow-priest.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/wow-rogue.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/wow-shaman.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/wow-warlock.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-classes/wow-warrior.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/ar.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/bo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/cl.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/co.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/cr.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/ec.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/gt.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/mx.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/pa.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/pe.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/py.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-country-flags/uy.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-general/account-settings.webp (100%) create mode 100644 static/nw-themes/nw-ryu/nw-images/nw-general/novawow-maintenance.webp rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-general/nw-divider-mini.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-general/nw-divider.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/account-icons.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/achievement-level-80.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/alliance-icon.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/alliance-no-border.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/death-knight-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/druid-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/horde-icon.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/horde-no-border.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/hunter-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/mage-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/money-copper.gif (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/money-gold.gif (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/money-silver.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/paladin-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/priest-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/refresh.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/rogue-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/shaman-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/warlock-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-icons/warrior-medium.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/bancolombia-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/discord-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/dlocalgo-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/facebook.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/nequi-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/novawow-main-logo-transparent.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/nw-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/nw-long-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/oficina-peru.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/paypal-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/paypal-p-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/plin-peru.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/skrill-logo-small.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/skrill-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/twitch.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/whatsapp-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/yape-peru.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-logos/youtube.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-mails/facebook-logo-gray.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-mails/instagram-logo-gray.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-mails/nw-mail-body.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-mails/nw-mail-footer.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-mails/nw-mail-logo.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-mails/twitter-logo-gray.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-mails/youtube-logo-gray.png (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-blood-elf-female.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-blood-elf-male.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-draenei-female.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-draenei-male.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-dwarf-female.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-dwarf-male.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-gnome-female.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-gnome-male.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-human-female.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-human-male.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-night-elf-female.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-night-elf-male.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-orc-female.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-orc-male.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-tauren-female.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-tauren-male.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-troll-female.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-troll-male.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-undead-female.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-races/big-undead-male.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/10_Proficient.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/11_Experienced.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/12_Mentor.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/13_Veteran.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/14_GrandMaster.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/1_Newbie.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/2_Rookie.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/3_Apprentice.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/4_Explorer.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/5_Contributor.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/6_Enthusiast.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/7_Collaborator.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/8_Regular.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-ranks/9_RisingStar.svg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-vote-sites/arenatop100.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-vote-sites/gtop100.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-vote-sites/top100arena.jpg (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-images/nw-vote-sites/topg.webp (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/change_email_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/change_faction_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/change_password_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/change_race_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/customize_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/gold_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/level_up_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/login_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/my_account_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/recruit-response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/register.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/rename_guild_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/rename_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/revive_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/security_token_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/store_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/trade_points_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/transfer_character_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/unstuck_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js-handlers/vote_points_response.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js/nw-scripts.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-js/power.js (100%) rename {home/static => static}/nw-themes/nw-ryu/nw-videos/nw-logo.mp4 (100%) rename {home/static => static}/safari-pinned-tab.svg (100%) rename {home/static => static}/site.webmanifest (100%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f7275bb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +venv/ diff --git a/home/__pycache__/__init__.cpython-39.pyc b/home/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..550a83c22145a8e2e50b47dbe6164ae50fbd7306 GIT binary patch literal 121 zcmYe~<>g`kfpoq6x~e($|`Z-y=}7Z8k3 zZ-%{I4x!)8W^q`s`3OFB3nqpb_R+!Qj}I{HE#Dg22R25`X3n?hz+t$9Dw&snMy(1? z@``Ki1wGZpMl>B+_#3|s_*51&@%IdCG{Db+afD#D&oX1o9BrN3Aa_8Lfq&*XI19?l zQs68Z8L&9dFh=``Eq7oJw1a@@+F<4M1xDixMlk`KYkGB*c?J=lSrhb^fFEbR$r!82 zY6F4g^&jymTCiLBKXx0b@5*X)7Y?I9U^EB38)-_SfON%>222nh5bhJj<*~Urz*E z86Uwn0UmSgQ|L<@@9p=`(52UK}o@(S1D6&i-V*QFXx*oEV$ zSjqBEr29g8aVm^U4FLrT^!lUIkiX2p?XK8~!>Fc7uFolh>LfYs4Y`Q)%NL-I-+J6^ zw|Co52&6u5VRA%$A9}n-Vw?>>1Jb_7Zr*UW`ho7}uN%kpKeDhwi^mOxH z+G9K^&GnsTJ6WCW_I5g*{oVG*Np_0MG7de-lf2|#o7dr1-gKo9+HHwrx-a(Kz8G?sb`R5A5S}JCrcIj)X4K|oSMR}u zik4+z=P$>x{>T^JwJmJ@na$p?3pj7x#06^&ui-cFD$Md7Kvy#II{ai2rliOQH0X&c hl=LV){uGi1wJ;F_&DV#5MLyp)RZ_-#9_Mk%`Wrbr@-hGb literal 0 HcmV?d00001 diff --git a/home/__pycache__/admin.cpython-39.pyc b/home/__pycache__/admin.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08b7e82675c464ebb658cbdee52cdd093da8b008 GIT binary patch literal 7625 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 XM%;hdF`8n{hv(yd7j%n`xHItw$+lb@ literal 0 HcmV?d00001 diff --git a/home/__pycache__/context_processors.cpython-39.pyc b/home/__pycache__/context_processors.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5809795ae87567ff87a1f067d19f90d56c54a692 GIT binary patch literal 1493 zcmZ8h&u<(x6t+Dx`zzTbpd4C+kdZ3E7Ac!noGL(s&7wx6yJeHGbT2FK*xAf>#vW`> zercCWxpPBE6e&6OKqZ94KaeYb!CX1@UqAx!Je!n+8QFegd!FC--uIc+>oo+=m$%aK z9|1ytx{vD*fsaq2nTODE#Bq!gJir)n!o8Rz-oOJJaXa?~VZ)`V6UNYf|iO( zv=-71xk^|hUm)$W`qu}|L#CTYM@P+$I%Iv-Zyu;bGy#tl$99-%6$)dNHf!lgUe9z4 zQqxF3x(%|b}2FmxQN z5sSeHRiY?Bmns=)G0y@NAmU2X6Su%FepQr(He>M`AYSftAAQzq4|m$VueLV3y?kM# zv(+7Lw08F(OP+QW(RJ6kpc+_Lo$Zn_?-szyS8s$foCo7pj6;n)AN&94Ww35Qc5BX2 z0r__@9ON@{j-bSN21V9Cp7yNA$!&DzpQG>Z&%CL37I5zz*a}t&cKTDF`x(}oFyh;2 zM*6^9A2{^P!$_{&L+0ysgp2nH^nE1n`^c70e!yr3+&+EFR(LQCfLP=icAg<&9(ZbN4Kx68sF4*?XqtjECD{as z10lp0zevFz(CEW;I5p@iyZuF8Z86Kj_{1a)4>VJVIe%mB`C3SMRUD^G8mI7@c0A9^ zYBT|rn>^T$w6Pj)Bb1jwSRjzRERIE(S&-kpu;BraIIp&kLy@{WA`hHwY+fC+M2xa1 z=8aN8ynJOIz|dS>CxgYSP*f(ZzEzx|g~?)@WAT5YE<3GXx^Q)R6SkXophKiafTe`s zC0xT5c<pZ>;MKqNyRf5C%NO{B$+22Vml6dRjhO?kUM};|C03)tr@|Iu kFX&(RxfW9)qe4NIkHAqDi%(p^jk_Hdv3o0|5>(3n0^>7{qW}N^ literal 0 HcmV?d00001 diff --git a/home/__pycache__/library_correo.cpython-39.pyc b/home/__pycache__/library_correo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ee1bdbdfdfba80ab444cf43171c756961f3d52c GIT binary patch literal 1089 zcmZ8g&2AGh5VoEDYiLkgB!mP9A2^Up!hutT5LKHBq_&8*s3Moe-F4Hgymn+eRTFKv zlq*kwcmNKZc!a)%ubg;=o)~A7s9icP_!J=Y+b`}80*lx1 zm>n=V%CSIw|0V*Lq))KN4bdorelWv<2+OD+&2T8{bkyd0MhUz#=i++CmNt;57{&xK6D~jn&`;U(=&uYT3YKKy*10KwiQ&JVt_q#Y5Y0%0&4UeJqHAGqEQzE0}7)jFK>P_I+8R~T60CY;F;AozhsdqIhdz1DAWo9I;qB$4yEjr6! z=oR;^Ttx2_nrB%7n?v}5kWb9Hfj%?KbfNB~^AZ?YzDPeDS>_Xg-~UWKH9s;XEx!VK zd68M*w_UFl9Wu>meS{!b|5Kyhakov}>bWgNT5@C9fV$7tb5(l10-1&Gox@E=xy{-fw~ULM~Z0&$KG*K0C~RAiWMjw@DyXWe;?SOQNvL{55ke|ePvnAB)D_ig8#~EH`v|u4APT*J zRDK3I@|S$=iF0ops?H?5DuJz;9ec+!-^_f`@^Tq))$@L*=K}nu!{g=PVHZVjqY@xk z0x1g^Bbz5Ybpj`K0~gPZaFasn1s;PhAPT}e2jQLZpeTw5Q1!3zJyeeRl#Sr)ab}ej{9n74Ud0NVDjO)9=D<-3By_=$=JLNi}MgqWwU-`0dj{3q{+9! IR#}Dr1H9=X1ONa4 literal 0 HcmV?d00001 diff --git a/home/__pycache__/models.cpython-39.pyc b/home/__pycache__/models.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..335bf6fcb4ecfded6b7c2a0c9aced07c157fdc3c GIT binary patch literal 13190 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 S<=p~ahb5Z8DaYF+C;tFqn%mO= literal 0 HcmV?d00001 diff --git a/home/__pycache__/urls.cpython-39.pyc b/home/__pycache__/urls.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dbaea806dc307b650a5c3f006d4f211618290784 GIT binary patch literal 4608 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

3^al9Hzi^+0aw1)?%b&!_a$Rn~ zBT=sbkM53;4j6<#*kTfaO0d5QRs+2AXF9@68K%y~Dm2+9ym4x~Q5(yL3t3$cJ0g z;b-{)ZTb_m9q~wO5Udi^ah_ts|8LTK)eYk{+v-!d4JT2kxct)Z5tGUegX#x z9nEI8vTiv&-3Ssgi#am6E(2YNq=gFGhf)T3jx+a*C=)}!2H+)iO`AbYrz3Jd05AC# zj)jcFc4U?x2lOENUB#UqO!yX;KPGcvG82M^KRzl~GcKGWBm>my0R`{{xzp?3@iw&U;}&(Q9})0- zK|%uN!SVv>TwksKBBD0H{sWdCYeQ#aye@UDa_c}mT46M>P2Ql`kccgaJ}h;wYQ|Xu zY&r~0fyja^EzuraC`uH!uE`~}9ujEx>JTQt23T~&s8?_%!6x4%5QX05KM4rcI@oOl z?q5l2)-EyocNYzU>qZD|(uvD&2&y-EGyJTV+lNPl+19kh*nzojPzZuSoP#OY^73NO z8lxruKJ4>kTG13^!i$&>(UL!S175ql2w9}ZE80w6oAg+|6x63H*VPn2TuzNLU>ITr zznDQ6VZ*`rnQC2Ijj5HySb>)#N`fnyGq2Hz#Lazk&lMV=w*aH}+?+kbjhWoHBb2b| z`Yc!>3Z`VILpEgc^3K4!mqzvqyxKF`mH_weNBVJsD}TN@P;Dn^yw(tw7AuIsAiEeK z6h$3<)IvGgfflxCuO`w@-qwkJU&rjvV7kbeR9^hzoAR zeFqm%&?IpsQsJF6sffB!B^YvVEsz}p?=j-=AOuKY6Mh3tSsruH_VND%%<<-bub6|8 z%>B57A~0Z?n+3}ZyZE4mH=3z)yk837mvs()S+6z-e%a{5B*ZV91i#QK(2rlPQ`rE1 zSz;HcKi@u-E(P=Lfy9q`ka$PEV%6%?XIrbQovL2}6hFMu@?HiML!NuORE3I!1b)Xz zI>u&gMRi30EM3uNjmo^%YuiAw{sOvOzrf^|ku;`P`mVrxeUP~IhLxdl*O=4&*+x1` z?M97TIn~Pm0V}>^4XKZwmueIzRy+1 zt#{j1eTED1JtzJplk!^x`5VyYYX|xI*YUk8Li~(Ce5b|BgZ$wo-y{p|IAQ*sXx`Ps zd|I?qB{2wNy5R`m{%@k00l1IzD~Xi7ZuVrvYRYV-Yr6T%?5$2h<>4g{$Tz%=-#`Er zis;{JZ%ZF8d)!MuN-d9rmftO`v9Sixvg`uJ2y^!%!dw#eRfw?;yYaQK8;{MUE+7ye z|MBX>*c)~?Wr^TF$Q;A=3S7k^>`t0d$3iEujD6IH0vu4%`V8XOrLeQD6OrACX7>`l zf>u%7d#n$f3uCkMocqM`9HMSH$G%;1&baKnpK;DJ&N-~DWjv2d~+42}vt7l<=BNqZs3HK#WWM>06?mvEHA}cqh%7yZ2V29aq z_BbxN^}~Px6+16m`e;ktn4RWx(=5vUcFjX7@Py&>roDiDvJ=(##6cEj)A87D?}5g6 z0Bc&+N`4MO*=bM!Yl2GlSRN=-!wdoN|2{A{+`LyY6e&0M5}S}QVVoKaFg_|DFv^Z< zFq*Xgd=+5!jD(MG6_SAS?SbU&q$!n)b7H1UHys-v3Q$?Awd(6BM0$a zTP;n9)RmwvFB&#mFrK!u+ri}M!ejMf0g9q*Ba=ONV#Gsa zcR9wj?X99!En0jxlhM{DV2+;AY35|x4rohxpjKz&-PQ7G?7G&r>z9l9JX2gJHkb6T zz}Jx|EMqx=r%Hu9c8C)Nx4ouPoeEsV?zC2ZwqSQV6--yH8r19WL{FNi$W#KD&0N+n zClXNdG1yZQMfIQZA|Ue>*r7M^uJA-}WR4&_uo3$)44cu|@8bR6<*6_|zr)=Bh9oBu z>`l8l!A!Vv-?>aMiSygKC?U~}!oS<#9b>es&2XX#I$uJp>{E%qecSo?@u7p#HysUp8UlTy0 z)Wvv+i=PgV-BHW_t-EAl^NOp>wT!W$MI=PZmWWEw}8}Yu4EQ{kN-+R$Zi<|JJ1GUXSKAYi^ zHQv8#15m1T{88;ki zyy7!Dt&Ty_@wX^vckxMVXH+XRx<_R{BM}7&^YP+llt95>!Heu9)Mp5TX%+jiN7;*a z;ZEb0m0;*3pr(T=j6g+a8(l^S1V^OC_N>$i)ZuLkd9KP`aI=saq21brq&ZqhcRXY*Uc9!@D+sCU8q2SWC$BCN_{Z7(R+$!wt3W+vA+T?M+Xp07-a0iiM*hRaOArV`xj3fMybF}prIrEldc{)EXs zHdK;v{XzV_yPj_6lh1m%XhL zI8R50z;k4ASAPkw4FF4=FVAs^nYPe255jB$DkM6Pm2iCF(k%4DTrvko4RSa8P@O6= zw7J+|Gsq~u8o>qSi4xt%N_aNFv6!bCp3ivTrv5V8){&j*amz_B#R2RM7ZcZic1_mXLuASIzS;x zv{270jKzSztTcbKulZlSV)H3icea=g>%kgKx5Ys^0<0Shfcse#L@dZ^nS!g@gGWB1!w~uvX@H>E?wH*njFBKZ8s-8Bvv^t;HGbZ0#DbAj$jTTDI zd3PPKDzD7V?pnSM;N?6u3vQv{N=~8K>S;*W%t+T50N!j$Np*p~oe9HFXwDc-agx55$*Y)gD`0ecTTwMA*7e#mH;?mRD?9A=tT*CBkE@8Sh7nfem z#ic`Y3DcL2F0UJNNv8+(e@82qbOcx{_e-rMJ<%8F3Cnu*RrJMQb?OT$6=nY2h)n1C z_iWmmeHqR^y$3~|A%ndjBEU>dgKV&J-ExqzS<>KMHn?^FINK|hsGY{{8;Okmn{QKV zM|vi5se9qjpyA(8$7@3;@})d>U9IGj2N1pwV(2=_wi7T5%j;^c>lAujE6~7=;m&>p zQvAS~JOtI1Tyx zAtjJI@Hn|XJK+RMsc&7bgwvZ|NR|34mMbYe*D6QnnU3%5JQl47mu-qO$X8R+jA^Un z4a+sgjB~3X7f;7lyA!Wfbjxx@Igwh$maWm9y{)3#maEa5$*r=>e$jozCcgJCJ6?w> zfpTNZz5GyV#&svERAIc;YQwTs-wQ0{Yr?W4de9)AR*lQ{>2W>nt8m#qJqbKEOSaIB z03`MU9S3w$&}OUPvag;58f_ILOV_bJx0@`4e1n3^ZNSLt7pdMUQfXeKD69C}OeonZ z{s9vTgo?k(ggTAl?=hhm=*91bMa+xe#e}iqUTiXXBa=5Xc?*+^OrBt}fTS^Sv^tCR zy%b#8z4_@gMFdtNuY>J9as&SJj!33>ljVvT+o-xJ{DNW;PsxKQ+t1)K3LPjhdMzETL`v-^>snS#rj~m=GE7=q`t2O>Pt&~T~c4Vt-fyT zqt5!E+41V@;VaW=Hj-|T~#=w}uN zngfp{76unqEetKJUKn0jQ%fu+o7hQrF-39T!diG*BlZ%6ZU42_C6@L5&qWs2RVHzL z05%N~y&i_6h=#PVz6sHulzd68f_`miVT1F;>gIZi^O_rwu7UCCy2`L~XKgLhTz!#| z#n!>4XdT3NJ&5Tvcrn~urJQ={4%A%NWXvQP)n~$wEn-(Toq{nD8ET8PwJN~WWS z4o_y6RcU!@ET}*{{g&5;druyJ;6!%+!yRrNKY8%bN#1h4DtqwIDZ^#+;}2AWWSvWXF@l&b;hFfmBag)}8N!X! zRyDe{Ji7H^@P^wtCGNy*kp1ZqqU7tmKvA5XFddRhI->;9sc7`9T)NfeZOo3Cwf_(y zC++$Zk<7m~w!7{=^QHU+^t*7Goh;lN@AN)7VEoA$hFM8seJA|A;dt~Kh^r)zP3k4@ zJ-D1zsMq7I=R0-!o|d|BNw4FhjLjxlLFx6IgT1b}EgtxDF3lR8Z)5?7u}m4REb^?| z|Iy2_)5Y1*%gNC)#JBY_EVZS(yFA7T>MTE*C-~$kIf1bu`9xtk{NpD4 zs3y&>V?Z`K&SW3jY?5*2zJcT?I7*O#hZ3pGWrh-xEjGWI-+?E+{&WVybiQ|$vlM@) z9yqqW1q!YV2=}@-A>MdEEWT#}B?06*RE>27kL?i)RH&X<8 zOb!M>3VYKd(n!FS6RK#;iztT9oeYG{c3fJVOSzo~-k$IjLI^URn#>g*lO@avkn42| zn$E~|`+CNmS@QXvCdjX~CP?~n24ZZHR(vzx)oFq_HUkD95QjMH_1O4pw@>Hi$K)*q zZHC@QpBV|7*PX%M5713AQ(IKZ+oAMmPg4WbnAu6y9YPXwB# zT??4t_>(J_@uw6?#(%6e{_tR07Dxa@#2gSE)ll0(FNOq8Z=x58@Pf>T!KH1~36^vQ zUW!vDWne&>5ANfsB;(9+`Tr?LmvX#BGW|_w`M;E>d%4#u?&8nGz`~=bUHX7W2Qs^3 zjm{Ru0&eBU;Emsgk3H1uA669g-nYzPE;E*n@kgL>SrQ^%eS}eaZv{EB_f~+5y|-rE31_TI)Dw*i#wz4evM?PdbtviCO7Fo8Pu?A=Xpvv)Tso4vbH8Yv1P#p8SS z?!lu-Q9V-Bj}$M!-4+gS?F{KnHK&h2+_X@?z7hSe{|A!B!Cg@6)QZ!)D(6RQXTZ!@ z%;^ht9*SjHF~|jxIPUU|&!_|&8NFlo*xdXqJpTTkHU0yWuQT~aCf{K4Kbia!lYeG% znaMYq;1|+|m>fpZ*nM>k;asqG31$nA>ihWQ*wsBLkOI#_aceLlTP`bLB%bT{ecBXZ zpji%ILnG}JKVEixjB&O#Ht0gWR7ST{&*jfo&rdl7hcOU|+X=CjuZ7Gre0Nv@3a`{e6f{Oth@xAU4uVfl8_{wsF2!0kiKz03rQ zH8iqOi#>c3`CPX#@qm?*zMy+?JJ&x`g>h1?2K~1Apj@}m15;84y3gvo`6%7T;;W?j zQ*OL-Q)n=Fk&!d>089IUi{;eV&l>$*qG@uN8}RppsdlaZQs9X}KGE&Fq+jCaw!x~` zu&a7lw72z<99o^hMa@CiM_Fc{my9E454DZBkeF{LfIElVP-MWOAF=T=>F|w_L?rSr zi3H9Pa+ZqxQzC=2RQnl1Oe7=!oan~AbQ%FC5Lu5#FWik1`dqjshS$SR6b3Osi-vN_ zbU7%Ji1M3y6`DK}o*4Oveh*uFn#mlK$C&&+lix*R_p3QbQL1AWaC2?CUbAEpNGL(O z+qnl-w7T5`Q5^j%(G0Qtn7%JnGgce_!_f&08Lj|Nas$YJbIJv`t`h z#8koVg6Ij7tXW9swWI}8}0ALRKolLnI~n7oV0 zyP15D$tRh7hRM$``8g&(&*T@F{0WmkWAYUyf6nADn0%GVUov@-$=8_t6_dYa@;6L| z@MSu~q?^g@Op;7eOinO)4U-3%Jiz4jObSe9nZUF-q>D@zm|SG?Rwhp}c{`KuVe%A{ zcQJXI$-9}nhsk@Hd><3K;piV=a*4?gGx;!+k2CpkCO^T1VHd>lUtH0}wOIUG#XnSB zeZ=lt46em^O^hj+jm4{w6RfwKN-p!TDG*5=QppJv#4KL{|Phg QE2f}MvSmfi)ksu`U)dPZ@Bjb+ literal 0 HcmV?d00001 diff --git a/home/__pycache__/zone_definitions.cpython-39.pyc b/home/__pycache__/zone_definitions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef939cb24261d2d979593872c39ffd3721f467b8 GIT binary patch literal 252717 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

5lLRP`eg)F6K*AMBxPsJLxLqB_9SrAA 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

bWyIN{b|&E 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 literal 0 HcmV?d00001 diff --git a/home/admin.py b/home/admin.py index ecca5cd..7abd91a 100644 --- a/home/admin.py +++ b/home/admin.py @@ -3,7 +3,7 @@ from django.contrib import admin from django import forms from .models import ( Noticia, ClienteCategoria, SistemaOperativo, ServerSelection, - RecruitAFriend, DownloadClientPage, ContentCreator, RecruitReward, GuildRenameSettings, VoteSite, RenamePrice, CustomizePrice, ChangeRacePrice, ChangeFactionPrice, LevelUpPrice, GoldPrice, TransferPrice + RecruitAFriend, DownloadClientPage, ContentCreator, RecruitReward, GuildRenameSettings, VoteSite, RenamePrice, CustomizePrice, ChangeRacePrice, ChangeFactionPrice, LevelUpPrice, GoldPrice, TransferPrice, MaintenanceMode ) from django.db import connections import logging @@ -17,6 +17,11 @@ logger = logging.getLogger(__name__) class ChangeFactionPriceAdmin(admin.ModelAdmin): list_display = ('price',) + +@admin.register(MaintenanceMode) +class MaintenanceModeAdmin(admin.ModelAdmin): + list_display = ('is_active',) + @admin.register(GoldPrice) class GoldPriceAdmin(admin.ModelAdmin): list_display = ('gold_amount', 'price') diff --git a/home/middleware.py b/home/middleware.py new file mode 100644 index 0000000..5f08c09 --- /dev/null +++ b/home/middleware.py @@ -0,0 +1,28 @@ +from django.shortcuts import redirect +from django.urls import resolve, reverse +from .models import MaintenanceMode + +class MaintenanceMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + # Excluir todas las rutas bajo /admin y la propia página de mantenimiento + excluded_prefixes = [ + reverse('admin:index').rstrip('/'), # Asegura que todas las rutas bajo /admin estén excluidas + reverse('maintenance').rstrip('/'), # Página de mantenimiento + ] + + # Verificar si la ruta actual está en los prefijos excluidos + if any(request.path.startswith(prefix) for prefix in excluded_prefixes): + return self.get_response(request) + + # Verificar si el modo de mantenimiento está activo + try: + maintenance = MaintenanceMode.objects.first() + if maintenance and maintenance.is_active: + return redirect('maintenance') + except MaintenanceMode.DoesNotExist: + pass + + return self.get_response(request) diff --git a/home/migrations/0007_maintenancemode.py b/home/migrations/0007_maintenancemode.py new file mode 100644 index 0000000..ab37484 --- /dev/null +++ b/home/migrations/0007_maintenancemode.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.17 on 2024-12-28 21:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0006_changefactionprice_changeraceprice_customizeprice_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='MaintenanceMode', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('is_active', models.BooleanField(default=False)), + ], + ), + ] diff --git a/home/migrations/__pycache__/0001_initial.cpython-39.pyc b/home/migrations/__pycache__/0001_initial.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..149297c8a3283bb2b0376a1e132fb0fb11c59186 GIT binary patch literal 2979 zcmaJ@NpllN6xNJJ(rC3T8!!$@logbKY#@-0Bp4YJ2QXlqqcB-77*mG0!Q z(M~lodvG?j(J)0}Ks}Bk%7Rd22MiNGbmiW`&pZ%U;R%09r&2^&>zLT+q`g!}>dj&k zr%A4FV*|bx&fx5>)iZGpczJB&{H_61K~V-Sf=p>Q-7~#3F7KM^eC5dVGwMV!IbS7( zez9M|v$&@8&8gjad<-AoH9`LgMK4V0lR%fj*5bq-e(43ysTVjezrc9~I2F+GsxoxyBwoLnc>PvFOQhb$rzH;fu!YRj!kHs2G{B!cpr}!O=Q;iF9`qKU z1!@K?8Tg#Ss0p;hB%!_R)Yj6GwsZ!Tr_r2Owl7TS=cD_tNG=|!{XLTVruuCP5V)lD zPAcW{l>a{PtM~)_q00D2z%MKLkCprt{0aV4#r2t@4XCwAZQ0Yvt{!Q7WoqNvA=|A( z)aq2~`ebzgv$Z2N-`+XY6LX)QHNZj@?Vt#82axfIWQ)0p zq`QTJfcT0z+e0qtGPdmuCvt^&h$XHLiU22DK^?FsqPEJO1U^GpXXY-*kLP7@hQ5_)Hp+Ok&*j0mmys)k*2|WqxL&Q-XgzmH(X+8^Tcul?( zX1NU(Q5Om!3mC*c6M1a`U=y=F0#P}`xa(6FNoAs{Sv?v!WCzm38s@%6ktKl-k&DVE zad}Lml{F6KhQ~Fa{WwB(RF8u?g1;mtiZtjkK2U#6Dx>R~b}3|3loJh`!;;9qQS_oKfZXnv3Ef#G(~=k_(LZmPm>ZVfG#=!@46!~ z(yqO@K7DB)s2mMw1d~XVFd0H=k-()Sx`t*l-bg#;D2nth+* zU9hiS&(1Az#-b%Tj9?ZmNxYW!Z*fb@%gg7X-4zVY;fTxoq76^@qgg<6)FD=c*T9G>LIBD*w7E?{T(FBT2k`l zPT|05&8rxT2Y6Cu@lQDSor#u*X*f34*pPX=cmV2 gNvJANs`ug5D|rVN_7z=apUPqhv+%MF+o-1h1t`*X5&!@I literal 0 HcmV?d00001 diff --git a/home/migrations/__pycache__/0002_accountactivation_remove_recruitreward_claimed_by_and_more.cpython-39.pyc b/home/migrations/__pycache__/0002_accountactivation_remove_recruitreward_claimed_by_and_more.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed3ee26431fcddfb8e9daec485dbd55cb7a66216 GIT binary patch literal 1258 zcmY*Z&2Jnv6rT^zW_EXWyJ=G>pAD4D9@tHC0VISHT8esTB%o5Ixfo~P%f#FH*xEA* z$q5Or`-kxVaPpPY9ylW*QF!)Dn&Q#e@8_TWzGuW}H1KGAcW;#)M4tDD1#b>U;E-ND zqX|6lb1(I24f3D})39JE^Sy692!Z|T0mE<^{Su}T_&<2lXhV0r<7r?9h0K(wWmRg^ zD=NTTFD&=w7!x?8SN~2EIxA@ae&(kkvSkDTgxFhd0i!2^9&D}IX#g?p#n6Yr+9xz5 z)Q6-)Bgc(9bnAa;;?Q=--6k|}n(wRw(zD~(yR`F`!*3HFVzL}9$IDxA&)UlR@Xk6Q z&nECLya(?)c^f`}58d7SunQlp1Ne9yW?_089#B3$G5x34d7z}Qv#LOo?CtICb6Lt- zirj1;Ef!T%)<=t4p1XvZK*F=fCV28_%1k1fy5b9kqDC;om6C-}m;41@n!ZLw8srtJ zJV$j>Y2>9K193x)l{VXy*r`v&5I^x8%d9>#5f(z`n^(k`cqO#Hs1$4tEo55cwTVfW zJe8<6Kikbj;X*aCM#Uvi4ADt0$`^)}O`cOgLZ5AR>D)9>6MMYZl=5YRX3)9JMNJND z0iKE`uWb&Ti#;-sgHA`Cc7+#00o}@lED-p~rRyQvH!db+ZKR`)zCJBiTmUH4`l`Qw z@Y!sSp8d_ItvmN=aXw8$^}x!zG?~a5KAzq&F?X6dHv`V8Lz^5)PB?$rh}=495#S0- zz;Yo`tH3H4K6JHsYF$&I-ATTd*%4Lgu?@-eAD#)-ii2-#s#`gEQr4JZ$BZ6PIiFFa zE!l&mD6`5$O)Yb6;+mMNszei()rA>;k41If9gU9wI_=d8yD#iFPkm0Fxasd7=c=me z`EhkFo>$N3w&mtGALE>w?|_T8=fvxt&R@YRHYUcWmATbV{$YQ*`_rDe+eSTeLC>yZR{NyX^g9kt eT-IHp-MyPYTj>jXI{vb)-&eLC+PW9}lkh)fEOFNW literal 0 HcmV?d00001 diff --git a/home/migrations/__pycache__/0003_alter_accountactivation_salt.cpython-39.pyc b/home/migrations/__pycache__/0003_alter_accountactivation_salt.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..be8762890a7f1a5f5a3f3bfedc908abde3625722 GIT binary patch literal 627 zcmZuu!D`$v5S1)><24PWw1<8{!4Tr5y_PmjAw6}W^bqhxD4wa;i)3wO??e)B^`Mi5=cg9q^Bp%%p2+5-JFqqez9tPamIc}aNi_>Lz?|da=?HaW_iVJ zQYD;yWRQTkWFU|)#Sc*lkY8AlUejGxBq6tLb^|~9MbIf$swya zuqpxG@JgUurZE9dmOCIJz2Y#r62xS%Lus-w{d60jlF5a$SiPIgX0Md4Yq#zOT@USM z%&$CJw?SHJzitPQXWE0RjczT1I=xW317)4Z>gj{GLH61V*WanWf|DkFt_*g~uqXtf zs7iI(VvwUxzqV*#UQ9!##&e}Yt|&IF4buLJQs36v#JdpzuCN2_>K1#SP>PVhHv{_P z7{!ZtF#WL5TO4w?!v78Z$^0{7NB8Hb^v(_C+->xUJ1Ju)%Ddi|)RWhWG@yT^Gf~{Z z>cYpLj-S!*k;_DKBU8x}8u?#&GqUqShAAv{*SG^X9jhHH9Lc+Cw!7yPC1h{5y5B}2 JeU!H+{sAp)tw;a> literal 0 HcmV?d00001 diff --git a/home/migrations/__pycache__/0004_alter_accountactivation_salt_and_more.cpython-39.pyc b/home/migrations/__pycache__/0004_alter_accountactivation_salt_and_more.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..27a08daa8f92165056ccefb07cf159c73a7f0b79 GIT binary patch literal 650 zcmaJ;&1w`u5bnR(ogEG6Ma7d|gt=rE^cW=Opa*e5JOt*_v{U6|mYMFgXLd1Xz2-rD zrM`N~D+ENVJBF+XR?|iOb=CJ(n}dUbk-UGjX^#YBKccfQikxG*<1Cv5BdDnUix&cRV45tmeRK z0lek4M77T10GzGopdh>8FuS;k&i{_KqRt_w;ft_%cQchBs53WUc)DCJpKH@k=(TAY zx3!aLrf!$8>5&rQ{y*`cV&d`%;VLB>FiU7J%oIRz9ZAG z2uZF}h1Q|anqF*sB>S$`pSPxuuc8OIK?`V`4o6R4z(VmV0(~9(c^LzDPC9G+d5VO> zZSc=hzcc@U@=0C2t-NznwQ@Ui>Q1Z3ySm+fMH_hW-wkMEfk1jZ+?@OP?K8ULV^X;k yzf`8Upi}(Zv#wIzs#IYCYhzn?2pZYAJ`P)n;;J+uO~Ql-6EZf2T#o5aD+mM&Mg z_8s8JEBVT)uh0W!oGfZ>c{HDAG(X>r9E}o2=kv2VUkw@i1GdY6L->P1h`}uU9!^7u4%xVOO}=c*T~eyt$VTbPy13MUh0VO_{_*KI=-HYC zvS|Qp$|1;uX^7FR=M!K&TY-pf4`NukicUH7G5*>A#Yh{FbpQzruL43Tp@cj~EqXv+ zN$d5Hw4vAX7*?-1MNi=omHOBX_W##N1xIJP#Odqx_4T(x77ZF9vrNycMrMt=Xgd*> z3_?~QN^Q`M4l$b>)hv$mIaZD`MOHp8zH)k$cMijCkOP8e5Uxfs430~I9 zpe372RPFx=S>IV3K0Z}gfIS$GTwk;qg>Z?WR$yKr>8TK3=Cbh49s$-^0alqpYdF>7 zhFfhv`+k^)7KXX>qslj_(;Xk$rF&I_Ihqa)w$9{I9c>d0N2fw%)R0kuF*D6T0b^?cMRQVRkGbUkRLZC6CAUU^Jhkd(J)Y*VV8_qh{ds@oeP% zrDYg@BVhEh5m>}KzKahqzzmF@iEk^g`h{M>BwQh|`^8?dU+R@ilT@R;9iG9>gxujb1M!u!whDFB%5d z+Itq5yztaU4W%zk&+3(V;h+K*6nOQZhWgP0C_(we-m{>BxCy924JM#|QrNRR3mPYu z=4f8YF$q&A);aoXSJF?zeKoc#)x${a$SX?Z8yhqzJT7;VHR$|TyEPp z;6?c6A1(OSNkRMc(pbKh=Ck43CnjorSwr7}+ZuXh6!L6%6~616LwT=_m3J1^8<%`; zU&-;kF;V*dSdQ1xt_J)7=Czdz7_%nD%sY$Gow0nUwq4HO569B~e?4!E<@=Gg@5fke zZ&EJcErciGC-75k@6R-J7v6?<^zOR|*Wo>QKg%2}BHTpYB~5)VhdKm#<-7`}pbN{e zqO0{9+=o@9n#S73yuq5zH(@^*i~SI>*HQjD-VaU+BlHh(r-9gyF6?w+19xT+Yx5fi zHxH@@FC5HLkHN<$cFtdc%`0P(HNfDYVV6aSJQXy+tD9qMRmKSslkkwx)AyC84ip1er}Wf5g3X=4=&VJY%6 zH&m6mE`UWi^bh%}kKvR@s_E`y=-h-$T`+?;w6?4S0v>wFzAC3N$7Cg{u`O8` z?{S&QZ|;O~lDdyiMO8i#3E%Qj6nQ%Ul4Qwwe97DRP=!ov}ID@8>*KIrcw`X5GE&i=s#1Sw+QD<&$8Ig| z1}uD>`Duq~5UA#m#@T1_{-8yIY%;5D%PsgxY!V z2SQdbwpkh3#C_a6(?hT-Q}wJ1Pu23^k^E-B;>5x7;7;QAIcgd4E0O}o7DcN*TvC}< zH9Zy=KW=Cx1QYnMJ*O&;&XeP)n&aTNY#MM}*B$4xlm%q1<4Bx0hMI|=uqdKF!{|jk z1RlCak_M@oT-w=Qb#}IvH=PF`b(hyweMsTs9G&Rs5&eLQLfXVozvp{PIJ{SAhN^lu zo4Yx*7Gf&6%%Ccc*L>ONVoJ8r>ujfjeUPmtHhEtho}!lkazXcm2sjHfsJ2XnmakVZ znZ6f(h$lq}4)Bl>%7R^-Bvcl7)~Ir4X{)o;T~;*_@%&T&Plk-qc>Q?x>4Fp@S$HT8 z*(332fx^0Q_OD<8PqViioFsUB?PbSTMCVS9!ui5;`1EMVKpfAQ1Ig#3BT45-1@HJS zc5kI%nYHJ3$u=!(#+-g`J-5r*dTL}nim#bd|3<3Hkg8~z2tTtYGECFN-`7^z{*U!f zyM9^jsH~=0J1=Xf{lX5)oWdVU{uk;Zsif1^Z-OBPj54-c(KeqYPWXlkvtS0h(7Z1U# ls;ff|-2l3BwY0M`$W{sQSKi5*=RIncn7$|~X5E}B{1+yAJ(2(b literal 0 HcmV?d00001 diff --git a/home/migrations/__pycache__/0007_maintenancemode.cpython-39.pyc b/home/migrations/__pycache__/0007_maintenancemode.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bdff31ae61e368d414fac9fe8a39bc617ee6ac0d GIT binary patch literal 709 zcmYk4&5qMB5XWsN{YcscggAk?BK5NA36Marz-keP_5#vMxme!JG@Fvd!A@J1D_r{^ zyppe+cm)o-jMJj7Bai&|jK@FEM4g<(jK&Gsd{lAwW!fRcj zdpn&@pUdo8)j2Ly=9wB(WO&#zD#L?b*;ZG@_k&b5$VwY@_h+i8TdY-`;f$W*L;+te zocMG;3Efz&S}ik!szq=k%2X+{m0xk|B8#R_B_(v@HJU4JQPzrxqQXiKvc?H_10bqZ z*?Qj2+g}t|f}KxdHg`kfAwl9``ZtREkrnU`4-AFo$Xd5gm)H$SB`C)EyQ#AhI8003;c B92fuq literal 0 HcmV?d00001 diff --git a/home/models.py b/home/models.py index b12023d..75f7890 100644 --- a/home/models.py +++ b/home/models.py @@ -17,6 +17,12 @@ class Noticia(models.Model): def __str__(self): return self.titulo +class MaintenanceMode(models.Model): + is_active = models.BooleanField(default=False) + + def __str__(self): + return "Maintenance Mode" + class UnstuckHistory(models.Model): character_name = models.CharField(max_length=50) used_at = models.DateTimeField() diff --git a/home/templates/maintenance/maintenance.html b/home/templates/maintenance/maintenance.html new file mode 100644 index 0000000..bed3b25 --- /dev/null +++ b/home/templates/maintenance/maintenance.html @@ -0,0 +1,9 @@ + + + {% include 'partials/head.html' %} + {% include 'partials/header.html' %} + {% include 'partials/video.html' %} + {% include 'partials/maintenance.html' %} + {% include 'partials/social.html' %} + {% include 'partials/footer.html' %} + {% include 'partials/final.html' %} \ No newline at end of file diff --git a/home/templates/partials/maintenance.html b/home/templates/partials/maintenance.html new file mode 100644 index 0000000..853f569 --- /dev/null +++ b/home/templates/partials/maintenance.html @@ -0,0 +1,16 @@ +

\ No newline at end of file diff --git a/home/urls.py b/home/urls.py index 0a6dda2..fb6ad81 100644 --- a/home/urls.py +++ b/home/urls.py @@ -64,6 +64,7 @@ urlpatterns = [ path('transfer-success/' , views.transfer_success_view, name='transfer-success'), path('transfer-cancel/' , views.transfer_cancel_view, name='transfer-cancel'), path('store-novawow/' , views.store_novawow_view, name='store-novawow'), + path('maintenance/', views.maintenance_view, name='maintenance'), diff --git a/home/views.py b/home/views.py index 69b7a60..3729484 100644 --- a/home/views.py +++ b/home/views.py @@ -408,6 +408,9 @@ def contact_us_view(request): def legal_notice_view(request): return render(request, 'legal/legal_notice.html') +def maintenance_view(request): + return render(request, 'maintenance/maintenance.html') + def not_found(request, exception=None): return render(request, '404.html', status=404) diff --git a/novawow/__pycache__/__init__.cpython-39.pyc b/novawow/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7186450cadc3a5b8dae0350befb1717bf648a7da GIT binary patch literal 124 zcmYe~<>g`kfY{lAjaE1i3&~WEC>jiuG>y z?cAG9No zS)8>;e+JP?-WRSA(2Esf855Ni(DB`W&aE|vUMsW;ewei^^dl%ay&zLEVIb+0Bx{zP z@Cnbkc?cF~N-iprN;YK^$5wOajCM)RE^3lbsd+1T&OVbbY*LwHbCy@GVd;qrXa~?A zBtx`B?9!BgpR*8?T-0+qh3L&{XIwjmcec@Pk6ly@Y7Q)}HFj_*V-CEzT(~&WnAe6#CG;x?(B~l#}HLa4+A1KWcSU1+!)?|S_E}X;% zzJfuI(l8WwEf>_RYMdIno~G~;3I~(+Tu54$SMXGaJvUNWSxvdk8FSGMRyOb+yO zxebg^m#%V$-k>h8(|Rczbd9>~|ErvZ=rpSsFY-r9h@vjUD3)o6dP9iQ)DN$|)P#`n zKnT4A+4MRxd}9j?OVjX&LGT#t&!tY)<)y9DtQ5=g#E*t?3w|L-v#HK4*mOC*61xzy TOfl>E@vN{X6r*E`25qq4?MO4e literal 0 HcmV?d00001 diff --git a/novawow/__pycache__/settings.cpython-39.pyc b/novawow/__pycache__/settings.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ff7f72b7ee6aec4bce838ad3d2ebf707cd7a448 GIT binary patch literal 4696 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 literal 0 HcmV?d00001 diff --git a/novawow/__pycache__/views.cpython-39.pyc b/novawow/__pycache__/views.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c87e8fdb2ade5e8bd5d729dd97b086ca717d5cc8 GIT binary patch literal 300 zcmYjL!AiqG5S`hyHi!kmOHbZ&>HdI-;5{H73cZw&UD`;Si94GHz3R{Om-gz(U-0Bi zQ0Rksvomk^y{+c+OAtIQx~-S~rNcRl3=dMg5OUyf4+mT$f-^4rgtc*#XDFuMqQVJN z9=vOUuVan6`GcO-=uwJup(sWlC=X5fKCzx{P`SV~3;wnD98VCYviZ5SfhgLNj@61* zwv|56V2_O-c-g(BoBzB`qz!jf+wd;a6!ilPGvTtx(zSc3+AS@4M$E T3lUO&cOcjA{k?vDG`ljt>uEl1 literal 0 HcmV?d00001 diff --git a/novawow/__pycache__/wsgi.cpython-39.pyc b/novawow/__pycache__/wsgi.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..226e99d18ccd00a12bb3a2574cf89f64816dffc9 GIT binary patch literal 527 zcmYjO!EO^V5cN7~6BdekKou7xUn9X94qOnbKx!KWK`NA@NV#mxda`lk^{m!zLVN9@ zzd?`vA|ziq@e7=oBt^_ zlSx8%%kruNTZtJ}}PONpqCi|L?Sa1LOS2`Z`2ckeXGo_eeBOET(3Rj|T zZ~;Zg(sU36{HW1`7hw)!TcE5}-z^B`g%TC&OAD_oEWwJUYRo3(R0Ud0r>d^4DO51% zrc>&7Mk*CHAdDlyYLgJ?sJZcCW-PoE9w42EQ2TdMYAk%F7s{3R-&28=1Sj8SZ{!?T z0i}l8;#CDM$dxaRO#je0*szzxXC;Ju{g&_8h({-%J`Vfm`RMfGVleEF@-OEn-#(vS zA3pp(^ALh@rSElOC(p@3o=1*89&U|f1^Lg`Z5vKPu>)>t8gwzGLJc!@X+wOxqj=An s^&&U$_l0Z_gB;SN$2gV`nj7a?eHFX!xAQ!vg)`qJXg})mC;Tb@2c)o~VgLXD literal 0 HcmV?d00001 diff --git a/novawow/middleware.py b/novawow/middleware.py deleted file mode 100644 index 4f75d78..0000000 --- a/novawow/middleware.py +++ /dev/null @@ -1,34 +0,0 @@ -from django.conf import settings -from django.http import HttpResponsePermanentRedirect - -class SSLRedirectMiddleware: - """ - Middleware para redirigir: - 1. HTTP a HTTPS. - 2. Dominio sin `www` a dominio con `www`. - 3. Añadir `/es/` si no está presente. - """ - def __init__(self, get_response): - self.get_response = get_response - - def __call__(self, request): - host = request.get_host() - is_https = request.is_secure() or settings.DEBUG # Para entornos locales en DEBUG - - # Redirigir a HTTPS si no está seguro - if not is_https: - url = request.build_absolute_uri().replace("http://", "https://") - return HttpResponsePermanentRedirect(url) - - # Redirigir al dominio con `www` - if not host.startswith("www."): - new_host = f"www.{host}" - url = request.build_absolute_uri().replace(host, new_host) - return HttpResponsePermanentRedirect(url) - - # Redirigir a `/es/` si no está incluido - if not request.path.startswith('/es/'): - url = f"https://{host}/es{request.get_full_path()}" - return HttpResponsePermanentRedirect(url) - - return self.get_response(request) diff --git a/novawow/settings.py b/novawow/settings.py index 63c6018..9323a9d 100644 --- a/novawow/settings.py +++ b/novawow/settings.py @@ -23,7 +23,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent SECRET_KEY = 'django-insecure-os9f6#@x_5*sfv2g6vyj*31$964_s%7(%&x0+m)crrbj^=0wus' # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = False ALLOWED_HOSTS = ['novawow.com', 'www.novawow.com', '95.216.107.200'] SECURE_SSL_REDIRECT = True @@ -105,12 +105,12 @@ MIDDLEWARE = [ 'django.middleware.common.CommonMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', - 'novawow.middleware.SSLRedirectMiddleware', + 'home.middleware.MaintenanceMiddleware', ] ROOT_URLCONF = 'novawow.urls' -URL_PRINCIPAL = 'http://localhost:8009' +URL_PRINCIPAL = 'http://novawow.com:8009' # Nombre del servidor NOMBRE_SERVIDOR = "Nova WoW" @@ -233,6 +233,7 @@ USE_TZ = True # https://docs.djangoproject.com/en/5.1/howto/static-files/ STATIC_URL = 'static/' +STATIC_ROOT = 'static/' # Default primary key field type # https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field diff --git a/novawow/urls.py b/novawow/urls.py index 065a928..91a023d 100644 --- a/novawow/urls.py +++ b/novawow/urls.py @@ -15,6 +15,3 @@ urlpatterns += i18n_patterns( path('ckeditor5/', include('django_ckeditor_5.urls')), ) -# Redirigir HTTP a HTTPS globalmente (opcional) -if settings.SECURE_SSL_REDIRECT: - urlpatterns = [path('', lambda request: HttpResponsePermanentRedirect('https://www.novawow.com'))] + urlpatterns \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b173823 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,15 @@ +asgiref==3.8.1 +certifi==2024.12.14 +charset-normalizer==3.4.1 +Django==4.2.17 +django-ckeditor-5==0.2.15 +django-extensions==3.2.3 +gmpy2==2.2.1 +idna==3.10 +mysqlclient==2.2.6 +pillow==11.0.0 +requests==2.32.3 +sqlparse==0.5.3 +stripe==11.4.1 +typing_extensions==4.12.2 +urllib3==2.3.0 diff --git a/static/admin/css/autocomplete.css b/static/admin/css/autocomplete.css new file mode 100644 index 0000000..69c94e7 --- /dev/null +++ b/static/admin/css/autocomplete.css @@ -0,0 +1,275 @@ +select.admin-autocomplete { + width: 20em; +} + +.select2-container--admin-autocomplete.select2-container { + min-height: 30px; +} + +.select2-container--admin-autocomplete .select2-selection--single, +.select2-container--admin-autocomplete .select2-selection--multiple { + min-height: 30px; + padding: 0; +} + +.select2-container--admin-autocomplete.select2-container--focus .select2-selection, +.select2-container--admin-autocomplete.select2-container--open .select2-selection { + border-color: var(--body-quiet-color); + min-height: 30px; +} + +.select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--single, +.select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--single { + padding: 0; +} + +.select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--multiple, +.select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--multiple { + padding: 0; +} + +.select2-container--admin-autocomplete .select2-selection--single { + background-color: var(--body-bg); + border: 1px solid var(--border-color); + border-radius: 4px; +} + +.select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered { + color: var(--body-fg); + line-height: 30px; +} + +.select2-container--admin-autocomplete .select2-selection--single .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; +} + +.select2-container--admin-autocomplete .select2-selection--single .select2-selection__placeholder { + color: var(--body-quiet-color); +} + +.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow { + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; +} + +.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; +} + +.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; +} + +.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__arrow { + left: 1px; + right: auto; +} + +.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single { + background-color: var(--darkened-bg); + cursor: default; +} + +.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single .select2-selection__clear { + display: none; +} + +.select2-container--admin-autocomplete.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; +} + +.select2-container--admin-autocomplete .select2-selection--multiple { + background-color: var(--body-bg); + border: 1px solid var(--border-color); + border-radius: 4px; + cursor: text; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered { + box-sizing: border-box; + list-style: none; + margin: 0; + padding: 0 10px 5px 5px; + width: 100%; + display: flex; + flex-wrap: wrap; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered li { + list-style: none; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__placeholder { + color: var(--body-quiet-color); + margin-top: 5px; + float: left; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin: 5px; + position: absolute; + right: 0; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice { + background-color: var(--darkened-bg); + border: 1px solid var(--border-color); + border-radius: 4px; + cursor: default; + float: left; + margin-right: 5px; + margin-top: 5px; + padding: 0 5px; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove { + color: var(--body-quiet-color); + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 2px; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove:hover { + color: var(--body-fg); +} + +.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-search--inline { + float: right; +} + +.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + margin-left: 5px; + margin-right: auto; +} + +.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; +} + +.select2-container--admin-autocomplete.select2-container--focus .select2-selection--multiple { + border: solid var(--body-quiet-color) 1px; + outline: 0; +} + +.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--multiple { + background-color: var(--darkened-bg); + cursor: default; +} + +.select2-container--admin-autocomplete.select2-container--disabled .select2-selection__choice__remove { + display: none; +} + +.select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--multiple { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--multiple { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.select2-container--admin-autocomplete .select2-search--dropdown { + background: var(--darkened-bg); +} + +.select2-container--admin-autocomplete .select2-search--dropdown .select2-search__field { + background: var(--body-bg); + color: var(--body-fg); + border: 1px solid var(--border-color); + border-radius: 4px; +} + +.select2-container--admin-autocomplete .select2-search--inline .select2-search__field { + background: transparent; + color: var(--body-fg); + border: none; + outline: 0; + box-shadow: none; + -webkit-appearance: textfield; +} + +.select2-container--admin-autocomplete .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; + color: var(--body-fg); + background: var(--body-bg); +} + +.select2-container--admin-autocomplete .select2-results__option[role=group] { + padding: 0; +} + +.select2-container--admin-autocomplete .select2-results__option[aria-disabled=true] { + color: var(--body-quiet-color); +} + +.select2-container--admin-autocomplete .select2-results__option[aria-selected=true] { + background-color: var(--selected-bg); + color: var(--body-fg); +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option { + padding-left: 1em; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__group { + padding-left: 0; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option { + margin-left: -1em; + padding-left: 2em; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -2em; + padding-left: 3em; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -3em; + padding-left: 4em; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -4em; + padding-left: 5em; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -5em; + padding-left: 6em; +} + +.select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] { + background-color: var(--primary); + color: var(--primary-fg); +} + +.select2-container--admin-autocomplete .select2-results__group { + cursor: default; + display: block; + padding: 6px; +} diff --git a/static/admin/css/base.css b/static/admin/css/base.css new file mode 100644 index 0000000..93db7d0 --- /dev/null +++ b/static/admin/css/base.css @@ -0,0 +1,1145 @@ +/* + DJANGO Admin styles +*/ + +/* VARIABLE DEFINITIONS */ +html[data-theme="light"], +:root { + --primary: #79aec8; + --secondary: #417690; + --accent: #f5dd5d; + --primary-fg: #fff; + + --body-fg: #333; + --body-bg: #fff; + --body-quiet-color: #666; + --body-loud-color: #000; + + --header-color: #ffc; + --header-branding-color: var(--accent); + --header-bg: var(--secondary); + --header-link-color: var(--primary-fg); + + --breadcrumbs-fg: #c4dce8; + --breadcrumbs-link-fg: var(--body-bg); + --breadcrumbs-bg: var(--primary); + + --link-fg: #417893; + --link-hover-color: #036; + --link-selected-fg: #5b80b2; + + --hairline-color: #e8e8e8; + --border-color: #ccc; + + --error-fg: #ba2121; + + --message-success-bg: #dfd; + --message-warning-bg: #ffc; + --message-error-bg: #ffefef; + + --darkened-bg: #f8f8f8; /* A bit darker than --body-bg */ + --selected-bg: #e4e4e4; /* E.g. selected table cells */ + --selected-row: #ffc; + + --button-fg: #fff; + --button-bg: var(--primary); + --button-hover-bg: #609ab6; + --default-button-bg: var(--secondary); + --default-button-hover-bg: #205067; + --close-button-bg: #747474; + --close-button-hover-bg: #333; + --delete-button-bg: #ba2121; + --delete-button-hover-bg: #a41515; + + --object-tools-fg: var(--button-fg); + --object-tools-bg: var(--close-button-bg); + --object-tools-hover-bg: var(--close-button-hover-bg); + + --font-family-primary: + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + system-ui, + Roboto, + "Helvetica Neue", + Arial, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji"; + --font-family-monospace: + ui-monospace, + Menlo, + Monaco, + "Cascadia Mono", + "Segoe UI Mono", + "Roboto Mono", + "Oxygen Mono", + "Ubuntu Monospace", + "Source Code Pro", + "Fira Mono", + "Droid Sans Mono", + "Courier New", + monospace, + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji"; +} + +html, body { + height: 100%; +} + +body { + margin: 0; + padding: 0; + font-size: 0.875rem; + font-family: var(--font-family-primary); + color: var(--body-fg); + background: var(--body-bg); +} + +/* LINKS */ + +a:link, a:visited { + color: var(--link-fg); + text-decoration: none; + transition: color 0.15s, background 0.15s; +} + +a:focus, a:hover { + color: var(--link-hover-color); +} + +a:focus { + text-decoration: underline; +} + +a img { + border: none; +} + +a.section:link, a.section:visited { + color: var(--header-link-color); + text-decoration: none; +} + +a.section:focus, a.section:hover { + text-decoration: underline; +} + +/* GLOBAL DEFAULTS */ + +p, ol, ul, dl { + margin: .2em 0 .8em 0; +} + +p { + padding: 0; + line-height: 140%; +} + +h1,h2,h3,h4,h5 { + font-weight: bold; +} + +h1 { + margin: 0 0 20px; + font-weight: 300; + font-size: 1.25rem; + color: var(--body-quiet-color); +} + +h2 { + font-size: 1rem; + margin: 1em 0 .5em 0; +} + +h2.subhead { + font-weight: normal; + margin-top: 0; +} + +h3 { + font-size: 0.875rem; + margin: .8em 0 .3em 0; + color: var(--body-quiet-color); + font-weight: bold; +} + +h4 { + font-size: 0.75rem; + margin: 1em 0 .8em 0; + padding-bottom: 3px; +} + +h5 { + font-size: 0.625rem; + margin: 1.5em 0 .5em 0; + color: var(--body-quiet-color); + text-transform: uppercase; + letter-spacing: 1px; +} + +ul > li { + list-style-type: square; + padding: 1px 0; +} + +li ul { + margin-bottom: 0; +} + +li, dt, dd { + font-size: 0.8125rem; + line-height: 1.25rem; +} + +dt { + font-weight: bold; + margin-top: 4px; +} + +dd { + margin-left: 0; +} + +form { + margin: 0; + padding: 0; +} + +fieldset { + margin: 0; + min-width: 0; + padding: 0; + border: none; + border-top: 1px solid var(--hairline-color); +} + +blockquote { + font-size: 0.6875rem; + color: #777; + margin-left: 2px; + padding-left: 10px; + border-left: 5px solid #ddd; +} + +code, pre { + font-family: var(--font-family-monospace); + color: var(--body-quiet-color); + font-size: 0.75rem; + overflow-x: auto; +} + +pre.literal-block { + margin: 10px; + background: var(--darkened-bg); + padding: 6px 8px; +} + +code strong { + color: #930; +} + +hr { + clear: both; + color: var(--hairline-color); + background-color: var(--hairline-color); + height: 1px; + border: none; + margin: 0; + padding: 0; + line-height: 1px; +} + +/* TEXT STYLES & MODIFIERS */ + +.small { + font-size: 0.6875rem; +} + +.mini { + font-size: 0.625rem; +} + +.help, p.help, form p.help, div.help, form div.help, div.help li { + font-size: 0.6875rem; + color: var(--body-quiet-color); +} + +div.help ul { + margin-bottom: 0; +} + +.help-tooltip { + cursor: help; +} + +p img, h1 img, h2 img, h3 img, h4 img, td img { + vertical-align: middle; +} + +.quiet, a.quiet:link, a.quiet:visited { + color: var(--body-quiet-color); + font-weight: normal; +} + +.clear { + clear: both; +} + +.nowrap { + white-space: nowrap; +} + +.hidden { + display: none !important; +} + +/* TABLES */ + +table { + border-collapse: collapse; + border-color: var(--border-color); +} + +td, th { + font-size: 0.8125rem; + line-height: 1rem; + border-bottom: 1px solid var(--hairline-color); + vertical-align: top; + padding: 8px; +} + +th { + font-weight: 600; + text-align: left; +} + +thead th, +tfoot td { + color: var(--body-quiet-color); + padding: 5px 10px; + font-size: 0.6875rem; + background: var(--body-bg); + border: none; + border-top: 1px solid var(--hairline-color); + border-bottom: 1px solid var(--hairline-color); +} + +tfoot td { + border-bottom: none; + border-top: 1px solid var(--hairline-color); +} + +thead th.required { + color: var(--body-loud-color); +} + +tr.alt { + background: var(--darkened-bg); +} + +tr:nth-child(odd), .row-form-errors { + background: var(--body-bg); +} + +tr:nth-child(even), +tr:nth-child(even) .errorlist, +tr:nth-child(odd) + .row-form-errors, +tr:nth-child(odd) + .row-form-errors .errorlist { + background: var(--darkened-bg); +} + +/* SORTABLE TABLES */ + +thead th { + padding: 5px 10px; + line-height: normal; + text-transform: uppercase; + background: var(--darkened-bg); +} + +thead th a:link, thead th a:visited { + color: var(--body-quiet-color); +} + +thead th.sorted { + background: var(--selected-bg); +} + +thead th.sorted .text { + padding-right: 42px; +} + +table thead th .text span { + padding: 8px 10px; + display: block; +} + +table thead th .text a { + display: block; + cursor: pointer; + padding: 8px 10px; +} + +table thead th .text a:focus, table thead th .text a:hover { + background: var(--selected-bg); +} + +thead th.sorted a.sortremove { + visibility: hidden; +} + +table thead th.sorted:hover a.sortremove { + visibility: visible; +} + +table thead th.sorted .sortoptions { + display: block; + padding: 9px 5px 0 5px; + float: right; + text-align: right; +} + +table thead th.sorted .sortpriority { + font-size: .8em; + min-width: 12px; + text-align: center; + vertical-align: 3px; + margin-left: 2px; + margin-right: 2px; +} + +table thead th.sorted .sortoptions a { + position: relative; + width: 14px; + height: 14px; + display: inline-block; + background: url(../img/sorting-icons.svg) 0 0 no-repeat; + background-size: 14px auto; +} + +table thead th.sorted .sortoptions a.sortremove { + background-position: 0 0; +} + +table thead th.sorted .sortoptions a.sortremove:after { + content: '\\'; + position: absolute; + top: -6px; + left: 3px; + font-weight: 200; + font-size: 1.125rem; + color: var(--body-quiet-color); +} + +table thead th.sorted .sortoptions a.sortremove:focus:after, +table thead th.sorted .sortoptions a.sortremove:hover:after { + color: var(--link-fg); +} + +table thead th.sorted .sortoptions a.sortremove:focus, +table thead th.sorted .sortoptions a.sortremove:hover { + background-position: 0 -14px; +} + +table thead th.sorted .sortoptions a.ascending { + background-position: 0 -28px; +} + +table thead th.sorted .sortoptions a.ascending:focus, +table thead th.sorted .sortoptions a.ascending:hover { + background-position: 0 -42px; +} + +table thead th.sorted .sortoptions a.descending { + top: 1px; + background-position: 0 -56px; +} + +table thead th.sorted .sortoptions a.descending:focus, +table thead th.sorted .sortoptions a.descending:hover { + background-position: 0 -70px; +} + +/* FORM DEFAULTS */ + +input, textarea, select, .form-row p, form .button { + margin: 2px 0; + padding: 2px 3px; + vertical-align: middle; + font-family: var(--font-family-primary); + font-weight: normal; + font-size: 0.8125rem; +} +.form-row div.help { + padding: 2px 3px; +} + +textarea { + vertical-align: top; +} + +input[type=text], input[type=password], input[type=email], input[type=url], +input[type=number], input[type=tel], textarea, select, .vTextField { + border: 1px solid var(--border-color); + border-radius: 4px; + padding: 5px 6px; + margin-top: 0; + color: var(--body-fg); + background-color: var(--body-bg); +} + +input[type=text]:focus, input[type=password]:focus, input[type=email]:focus, +input[type=url]:focus, input[type=number]:focus, input[type=tel]:focus, +textarea:focus, select:focus, .vTextField:focus { + border-color: var(--body-quiet-color); +} + +select { + height: 1.875rem; +} + +select[multiple] { + /* Allow HTML size attribute to override the height in the rule above. */ + height: auto; + min-height: 150px; +} + +/* FORM BUTTONS */ + +.button, input[type=submit], input[type=button], .submit-row input, a.button { + background: var(--button-bg); + padding: 10px 15px; + border: none; + border-radius: 4px; + color: var(--button-fg); + cursor: pointer; + transition: background 0.15s; +} + +a.button { + padding: 4px 5px; +} + +.button:active, input[type=submit]:active, input[type=button]:active, +.button:focus, input[type=submit]:focus, input[type=button]:focus, +.button:hover, input[type=submit]:hover, input[type=button]:hover { + background: var(--button-hover-bg); +} + +.button[disabled], input[type=submit][disabled], input[type=button][disabled] { + opacity: 0.4; +} + +.button.default, input[type=submit].default, .submit-row input.default { + border: none; + font-weight: 400; + background: var(--default-button-bg); +} + +.button.default:active, input[type=submit].default:active, +.button.default:focus, input[type=submit].default:focus, +.button.default:hover, input[type=submit].default:hover { + background: var(--default-button-hover-bg); +} + +.button[disabled].default, +input[type=submit][disabled].default, +input[type=button][disabled].default { + opacity: 0.4; +} + + +/* MODULES */ + +.module { + border: none; + margin-bottom: 30px; + background: var(--body-bg); +} + +.module p, .module ul, .module h3, .module h4, .module dl, .module pre { + padding-left: 10px; + padding-right: 10px; +} + +.module blockquote { + margin-left: 12px; +} + +.module ul, .module ol { + margin-left: 1.5em; +} + +.module h3 { + margin-top: .6em; +} + +.module h2, .module caption, .inline-group h2 { + margin: 0; + padding: 8px; + font-weight: 400; + font-size: 0.8125rem; + text-align: left; + background: var(--primary); + color: var(--header-link-color); +} + +.module caption, +.inline-group h2 { + font-size: 0.75rem; + letter-spacing: 0.5px; + text-transform: uppercase; +} + +.module table { + border-collapse: collapse; +} + +/* MESSAGES & ERRORS */ + +ul.messagelist { + padding: 0; + margin: 0; +} + +ul.messagelist li { + display: block; + font-weight: 400; + font-size: 0.8125rem; + padding: 10px 10px 10px 65px; + margin: 0 0 10px 0; + background: var(--message-success-bg) url(../img/icon-yes.svg) 40px 12px no-repeat; + background-size: 16px auto; + color: var(--body-fg); + word-break: break-word; +} + +ul.messagelist li.warning { + background: var(--message-warning-bg) url(../img/icon-alert.svg) 40px 14px no-repeat; + background-size: 14px auto; +} + +ul.messagelist li.error { + background: var(--message-error-bg) url(../img/icon-no.svg) 40px 12px no-repeat; + background-size: 16px auto; +} + +.errornote { + font-size: 0.875rem; + font-weight: 700; + display: block; + padding: 10px 12px; + margin: 0 0 10px 0; + color: var(--error-fg); + border: 1px solid var(--error-fg); + border-radius: 4px; + background-color: var(--body-bg); + background-position: 5px 12px; + overflow-wrap: break-word; +} + +ul.errorlist { + margin: 0 0 4px; + padding: 0; + color: var(--error-fg); + background: var(--body-bg); +} + +ul.errorlist li { + font-size: 0.8125rem; + display: block; + margin-bottom: 4px; + overflow-wrap: break-word; +} + +ul.errorlist li:first-child { + margin-top: 0; +} + +ul.errorlist li a { + color: inherit; + text-decoration: underline; +} + +td ul.errorlist { + margin: 0; + padding: 0; +} + +td ul.errorlist li { + margin: 0; +} + +.form-row.errors { + margin: 0; + border: none; + border-bottom: 1px solid var(--hairline-color); + background: none; +} + +.form-row.errors ul.errorlist li { + padding-left: 0; +} + +.errors input, .errors select, .errors textarea, +td ul.errorlist + input, td ul.errorlist + select, td ul.errorlist + textarea { + border: 1px solid var(--error-fg); +} + +.description { + font-size: 0.75rem; + padding: 5px 0 0 12px; +} + +/* BREADCRUMBS */ + +div.breadcrumbs { + background: var(--breadcrumbs-bg); + padding: 10px 40px; + border: none; + color: var(--breadcrumbs-fg); + text-align: left; +} + +div.breadcrumbs a { + color: var(--breadcrumbs-link-fg); +} + +div.breadcrumbs a:focus, div.breadcrumbs a:hover { + color: var(--breadcrumbs-fg); +} + +/* ACTION ICONS */ + +.viewlink, .inlineviewlink { + padding-left: 16px; + background: url(../img/icon-viewlink.svg) 0 1px no-repeat; +} + +.addlink { + padding-left: 16px; + background: url(../img/icon-addlink.svg) 0 1px no-repeat; +} + +.changelink, .inlinechangelink { + padding-left: 16px; + background: url(../img/icon-changelink.svg) 0 1px no-repeat; +} + +.deletelink { + padding-left: 16px; + background: url(../img/icon-deletelink.svg) 0 1px no-repeat; +} + +a.deletelink:link, a.deletelink:visited { + color: #CC3434; /* XXX Probably unused? */ +} + +a.deletelink:focus, a.deletelink:hover { + color: #993333; /* XXX Probably unused? */ + text-decoration: none; +} + +/* OBJECT TOOLS */ + +.object-tools { + font-size: 0.625rem; + font-weight: bold; + padding-left: 0; + float: right; + position: relative; + margin-top: -48px; +} + +.object-tools li { + display: block; + float: left; + margin-left: 5px; + height: 1rem; +} + +.object-tools a { + border-radius: 15px; +} + +.object-tools a:link, .object-tools a:visited { + display: block; + float: left; + padding: 3px 12px; + background: var(--object-tools-bg); + color: var(--object-tools-fg); + font-weight: 400; + font-size: 0.6875rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.object-tools a:focus, .object-tools a:hover { + background-color: var(--object-tools-hover-bg); +} + +.object-tools a:focus{ + text-decoration: none; +} + +.object-tools a.viewsitelink, .object-tools a.addlink { + background-repeat: no-repeat; + background-position: right 7px center; + padding-right: 26px; +} + +.object-tools a.viewsitelink { + background-image: url(../img/tooltag-arrowright.svg); +} + +.object-tools a.addlink { + background-image: url(../img/tooltag-add.svg); +} + +/* OBJECT HISTORY */ + +#change-history table { + width: 100%; +} + +#change-history table tbody th { + width: 16em; +} + +#change-history .paginator { + color: var(--body-quiet-color); + border-bottom: 1px solid var(--hairline-color); + background: var(--body-bg); + overflow: hidden; +} + +/* PAGE STRUCTURE */ + +#container { + position: relative; + width: 100%; + min-width: 980px; + padding: 0; + display: flex; + flex-direction: column; + height: 100%; +} + +#container > div { + flex-shrink: 0; +} + +#container > .main { + display: flex; + flex: 1 0 auto; +} + +.main > .content { + flex: 1 0; + max-width: 100%; +} + +.skip-to-content-link { + position: absolute; + top: -999px; + margin: 5px; + padding: 5px; + background: var(--body-bg); + z-index: 1; +} + +.skip-to-content-link:focus { + left: 0px; + top: 0px; +} + +#content { + padding: 20px 40px; +} + +.dashboard #content { + width: 600px; +} + +#content-main { + float: left; + width: 100%; +} + +#content-related { + float: right; + width: 260px; + position: relative; + margin-right: -300px; +} + +#footer { + clear: both; + padding: 10px; +} + +/* COLUMN TYPES */ + +.colMS { + margin-right: 300px; +} + +.colSM { + margin-left: 300px; +} + +.colSM #content-related { + float: left; + margin-right: 0; + margin-left: -300px; +} + +.colSM #content-main { + float: right; +} + +.popup .colM { + width: auto; +} + +/* HEADER */ + +#header { + width: auto; + height: auto; + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 40px; + background: var(--header-bg); + color: var(--header-color); + overflow: hidden; +} + +#header a:link, #header a:visited, #logout-form button { + color: var(--header-link-color); +} + +#header a:focus , #header a:hover { + text-decoration: underline; +} + +#branding { + display: flex; +} + +#branding h1 { + padding: 0; + margin: 0; + margin-inline-end: 20px; + font-weight: 300; + font-size: 1.5rem; + color: var(--header-branding-color); +} + +#branding h1 a:link, #branding h1 a:visited { + color: var(--accent); +} + +#branding h2 { + padding: 0 10px; + font-size: 0.875rem; + margin: -8px 0 8px 0; + font-weight: normal; + color: var(--header-color); +} + +#branding a:hover { + text-decoration: none; +} + +#logout-form { + display: inline; +} + +#logout-form button { + background: none; + border: 0; + cursor: pointer; + font-family: var(--font-family-primary); +} + +#user-tools { + float: right; + margin: 0 0 0 20px; + text-align: right; +} + +#user-tools, #logout-form button{ + padding: 0; + font-weight: 300; + font-size: 0.6875rem; + letter-spacing: 0.5px; + text-transform: uppercase; +} + +#user-tools a, #logout-form button { + border-bottom: 1px solid rgba(255, 255, 255, 0.25); +} + +#user-tools a:focus, #user-tools a:hover, +#logout-form button:active, #logout-form button:hover { + text-decoration: none; + border-bottom: 0; +} + +#logout-form button:active, #logout-form button:hover { + margin-bottom: 1px; +} + +/* SIDEBAR */ + +#content-related { + background: var(--darkened-bg); +} + +#content-related .module { + background: none; +} + +#content-related h3 { + color: var(--body-quiet-color); + padding: 0 16px; + margin: 0 0 16px; +} + +#content-related h4 { + font-size: 0.8125rem; +} + +#content-related p { + padding-left: 16px; + padding-right: 16px; +} + +#content-related .actionlist { + padding: 0; + margin: 16px; +} + +#content-related .actionlist li { + line-height: 1.2; + margin-bottom: 10px; + padding-left: 18px; +} + +#content-related .module h2 { + background: none; + padding: 16px; + margin-bottom: 16px; + border-bottom: 1px solid var(--hairline-color); + font-size: 1.125rem; + color: var(--body-fg); +} + +.delete-confirmation form input[type="submit"] { + background: var(--delete-button-bg); + border-radius: 4px; + padding: 10px 15px; + color: var(--button-fg); +} + +.delete-confirmation form input[type="submit"]:active, +.delete-confirmation form input[type="submit"]:focus, +.delete-confirmation form input[type="submit"]:hover { + background: var(--delete-button-hover-bg); +} + +.delete-confirmation form .cancel-link { + display: inline-block; + vertical-align: middle; + height: 0.9375rem; + line-height: 0.9375rem; + border-radius: 4px; + padding: 10px 15px; + color: var(--button-fg); + background: var(--close-button-bg); + margin: 0 0 0 10px; +} + +.delete-confirmation form .cancel-link:active, +.delete-confirmation form .cancel-link:focus, +.delete-confirmation form .cancel-link:hover { + background: var(--close-button-hover-bg); +} + +/* POPUP */ +.popup #content { + padding: 20px; +} + +.popup #container { + min-width: 0; +} + +.popup #header { + padding: 10px 20px; +} + +/* PAGINATOR */ + +.paginator { + display: flex; + align-items: center; + gap: 4px; + font-size: 0.8125rem; + padding-top: 10px; + padding-bottom: 10px; + line-height: 22px; + margin: 0; + border-top: 1px solid var(--hairline-color); + width: 100%; +} + +.paginator a:link, .paginator a:visited { + padding: 2px 6px; + background: var(--button-bg); + text-decoration: none; + color: var(--button-fg); +} + +.paginator a.showall { + border: none; + background: none; + color: var(--link-fg); +} + +.paginator a.showall:focus, .paginator a.showall:hover { + background: none; + color: var(--link-hover-color); +} + +.paginator .end { + margin-right: 6px; +} + +.paginator .this-page { + padding: 2px 6px; + font-weight: bold; + font-size: 0.8125rem; + vertical-align: top; +} + +.paginator a:focus, .paginator a:hover { + color: white; + background: var(--link-hover-color); +} + +.paginator input { + margin-left: auto; +} + +.base-svgs { + display: none; +} diff --git a/static/admin/css/changelists.css b/static/admin/css/changelists.css new file mode 100644 index 0000000..a754513 --- /dev/null +++ b/static/admin/css/changelists.css @@ -0,0 +1,328 @@ +/* CHANGELISTS */ + +#changelist { + display: flex; + align-items: flex-start; + justify-content: space-between; +} + +#changelist .changelist-form-container { + flex: 1 1 auto; + min-width: 0; +} + +#changelist table { + width: 100%; +} + +.change-list .hiddenfields { display:none; } + +.change-list .filtered table { + border-right: none; +} + +.change-list .filtered { + min-height: 400px; +} + +.change-list .filtered .results, .change-list .filtered .paginator, +.filtered #toolbar, .filtered div.xfull { + width: auto; +} + +.change-list .filtered table tbody th { + padding-right: 1em; +} + +#changelist-form .results { + overflow-x: auto; + width: 100%; +} + +#changelist .toplinks { + border-bottom: 1px solid var(--hairline-color); +} + +#changelist .paginator { + color: var(--body-quiet-color); + border-bottom: 1px solid var(--hairline-color); + background: var(--body-bg); + overflow: hidden; +} + +/* CHANGELIST TABLES */ + +#changelist table thead th { + padding: 0; + white-space: nowrap; + vertical-align: middle; +} + +#changelist table thead th.action-checkbox-column { + width: 1.5em; + text-align: center; +} + +#changelist table tbody td.action-checkbox { + text-align: center; +} + +#changelist table tfoot { + color: var(--body-quiet-color); +} + +/* TOOLBAR */ + +#toolbar { + padding: 8px 10px; + margin-bottom: 15px; + border-top: 1px solid var(--hairline-color); + border-bottom: 1px solid var(--hairline-color); + background: var(--darkened-bg); + color: var(--body-quiet-color); +} + +#toolbar form input { + border-radius: 4px; + font-size: 0.875rem; + padding: 5px; + color: var(--body-fg); +} + +#toolbar #searchbar { + height: 1.1875rem; + border: 1px solid var(--border-color); + padding: 2px 5px; + margin: 0; + vertical-align: top; + font-size: 0.8125rem; + max-width: 100%; +} + +#toolbar #searchbar:focus { + border-color: var(--body-quiet-color); +} + +#toolbar form input[type="submit"] { + border: 1px solid var(--border-color); + font-size: 0.8125rem; + padding: 4px 8px; + margin: 0; + vertical-align: middle; + background: var(--body-bg); + box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; + cursor: pointer; + color: var(--body-fg); +} + +#toolbar form input[type="submit"]:focus, +#toolbar form input[type="submit"]:hover { + border-color: var(--body-quiet-color); +} + +#changelist-search img { + vertical-align: middle; + margin-right: 4px; +} + +#changelist-search .help { + word-break: break-word; +} + +/* FILTER COLUMN */ + +#changelist-filter { + flex: 0 0 240px; + order: 1; + background: var(--darkened-bg); + border-left: none; + margin: 0 0 0 30px; +} + +#changelist-filter h2 { + font-size: 0.875rem; + text-transform: uppercase; + letter-spacing: 0.5px; + padding: 5px 15px; + margin-bottom: 12px; + border-bottom: none; +} + +#changelist-filter h3, +#changelist-filter details summary { + font-weight: 400; + padding: 0 15px; + margin-bottom: 10px; +} + +#changelist-filter details summary > * { + display: inline; +} + +#changelist-filter details > summary { + list-style-type: none; +} + +#changelist-filter details > summary::-webkit-details-marker { + display: none; +} + +#changelist-filter details > summary::before { + content: '→'; + font-weight: bold; + color: var(--link-hover-color); +} + +#changelist-filter details[open] > summary::before { + content: '↓'; +} + +#changelist-filter ul { + margin: 5px 0; + padding: 0 15px 15px; + border-bottom: 1px solid var(--hairline-color); +} + +#changelist-filter ul:last-child { + border-bottom: none; +} + +#changelist-filter li { + list-style-type: none; + margin-left: 0; + padding-left: 0; +} + +#changelist-filter a { + display: block; + color: var(--body-quiet-color); + word-break: break-word; +} + +#changelist-filter li.selected { + border-left: 5px solid var(--hairline-color); + padding-left: 10px; + margin-left: -15px; +} + +#changelist-filter li.selected a { + color: var(--link-selected-fg); +} + +#changelist-filter a:focus, #changelist-filter a:hover, +#changelist-filter li.selected a:focus, +#changelist-filter li.selected a:hover { + color: var(--link-hover-color); +} + +#changelist-filter #changelist-filter-clear a { + font-size: 0.8125rem; + padding-bottom: 10px; + border-bottom: 1px solid var(--hairline-color); +} + +/* DATE DRILLDOWN */ + +.change-list .toplinks { + display: flex; + padding-bottom: 5px; + flex-wrap: wrap; + gap: 3px 17px; + font-weight: bold; +} + +.change-list .toplinks a { + font-size: 0.8125rem; +} + +.change-list .toplinks .date-back { + color: var(--body-quiet-color); +} + +.change-list .toplinks .date-back:focus, +.change-list .toplinks .date-back:hover { + color: var(--link-hover-color); +} + +/* ACTIONS */ + +.filtered .actions { + border-right: none; +} + +#changelist table input { + margin: 0; + vertical-align: baseline; +} + +/* Once the :has() pseudo-class is supported by all browsers, the tr.selected + selector and the JS adding the class can be removed. */ +#changelist tbody tr.selected { + background-color: var(--selected-row); +} + +#changelist tbody tr:has(.action-select:checked) { + background-color: var(--selected-row); +} + +#changelist .actions { + padding: 10px; + background: var(--body-bg); + border-top: none; + border-bottom: none; + line-height: 1.5rem; + color: var(--body-quiet-color); + width: 100%; +} + +#changelist .actions span.all, +#changelist .actions span.action-counter, +#changelist .actions span.clear, +#changelist .actions span.question { + font-size: 0.8125rem; + margin: 0 0.5em; +} + +#changelist .actions:last-child { + border-bottom: none; +} + +#changelist .actions select { + vertical-align: top; + height: 1.5rem; + color: var(--body-fg); + border: 1px solid var(--border-color); + border-radius: 4px; + font-size: 0.875rem; + padding: 0 0 0 4px; + margin: 0; + margin-left: 10px; +} + +#changelist .actions select:focus { + border-color: var(--body-quiet-color); +} + +#changelist .actions label { + display: inline-block; + vertical-align: middle; + font-size: 0.8125rem; +} + +#changelist .actions .button { + font-size: 0.8125rem; + border: 1px solid var(--border-color); + border-radius: 4px; + background: var(--body-bg); + box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; + cursor: pointer; + height: 1.5rem; + line-height: 1; + padding: 4px 8px; + margin: 0; + color: var(--body-fg); +} + +#changelist .actions .button:focus, #changelist .actions .button:hover { + border-color: var(--body-quiet-color); +} diff --git a/static/admin/css/dark_mode.css b/static/admin/css/dark_mode.css new file mode 100644 index 0000000..6d08233 --- /dev/null +++ b/static/admin/css/dark_mode.css @@ -0,0 +1,137 @@ +@media (prefers-color-scheme: dark) { + :root { + --primary: #264b5d; + --primary-fg: #f7f7f7; + + --body-fg: #eeeeee; + --body-bg: #121212; + --body-quiet-color: #e0e0e0; + --body-loud-color: #ffffff; + + --breadcrumbs-link-fg: #e0e0e0; + --breadcrumbs-bg: var(--primary); + + --link-fg: #81d4fa; + --link-hover-color: #4ac1f7; + --link-selected-fg: #6f94c6; + + --hairline-color: #272727; + --border-color: #353535; + + --error-fg: #e35f5f; + --message-success-bg: #006b1b; + --message-warning-bg: #583305; + --message-error-bg: #570808; + + --darkened-bg: #212121; + --selected-bg: #1b1b1b; + --selected-row: #00363a; + + --close-button-bg: #333333; + --close-button-hover-bg: #666666; + } + } + + +html[data-theme="dark"] { + --primary: #264b5d; + --primary-fg: #f7f7f7; + + --body-fg: #eeeeee; + --body-bg: #121212; + --body-quiet-color: #e0e0e0; + --body-loud-color: #ffffff; + + --breadcrumbs-link-fg: #e0e0e0; + --breadcrumbs-bg: var(--primary); + + --link-fg: #81d4fa; + --link-hover-color: #4ac1f7; + --link-selected-fg: #6f94c6; + + --hairline-color: #272727; + --border-color: #353535; + + --error-fg: #e35f5f; + --message-success-bg: #006b1b; + --message-warning-bg: #583305; + --message-error-bg: #570808; + + --darkened-bg: #212121; + --selected-bg: #1b1b1b; + --selected-row: #00363a; + + --close-button-bg: #333333; + --close-button-hover-bg: #666666; +} + +/* THEME SWITCH */ +.theme-toggle { + cursor: pointer; + border: none; + padding: 0; + background: transparent; + vertical-align: middle; + margin-inline-start: 5px; + margin-top: -1px; +} + +.theme-toggle svg { + vertical-align: middle; + height: 1rem; + width: 1rem; + display: none; +} + +/* +Fully hide screen reader text so we only show the one matching the current +theme. +*/ +.theme-toggle .visually-hidden { + display: none; +} + +html[data-theme="auto"] .theme-toggle .theme-label-when-auto { + display: block; +} + +html[data-theme="dark"] .theme-toggle .theme-label-when-dark { + display: block; +} + +html[data-theme="light"] .theme-toggle .theme-label-when-light { + display: block; +} + +/* ICONS */ +.theme-toggle svg.theme-icon-when-auto, +.theme-toggle svg.theme-icon-when-dark, +.theme-toggle svg.theme-icon-when-light { + fill: var(--header-link-color); + color: var(--header-bg); +} + +html[data-theme="auto"] .theme-toggle svg.theme-icon-when-auto { + display: block; +} + +html[data-theme="dark"] .theme-toggle svg.theme-icon-when-dark { + display: block; +} + +html[data-theme="light"] .theme-toggle svg.theme-icon-when-light { + display: block; +} + +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip: rect(0,0,0,0); + white-space: nowrap; + border: 0; + color: var(--body-fg); + background-color: var(--body-bg); +} diff --git a/static/admin/css/dashboard.css b/static/admin/css/dashboard.css new file mode 100644 index 0000000..242b81a --- /dev/null +++ b/static/admin/css/dashboard.css @@ -0,0 +1,29 @@ +/* DASHBOARD */ +.dashboard td, .dashboard th { + word-break: break-word; +} + +.dashboard .module table th { + width: 100%; +} + +.dashboard .module table td { + white-space: nowrap; +} + +.dashboard .module table td a { + display: block; + padding-right: .6em; +} + +/* RECENT ACTIONS MODULE */ + +.module ul.actionlist { + margin-left: 0; +} + +ul.actionlist li { + list-style-type: none; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/static/admin/css/forms.css b/static/admin/css/forms.css new file mode 100644 index 0000000..9a8dad0 --- /dev/null +++ b/static/admin/css/forms.css @@ -0,0 +1,534 @@ +@import url('widgets.css'); + +/* FORM ROWS */ + +.form-row { + overflow: hidden; + padding: 10px; + font-size: 0.8125rem; + border-bottom: 1px solid var(--hairline-color); +} + +.form-row img, .form-row input { + vertical-align: middle; +} + +.form-row label input[type="checkbox"] { + margin-top: 0; + vertical-align: 0; +} + +form .form-row p { + padding-left: 0; +} + +.flex-container { + display: flex; +} + +.form-multiline { + flex-wrap: wrap; +} + +.form-multiline > div { + padding-bottom: 10px; +} + +/* FORM LABELS */ + +label { + font-weight: normal; + color: var(--body-quiet-color); + font-size: 0.8125rem; +} + +.required label, label.required { + font-weight: bold; + color: var(--body-fg); +} + +/* RADIO BUTTONS */ + +form div.radiolist div { + padding-right: 7px; +} + +form div.radiolist.inline div { + display: inline-block; +} + +form div.radiolist label { + width: auto; +} + +form div.radiolist input[type="radio"] { + margin: -2px 4px 0 0; + padding: 0; +} + +form ul.inline { + margin-left: 0; + padding: 0; +} + +form ul.inline li { + float: left; + padding-right: 7px; +} + +/* ALIGNED FIELDSETS */ + +.aligned label { + display: block; + padding: 4px 10px 0 0; + min-width: 160px; + width: 160px; + word-wrap: break-word; + line-height: 1; +} + +.aligned label:not(.vCheckboxLabel):after { + content: ''; + display: inline-block; + vertical-align: middle; + height: 1.625rem; +} + +.aligned label + p, .aligned .checkbox-row + div.help, .aligned label + div.readonly { + padding: 6px 0; + margin-top: 0; + margin-bottom: 0; + margin-left: 0; + overflow-wrap: break-word; +} + +.aligned ul label { + display: inline; + float: none; + width: auto; +} + +.aligned .form-row input { + margin-bottom: 0; +} + +.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField { + width: 350px; +} + +form .aligned ul { + margin-left: 160px; + padding-left: 10px; +} + +form .aligned div.radiolist { + display: inline-block; + margin: 0; + padding: 0; +} + +form .aligned p.help, +form .aligned div.help { + margin-top: 0; + margin-left: 160px; + padding-left: 10px; +} + +form .aligned p.date div.help.timezonewarning, +form .aligned p.datetime div.help.timezonewarning, +form .aligned p.time div.help.timezonewarning { + margin-left: 0; + padding-left: 0; + font-weight: normal; +} + +form .aligned p.help:last-child, +form .aligned div.help:last-child { + margin-bottom: 0; + padding-bottom: 0; +} + +form .aligned input + p.help, +form .aligned textarea + p.help, +form .aligned select + p.help, +form .aligned input + div.help, +form .aligned textarea + div.help, +form .aligned select + div.help { + margin-left: 160px; + padding-left: 10px; +} + +form .aligned ul li { + list-style: none; +} + +form .aligned table p { + margin-left: 0; + padding-left: 0; +} + +.aligned .vCheckboxLabel { + float: none; + width: auto; + display: inline-block; + vertical-align: -3px; + padding: 0 0 5px 5px; +} + +.aligned .vCheckboxLabel + p.help, +.aligned .vCheckboxLabel + div.help { + margin-top: -4px; +} + +.colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField { + width: 610px; +} + +fieldset .fieldBox { + margin-right: 20px; +} + +/* WIDE FIELDSETS */ + +.wide label { + width: 200px; +} + +form .wide p, +form .wide ul.errorlist, +form .wide input + p.help, +form .wide input + div.help { + margin-left: 200px; +} + +form .wide p.help, +form .wide div.help { + padding-left: 50px; +} + +form div.help ul { + padding-left: 0; + margin-left: 0; +} + +.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField { + width: 450px; +} + +/* COLLAPSED FIELDSETS */ + +fieldset.collapsed * { + display: none; +} + +fieldset.collapsed h2, fieldset.collapsed { + display: block; +} + +fieldset.collapsed { + border: 1px solid var(--hairline-color); + border-radius: 4px; + overflow: hidden; +} + +fieldset.collapsed h2 { + background: var(--darkened-bg); + color: var(--body-quiet-color); +} + +fieldset .collapse-toggle { + color: var(--header-link-color); +} + +fieldset.collapsed .collapse-toggle { + background: transparent; + display: inline; + color: var(--link-fg); +} + +/* MONOSPACE TEXTAREAS */ + +fieldset.monospace textarea { + font-family: var(--font-family-monospace); +} + +/* SUBMIT ROW */ + +.submit-row { + padding: 12px 14px 12px; + margin: 0 0 20px; + background: var(--darkened-bg); + border: 1px solid var(--hairline-color); + border-radius: 4px; + overflow: hidden; + display: flex; + gap: 10px; + flex-wrap: wrap; +} + +body.popup .submit-row { + overflow: auto; +} + +.submit-row input { + height: 2.1875rem; + line-height: 0.9375rem; +} + +.submit-row input, .submit-row a { + margin: 0; +} + +.submit-row input.default { + text-transform: uppercase; +} + +.submit-row a.deletelink { + margin-left: auto; +} + +.submit-row a.deletelink { + display: block; + background: var(--delete-button-bg); + border-radius: 4px; + padding: 0.625rem 0.9375rem; + height: 0.9375rem; + line-height: 0.9375rem; + color: var(--button-fg); +} + +.submit-row a.closelink { + display: inline-block; + background: var(--close-button-bg); + border-radius: 4px; + padding: 10px 15px; + height: 0.9375rem; + line-height: 0.9375rem; + color: var(--button-fg); +} + +.submit-row a.deletelink:focus, +.submit-row a.deletelink:hover, +.submit-row a.deletelink:active { + background: var(--delete-button-hover-bg); + text-decoration: none; +} + +.submit-row a.closelink:focus, +.submit-row a.closelink:hover, +.submit-row a.closelink:active { + background: var(--close-button-hover-bg); + text-decoration: none; +} + +/* CUSTOM FORM FIELDS */ + +.vSelectMultipleField { + vertical-align: top; +} + +.vCheckboxField { + border: none; +} + +.vDateField, .vTimeField { + margin-right: 2px; + margin-bottom: 4px; +} + +.vDateField { + min-width: 6.85em; +} + +.vTimeField { + min-width: 4.7em; +} + +.vURLField { + width: 30em; +} + +.vLargeTextField, .vXMLLargeTextField { + width: 48em; +} + +.flatpages-flatpage #id_content { + height: 40.2em; +} + +.module table .vPositiveSmallIntegerField { + width: 2.2em; +} + +.vIntegerField { + width: 5em; +} + +.vBigIntegerField { + width: 10em; +} + +.vForeignKeyRawIdAdminField { + width: 5em; +} + +.vTextField, .vUUIDField { + width: 20em; +} + +/* INLINES */ + +.inline-group { + padding: 0; + margin: 0 0 30px; +} + +.inline-group thead th { + padding: 8px 10px; +} + +.inline-group .aligned label { + width: 160px; +} + +.inline-related { + position: relative; +} + +.inline-related h3 { + margin: 0; + color: var(--body-quiet-color); + padding: 5px; + font-size: 0.8125rem; + background: var(--darkened-bg); + border-top: 1px solid var(--hairline-color); + border-bottom: 1px solid var(--hairline-color); +} + +.inline-related h3 span.delete { + float: right; +} + +.inline-related h3 span.delete label { + margin-left: 2px; + font-size: 0.6875rem; +} + +.inline-related fieldset { + margin: 0; + background: var(--body-bg); + border: none; + width: 100%; +} + +.inline-related fieldset.module h3 { + margin: 0; + padding: 2px 5px 3px 5px; + font-size: 0.6875rem; + text-align: left; + font-weight: bold; + background: #bcd; + color: var(--body-bg); +} + +.inline-group .tabular fieldset.module { + border: none; +} + +.inline-related.tabular fieldset.module table { + width: 100%; + overflow-x: scroll; +} + +.last-related fieldset { + border: none; +} + +.inline-group .tabular tr.has_original td { + padding-top: 2em; +} + +.inline-group .tabular tr td.original { + padding: 2px 0 0 0; + width: 0; + _position: relative; +} + +.inline-group .tabular th.original { + width: 0px; + padding: 0; +} + +.inline-group .tabular td.original p { + position: absolute; + left: 0; + height: 1.1em; + padding: 2px 9px; + overflow: hidden; + font-size: 0.5625rem; + font-weight: bold; + color: var(--body-quiet-color); + _width: 700px; +} + +.inline-group ul.tools { + padding: 0; + margin: 0; + list-style: none; +} + +.inline-group ul.tools li { + display: inline; + padding: 0 5px; +} + +.inline-group div.add-row, +.inline-group .tabular tr.add-row td { + color: var(--body-quiet-color); + background: var(--darkened-bg); + padding: 8px 10px; + border-bottom: 1px solid var(--hairline-color); +} + +.inline-group .tabular tr.add-row td { + padding: 8px 10px; + border-bottom: 1px solid var(--hairline-color); +} + +.inline-group ul.tools a.add, +.inline-group div.add-row a, +.inline-group .tabular tr.add-row td a { + background: url(../img/icon-addlink.svg) 0 1px no-repeat; + padding-left: 16px; + font-size: 0.75rem; +} + +.empty-form { + display: none; +} + +/* RELATED FIELD ADD ONE / LOOKUP */ + +.related-lookup { + margin-left: 5px; + display: inline-block; + vertical-align: middle; + background-repeat: no-repeat; + background-size: 14px; +} + +.related-lookup { + width: 1rem; + height: 1rem; + background-image: url(../img/search.svg); +} + +form .related-widget-wrapper ul { + display: inline-block; + margin-left: 0; + padding-left: 0; +} + +.clearable-file-input input { + margin-top: 0; +} diff --git a/static/admin/css/login.css b/static/admin/css/login.css new file mode 100644 index 0000000..389772f --- /dev/null +++ b/static/admin/css/login.css @@ -0,0 +1,61 @@ +/* LOGIN FORM */ + +.login { + background: var(--darkened-bg); + height: auto; +} + +.login #header { + height: auto; + padding: 15px 16px; + justify-content: center; +} + +.login #header h1 { + font-size: 1.125rem; + margin: 0; +} + +.login #header h1 a { + color: var(--header-link-color); +} + +.login #content { + padding: 20px 20px 0; +} + +.login #container { + background: var(--body-bg); + border: 1px solid var(--hairline-color); + border-radius: 4px; + overflow: hidden; + width: 28em; + min-width: 300px; + margin: 100px auto; + height: auto; +} + +.login .form-row { + padding: 4px 0; +} + +.login .form-row label { + display: block; + line-height: 2em; +} + +.login .form-row #id_username, .login .form-row #id_password { + padding: 8px; + width: 100%; + box-sizing: border-box; +} + +.login .submit-row { + padding: 1em 0 0 0; + margin: 0; + text-align: center; +} + +.login .password-reset-link { + text-align: center; +} diff --git a/static/admin/css/nav_sidebar.css b/static/admin/css/nav_sidebar.css new file mode 100644 index 0000000..f76e6ce --- /dev/null +++ b/static/admin/css/nav_sidebar.css @@ -0,0 +1,144 @@ +.sticky { + position: sticky; + top: 0; + max-height: 100vh; +} + +.toggle-nav-sidebar { + z-index: 20; + left: 0; + display: flex; + align-items: center; + justify-content: center; + flex: 0 0 23px; + width: 23px; + border: 0; + border-right: 1px solid var(--hairline-color); + background-color: var(--body-bg); + cursor: pointer; + font-size: 1.25rem; + color: var(--link-fg); + padding: 0; +} + +[dir="rtl"] .toggle-nav-sidebar { + border-left: 1px solid var(--hairline-color); + border-right: 0; +} + +.toggle-nav-sidebar:hover, +.toggle-nav-sidebar:focus { + background-color: var(--darkened-bg); +} + +#nav-sidebar { + z-index: 15; + flex: 0 0 275px; + left: -276px; + margin-left: -276px; + border-top: 1px solid transparent; + border-right: 1px solid var(--hairline-color); + background-color: var(--body-bg); + overflow: auto; +} + +[dir="rtl"] #nav-sidebar { + border-left: 1px solid var(--hairline-color); + border-right: 0; + left: 0; + margin-left: 0; + right: -276px; + margin-right: -276px; +} + +.toggle-nav-sidebar::before { + content: '\00BB'; +} + +.main.shifted .toggle-nav-sidebar::before { + content: '\00AB'; +} + +.main > #nav-sidebar { + visibility: hidden; +} + +.main.shifted > #nav-sidebar { + margin-left: 0; + visibility: visible; +} + +[dir="rtl"] .main.shifted > #nav-sidebar { + margin-right: 0; +} + +#nav-sidebar .module th { + width: 100%; + overflow-wrap: anywhere; +} + +#nav-sidebar .module th, +#nav-sidebar .module caption { + padding-left: 16px; +} + +#nav-sidebar .module td { + white-space: nowrap; +} + +[dir="rtl"] #nav-sidebar .module th, +[dir="rtl"] #nav-sidebar .module caption { + padding-left: 8px; + padding-right: 16px; +} + +#nav-sidebar .current-app .section:link, +#nav-sidebar .current-app .section:visited { + color: var(--header-color); + font-weight: bold; +} + +#nav-sidebar .current-model { + background: var(--selected-row); +} + +.main > #nav-sidebar + .content { + max-width: calc(100% - 23px); +} + +.main.shifted > #nav-sidebar + .content { + max-width: calc(100% - 299px); +} + +@media (max-width: 767px) { + #nav-sidebar, #toggle-nav-sidebar { + display: none; + } + + .main > #nav-sidebar + .content, + .main.shifted > #nav-sidebar + .content { + max-width: 100%; + } +} + +#nav-filter { + width: 100%; + box-sizing: border-box; + padding: 2px 5px; + margin: 5px 0; + border: 1px solid var(--border-color); + background-color: var(--darkened-bg); + color: var(--body-fg); +} + +#nav-filter:focus { + border-color: var(--body-quiet-color); +} + +#nav-filter.no-results { + background: var(--message-error-bg); +} + +#nav-sidebar table { + width: 100%; +} diff --git a/static/admin/css/responsive.css b/static/admin/css/responsive.css new file mode 100644 index 0000000..1d0a188 --- /dev/null +++ b/static/admin/css/responsive.css @@ -0,0 +1,999 @@ +/* Tablets */ + +input[type="submit"], button { + -webkit-appearance: none; + appearance: none; +} + +@media (max-width: 1024px) { + /* Basic */ + + html { + -webkit-text-size-adjust: 100%; + } + + td, th { + padding: 10px; + font-size: 0.875rem; + } + + .small { + font-size: 0.75rem; + } + + /* Layout */ + + #container { + min-width: 0; + } + + #content { + padding: 15px 20px 20px; + } + + div.breadcrumbs { + padding: 10px 30px; + } + + /* Header */ + + #header { + flex-direction: column; + padding: 15px 30px; + justify-content: flex-start; + } + + #branding h1 { + margin: 0 0 8px; + line-height: 1.2; + } + + #user-tools { + margin: 0; + font-weight: 400; + line-height: 1.85; + text-align: left; + } + + #user-tools a { + display: inline-block; + line-height: 1.4; + } + + /* Dashboard */ + + .dashboard #content { + width: auto; + } + + #content-related { + margin-right: -290px; + } + + .colSM #content-related { + margin-left: -290px; + } + + .colMS { + margin-right: 290px; + } + + .colSM { + margin-left: 290px; + } + + .dashboard .module table td a { + padding-right: 0; + } + + td .changelink, td .addlink { + font-size: 0.8125rem; + } + + /* Changelist */ + + #toolbar { + border: none; + padding: 15px; + } + + #changelist-search > div { + display: flex; + flex-wrap: nowrap; + max-width: 480px; + } + + #changelist-search label { + line-height: 1.375rem; + } + + #toolbar form #searchbar { + flex: 1 0 auto; + width: 0; + height: 1.375rem; + margin: 0 10px 0 6px; + } + + #toolbar form input[type=submit] { + flex: 0 1 auto; + } + + #changelist-search .quiet { + width: 0; + flex: 1 0 auto; + margin: 5px 0 0 25px; + } + + #changelist .actions { + display: flex; + flex-wrap: wrap; + padding: 15px 0; + } + + #changelist .actions label { + display: flex; + } + + #changelist .actions select { + background: var(--body-bg); + } + + #changelist .actions .button { + min-width: 48px; + margin: 0 10px; + } + + #changelist .actions span.all, + #changelist .actions span.clear, + #changelist .actions span.question, + #changelist .actions span.action-counter { + font-size: 0.6875rem; + margin: 0 10px 0 0; + } + + #changelist-filter { + flex-basis: 200px; + } + + .change-list .filtered .results, + .change-list .filtered .paginator, + .filtered #toolbar, + .filtered .actions, + + #changelist .paginator { + border-top-color: var(--hairline-color); /* XXX Is this used at all? */ + } + + #changelist .results + .paginator { + border-top: none; + } + + /* Forms */ + + label { + font-size: 0.875rem; + } + + .form-row input[type=text], + .form-row input[type=password], + .form-row input[type=email], + .form-row input[type=url], + .form-row input[type=tel], + .form-row input[type=number], + .form-row textarea, + .form-row select, + .form-row .vTextField { + box-sizing: border-box; + margin: 0; + padding: 6px 8px; + min-height: 2.25rem; + font-size: 0.875rem; + } + + .form-row select { + height: 2.25rem; + } + + .form-row select[multiple] { + height: auto; + min-height: 0; + } + + fieldset .fieldBox + .fieldBox { + margin-top: 10px; + padding-top: 10px; + border-top: 1px solid var(--hairline-color); + } + + textarea { + max-width: 100%; + max-height: 120px; + } + + .aligned label { + padding-top: 6px; + } + + .aligned .related-lookup, + .aligned .datetimeshortcuts, + .aligned .related-lookup + strong { + align-self: center; + margin-left: 15px; + } + + form .aligned div.radiolist { + margin-left: 2px; + } + + .submit-row { + padding: 8px; + } + + .submit-row a.deletelink { + padding: 10px 7px; + } + + .button, input[type=submit], input[type=button], .submit-row input, a.button { + padding: 7px; + } + + /* Related widget */ + + .related-widget-wrapper { + float: none; + } + + .related-widget-wrapper-link + .selector { + max-width: calc(100% - 30px); + margin-right: 15px; + } + + select + .related-widget-wrapper-link, + .related-widget-wrapper-link + .related-widget-wrapper-link { + margin-left: 10px; + } + + /* Selector */ + + .selector { + display: flex; + width: 100%; + } + + .selector .selector-filter { + display: flex; + align-items: center; + } + + .selector .selector-filter label { + margin: 0 8px 0 0; + } + + .selector .selector-filter input { + width: auto; + min-height: 0; + flex: 1 1; + } + + .selector-available, .selector-chosen { + width: auto; + flex: 1 1; + display: flex; + flex-direction: column; + } + + .selector select { + width: 100%; + flex: 1 0 auto; + margin-bottom: 5px; + } + + .selector ul.selector-chooser { + width: 26px; + height: 52px; + padding: 2px 0; + margin: auto 15px; + border-radius: 20px; + transform: translateY(-10px); + } + + .selector-add, .selector-remove { + width: 20px; + height: 20px; + background-size: 20px auto; + } + + .selector-add { + background-position: 0 -120px; + } + + .selector-remove { + background-position: 0 -80px; + } + + a.selector-chooseall, a.selector-clearall { + align-self: center; + } + + .stacked { + flex-direction: column; + max-width: 480px; + } + + .stacked > * { + flex: 0 1 auto; + } + + .stacked select { + margin-bottom: 0; + } + + .stacked .selector-available, .stacked .selector-chosen { + width: auto; + } + + .stacked ul.selector-chooser { + width: 52px; + height: 26px; + padding: 0 2px; + margin: 15px auto; + transform: none; + } + + .stacked .selector-chooser li { + padding: 3px; + } + + .stacked .selector-add, .stacked .selector-remove { + background-size: 20px auto; + } + + .stacked .selector-add { + background-position: 0 -40px; + } + + .stacked .active.selector-add { + background-position: 0 -40px; + } + + .active.selector-add:focus, .active.selector-add:hover { + background-position: 0 -140px; + } + + .stacked .active.selector-add:focus, .stacked .active.selector-add:hover { + background-position: 0 -60px; + } + + .stacked .selector-remove { + background-position: 0 0; + } + + .stacked .active.selector-remove { + background-position: 0 0; + } + + .active.selector-remove:focus, .active.selector-remove:hover { + background-position: 0 -100px; + } + + .stacked .active.selector-remove:focus, .stacked .active.selector-remove:hover { + background-position: 0 -20px; + } + + .help-tooltip, .selector .help-icon { + display: none; + } + + .datetime input { + width: 50%; + max-width: 120px; + } + + .datetime span { + font-size: 0.8125rem; + } + + .datetime .timezonewarning { + display: block; + font-size: 0.6875rem; + color: var(--body-quiet-color); + } + + .datetimeshortcuts { + color: var(--border-color); /* XXX Redundant, .datetime span also sets #ccc */ + } + + .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField { + width: 75%; + } + + .inline-group { + overflow: auto; + } + + /* Messages */ + + ul.messagelist li { + padding-left: 55px; + background-position: 30px 12px; + } + + ul.messagelist li.error { + background-position: 30px 12px; + } + + ul.messagelist li.warning { + background-position: 30px 14px; + } + + /* Login */ + + .login #header { + padding: 15px 20px; + } + + .login #branding h1 { + margin: 0; + } + + /* GIS */ + + div.olMap { + max-width: calc(100vw - 30px); + max-height: 300px; + } + + .olMap + .clear_features { + display: block; + margin-top: 10px; + } + + /* Docs */ + + .module table.xfull { + width: 100%; + } + + pre.literal-block { + overflow: auto; + } +} + +/* Mobile */ + +@media (max-width: 767px) { + /* Layout */ + + #header, #content, #footer { + padding: 15px; + } + + #footer:empty { + padding: 0; + } + + div.breadcrumbs { + padding: 10px 15px; + } + + /* Dashboard */ + + .colMS, .colSM { + margin: 0; + } + + #content-related, .colSM #content-related { + width: 100%; + margin: 0; + } + + #content-related .module { + margin-bottom: 0; + } + + #content-related .module h2 { + padding: 10px 15px; + font-size: 1rem; + } + + /* Changelist */ + + #changelist { + align-items: stretch; + flex-direction: column; + } + + #toolbar { + padding: 10px; + } + + #changelist-filter { + margin-left: 0; + } + + #changelist .actions label { + flex: 1 1; + } + + #changelist .actions select { + flex: 1 0; + width: 100%; + } + + #changelist .actions span { + flex: 1 0 100%; + } + + #changelist-filter { + position: static; + width: auto; + margin-top: 30px; + } + + .object-tools { + float: none; + margin: 0 0 15px; + padding: 0; + overflow: hidden; + } + + .object-tools li { + height: auto; + margin-left: 0; + } + + .object-tools li + li { + margin-left: 15px; + } + + /* Forms */ + + .form-row { + padding: 15px 0; + } + + .aligned .form-row, + .aligned .form-row > div { + max-width: 100vw; + } + + .aligned .form-row > div { + width: calc(100vw - 30px); + } + + .flex-container { + flex-flow: column; + } + + .flex-container.checkbox-row { + flex-flow: row; + } + + textarea { + max-width: none; + } + + .vURLField { + width: auto; + } + + fieldset .fieldBox + .fieldBox { + margin-top: 15px; + padding-top: 15px; + } + + fieldset.collapsed .form-row { + display: none; + } + + .aligned label { + width: 100%; + min-width: auto; + padding: 0 0 10px; + } + + .aligned label:after { + max-height: 0; + } + + .aligned .form-row input, + .aligned .form-row select, + .aligned .form-row textarea { + flex: 1 1 auto; + max-width: 100%; + } + + .aligned .checkbox-row input { + flex: 0 1 auto; + margin: 0; + } + + .aligned .vCheckboxLabel { + flex: 1 0; + padding: 1px 0 0 5px; + } + + .aligned label + p, + .aligned label + div.help, + .aligned label + div.readonly { + padding: 0; + margin-left: 0; + } + + .aligned p.file-upload { + font-size: 0.8125rem; + } + + span.clearable-file-input { + margin-left: 15px; + } + + span.clearable-file-input label { + font-size: 0.8125rem; + padding-bottom: 0; + } + + .aligned .timezonewarning { + flex: 1 0 100%; + margin-top: 5px; + } + + form .aligned .form-row div.help { + width: 100%; + margin: 5px 0 0; + padding: 0; + } + + form .aligned ul, + form .aligned ul.errorlist { + margin-left: 0; + padding-left: 0; + } + + form .aligned div.radiolist { + margin-top: 5px; + margin-right: 15px; + margin-bottom: -3px; + } + + form .aligned div.radiolist:not(.inline) div + div { + margin-top: 5px; + } + + /* Related widget */ + + .related-widget-wrapper { + width: 100%; + display: flex; + align-items: flex-start; + } + + .related-widget-wrapper .selector { + order: 1; + } + + .related-widget-wrapper > a { + order: 2; + } + + .related-widget-wrapper .radiolist ~ a { + align-self: flex-end; + } + + .related-widget-wrapper > select ~ a { + align-self: center; + } + + select + .related-widget-wrapper-link, + .related-widget-wrapper-link + .related-widget-wrapper-link { + margin-left: 15px; + } + + /* Selector */ + + .selector { + flex-direction: column; + } + + .selector > * { + float: none; + } + + .selector-available, .selector-chosen { + margin-bottom: 0; + flex: 1 1 auto; + } + + .selector select { + max-height: 96px; + } + + .selector ul.selector-chooser { + display: block; + float: none; + width: 52px; + height: 26px; + padding: 0 2px; + margin: 15px auto 20px; + transform: none; + } + + .selector ul.selector-chooser li { + float: left; + } + + .selector-remove { + background-position: 0 0; + } + + .active.selector-remove:focus, .active.selector-remove:hover { + background-position: 0 -20px; + } + + .selector-add { + background-position: 0 -40px; + } + + .active.selector-add:focus, .active.selector-add:hover { + background-position: 0 -60px; + } + + /* Inlines */ + + .inline-group[data-inline-type="stacked"] .inline-related { + border: 1px solid var(--hairline-color); + border-radius: 4px; + margin-top: 15px; + overflow: auto; + } + + .inline-group[data-inline-type="stacked"] .inline-related > * { + box-sizing: border-box; + } + + .inline-group[data-inline-type="stacked"] .inline-related .module { + padding: 0 10px; + } + + .inline-group[data-inline-type="stacked"] .inline-related .module .form-row { + border-top: 1px solid var(--hairline-color); + border-bottom: none; + } + + .inline-group[data-inline-type="stacked"] .inline-related .module .form-row:first-child { + border-top: none; + } + + .inline-group[data-inline-type="stacked"] .inline-related h3 { + padding: 10px; + border-top-width: 0; + border-bottom-width: 2px; + display: flex; + flex-wrap: wrap; + align-items: center; + } + + .inline-group[data-inline-type="stacked"] .inline-related h3 .inline_label { + margin-right: auto; + } + + .inline-group[data-inline-type="stacked"] .inline-related h3 span.delete { + float: none; + flex: 1 1 100%; + margin-top: 5px; + } + + .inline-group[data-inline-type="stacked"] .aligned .form-row > div:not([class]) { + width: 100%; + } + + .inline-group[data-inline-type="stacked"] .aligned label { + width: 100%; + } + + .inline-group[data-inline-type="stacked"] div.add-row { + margin-top: 15px; + border: 1px solid var(--hairline-color); + border-radius: 4px; + } + + .inline-group div.add-row, + .inline-group .tabular tr.add-row td { + padding: 0; + } + + .inline-group div.add-row a, + .inline-group .tabular tr.add-row td a { + display: block; + padding: 8px 10px 8px 26px; + background-position: 8px 9px; + } + + /* Submit row */ + + .submit-row { + padding: 10px; + margin: 0 0 15px; + flex-direction: column; + gap: 8px; + } + + .submit-row input, .submit-row input.default, .submit-row a { + text-align: center; + } + + .submit-row a.closelink { + padding: 10px 0; + text-align: center; + } + + .submit-row a.deletelink { + margin: 0; + } + + /* Messages */ + + ul.messagelist li { + padding-left: 40px; + background-position: 15px 12px; + } + + ul.messagelist li.error { + background-position: 15px 12px; + } + + ul.messagelist li.warning { + background-position: 15px 14px; + } + + /* Paginator */ + + .paginator .this-page, .paginator a:link, .paginator a:visited { + padding: 4px 10px; + } + + /* Login */ + + body.login { + padding: 0 15px; + } + + .login #container { + width: auto; + max-width: 480px; + margin: 50px auto; + } + + .login #header, + .login #content { + padding: 15px; + } + + .login #content-main { + float: none; + } + + .login .form-row { + padding: 0; + } + + .login .form-row + .form-row { + margin-top: 15px; + } + + .login .form-row label { + margin: 0 0 5px; + line-height: 1.2; + } + + .login .submit-row { + padding: 15px 0 0; + } + + .login br { + display: none; + } + + .login .submit-row input { + margin: 0; + text-transform: uppercase; + } + + .errornote { + margin: 0 0 20px; + padding: 8px 12px; + font-size: 0.8125rem; + } + + /* Calendar and clock */ + + .calendarbox, .clockbox { + position: fixed !important; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%); + margin: 0; + border: none; + overflow: visible; + } + + .calendarbox:before, .clockbox:before { + content: ''; + position: fixed; + top: 50%; + left: 50%; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.75); + transform: translate(-50%, -50%); + } + + .calendarbox > *, .clockbox > * { + position: relative; + z-index: 1; + } + + .calendarbox > div:first-child { + z-index: 2; + } + + .calendarbox .calendar, .clockbox h2 { + border-radius: 4px 4px 0 0; + overflow: hidden; + } + + .calendarbox .calendar-cancel, .clockbox .calendar-cancel { + border-radius: 0 0 4px 4px; + overflow: hidden; + } + + .calendar-shortcuts { + padding: 10px 0; + font-size: 0.75rem; + line-height: 0.75rem; + } + + .calendar-shortcuts a { + margin: 0 4px; + } + + .timelist a { + background: var(--body-bg); + padding: 4px; + } + + .calendar-cancel { + padding: 8px 10px; + } + + .clockbox h2 { + padding: 8px 15px; + } + + .calendar caption { + padding: 10px; + } + + .calendarbox .calendarnav-previous, .calendarbox .calendarnav-next { + z-index: 1; + top: 10px; + } + + /* History */ + + table#change-history tbody th, table#change-history tbody td { + font-size: 0.8125rem; + word-break: break-word; + } + + table#change-history tbody th { + width: auto; + } + + /* Docs */ + + table.model tbody th, table.model tbody td { + font-size: 0.8125rem; + word-break: break-word; + } +} diff --git a/static/admin/css/responsive_rtl.css b/static/admin/css/responsive_rtl.css new file mode 100644 index 0000000..31dc8ff --- /dev/null +++ b/static/admin/css/responsive_rtl.css @@ -0,0 +1,84 @@ +/* TABLETS */ + +@media (max-width: 1024px) { + [dir="rtl"] .colMS { + margin-right: 0; + } + + [dir="rtl"] #user-tools { + text-align: right; + } + + [dir="rtl"] #changelist .actions label { + padding-left: 10px; + padding-right: 0; + } + + [dir="rtl"] #changelist .actions select { + margin-left: 0; + margin-right: 15px; + } + + [dir="rtl"] .change-list .filtered .results, + [dir="rtl"] .change-list .filtered .paginator, + [dir="rtl"] .filtered #toolbar, + [dir="rtl"] .filtered div.xfull, + [dir="rtl"] .filtered .actions, + [dir="rtl"] #changelist-filter { + margin-left: 0; + } + + [dir="rtl"] .inline-group ul.tools a.add, + [dir="rtl"] .inline-group div.add-row a, + [dir="rtl"] .inline-group .tabular tr.add-row td a { + padding: 8px 26px 8px 10px; + background-position: calc(100% - 8px) 9px; + } + + [dir="rtl"] .related-widget-wrapper-link + .selector { + margin-right: 0; + margin-left: 15px; + } + + [dir="rtl"] .selector .selector-filter label { + margin-right: 0; + margin-left: 8px; + } + + [dir="rtl"] .object-tools li { + float: right; + } + + [dir="rtl"] .object-tools li + li { + margin-left: 0; + margin-right: 15px; + } + + [dir="rtl"] .dashboard .module table td a { + padding-left: 0; + padding-right: 16px; + } +} + +/* MOBILE */ + +@media (max-width: 767px) { + [dir="rtl"] .aligned .related-lookup, + [dir="rtl"] .aligned .datetimeshortcuts { + margin-left: 0; + margin-right: 15px; + } + + [dir="rtl"] .aligned ul, + [dir="rtl"] form .aligned ul.errorlist { + margin-right: 0; + } + + [dir="rtl"] #changelist-filter { + margin-left: 0; + margin-right: 0; + } + [dir="rtl"] .aligned .vCheckboxLabel { + padding: 1px 5px 0 0; + } +} diff --git a/static/admin/css/rtl.css b/static/admin/css/rtl.css new file mode 100644 index 0000000..c349a93 --- /dev/null +++ b/static/admin/css/rtl.css @@ -0,0 +1,298 @@ +/* GLOBAL */ + +th { + text-align: right; +} + +.module h2, .module caption { + text-align: right; +} + +.module ul, .module ol { + margin-left: 0; + margin-right: 1.5em; +} + +.viewlink, .addlink, .changelink { + padding-left: 0; + padding-right: 16px; + background-position: 100% 1px; +} + +.deletelink { + padding-left: 0; + padding-right: 16px; + background-position: 100% 1px; +} + +.object-tools { + float: left; +} + +thead th:first-child, +tfoot td:first-child { + border-left: none; +} + +/* LAYOUT */ + +#user-tools { + right: auto; + left: 0; + text-align: left; +} + +div.breadcrumbs { + text-align: right; +} + +#content-main { + float: right; +} + +#content-related { + float: left; + margin-left: -300px; + margin-right: auto; +} + +.colMS { + margin-left: 300px; + margin-right: 0; +} + +/* SORTABLE TABLES */ + +table thead th.sorted .sortoptions { + float: left; +} + +thead th.sorted .text { + padding-right: 0; + padding-left: 42px; +} + +/* dashboard styles */ + +.dashboard .module table td a { + padding-left: .6em; + padding-right: 16px; +} + +/* changelists styles */ + +.change-list .filtered table { + border-left: none; + border-right: 0px none; +} + +#changelist-filter { + border-left: none; + border-right: none; + margin-left: 0; + margin-right: 30px; +} + +#changelist-filter li.selected { + border-left: none; + padding-left: 10px; + margin-left: 0; + border-right: 5px solid var(--hairline-color); + padding-right: 10px; + margin-right: -15px; +} + +#changelist table tbody td:first-child, #changelist table tbody th:first-child { + border-right: none; + border-left: none; +} + +.paginator .end { + margin-left: 6px; + margin-right: 0; +} + +.paginator input { + margin-left: 0; + margin-right: auto; +} + +/* FORMS */ + +.aligned label { + padding: 0 0 3px 1em; +} + +.submit-row a.deletelink { + margin-left: 0; + margin-right: auto; +} + +.vDateField, .vTimeField { + margin-left: 2px; +} + +.aligned .form-row input { + margin-left: 5px; +} + +form .aligned ul { + margin-right: 163px; + padding-right: 10px; + margin-left: 0; + padding-left: 0; +} + +form ul.inline li { + float: right; + padding-right: 0; + padding-left: 7px; +} + +form .aligned p.help, +form .aligned div.help { + margin-right: 160px; + padding-right: 10px; +} + +form div.help ul, +form .aligned .checkbox-row + .help, +form .aligned p.date div.help.timezonewarning, +form .aligned p.datetime div.help.timezonewarning, +form .aligned p.time div.help.timezonewarning { + margin-right: 0; + padding-right: 0; +} + +form .wide p.help, form .wide div.help { + padding-left: 0; + padding-right: 50px; +} + +form .wide p, +form .wide ul.errorlist, +form .wide input + p.help, +form .wide input + div.help { + margin-right: 200px; + margin-left: 0px; +} + +.submit-row { + text-align: right; +} + +fieldset .fieldBox { + margin-left: 20px; + margin-right: 0; +} + +.errorlist li { + background-position: 100% 12px; + padding: 0; +} + +.errornote { + background-position: 100% 12px; + padding: 10px 12px; +} + +/* WIDGETS */ + +.calendarnav-previous { + top: 0; + left: auto; + right: 10px; + background: url(../img/calendar-icons.svg) 0 -30px no-repeat; +} + +.calendarbox .calendarnav-previous:focus, +.calendarbox .calendarnav-previous:hover { + background-position: 0 -45px; +} + +.calendarnav-next { + top: 0; + right: auto; + left: 10px; + background: url(../img/calendar-icons.svg) 0 0 no-repeat; +} + +.calendarbox .calendarnav-next:focus, +.calendarbox .calendarnav-next:hover { + background-position: 0 -15px; +} + +.calendar caption, .calendarbox h2 { + text-align: center; +} + +.selector { + float: right; +} + +.selector .selector-filter { + text-align: right; +} + +.selector-add { + background: url(../img/selector-icons.svg) 0 -64px no-repeat; +} + +.active.selector-add:focus, .active.selector-add:hover { + background-position: 0 -80px; +} + +.selector-remove { + background: url(../img/selector-icons.svg) 0 -96px no-repeat; +} + +.active.selector-remove:focus, .active.selector-remove:hover { + background-position: 0 -112px; +} + +a.selector-chooseall { + background: url(../img/selector-icons.svg) right -128px no-repeat; +} + +a.active.selector-chooseall:focus, a.active.selector-chooseall:hover { + background-position: 100% -144px; +} + +a.selector-clearall { + background: url(../img/selector-icons.svg) 0 -160px no-repeat; +} + +a.active.selector-clearall:focus, a.active.selector-clearall:hover { + background-position: 0 -176px; +} + +.inline-deletelink { + float: left; +} + +form .form-row p.datetime { + overflow: hidden; +} + +.related-widget-wrapper { + float: right; +} + +/* MISC */ + +.inline-related h2, .inline-group h2 { + text-align: right +} + +.inline-related h3 span.delete { + padding-right: 20px; + padding-left: inherit; + left: 10px; + right: inherit; + float:left; +} + +.inline-related h3 span.delete label { + margin-left: inherit; + margin-right: 2px; +} diff --git a/static/admin/css/vendor/select2/LICENSE-SELECT2.md b/static/admin/css/vendor/select2/LICENSE-SELECT2.md new file mode 100644 index 0000000..8cb8a2b --- /dev/null +++ b/static/admin/css/vendor/select2/LICENSE-SELECT2.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/static/admin/css/vendor/select2/select2.css b/static/admin/css/vendor/select2/select2.css new file mode 100644 index 0000000..750b320 --- /dev/null +++ b/static/admin/css/vendor/select2/select2.css @@ -0,0 +1,481 @@ +.select2-container { + box-sizing: border-box; + display: inline-block; + margin: 0; + position: relative; + vertical-align: middle; } + .select2-container .select2-selection--single { + box-sizing: border-box; + cursor: pointer; + display: block; + height: 28px; + user-select: none; + -webkit-user-select: none; } + .select2-container .select2-selection--single .select2-selection__rendered { + display: block; + padding-left: 8px; + padding-right: 20px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } + .select2-container .select2-selection--single .select2-selection__clear { + position: relative; } + .select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered { + padding-right: 8px; + padding-left: 20px; } + .select2-container .select2-selection--multiple { + box-sizing: border-box; + cursor: pointer; + display: block; + min-height: 32px; + user-select: none; + -webkit-user-select: none; } + .select2-container .select2-selection--multiple .select2-selection__rendered { + display: inline-block; + overflow: hidden; + padding-left: 8px; + text-overflow: ellipsis; + white-space: nowrap; } + .select2-container .select2-search--inline { + float: left; } + .select2-container .select2-search--inline .select2-search__field { + box-sizing: border-box; + border: none; + font-size: 100%; + margin-top: 5px; + padding: 0; } + .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button { + -webkit-appearance: none; } + +.select2-dropdown { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + box-sizing: border-box; + display: block; + position: absolute; + left: -100000px; + width: 100%; + z-index: 1051; } + +.select2-results { + display: block; } + +.select2-results__options { + list-style: none; + margin: 0; + padding: 0; } + +.select2-results__option { + padding: 6px; + user-select: none; + -webkit-user-select: none; } + .select2-results__option[aria-selected] { + cursor: pointer; } + +.select2-container--open .select2-dropdown { + left: 0; } + +.select2-container--open .select2-dropdown--above { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--open .select2-dropdown--below { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-search--dropdown { + display: block; + padding: 4px; } + .select2-search--dropdown .select2-search__field { + padding: 4px; + width: 100%; + box-sizing: border-box; } + .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button { + -webkit-appearance: none; } + .select2-search--dropdown.select2-search--hide { + display: none; } + +.select2-close-mask { + border: 0; + margin: 0; + padding: 0; + display: block; + position: fixed; + left: 0; + top: 0; + min-height: 100%; + min-width: 100%; + height: auto; + width: auto; + opacity: 0; + z-index: 99; + background-color: #fff; + filter: alpha(opacity=0); } + +.select2-hidden-accessible { + border: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + height: 1px !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + width: 1px !important; + white-space: nowrap !important; } + +.select2-container--default .select2-selection--single { + background-color: #fff; + border: 1px solid #aaa; + border-radius: 4px; } + .select2-container--default .select2-selection--single .select2-selection__rendered { + color: #444; + line-height: 28px; } + .select2-container--default .select2-selection--single .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; } + .select2-container--default .select2-selection--single .select2-selection__placeholder { + color: #999; } + .select2-container--default .select2-selection--single .select2-selection__arrow { + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; } + .select2-container--default .select2-selection--single .select2-selection__arrow b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; } + +.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; } + +.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow { + left: 1px; + right: auto; } + +.select2-container--default.select2-container--disabled .select2-selection--single { + background-color: #eee; + cursor: default; } + .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear { + display: none; } + +.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; } + +.select2-container--default .select2-selection--multiple { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + cursor: text; } + .select2-container--default .select2-selection--multiple .select2-selection__rendered { + box-sizing: border-box; + list-style: none; + margin: 0; + padding: 0 5px; + width: 100%; } + .select2-container--default .select2-selection--multiple .select2-selection__rendered li { + list-style: none; } + .select2-container--default .select2-selection--multiple .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin-top: 5px; + margin-right: 10px; + padding: 1px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice { + background-color: #e4e4e4; + border: 1px solid #aaa; + border-radius: 4px; + cursor: default; + float: left; + margin-right: 5px; + margin-top: 5px; + padding: 0 5px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { + color: #999; + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 2px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { + color: #333; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline { + float: right; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + margin-left: 5px; + margin-right: auto; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; } + +.select2-container--default.select2-container--focus .select2-selection--multiple { + border: solid black 1px; + outline: 0; } + +.select2-container--default.select2-container--disabled .select2-selection--multiple { + background-color: #eee; + cursor: default; } + +.select2-container--default.select2-container--disabled .select2-selection__choice__remove { + display: none; } + +.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple { + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--default .select2-search--dropdown .select2-search__field { + border: 1px solid #aaa; } + +.select2-container--default .select2-search--inline .select2-search__field { + background: transparent; + border: none; + outline: 0; + box-shadow: none; + -webkit-appearance: textfield; } + +.select2-container--default .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; } + +.select2-container--default .select2-results__option[role=group] { + padding: 0; } + +.select2-container--default .select2-results__option[aria-disabled=true] { + color: #999; } + +.select2-container--default .select2-results__option[aria-selected=true] { + background-color: #ddd; } + +.select2-container--default .select2-results__option .select2-results__option { + padding-left: 1em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__group { + padding-left: 0; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option { + margin-left: -1em; + padding-left: 2em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -2em; + padding-left: 3em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -3em; + padding-left: 4em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -4em; + padding-left: 5em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -5em; + padding-left: 6em; } + +.select2-container--default .select2-results__option--highlighted[aria-selected] { + background-color: #5897fb; + color: white; } + +.select2-container--default .select2-results__group { + cursor: default; + display: block; + padding: 6px; } + +.select2-container--classic .select2-selection--single { + background-color: #f7f7f7; + border: 1px solid #aaa; + border-radius: 4px; + outline: 0; + background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%); + background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%); + background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } + .select2-container--classic .select2-selection--single:focus { + border: 1px solid #5897fb; } + .select2-container--classic .select2-selection--single .select2-selection__rendered { + color: #444; + line-height: 28px; } + .select2-container--classic .select2-selection--single .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin-right: 10px; } + .select2-container--classic .select2-selection--single .select2-selection__placeholder { + color: #999; } + .select2-container--classic .select2-selection--single .select2-selection__arrow { + background-color: #ddd; + border: none; + border-left: 1px solid #aaa; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; + background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%); + background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%); + background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); } + .select2-container--classic .select2-selection--single .select2-selection__arrow b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; } + +.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; } + +.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow { + border: none; + border-right: 1px solid #aaa; + border-radius: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + left: 1px; + right: auto; } + +.select2-container--classic.select2-container--open .select2-selection--single { + border: 1px solid #5897fb; } + .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow { + background: transparent; + border: none; } + .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; } + +.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; + background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%); + background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%); + background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } + +.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%); + background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%); + background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); } + +.select2-container--classic .select2-selection--multiple { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + cursor: text; + outline: 0; } + .select2-container--classic .select2-selection--multiple:focus { + border: 1px solid #5897fb; } + .select2-container--classic .select2-selection--multiple .select2-selection__rendered { + list-style: none; + margin: 0; + padding: 0 5px; } + .select2-container--classic .select2-selection--multiple .select2-selection__clear { + display: none; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice { + background-color: #e4e4e4; + border: 1px solid #aaa; + border-radius: 4px; + cursor: default; + float: left; + margin-right: 5px; + margin-top: 5px; + padding: 0 5px; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove { + color: #888; + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 2px; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover { + color: #555; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + float: right; + margin-left: 5px; + margin-right: auto; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; } + +.select2-container--classic.select2-container--open .select2-selection--multiple { + border: 1px solid #5897fb; } + +.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--classic .select2-search--dropdown .select2-search__field { + border: 1px solid #aaa; + outline: 0; } + +.select2-container--classic .select2-search--inline .select2-search__field { + outline: 0; + box-shadow: none; } + +.select2-container--classic .select2-dropdown { + background-color: white; + border: 1px solid transparent; } + +.select2-container--classic .select2-dropdown--above { + border-bottom: none; } + +.select2-container--classic .select2-dropdown--below { + border-top: none; } + +.select2-container--classic .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; } + +.select2-container--classic .select2-results__option[role=group] { + padding: 0; } + +.select2-container--classic .select2-results__option[aria-disabled=true] { + color: grey; } + +.select2-container--classic .select2-results__option--highlighted[aria-selected] { + background-color: #3875d7; + color: white; } + +.select2-container--classic .select2-results__group { + cursor: default; + display: block; + padding: 6px; } + +.select2-container--classic.select2-container--open .select2-dropdown { + border-color: #5897fb; } diff --git a/static/admin/css/vendor/select2/select2.min.css b/static/admin/css/vendor/select2/select2.min.css new file mode 100644 index 0000000..7c18ad5 --- /dev/null +++ b/static/admin/css/vendor/select2/select2.min.css @@ -0,0 +1 @@ +.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} diff --git a/static/admin/css/widgets.css b/static/admin/css/widgets.css new file mode 100644 index 0000000..1104e8b --- /dev/null +++ b/static/admin/css/widgets.css @@ -0,0 +1,604 @@ +/* SELECTOR (FILTER INTERFACE) */ + +.selector { + width: 800px; + float: left; + display: flex; +} + +.selector select { + width: 380px; + height: 17.2em; + flex: 1 0 auto; +} + +.selector-available, .selector-chosen { + width: 380px; + text-align: center; + margin-bottom: 5px; + display: flex; + flex-direction: column; +} + +.selector-available h2, .selector-chosen h2 { + border: 1px solid var(--border-color); + border-radius: 4px 4px 0 0; +} + +.selector-chosen .list-footer-display { + border: 1px solid var(--border-color); + border-top: none; + border-radius: 0 0 4px 4px; + margin: 0 0 10px; + padding: 8px; + text-align: center; + background: var(--primary); + color: var(--header-link-color); + cursor: pointer; +} +.selector-chosen .list-footer-display__clear { + color: var(--breadcrumbs-fg); +} + +.selector-chosen h2 { + background: var(--primary); + color: var(--header-link-color); +} + +.selector .selector-available h2 { + background: var(--darkened-bg); + color: var(--body-quiet-color); +} + +.selector .selector-filter { + border: 1px solid var(--border-color); + border-width: 0 1px; + padding: 8px; + color: var(--body-quiet-color); + font-size: 0.625rem; + margin: 0; + text-align: left; +} + +.selector .selector-filter label, +.inline-group .aligned .selector .selector-filter label { + float: left; + margin: 7px 0 0; + width: 18px; + height: 18px; + padding: 0; + overflow: hidden; + line-height: 1; + min-width: auto; +} + +.selector .selector-available input, +.selector .selector-chosen input { + width: 320px; + margin-left: 8px; +} + +.selector ul.selector-chooser { + align-self: center; + width: 22px; + background-color: var(--selected-bg); + border-radius: 10px; + margin: 0 5px; + padding: 0; + transform: translateY(-17px); +} + +.selector-chooser li { + margin: 0; + padding: 3px; + list-style-type: none; +} + +.selector select { + padding: 0 10px; + margin: 0 0 10px; + border-radius: 0 0 4px 4px; +} +.selector .selector-chosen--with-filtered select { + margin: 0; + border-radius: 0; + height: 14em; +} + +.selector .selector-chosen:not(.selector-chosen--with-filtered) .list-footer-display { + display: none; +} + +.selector-add, .selector-remove { + width: 16px; + height: 16px; + display: block; + text-indent: -3000px; + overflow: hidden; + cursor: default; + opacity: 0.55; +} + +.active.selector-add, .active.selector-remove { + opacity: 1; +} + +.active.selector-add:hover, .active.selector-remove:hover { + cursor: pointer; +} + +.selector-add { + background: url(../img/selector-icons.svg) 0 -96px no-repeat; +} + +.active.selector-add:focus, .active.selector-add:hover { + background-position: 0 -112px; +} + +.selector-remove { + background: url(../img/selector-icons.svg) 0 -64px no-repeat; +} + +.active.selector-remove:focus, .active.selector-remove:hover { + background-position: 0 -80px; +} + +a.selector-chooseall, a.selector-clearall { + display: inline-block; + height: 16px; + text-align: left; + margin: 1px auto 3px; + overflow: hidden; + font-weight: bold; + line-height: 16px; + color: var(--body-quiet-color); + text-decoration: none; + opacity: 0.55; +} + +a.active.selector-chooseall:focus, a.active.selector-clearall:focus, +a.active.selector-chooseall:hover, a.active.selector-clearall:hover { + color: var(--link-fg); +} + +a.active.selector-chooseall, a.active.selector-clearall { + opacity: 1; +} + +a.active.selector-chooseall:hover, a.active.selector-clearall:hover { + cursor: pointer; +} + +a.selector-chooseall { + padding: 0 18px 0 0; + background: url(../img/selector-icons.svg) right -160px no-repeat; + cursor: default; +} + +a.active.selector-chooseall:focus, a.active.selector-chooseall:hover { + background-position: 100% -176px; +} + +a.selector-clearall { + padding: 0 0 0 18px; + background: url(../img/selector-icons.svg) 0 -128px no-repeat; + cursor: default; +} + +a.active.selector-clearall:focus, a.active.selector-clearall:hover { + background-position: 0 -144px; +} + +/* STACKED SELECTORS */ + +.stacked { + float: left; + width: 490px; + display: block; +} + +.stacked select { + width: 480px; + height: 10.1em; +} + +.stacked .selector-available, .stacked .selector-chosen { + width: 480px; +} + +.stacked .selector-available { + margin-bottom: 0; +} + +.stacked .selector-available input { + width: 422px; +} + +.stacked ul.selector-chooser { + height: 22px; + width: 50px; + margin: 0 0 10px 40%; + background-color: #eee; + border-radius: 10px; + transform: none; +} + +.stacked .selector-chooser li { + float: left; + padding: 3px 3px 3px 5px; +} + +.stacked .selector-chooseall, .stacked .selector-clearall { + display: none; +} + +.stacked .selector-add { + background: url(../img/selector-icons.svg) 0 -32px no-repeat; + cursor: default; +} + +.stacked .active.selector-add { + background-position: 0 -32px; + cursor: pointer; +} + +.stacked .active.selector-add:focus, .stacked .active.selector-add:hover { + background-position: 0 -48px; + cursor: pointer; +} + +.stacked .selector-remove { + background: url(../img/selector-icons.svg) 0 0 no-repeat; + cursor: default; +} + +.stacked .active.selector-remove { + background-position: 0 0px; + cursor: pointer; +} + +.stacked .active.selector-remove:focus, .stacked .active.selector-remove:hover { + background-position: 0 -16px; + cursor: pointer; +} + +.selector .help-icon { + background: url(../img/icon-unknown.svg) 0 0 no-repeat; + display: inline-block; + vertical-align: middle; + margin: -2px 0 0 2px; + width: 13px; + height: 13px; +} + +.selector .selector-chosen .help-icon { + background: url(../img/icon-unknown-alt.svg) 0 0 no-repeat; +} + +.selector .search-label-icon { + background: url(../img/search.svg) 0 0 no-repeat; + display: inline-block; + height: 1.125rem; + width: 1.125rem; +} + +/* DATE AND TIME */ + +p.datetime { + line-height: 20px; + margin: 0; + padding: 0; + color: var(--body-quiet-color); + font-weight: bold; +} + +.datetime span { + white-space: nowrap; + font-weight: normal; + font-size: 0.6875rem; + color: var(--body-quiet-color); +} + +.datetime input, .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField { + margin-left: 5px; + margin-bottom: 4px; +} + +table p.datetime { + font-size: 0.6875rem; + margin-left: 0; + padding-left: 0; +} + +.datetimeshortcuts .clock-icon, .datetimeshortcuts .date-icon { + position: relative; + display: inline-block; + vertical-align: middle; + height: 16px; + width: 16px; + overflow: hidden; +} + +.datetimeshortcuts .clock-icon { + background: url(../img/icon-clock.svg) 0 0 no-repeat; +} + +.datetimeshortcuts a:focus .clock-icon, +.datetimeshortcuts a:hover .clock-icon { + background-position: 0 -16px; +} + +.datetimeshortcuts .date-icon { + background: url(../img/icon-calendar.svg) 0 0 no-repeat; + top: -1px; +} + +.datetimeshortcuts a:focus .date-icon, +.datetimeshortcuts a:hover .date-icon { + background-position: 0 -16px; +} + +.timezonewarning { + font-size: 0.6875rem; + color: var(--body-quiet-color); +} + +/* URL */ + +p.url { + line-height: 20px; + margin: 0; + padding: 0; + color: var(--body-quiet-color); + font-size: 0.6875rem; + font-weight: bold; +} + +.url a { + font-weight: normal; +} + +/* FILE UPLOADS */ + +p.file-upload { + line-height: 20px; + margin: 0; + padding: 0; + color: var(--body-quiet-color); + font-size: 0.6875rem; + font-weight: bold; +} + +.file-upload a { + font-weight: normal; +} + +.file-upload .deletelink { + margin-left: 5px; +} + +span.clearable-file-input label { + color: var(--body-fg); + font-size: 0.6875rem; + display: inline; + float: none; +} + +/* CALENDARS & CLOCKS */ + +.calendarbox, .clockbox { + margin: 5px auto; + font-size: 0.75rem; + width: 19em; + text-align: center; + background: var(--body-bg); + color: var(--body-fg); + border: 1px solid var(--hairline-color); + border-radius: 4px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); + overflow: hidden; + position: relative; +} + +.clockbox { + width: auto; +} + +.calendar { + margin: 0; + padding: 0; +} + +.calendar table { + margin: 0; + padding: 0; + border-collapse: collapse; + background: white; + width: 100%; +} + +.calendar caption, .calendarbox h2 { + margin: 0; + text-align: center; + border-top: none; + font-weight: 700; + font-size: 0.75rem; + color: #333; + background: var(--accent); +} + +.calendar th { + padding: 8px 5px; + background: var(--darkened-bg); + border-bottom: 1px solid var(--border-color); + font-weight: 400; + font-size: 0.75rem; + text-align: center; + color: var(--body-quiet-color); +} + +.calendar td { + font-weight: 400; + font-size: 0.75rem; + text-align: center; + padding: 0; + border-top: 1px solid var(--hairline-color); + border-bottom: none; +} + +.calendar td.selected a { + background: var(--primary); + color: var(--button-fg); +} + +.calendar td.nonday { + background: var(--darkened-bg); +} + +.calendar td.today a { + font-weight: 700; +} + +.calendar td a, .timelist a { + display: block; + font-weight: 400; + padding: 6px; + text-decoration: none; + color: var(--body-quiet-color); +} + +.calendar td a:focus, .timelist a:focus, +.calendar td a:hover, .timelist a:hover { + background: var(--primary); + color: white; +} + +.calendar td a:active, .timelist a:active { + background: var(--header-bg); + color: white; +} + +.calendarnav { + font-size: 0.625rem; + text-align: center; + color: #ccc; + margin: 0; + padding: 1px 3px; +} + +.calendarnav a:link, #calendarnav a:visited, +#calendarnav a:focus, #calendarnav a:hover { + color: var(--body-quiet-color); +} + +.calendar-shortcuts { + background: var(--body-bg); + color: var(--body-quiet-color); + font-size: 0.6875rem; + line-height: 0.6875rem; + border-top: 1px solid var(--hairline-color); + padding: 8px 0; +} + +.calendarbox .calendarnav-previous, .calendarbox .calendarnav-next { + display: block; + position: absolute; + top: 8px; + width: 15px; + height: 15px; + text-indent: -9999px; + padding: 0; +} + +.calendarnav-previous { + left: 10px; + background: url(../img/calendar-icons.svg) 0 0 no-repeat; +} + +.calendarbox .calendarnav-previous:focus, +.calendarbox .calendarnav-previous:hover { + background-position: 0 -15px; +} + +.calendarnav-next { + right: 10px; + background: url(../img/calendar-icons.svg) 0 -30px no-repeat; +} + +.calendarbox .calendarnav-next:focus, +.calendarbox .calendarnav-next:hover { + background-position: 0 -45px; +} + +.calendar-cancel { + margin: 0; + padding: 4px 0; + font-size: 0.75rem; + background: #eee; + border-top: 1px solid var(--border-color); + color: var(--body-fg); +} + +.calendar-cancel:focus, .calendar-cancel:hover { + background: #ddd; +} + +.calendar-cancel a { + color: black; + display: block; +} + +ul.timelist, .timelist li { + list-style-type: none; + margin: 0; + padding: 0; +} + +.timelist a { + padding: 2px; +} + +/* EDIT INLINE */ + +.inline-deletelink { + float: right; + text-indent: -9999px; + background: url(../img/inline-delete.svg) 0 0 no-repeat; + width: 16px; + height: 16px; + border: 0px none; +} + +.inline-deletelink:focus, .inline-deletelink:hover { + cursor: pointer; +} + +/* RELATED WIDGET WRAPPER */ +.related-widget-wrapper { + float: left; /* display properly in form rows with multiple fields */ + overflow: hidden; /* clear floated contents */ +} + +.related-widget-wrapper-link { + opacity: 0.3; +} + +.related-widget-wrapper-link:link { + opacity: .8; +} + +.related-widget-wrapper-link:link:focus, +.related-widget-wrapper-link:link:hover { + opacity: 1; +} + +select + .related-widget-wrapper-link, +.related-widget-wrapper-link + .related-widget-wrapper-link { + margin-left: 7px; +} + +/* GIS MAPS */ +.dj_map { + width: 600px; + height: 400px; +} diff --git a/static/admin/img/LICENSE b/static/admin/img/LICENSE new file mode 100644 index 0000000..a4faaa1 --- /dev/null +++ b/static/admin/img/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Code Charm Ltd + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/static/admin/img/README.txt b/static/admin/img/README.txt new file mode 100644 index 0000000..4eb2e49 --- /dev/null +++ b/static/admin/img/README.txt @@ -0,0 +1,7 @@ +All icons are taken from Font Awesome (http://fontawesome.io/) project. +The Font Awesome font is licensed under the SIL OFL 1.1: +- https://scripts.sil.org/OFL + +SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG +Font-Awesome-SVG-PNG is licensed under the MIT license (see file license +in current folder). diff --git a/static/admin/img/calendar-icons.svg b/static/admin/img/calendar-icons.svg new file mode 100644 index 0000000..dbf21c3 --- /dev/null +++ b/static/admin/img/calendar-icons.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/static/admin/img/gis/move_vertex_off.svg b/static/admin/img/gis/move_vertex_off.svg new file mode 100644 index 0000000..228854f --- /dev/null +++ b/static/admin/img/gis/move_vertex_off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/admin/img/gis/move_vertex_on.svg b/static/admin/img/gis/move_vertex_on.svg new file mode 100644 index 0000000..96b87fd --- /dev/null +++ b/static/admin/img/gis/move_vertex_on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/admin/img/icon-addlink.svg b/static/admin/img/icon-addlink.svg new file mode 100644 index 0000000..e004fb1 --- /dev/null +++ b/static/admin/img/icon-addlink.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/icon-alert.svg b/static/admin/img/icon-alert.svg new file mode 100644 index 0000000..e51ea83 --- /dev/null +++ b/static/admin/img/icon-alert.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/icon-calendar.svg b/static/admin/img/icon-calendar.svg new file mode 100644 index 0000000..97910a9 --- /dev/null +++ b/static/admin/img/icon-calendar.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/static/admin/img/icon-changelink.svg b/static/admin/img/icon-changelink.svg new file mode 100644 index 0000000..bbb137a --- /dev/null +++ b/static/admin/img/icon-changelink.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/icon-clock.svg b/static/admin/img/icon-clock.svg new file mode 100644 index 0000000..bf9985d --- /dev/null +++ b/static/admin/img/icon-clock.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/static/admin/img/icon-deletelink.svg b/static/admin/img/icon-deletelink.svg new file mode 100644 index 0000000..4059b15 --- /dev/null +++ b/static/admin/img/icon-deletelink.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/icon-no.svg b/static/admin/img/icon-no.svg new file mode 100644 index 0000000..2e0d383 --- /dev/null +++ b/static/admin/img/icon-no.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/icon-unknown-alt.svg b/static/admin/img/icon-unknown-alt.svg new file mode 100644 index 0000000..1c6b99f --- /dev/null +++ b/static/admin/img/icon-unknown-alt.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/icon-unknown.svg b/static/admin/img/icon-unknown.svg new file mode 100644 index 0000000..50b4f97 --- /dev/null +++ b/static/admin/img/icon-unknown.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/icon-viewlink.svg b/static/admin/img/icon-viewlink.svg new file mode 100644 index 0000000..a1ca1d3 --- /dev/null +++ b/static/admin/img/icon-viewlink.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/icon-yes.svg b/static/admin/img/icon-yes.svg new file mode 100644 index 0000000..5883d87 --- /dev/null +++ b/static/admin/img/icon-yes.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/inline-delete.svg b/static/admin/img/inline-delete.svg new file mode 100644 index 0000000..17d1ad6 --- /dev/null +++ b/static/admin/img/inline-delete.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/search.svg b/static/admin/img/search.svg new file mode 100644 index 0000000..c8c69b2 --- /dev/null +++ b/static/admin/img/search.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/selector-icons.svg b/static/admin/img/selector-icons.svg new file mode 100644 index 0000000..926b8e2 --- /dev/null +++ b/static/admin/img/selector-icons.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/admin/img/sorting-icons.svg b/static/admin/img/sorting-icons.svg new file mode 100644 index 0000000..7c31ec9 --- /dev/null +++ b/static/admin/img/sorting-icons.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/static/admin/img/tooltag-add.svg b/static/admin/img/tooltag-add.svg new file mode 100644 index 0000000..1ca64ae --- /dev/null +++ b/static/admin/img/tooltag-add.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/img/tooltag-arrowright.svg b/static/admin/img/tooltag-arrowright.svg new file mode 100644 index 0000000..b664d61 --- /dev/null +++ b/static/admin/img/tooltag-arrowright.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/admin/js/SelectBox.js b/static/admin/js/SelectBox.js new file mode 100644 index 0000000..3db4ec7 --- /dev/null +++ b/static/admin/js/SelectBox.js @@ -0,0 +1,116 @@ +'use strict'; +{ + const SelectBox = { + cache: {}, + init: function(id) { + const box = document.getElementById(id); + SelectBox.cache[id] = []; + const cache = SelectBox.cache[id]; + for (const node of box.options) { + cache.push({value: node.value, text: node.text, displayed: 1}); + } + }, + redisplay: function(id) { + // Repopulate HTML select box from cache + const box = document.getElementById(id); + const scroll_value_from_top = box.scrollTop; + box.innerHTML = ''; + for (const node of SelectBox.cache[id]) { + if (node.displayed) { + const new_option = new Option(node.text, node.value, false, false); + // Shows a tooltip when hovering over the option + new_option.title = node.text; + box.appendChild(new_option); + } + } + box.scrollTop = scroll_value_from_top; + }, + filter: function(id, text) { + // Redisplay the HTML select box, displaying only the choices containing ALL + // the words in text. (It's an AND search.) + const tokens = text.toLowerCase().split(/\s+/); + for (const node of SelectBox.cache[id]) { + node.displayed = 1; + const node_text = node.text.toLowerCase(); + for (const token of tokens) { + if (!node_text.includes(token)) { + node.displayed = 0; + break; // Once the first token isn't found we're done + } + } + } + SelectBox.redisplay(id); + }, + get_hidden_node_count(id) { + const cache = SelectBox.cache[id] || []; + return cache.filter(node => node.displayed === 0).length; + }, + delete_from_cache: function(id, value) { + let delete_index = null; + const cache = SelectBox.cache[id]; + for (const [i, node] of cache.entries()) { + if (node.value === value) { + delete_index = i; + break; + } + } + cache.splice(delete_index, 1); + }, + add_to_cache: function(id, option) { + SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1}); + }, + cache_contains: function(id, value) { + // Check if an item is contained in the cache + for (const node of SelectBox.cache[id]) { + if (node.value === value) { + return true; + } + } + return false; + }, + move: function(from, to) { + const from_box = document.getElementById(from); + for (const option of from_box.options) { + const option_value = option.value; + if (option.selected && SelectBox.cache_contains(from, option_value)) { + SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1}); + SelectBox.delete_from_cache(from, option_value); + } + } + SelectBox.redisplay(from); + SelectBox.redisplay(to); + }, + move_all: function(from, to) { + const from_box = document.getElementById(from); + for (const option of from_box.options) { + const option_value = option.value; + if (SelectBox.cache_contains(from, option_value)) { + SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1}); + SelectBox.delete_from_cache(from, option_value); + } + } + SelectBox.redisplay(from); + SelectBox.redisplay(to); + }, + sort: function(id) { + SelectBox.cache[id].sort(function(a, b) { + a = a.text.toLowerCase(); + b = b.text.toLowerCase(); + if (a > b) { + return 1; + } + if (a < b) { + return -1; + } + return 0; + } ); + }, + select_all: function(id) { + const box = document.getElementById(id); + for (const option of box.options) { + option.selected = true; + } + } + }; + window.SelectBox = SelectBox; +} diff --git a/static/admin/js/SelectFilter2.js b/static/admin/js/SelectFilter2.js new file mode 100644 index 0000000..9a4e0a3 --- /dev/null +++ b/static/admin/js/SelectFilter2.js @@ -0,0 +1,283 @@ +/*global SelectBox, gettext, interpolate, quickElement, SelectFilter*/ +/* +SelectFilter2 - Turns a multiple-select box into a filter interface. + +Requires core.js and SelectBox.js. +*/ +'use strict'; +{ + window.SelectFilter = { + init: function(field_id, field_name, is_stacked) { + if (field_id.match(/__prefix__/)) { + // Don't initialize on empty forms. + return; + } + const from_box = document.getElementById(field_id); + from_box.id += '_from'; // change its ID + from_box.className = 'filtered'; + + for (const p of from_box.parentNode.getElementsByTagName('p')) { + if (p.classList.contains("info")) { + // Remove

, because it just gets in the way. + from_box.parentNode.removeChild(p); + } else if (p.classList.contains("help")) { + // Move help text up to the top so it isn't below the select + // boxes or wrapped off on the side to the right of the add + // button: + from_box.parentNode.insertBefore(p, from_box.parentNode.firstChild); + } + } + + //

or
+ const selector_div = quickElement('div', from_box.parentNode); + selector_div.className = is_stacked ? 'selector stacked' : 'selector'; + + //
+ const selector_available = quickElement('div', selector_div); + selector_available.className = 'selector-available'; + const title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name])); + quickElement( + 'span', title_available, '', + 'class', 'help help-tooltip help-icon', + 'title', interpolate( + gettext( + 'This is the list of available %s. You may choose some by ' + + 'selecting them in the box below and then clicking the ' + + '"Choose" arrow between the two boxes.' + ), + [field_name] + ) + ); + + const filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter'); + filter_p.className = 'selector-filter'; + + const search_filter_label = quickElement('label', filter_p, '', 'for', field_id + '_input'); + + quickElement( + 'span', search_filter_label, '', + 'class', 'help-tooltip search-label-icon', + 'title', interpolate(gettext("Type into this box to filter down the list of available %s."), [field_name]) + ); + + filter_p.appendChild(document.createTextNode(' ')); + + const filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter")); + filter_input.id = field_id + '_input'; + + selector_available.appendChild(from_box); + const choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', '#', 'id', field_id + '_add_all_link'); + choose_all.className = 'selector-chooseall'; + + //
    + const selector_chooser = quickElement('ul', selector_div); + selector_chooser.className = 'selector-chooser'; + const add_link = quickElement('a', quickElement('li', selector_chooser), gettext('Choose'), 'title', gettext('Choose'), 'href', '#', 'id', field_id + '_add_link'); + add_link.className = 'selector-add'; + const remove_link = quickElement('a', quickElement('li', selector_chooser), gettext('Remove'), 'title', gettext('Remove'), 'href', '#', 'id', field_id + '_remove_link'); + remove_link.className = 'selector-remove'; + + //
    + const selector_chosen = quickElement('div', selector_div, '', 'id', field_id + '_selector_chosen'); + selector_chosen.className = 'selector-chosen'; + const title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name])); + quickElement( + 'span', title_chosen, '', + 'class', 'help help-tooltip help-icon', + 'title', interpolate( + gettext( + 'This is the list of chosen %s. You may remove some by ' + + 'selecting them in the box below and then clicking the ' + + '"Remove" arrow between the two boxes.' + ), + [field_name] + ) + ); + + const filter_selected_p = quickElement('p', selector_chosen, '', 'id', field_id + '_filter_selected'); + filter_selected_p.className = 'selector-filter'; + + const search_filter_selected_label = quickElement('label', filter_selected_p, '', 'for', field_id + '_selected_input'); + + quickElement( + 'span', search_filter_selected_label, '', + 'class', 'help-tooltip search-label-icon', + 'title', interpolate(gettext("Type into this box to filter down the list of selected %s."), [field_name]) + ); + + filter_selected_p.appendChild(document.createTextNode(' ')); + + const filter_selected_input = quickElement('input', filter_selected_p, '', 'type', 'text', 'placeholder', gettext("Filter")); + filter_selected_input.id = field_id + '_selected_input'; + + const to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', '', 'size', from_box.size, 'name', from_box.name); + to_box.className = 'filtered'; + + const warning_footer = quickElement('div', selector_chosen, '', 'class', 'list-footer-display'); + quickElement('span', warning_footer, '', 'id', field_id + '_list-footer-display-text'); + quickElement('span', warning_footer, ' (click to clear)', 'class', 'list-footer-display__clear'); + + const clear_all = quickElement('a', selector_chosen, gettext('Remove all'), 'title', interpolate(gettext('Click to remove all chosen %s at once.'), [field_name]), 'href', '#', 'id', field_id + '_remove_all_link'); + clear_all.className = 'selector-clearall'; + + from_box.name = from_box.name + '_old'; + + // Set up the JavaScript event handlers for the select box filter interface + const move_selection = function(e, elem, move_func, from, to) { + if (elem.classList.contains('active')) { + move_func(from, to); + SelectFilter.refresh_icons(field_id); + SelectFilter.refresh_filtered_selects(field_id); + SelectFilter.refresh_filtered_warning(field_id); + } + e.preventDefault(); + }; + choose_all.addEventListener('click', function(e) { + move_selection(e, this, SelectBox.move_all, field_id + '_from', field_id + '_to'); + }); + add_link.addEventListener('click', function(e) { + move_selection(e, this, SelectBox.move, field_id + '_from', field_id + '_to'); + }); + remove_link.addEventListener('click', function(e) { + move_selection(e, this, SelectBox.move, field_id + '_to', field_id + '_from'); + }); + clear_all.addEventListener('click', function(e) { + move_selection(e, this, SelectBox.move_all, field_id + '_to', field_id + '_from'); + }); + warning_footer.addEventListener('click', function(e) { + filter_selected_input.value = ''; + SelectBox.filter(field_id + '_to', ''); + SelectFilter.refresh_filtered_warning(field_id); + SelectFilter.refresh_icons(field_id); + }); + filter_input.addEventListener('keypress', function(e) { + SelectFilter.filter_key_press(e, field_id, '_from', '_to'); + }); + filter_input.addEventListener('keyup', function(e) { + SelectFilter.filter_key_up(e, field_id, '_from'); + }); + filter_input.addEventListener('keydown', function(e) { + SelectFilter.filter_key_down(e, field_id, '_from', '_to'); + }); + filter_selected_input.addEventListener('keypress', function(e) { + SelectFilter.filter_key_press(e, field_id, '_to', '_from'); + }); + filter_selected_input.addEventListener('keyup', function(e) { + SelectFilter.filter_key_up(e, field_id, '_to', '_selected_input'); + }); + filter_selected_input.addEventListener('keydown', function(e) { + SelectFilter.filter_key_down(e, field_id, '_to', '_from'); + }); + selector_div.addEventListener('change', function(e) { + if (e.target.tagName === 'SELECT') { + SelectFilter.refresh_icons(field_id); + } + }); + selector_div.addEventListener('dblclick', function(e) { + if (e.target.tagName === 'OPTION') { + if (e.target.closest('select').id === field_id + '_to') { + SelectBox.move(field_id + '_to', field_id + '_from'); + } else { + SelectBox.move(field_id + '_from', field_id + '_to'); + } + SelectFilter.refresh_icons(field_id); + } + }); + from_box.closest('form').addEventListener('submit', function() { + SelectBox.filter(field_id + '_to', ''); + SelectBox.select_all(field_id + '_to'); + }); + SelectBox.init(field_id + '_from'); + SelectBox.init(field_id + '_to'); + // Move selected from_box options to to_box + SelectBox.move(field_id + '_from', field_id + '_to'); + + // Initial icon refresh + SelectFilter.refresh_icons(field_id); + }, + any_selected: function(field) { + // Temporarily add the required attribute and check validity. + field.required = true; + const any_selected = field.checkValidity(); + field.required = false; + return any_selected; + }, + refresh_filtered_warning: function(field_id) { + const count = SelectBox.get_hidden_node_count(field_id + '_to'); + const selector = document.getElementById(field_id + '_selector_chosen'); + const warning = document.getElementById(field_id + '_list-footer-display-text'); + selector.className = selector.className.replace('selector-chosen--with-filtered', ''); + warning.textContent = interpolate(ngettext( + '%s selected option not visible', + '%s selected options not visible', + count + ), [count]); + if(count > 0) { + selector.className += ' selector-chosen--with-filtered'; + } + }, + refresh_filtered_selects: function(field_id) { + SelectBox.filter(field_id + '_from', document.getElementById(field_id + "_input").value); + SelectBox.filter(field_id + '_to', document.getElementById(field_id + "_selected_input").value); + }, + refresh_icons: function(field_id) { + const from = document.getElementById(field_id + '_from'); + const to = document.getElementById(field_id + '_to'); + // Active if at least one item is selected + document.getElementById(field_id + '_add_link').classList.toggle('active', SelectFilter.any_selected(from)); + document.getElementById(field_id + '_remove_link').classList.toggle('active', SelectFilter.any_selected(to)); + // Active if the corresponding box isn't empty + document.getElementById(field_id + '_add_all_link').classList.toggle('active', from.querySelector('option')); + document.getElementById(field_id + '_remove_all_link').classList.toggle('active', to.querySelector('option')); + SelectFilter.refresh_filtered_warning(field_id); + }, + filter_key_press: function(event, field_id, source, target) { + const source_box = document.getElementById(field_id + source); + // don't submit form if user pressed Enter + if ((event.which && event.which === 13) || (event.keyCode && event.keyCode === 13)) { + source_box.selectedIndex = 0; + SelectBox.move(field_id + source, field_id + target); + source_box.selectedIndex = 0; + event.preventDefault(); + } + }, + filter_key_up: function(event, field_id, source, filter_input) { + const input = filter_input || '_input'; + const source_box = document.getElementById(field_id + source); + const temp = source_box.selectedIndex; + SelectBox.filter(field_id + source, document.getElementById(field_id + input).value); + source_box.selectedIndex = temp; + SelectFilter.refresh_filtered_warning(field_id); + SelectFilter.refresh_icons(field_id); + }, + filter_key_down: function(event, field_id, source, target) { + const source_box = document.getElementById(field_id + source); + // right key (39) or left key (37) + const direction = source === '_from' ? 39 : 37; + // right arrow -- move across + if ((event.which && event.which === direction) || (event.keyCode && event.keyCode === direction)) { + const old_index = source_box.selectedIndex; + SelectBox.move(field_id + source, field_id + target); + SelectFilter.refresh_filtered_selects(field_id); + SelectFilter.refresh_filtered_warning(field_id); + source_box.selectedIndex = (old_index === source_box.length) ? source_box.length - 1 : old_index; + return; + } + // down arrow -- wrap around + if ((event.which && event.which === 40) || (event.keyCode && event.keyCode === 40)) { + source_box.selectedIndex = (source_box.length === source_box.selectedIndex + 1) ? 0 : source_box.selectedIndex + 1; + } + // up arrow -- wrap around + if ((event.which && event.which === 38) || (event.keyCode && event.keyCode === 38)) { + source_box.selectedIndex = (source_box.selectedIndex === 0) ? source_box.length - 1 : source_box.selectedIndex - 1; + } + } + }; + + window.addEventListener('load', function(e) { + document.querySelectorAll('select.selectfilter, select.selectfilterstacked').forEach(function(el) { + const data = el.dataset; + SelectFilter.init(el.id, data.fieldName, parseInt(data.isStacked, 10)); + }); + }); +} diff --git a/static/admin/js/actions.js b/static/admin/js/actions.js new file mode 100644 index 0000000..20a5c14 --- /dev/null +++ b/static/admin/js/actions.js @@ -0,0 +1,201 @@ +/*global gettext, interpolate, ngettext*/ +'use strict'; +{ + function show(selector) { + document.querySelectorAll(selector).forEach(function(el) { + el.classList.remove('hidden'); + }); + } + + function hide(selector) { + document.querySelectorAll(selector).forEach(function(el) { + el.classList.add('hidden'); + }); + } + + function showQuestion(options) { + hide(options.acrossClears); + show(options.acrossQuestions); + hide(options.allContainer); + } + + function showClear(options) { + show(options.acrossClears); + hide(options.acrossQuestions); + document.querySelector(options.actionContainer).classList.remove(options.selectedClass); + show(options.allContainer); + hide(options.counterContainer); + } + + function reset(options) { + hide(options.acrossClears); + hide(options.acrossQuestions); + hide(options.allContainer); + show(options.counterContainer); + } + + function clearAcross(options) { + reset(options); + const acrossInputs = document.querySelectorAll(options.acrossInput); + acrossInputs.forEach(function(acrossInput) { + acrossInput.value = 0; + }); + document.querySelector(options.actionContainer).classList.remove(options.selectedClass); + } + + function checker(actionCheckboxes, options, checked) { + if (checked) { + showQuestion(options); + } else { + reset(options); + } + actionCheckboxes.forEach(function(el) { + el.checked = checked; + el.closest('tr').classList.toggle(options.selectedClass, checked); + }); + } + + function updateCounter(actionCheckboxes, options) { + const sel = Array.from(actionCheckboxes).filter(function(el) { + return el.checked; + }).length; + const counter = document.querySelector(options.counterContainer); + // data-actions-icnt is defined in the generated HTML + // and contains the total amount of objects in the queryset + const actions_icnt = Number(counter.dataset.actionsIcnt); + counter.textContent = interpolate( + ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), { + sel: sel, + cnt: actions_icnt + }, true); + const allToggle = document.getElementById(options.allToggleId); + allToggle.checked = sel === actionCheckboxes.length; + if (allToggle.checked) { + showQuestion(options); + } else { + clearAcross(options); + } + } + + const defaults = { + actionContainer: "div.actions", + counterContainer: "span.action-counter", + allContainer: "div.actions span.all", + acrossInput: "div.actions input.select-across", + acrossQuestions: "div.actions span.question", + acrossClears: "div.actions span.clear", + allToggleId: "action-toggle", + selectedClass: "selected" + }; + + window.Actions = function(actionCheckboxes, options) { + options = Object.assign({}, defaults, options); + let list_editable_changed = false; + let lastChecked = null; + let shiftPressed = false; + + document.addEventListener('keydown', (event) => { + shiftPressed = event.shiftKey; + }); + + document.addEventListener('keyup', (event) => { + shiftPressed = event.shiftKey; + }); + + document.getElementById(options.allToggleId).addEventListener('click', function(event) { + checker(actionCheckboxes, options, this.checked); + updateCounter(actionCheckboxes, options); + }); + + document.querySelectorAll(options.acrossQuestions + " a").forEach(function(el) { + el.addEventListener('click', function(event) { + event.preventDefault(); + const acrossInputs = document.querySelectorAll(options.acrossInput); + acrossInputs.forEach(function(acrossInput) { + acrossInput.value = 1; + }); + showClear(options); + }); + }); + + document.querySelectorAll(options.acrossClears + " a").forEach(function(el) { + el.addEventListener('click', function(event) { + event.preventDefault(); + document.getElementById(options.allToggleId).checked = false; + clearAcross(options); + checker(actionCheckboxes, options, false); + updateCounter(actionCheckboxes, options); + }); + }); + + function affectedCheckboxes(target, withModifier) { + const multiSelect = (lastChecked && withModifier && lastChecked !== target); + if (!multiSelect) { + return [target]; + } + const checkboxes = Array.from(actionCheckboxes); + const targetIndex = checkboxes.findIndex(el => el === target); + const lastCheckedIndex = checkboxes.findIndex(el => el === lastChecked); + const startIndex = Math.min(targetIndex, lastCheckedIndex); + const endIndex = Math.max(targetIndex, lastCheckedIndex); + const filtered = checkboxes.filter((el, index) => (startIndex <= index) && (index <= endIndex)); + return filtered; + }; + + Array.from(document.getElementById('result_list').tBodies).forEach(function(el) { + el.addEventListener('change', function(event) { + const target = event.target; + if (target.classList.contains('action-select')) { + const checkboxes = affectedCheckboxes(target, shiftPressed); + checker(checkboxes, options, target.checked); + updateCounter(actionCheckboxes, options); + lastChecked = target; + } else { + list_editable_changed = true; + } + }); + }); + + document.querySelector('#changelist-form button[name=index]').addEventListener('click', function(event) { + if (list_editable_changed) { + const confirmed = confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.")); + if (!confirmed) { + event.preventDefault(); + } + } + }); + + const el = document.querySelector('#changelist-form input[name=_save]'); + // The button does not exist if no fields are editable. + if (el) { + el.addEventListener('click', function(event) { + if (document.querySelector('[name=action]').value) { + const text = list_editable_changed + ? gettext("You have selected an action, but you haven’t saved your changes to individual fields yet. Please click OK to save. You’ll need to re-run the action.") + : gettext("You have selected an action, and you haven’t made any changes on individual fields. You’re probably looking for the Go button rather than the Save button."); + if (!confirm(text)) { + event.preventDefault(); + } + } + }); + } + }; + + // Call function fn when the DOM is loaded and ready. If it is already + // loaded, call the function now. + // http://youmightnotneedjquery.com/#ready + function ready(fn) { + if (document.readyState !== 'loading') { + fn(); + } else { + document.addEventListener('DOMContentLoaded', fn); + } + } + + ready(function() { + const actionsEls = document.querySelectorAll('tr input.action-select'); + if (actionsEls.length > 0) { + Actions(actionsEls); + } + }); +} diff --git a/static/admin/js/admin/DateTimeShortcuts.js b/static/admin/js/admin/DateTimeShortcuts.js new file mode 100644 index 0000000..aa1cae9 --- /dev/null +++ b/static/admin/js/admin/DateTimeShortcuts.js @@ -0,0 +1,408 @@ +/*global Calendar, findPosX, findPosY, get_format, gettext, gettext_noop, interpolate, ngettext, quickElement*/ +// Inserts shortcut buttons after all of the following: +// +// +'use strict'; +{ + const DateTimeShortcuts = { + calendars: [], + calendarInputs: [], + clockInputs: [], + clockHours: { + default_: [ + [gettext_noop('Now'), -1], + [gettext_noop('Midnight'), 0], + [gettext_noop('6 a.m.'), 6], + [gettext_noop('Noon'), 12], + [gettext_noop('6 p.m.'), 18] + ] + }, + dismissClockFunc: [], + dismissCalendarFunc: [], + calendarDivName1: 'calendarbox', // name of calendar
    that gets toggled + calendarDivName2: 'calendarin', // name of
    that contains calendar + calendarLinkName: 'calendarlink', // name of the link that is used to toggle + clockDivName: 'clockbox', // name of clock
    that gets toggled + clockLinkName: 'clocklink', // name of the link that is used to toggle + shortCutsClass: 'datetimeshortcuts', // class of the clock and cal shortcuts + timezoneWarningClass: 'timezonewarning', // class of the warning for timezone mismatch + timezoneOffset: 0, + init: function() { + const serverOffset = document.body.dataset.adminUtcOffset; + if (serverOffset) { + const localOffset = new Date().getTimezoneOffset() * -60; + DateTimeShortcuts.timezoneOffset = localOffset - serverOffset; + } + + for (const inp of document.getElementsByTagName('input')) { + if (inp.type === 'text' && inp.classList.contains('vTimeField')) { + DateTimeShortcuts.addClock(inp); + DateTimeShortcuts.addTimezoneWarning(inp); + } + else if (inp.type === 'text' && inp.classList.contains('vDateField')) { + DateTimeShortcuts.addCalendar(inp); + DateTimeShortcuts.addTimezoneWarning(inp); + } + } + }, + // Return the current time while accounting for the server timezone. + now: function() { + const serverOffset = document.body.dataset.adminUtcOffset; + if (serverOffset) { + const localNow = new Date(); + const localOffset = localNow.getTimezoneOffset() * -60; + localNow.setTime(localNow.getTime() + 1000 * (serverOffset - localOffset)); + return localNow; + } else { + return new Date(); + } + }, + // Add a warning when the time zone in the browser and backend do not match. + addTimezoneWarning: function(inp) { + const warningClass = DateTimeShortcuts.timezoneWarningClass; + let timezoneOffset = DateTimeShortcuts.timezoneOffset / 3600; + + // Only warn if there is a time zone mismatch. + if (!timezoneOffset) { + return; + } + + // Check if warning is already there. + if (inp.parentNode.querySelectorAll('.' + warningClass).length) { + return; + } + + let message; + if (timezoneOffset > 0) { + message = ngettext( + 'Note: You are %s hour ahead of server time.', + 'Note: You are %s hours ahead of server time.', + timezoneOffset + ); + } + else { + timezoneOffset *= -1; + message = ngettext( + 'Note: You are %s hour behind server time.', + 'Note: You are %s hours behind server time.', + timezoneOffset + ); + } + message = interpolate(message, [timezoneOffset]); + + const warning = document.createElement('div'); + warning.classList.add('help', warningClass); + warning.textContent = message; + inp.parentNode.appendChild(warning); + }, + // Add clock widget to a given field + addClock: function(inp) { + const num = DateTimeShortcuts.clockInputs.length; + DateTimeShortcuts.clockInputs[num] = inp; + DateTimeShortcuts.dismissClockFunc[num] = function() { DateTimeShortcuts.dismissClock(num); return true; }; + + // Shortcut links (clock icon and "Now" link) + const shortcuts_span = document.createElement('span'); + shortcuts_span.className = DateTimeShortcuts.shortCutsClass; + inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling); + const now_link = document.createElement('a'); + now_link.href = "#"; + now_link.textContent = gettext('Now'); + now_link.addEventListener('click', function(e) { + e.preventDefault(); + DateTimeShortcuts.handleClockQuicklink(num, -1); + }); + const clock_link = document.createElement('a'); + clock_link.href = '#'; + clock_link.id = DateTimeShortcuts.clockLinkName + num; + clock_link.addEventListener('click', function(e) { + e.preventDefault(); + // avoid triggering the document click handler to dismiss the clock + e.stopPropagation(); + DateTimeShortcuts.openClock(num); + }); + + quickElement( + 'span', clock_link, '', + 'class', 'clock-icon', + 'title', gettext('Choose a Time') + ); + shortcuts_span.appendChild(document.createTextNode('\u00A0')); + shortcuts_span.appendChild(now_link); + shortcuts_span.appendChild(document.createTextNode('\u00A0|\u00A0')); + shortcuts_span.appendChild(clock_link); + + // Create clock link div + // + // Markup looks like: + //
    + //

    Choose a time

    + // + //

    Cancel

    + //
    + + const clock_box = document.createElement('div'); + clock_box.style.display = 'none'; + clock_box.style.position = 'absolute'; + clock_box.className = 'clockbox module'; + clock_box.id = DateTimeShortcuts.clockDivName + num; + document.body.appendChild(clock_box); + clock_box.addEventListener('click', function(e) { e.stopPropagation(); }); + + quickElement('h2', clock_box, gettext('Choose a time')); + const time_list = quickElement('ul', clock_box); + time_list.className = 'timelist'; + // The list of choices can be overridden in JavaScript like this: + // DateTimeShortcuts.clockHours.name = [['3 a.m.', 3]]; + // where name is the name attribute of the . + const name = typeof DateTimeShortcuts.clockHours[inp.name] === 'undefined' ? 'default_' : inp.name; + DateTimeShortcuts.clockHours[name].forEach(function(element) { + const time_link = quickElement('a', quickElement('li', time_list), gettext(element[0]), 'href', '#'); + time_link.addEventListener('click', function(e) { + e.preventDefault(); + DateTimeShortcuts.handleClockQuicklink(num, element[1]); + }); + }); + + const cancel_p = quickElement('p', clock_box); + cancel_p.className = 'calendar-cancel'; + const cancel_link = quickElement('a', cancel_p, gettext('Cancel'), 'href', '#'); + cancel_link.addEventListener('click', function(e) { + e.preventDefault(); + DateTimeShortcuts.dismissClock(num); + }); + + document.addEventListener('keyup', function(event) { + if (event.which === 27) { + // ESC key closes popup + DateTimeShortcuts.dismissClock(num); + event.preventDefault(); + } + }); + }, + openClock: function(num) { + const clock_box = document.getElementById(DateTimeShortcuts.clockDivName + num); + const clock_link = document.getElementById(DateTimeShortcuts.clockLinkName + num); + + // Recalculate the clockbox position + // is it left-to-right or right-to-left layout ? + if (window.getComputedStyle(document.body).direction !== 'rtl') { + clock_box.style.left = findPosX(clock_link) + 17 + 'px'; + } + else { + // since style's width is in em, it'd be tough to calculate + // px value of it. let's use an estimated px for now + clock_box.style.left = findPosX(clock_link) - 110 + 'px'; + } + clock_box.style.top = Math.max(0, findPosY(clock_link) - 30) + 'px'; + + // Show the clock box + clock_box.style.display = 'block'; + document.addEventListener('click', DateTimeShortcuts.dismissClockFunc[num]); + }, + dismissClock: function(num) { + document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none'; + document.removeEventListener('click', DateTimeShortcuts.dismissClockFunc[num]); + }, + handleClockQuicklink: function(num, val) { + let d; + if (val === -1) { + d = DateTimeShortcuts.now(); + } + else { + d = new Date(1970, 1, 1, val, 0, 0, 0); + } + DateTimeShortcuts.clockInputs[num].value = d.strftime(get_format('TIME_INPUT_FORMATS')[0]); + DateTimeShortcuts.clockInputs[num].focus(); + DateTimeShortcuts.dismissClock(num); + }, + // Add calendar widget to a given field. + addCalendar: function(inp) { + const num = DateTimeShortcuts.calendars.length; + + DateTimeShortcuts.calendarInputs[num] = inp; + DateTimeShortcuts.dismissCalendarFunc[num] = function() { DateTimeShortcuts.dismissCalendar(num); return true; }; + + // Shortcut links (calendar icon and "Today" link) + const shortcuts_span = document.createElement('span'); + shortcuts_span.className = DateTimeShortcuts.shortCutsClass; + inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling); + const today_link = document.createElement('a'); + today_link.href = '#'; + today_link.appendChild(document.createTextNode(gettext('Today'))); + today_link.addEventListener('click', function(e) { + e.preventDefault(); + DateTimeShortcuts.handleCalendarQuickLink(num, 0); + }); + const cal_link = document.createElement('a'); + cal_link.href = '#'; + cal_link.id = DateTimeShortcuts.calendarLinkName + num; + cal_link.addEventListener('click', function(e) { + e.preventDefault(); + // avoid triggering the document click handler to dismiss the calendar + e.stopPropagation(); + DateTimeShortcuts.openCalendar(num); + }); + quickElement( + 'span', cal_link, '', + 'class', 'date-icon', + 'title', gettext('Choose a Date') + ); + shortcuts_span.appendChild(document.createTextNode('\u00A0')); + shortcuts_span.appendChild(today_link); + shortcuts_span.appendChild(document.createTextNode('\u00A0|\u00A0')); + shortcuts_span.appendChild(cal_link); + + // Create calendarbox div. + // + // Markup looks like: + // + //
    + //

    + // + // February 2003 + //

    + //
    + // + //
    + //
    + // Yesterday | Today | Tomorrow + //
    + //

    Cancel

    + //
    + const cal_box = document.createElement('div'); + cal_box.style.display = 'none'; + cal_box.style.position = 'absolute'; + cal_box.className = 'calendarbox module'; + cal_box.id = DateTimeShortcuts.calendarDivName1 + num; + document.body.appendChild(cal_box); + cal_box.addEventListener('click', function(e) { e.stopPropagation(); }); + + // next-prev links + const cal_nav = quickElement('div', cal_box); + const cal_nav_prev = quickElement('a', cal_nav, '<', 'href', '#'); + cal_nav_prev.className = 'calendarnav-previous'; + cal_nav_prev.addEventListener('click', function(e) { + e.preventDefault(); + DateTimeShortcuts.drawPrev(num); + }); + + const cal_nav_next = quickElement('a', cal_nav, '>', 'href', '#'); + cal_nav_next.className = 'calendarnav-next'; + cal_nav_next.addEventListener('click', function(e) { + e.preventDefault(); + DateTimeShortcuts.drawNext(num); + }); + + // main box + const cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num); + cal_main.className = 'calendar'; + DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num)); + DateTimeShortcuts.calendars[num].drawCurrent(); + + // calendar shortcuts + const shortcuts = quickElement('div', cal_box); + shortcuts.className = 'calendar-shortcuts'; + let day_link = quickElement('a', shortcuts, gettext('Yesterday'), 'href', '#'); + day_link.addEventListener('click', function(e) { + e.preventDefault(); + DateTimeShortcuts.handleCalendarQuickLink(num, -1); + }); + shortcuts.appendChild(document.createTextNode('\u00A0|\u00A0')); + day_link = quickElement('a', shortcuts, gettext('Today'), 'href', '#'); + day_link.addEventListener('click', function(e) { + e.preventDefault(); + DateTimeShortcuts.handleCalendarQuickLink(num, 0); + }); + shortcuts.appendChild(document.createTextNode('\u00A0|\u00A0')); + day_link = quickElement('a', shortcuts, gettext('Tomorrow'), 'href', '#'); + day_link.addEventListener('click', function(e) { + e.preventDefault(); + DateTimeShortcuts.handleCalendarQuickLink(num, +1); + }); + + // cancel bar + const cancel_p = quickElement('p', cal_box); + cancel_p.className = 'calendar-cancel'; + const cancel_link = quickElement('a', cancel_p, gettext('Cancel'), 'href', '#'); + cancel_link.addEventListener('click', function(e) { + e.preventDefault(); + DateTimeShortcuts.dismissCalendar(num); + }); + document.addEventListener('keyup', function(event) { + if (event.which === 27) { + // ESC key closes popup + DateTimeShortcuts.dismissCalendar(num); + event.preventDefault(); + } + }); + }, + openCalendar: function(num) { + const cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1 + num); + const cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName + num); + const inp = DateTimeShortcuts.calendarInputs[num]; + + // Determine if the current value in the input has a valid date. + // If so, draw the calendar with that date's year and month. + if (inp.value) { + const format = get_format('DATE_INPUT_FORMATS')[0]; + const selected = inp.value.strptime(format); + const year = selected.getUTCFullYear(); + const month = selected.getUTCMonth() + 1; + const re = /\d{4}/; + if (re.test(year.toString()) && month >= 1 && month <= 12) { + DateTimeShortcuts.calendars[num].drawDate(month, year, selected); + } + } + + // Recalculate the clockbox position + // is it left-to-right or right-to-left layout ? + if (window.getComputedStyle(document.body).direction !== 'rtl') { + cal_box.style.left = findPosX(cal_link) + 17 + 'px'; + } + else { + // since style's width is in em, it'd be tough to calculate + // px value of it. let's use an estimated px for now + cal_box.style.left = findPosX(cal_link) - 180 + 'px'; + } + cal_box.style.top = Math.max(0, findPosY(cal_link) - 75) + 'px'; + + cal_box.style.display = 'block'; + document.addEventListener('click', DateTimeShortcuts.dismissCalendarFunc[num]); + }, + dismissCalendar: function(num) { + document.getElementById(DateTimeShortcuts.calendarDivName1 + num).style.display = 'none'; + document.removeEventListener('click', DateTimeShortcuts.dismissCalendarFunc[num]); + }, + drawPrev: function(num) { + DateTimeShortcuts.calendars[num].drawPreviousMonth(); + }, + drawNext: function(num) { + DateTimeShortcuts.calendars[num].drawNextMonth(); + }, + handleCalendarCallback: function(num) { + const format = get_format('DATE_INPUT_FORMATS')[0]; + return function(y, m, d) { + DateTimeShortcuts.calendarInputs[num].value = new Date(y, m - 1, d).strftime(format); + DateTimeShortcuts.calendarInputs[num].focus(); + document.getElementById(DateTimeShortcuts.calendarDivName1 + num).style.display = 'none'; + }; + }, + handleCalendarQuickLink: function(num, offset) { + const d = DateTimeShortcuts.now(); + d.setDate(d.getDate() + offset); + DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]); + DateTimeShortcuts.calendarInputs[num].focus(); + DateTimeShortcuts.dismissCalendar(num); + } + }; + + window.addEventListener('load', DateTimeShortcuts.init); + window.DateTimeShortcuts = DateTimeShortcuts; +} diff --git a/static/admin/js/admin/RelatedObjectLookups.js b/static/admin/js/admin/RelatedObjectLookups.js new file mode 100644 index 0000000..afb6b66 --- /dev/null +++ b/static/admin/js/admin/RelatedObjectLookups.js @@ -0,0 +1,238 @@ +/*global SelectBox, interpolate*/ +// Handles related-objects functionality: lookup link for raw_id_fields +// and Add Another links. +'use strict'; +{ + const $ = django.jQuery; + let popupIndex = 0; + const relatedWindows = []; + + function dismissChildPopups() { + relatedWindows.forEach(function(win) { + if(!win.closed) { + win.dismissChildPopups(); + win.close(); + } + }); + } + + function setPopupIndex() { + if(document.getElementsByName("_popup").length > 0) { + const index = window.name.lastIndexOf("__") + 2; + popupIndex = parseInt(window.name.substring(index)); + } else { + popupIndex = 0; + } + } + + function addPopupIndex(name) { + return name + "__" + (popupIndex + 1); + } + + function removePopupIndex(name) { + return name.replace(new RegExp("__" + (popupIndex + 1) + "$"), ''); + } + + function showAdminPopup(triggeringLink, name_regexp, add_popup) { + const name = addPopupIndex(triggeringLink.id.replace(name_regexp, '')); + const href = new URL(triggeringLink.href); + if (add_popup) { + href.searchParams.set('_popup', 1); + } + const win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); + relatedWindows.push(win); + win.focus(); + return false; + } + + function showRelatedObjectLookupPopup(triggeringLink) { + return showAdminPopup(triggeringLink, /^lookup_/, true); + } + + function dismissRelatedLookupPopup(win, chosenId) { + const name = removePopupIndex(win.name); + const elem = document.getElementById(name); + if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) { + elem.value += ',' + chosenId; + } else { + document.getElementById(name).value = chosenId; + } + const index = relatedWindows.indexOf(win); + if (index > -1) { + relatedWindows.splice(index, 1); + } + win.close(); + } + + function showRelatedObjectPopup(triggeringLink) { + return showAdminPopup(triggeringLink, /^(change|add|delete)_/, false); + } + + function updateRelatedObjectLinks(triggeringLink) { + const $this = $(triggeringLink); + const siblings = $this.nextAll('.view-related, .change-related, .delete-related'); + if (!siblings.length) { + return; + } + const value = $this.val(); + if (value) { + siblings.each(function() { + const elm = $(this); + elm.attr('href', elm.attr('data-href-template').replace('__fk__', value)); + }); + } else { + siblings.removeAttr('href'); + } + } + + function updateRelatedSelectsOptions(currentSelect, win, objId, newRepr, newId) { + // After create/edit a model from the options next to the current + // select (+ or :pencil:) update ForeignKey PK of the rest of selects + // in the page. + + const path = win.location.pathname; + // Extract the model from the popup url '...//add/' or + // '...///change/' depending the action (add or change). + const modelName = path.split('/')[path.split('/').length - (objId ? 4 : 3)]; + // Exclude autocomplete selects. + const selectsRelated = document.querySelectorAll(`[data-model-ref="${modelName}"] select:not(.admin-autocomplete)`); + + selectsRelated.forEach(function(select) { + if (currentSelect === select) { + return; + } + + let option = select.querySelector(`option[value="${objId}"]`); + + if (!option) { + option = new Option(newRepr, newId); + select.options.add(option); + return; + } + + option.textContent = newRepr; + option.value = newId; + }); + } + + function dismissAddRelatedObjectPopup(win, newId, newRepr) { + const name = removePopupIndex(win.name); + const elem = document.getElementById(name); + if (elem) { + const elemName = elem.nodeName.toUpperCase(); + if (elemName === 'SELECT') { + elem.options[elem.options.length] = new Option(newRepr, newId, true, true); + updateRelatedSelectsOptions(elem, win, null, newRepr, newId); + } else if (elemName === 'INPUT') { + if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) { + elem.value += ',' + newId; + } else { + elem.value = newId; + } + } + // Trigger a change event to update related links if required. + $(elem).trigger('change'); + } else { + const toId = name + "_to"; + const o = new Option(newRepr, newId); + SelectBox.add_to_cache(toId, o); + SelectBox.redisplay(toId); + } + const index = relatedWindows.indexOf(win); + if (index > -1) { + relatedWindows.splice(index, 1); + } + win.close(); + } + + function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) { + const id = removePopupIndex(win.name.replace(/^edit_/, '')); + const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); + const selects = $(selectsSelector); + selects.find('option').each(function() { + if (this.value === objId) { + this.textContent = newRepr; + this.value = newId; + } + }).trigger('change'); + updateRelatedSelectsOptions(selects[0], win, objId, newRepr, newId); + selects.next().find('.select2-selection__rendered').each(function() { + // The element can have a clear button as a child. + // Use the lastChild to modify only the displayed value. + this.lastChild.textContent = newRepr; + this.title = newRepr; + }); + const index = relatedWindows.indexOf(win); + if (index > -1) { + relatedWindows.splice(index, 1); + } + win.close(); + } + + function dismissDeleteRelatedObjectPopup(win, objId) { + const id = removePopupIndex(win.name.replace(/^delete_/, '')); + const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); + const selects = $(selectsSelector); + selects.find('option').each(function() { + if (this.value === objId) { + $(this).remove(); + } + }).trigger('change'); + const index = relatedWindows.indexOf(win); + if (index > -1) { + relatedWindows.splice(index, 1); + } + win.close(); + } + + window.showRelatedObjectLookupPopup = showRelatedObjectLookupPopup; + window.dismissRelatedLookupPopup = dismissRelatedLookupPopup; + window.showRelatedObjectPopup = showRelatedObjectPopup; + window.updateRelatedObjectLinks = updateRelatedObjectLinks; + window.dismissAddRelatedObjectPopup = dismissAddRelatedObjectPopup; + window.dismissChangeRelatedObjectPopup = dismissChangeRelatedObjectPopup; + window.dismissDeleteRelatedObjectPopup = dismissDeleteRelatedObjectPopup; + window.dismissChildPopups = dismissChildPopups; + + // Kept for backward compatibility + window.showAddAnotherPopup = showRelatedObjectPopup; + window.dismissAddAnotherPopup = dismissAddRelatedObjectPopup; + + window.addEventListener('unload', function(evt) { + window.dismissChildPopups(); + }); + + $(document).ready(function() { + setPopupIndex(); + $("a[data-popup-opener]").on('click', function(event) { + event.preventDefault(); + opener.dismissRelatedLookupPopup(window, $(this).data("popup-opener")); + }); + $('body').on('click', '.related-widget-wrapper-link[data-popup="yes"]', function(e) { + e.preventDefault(); + if (this.href) { + const event = $.Event('django:show-related', {href: this.href}); + $(this).trigger(event); + if (!event.isDefaultPrevented()) { + showRelatedObjectPopup(this); + } + } + }); + $('body').on('change', '.related-widget-wrapper select', function(e) { + const event = $.Event('django:update-related'); + $(this).trigger(event); + if (!event.isDefaultPrevented()) { + updateRelatedObjectLinks(this); + } + }); + $('.related-widget-wrapper select').trigger('change'); + $('body').on('click', '.related-lookup', function(e) { + e.preventDefault(); + const event = $.Event('django:lookup-related'); + $(this).trigger(event); + if (!event.isDefaultPrevented()) { + showRelatedObjectLookupPopup(this); + } + }); + }); +} diff --git a/static/admin/js/autocomplete.js b/static/admin/js/autocomplete.js new file mode 100644 index 0000000..d3daeab --- /dev/null +++ b/static/admin/js/autocomplete.js @@ -0,0 +1,33 @@ +'use strict'; +{ + const $ = django.jQuery; + + $.fn.djangoAdminSelect2 = function() { + $.each(this, function(i, element) { + $(element).select2({ + ajax: { + data: (params) => { + return { + term: params.term, + page: params.page, + app_label: element.dataset.appLabel, + model_name: element.dataset.modelName, + field_name: element.dataset.fieldName + }; + } + } + }); + }); + return this; + }; + + $(function() { + // Initialize all autocomplete widgets except the one in the template + // form used when a new formset is added. + $('.admin-autocomplete').not('[name*=__prefix__]').djangoAdminSelect2(); + }); + + document.addEventListener('formset:added', (event) => { + $(event.target).find('.admin-autocomplete').djangoAdminSelect2(); + }); +} diff --git a/static/admin/js/calendar.js b/static/admin/js/calendar.js new file mode 100644 index 0000000..a62d10a --- /dev/null +++ b/static/admin/js/calendar.js @@ -0,0 +1,221 @@ +/*global gettext, pgettext, get_format, quickElement, removeChildren*/ +/* +calendar.js - Calendar functions by Adrian Holovaty +depends on core.js for utility functions like removeChildren or quickElement +*/ +'use strict'; +{ + // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions + const CalendarNamespace = { + monthsOfYear: [ + gettext('January'), + gettext('February'), + gettext('March'), + gettext('April'), + gettext('May'), + gettext('June'), + gettext('July'), + gettext('August'), + gettext('September'), + gettext('October'), + gettext('November'), + gettext('December') + ], + monthsOfYearAbbrev: [ + pgettext('abbrev. month January', 'Jan'), + pgettext('abbrev. month February', 'Feb'), + pgettext('abbrev. month March', 'Mar'), + pgettext('abbrev. month April', 'Apr'), + pgettext('abbrev. month May', 'May'), + pgettext('abbrev. month June', 'Jun'), + pgettext('abbrev. month July', 'Jul'), + pgettext('abbrev. month August', 'Aug'), + pgettext('abbrev. month September', 'Sep'), + pgettext('abbrev. month October', 'Oct'), + pgettext('abbrev. month November', 'Nov'), + pgettext('abbrev. month December', 'Dec') + ], + daysOfWeek: [ + pgettext('one letter Sunday', 'S'), + pgettext('one letter Monday', 'M'), + pgettext('one letter Tuesday', 'T'), + pgettext('one letter Wednesday', 'W'), + pgettext('one letter Thursday', 'T'), + pgettext('one letter Friday', 'F'), + pgettext('one letter Saturday', 'S') + ], + firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')), + isLeapYear: function(year) { + return (((year % 4) === 0) && ((year % 100) !== 0 ) || ((year % 400) === 0)); + }, + getDaysInMonth: function(month, year) { + let days; + if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) { + days = 31; + } + else if (month === 4 || month === 6 || month === 9 || month === 11) { + days = 30; + } + else if (month === 2 && CalendarNamespace.isLeapYear(year)) { + days = 29; + } + else { + days = 28; + } + return days; + }, + draw: function(month, year, div_id, callback, selected) { // month = 1-12, year = 1-9999 + const today = new Date(); + const todayDay = today.getDate(); + const todayMonth = today.getMonth() + 1; + const todayYear = today.getFullYear(); + let todayClass = ''; + + // Use UTC functions here because the date field does not contain time + // and using the UTC function variants prevent the local time offset + // from altering the date, specifically the day field. For example: + // + // ``` + // var x = new Date('2013-10-02'); + // var day = x.getDate(); + // ``` + // + // The day variable above will be 1 instead of 2 in, say, US Pacific time + // zone. + let isSelectedMonth = false; + if (typeof selected !== 'undefined') { + isSelectedMonth = (selected.getUTCFullYear() === year && (selected.getUTCMonth() + 1) === month); + } + + month = parseInt(month); + year = parseInt(year); + const calDiv = document.getElementById(div_id); + removeChildren(calDiv); + const calTable = document.createElement('table'); + quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month - 1] + ' ' + year); + const tableBody = quickElement('tbody', calTable); + + // Draw days-of-week header + let tableRow = quickElement('tr', tableBody); + for (let i = 0; i < 7; i++) { + quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]); + } + + const startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay(); + const days = CalendarNamespace.getDaysInMonth(month, year); + + let nonDayCell; + + // Draw blanks before first of month + tableRow = quickElement('tr', tableBody); + for (let i = 0; i < startingPos; i++) { + nonDayCell = quickElement('td', tableRow, ' '); + nonDayCell.className = "nonday"; + } + + function calendarMonth(y, m) { + function onClick(e) { + e.preventDefault(); + callback(y, m, this.textContent); + } + return onClick; + } + + // Draw days of month + let currentDay = 1; + for (let i = startingPos; currentDay <= days; i++) { + if (i % 7 === 0 && currentDay !== 1) { + tableRow = quickElement('tr', tableBody); + } + if ((currentDay === todayDay) && (month === todayMonth) && (year === todayYear)) { + todayClass = 'today'; + } else { + todayClass = ''; + } + + // use UTC function; see above for explanation. + if (isSelectedMonth && currentDay === selected.getUTCDate()) { + if (todayClass !== '') { + todayClass += " "; + } + todayClass += "selected"; + } + + const cell = quickElement('td', tableRow, '', 'class', todayClass); + const link = quickElement('a', cell, currentDay, 'href', '#'); + link.addEventListener('click', calendarMonth(year, month)); + currentDay++; + } + + // Draw blanks after end of month (optional, but makes for valid code) + while (tableRow.childNodes.length < 7) { + nonDayCell = quickElement('td', tableRow, ' '); + nonDayCell.className = "nonday"; + } + + calDiv.appendChild(calTable); + } + }; + + // Calendar -- A calendar instance + function Calendar(div_id, callback, selected) { + // div_id (string) is the ID of the element in which the calendar will + // be displayed + // callback (string) is the name of a JavaScript function that will be + // called with the parameters (year, month, day) when a day in the + // calendar is clicked + this.div_id = div_id; + this.callback = callback; + this.today = new Date(); + this.currentMonth = this.today.getMonth() + 1; + this.currentYear = this.today.getFullYear(); + if (typeof selected !== 'undefined') { + this.selected = selected; + } + } + Calendar.prototype = { + drawCurrent: function() { + CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback, this.selected); + }, + drawDate: function(month, year, selected) { + this.currentMonth = month; + this.currentYear = year; + + if(selected) { + this.selected = selected; + } + + this.drawCurrent(); + }, + drawPreviousMonth: function() { + if (this.currentMonth === 1) { + this.currentMonth = 12; + this.currentYear--; + } + else { + this.currentMonth--; + } + this.drawCurrent(); + }, + drawNextMonth: function() { + if (this.currentMonth === 12) { + this.currentMonth = 1; + this.currentYear++; + } + else { + this.currentMonth++; + } + this.drawCurrent(); + }, + drawPreviousYear: function() { + this.currentYear--; + this.drawCurrent(); + }, + drawNextYear: function() { + this.currentYear++; + this.drawCurrent(); + } + }; + window.Calendar = Calendar; + window.CalendarNamespace = CalendarNamespace; +} diff --git a/static/admin/js/cancel.js b/static/admin/js/cancel.js new file mode 100644 index 0000000..3069c6f --- /dev/null +++ b/static/admin/js/cancel.js @@ -0,0 +1,29 @@ +'use strict'; +{ + // Call function fn when the DOM is loaded and ready. If it is already + // loaded, call the function now. + // http://youmightnotneedjquery.com/#ready + function ready(fn) { + if (document.readyState !== 'loading') { + fn(); + } else { + document.addEventListener('DOMContentLoaded', fn); + } + } + + ready(function() { + function handleClick(event) { + event.preventDefault(); + const params = new URLSearchParams(window.location.search); + if (params.has('_popup')) { + window.close(); // Close the popup. + } else { + window.history.back(); // Otherwise, go back. + } + } + + document.querySelectorAll('.cancel-link').forEach(function(el) { + el.addEventListener('click', handleClick); + }); + }); +} diff --git a/static/admin/js/change_form.js b/static/admin/js/change_form.js new file mode 100644 index 0000000..96a4c62 --- /dev/null +++ b/static/admin/js/change_form.js @@ -0,0 +1,16 @@ +'use strict'; +{ + const inputTags = ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA']; + const modelName = document.getElementById('django-admin-form-add-constants').dataset.modelName; + if (modelName) { + const form = document.getElementById(modelName + '_form'); + for (const element of form.elements) { + // HTMLElement.offsetParent returns null when the element is not + // rendered. + if (inputTags.includes(element.tagName) && !element.disabled && element.offsetParent) { + element.focus(); + break; + } + } + } +} diff --git a/static/admin/js/collapse.js b/static/admin/js/collapse.js new file mode 100644 index 0000000..c6c7b0f --- /dev/null +++ b/static/admin/js/collapse.js @@ -0,0 +1,43 @@ +/*global gettext*/ +'use strict'; +{ + window.addEventListener('load', function() { + // Add anchor tag for Show/Hide link + const fieldsets = document.querySelectorAll('fieldset.collapse'); + for (const [i, elem] of fieldsets.entries()) { + // Don't hide if fields in this fieldset have errors + if (elem.querySelectorAll('div.errors, ul.errorlist').length === 0) { + elem.classList.add('collapsed'); + const h2 = elem.querySelector('h2'); + const link = document.createElement('a'); + link.id = 'fieldsetcollapser' + i; + link.className = 'collapse-toggle'; + link.href = '#'; + link.textContent = gettext('Show'); + h2.appendChild(document.createTextNode(' (')); + h2.appendChild(link); + h2.appendChild(document.createTextNode(')')); + } + } + // Add toggle to hide/show anchor tag + const toggleFunc = function(ev) { + if (ev.target.matches('.collapse-toggle')) { + ev.preventDefault(); + ev.stopPropagation(); + const fieldset = ev.target.closest('fieldset'); + if (fieldset.classList.contains('collapsed')) { + // Show + ev.target.textContent = gettext('Hide'); + fieldset.classList.remove('collapsed'); + } else { + // Hide + ev.target.textContent = gettext('Show'); + fieldset.classList.add('collapsed'); + } + } + }; + document.querySelectorAll('fieldset.module').forEach(function(el) { + el.addEventListener('click', toggleFunc); + }); + }); +} diff --git a/static/admin/js/core.js b/static/admin/js/core.js new file mode 100644 index 0000000..0344a13 --- /dev/null +++ b/static/admin/js/core.js @@ -0,0 +1,170 @@ +// Core JavaScript helper functions +'use strict'; + +// quickElement(tagType, parentReference [, textInChildNode, attribute, attributeValue ...]); +function quickElement() { + const obj = document.createElement(arguments[0]); + if (arguments[2]) { + const textNode = document.createTextNode(arguments[2]); + obj.appendChild(textNode); + } + const len = arguments.length; + for (let i = 3; i < len; i += 2) { + obj.setAttribute(arguments[i], arguments[i + 1]); + } + arguments[1].appendChild(obj); + return obj; +} + +// "a" is reference to an object +function removeChildren(a) { + while (a.hasChildNodes()) { + a.removeChild(a.lastChild); + } +} + +// ---------------------------------------------------------------------------- +// Find-position functions by PPK +// See https://www.quirksmode.org/js/findpos.html +// ---------------------------------------------------------------------------- +function findPosX(obj) { + let curleft = 0; + if (obj.offsetParent) { + while (obj.offsetParent) { + curleft += obj.offsetLeft - obj.scrollLeft; + obj = obj.offsetParent; + } + } else if (obj.x) { + curleft += obj.x; + } + return curleft; +} + +function findPosY(obj) { + let curtop = 0; + if (obj.offsetParent) { + while (obj.offsetParent) { + curtop += obj.offsetTop - obj.scrollTop; + obj = obj.offsetParent; + } + } else if (obj.y) { + curtop += obj.y; + } + return curtop; +} + +//----------------------------------------------------------------------------- +// Date object extensions +// ---------------------------------------------------------------------------- +{ + Date.prototype.getTwelveHours = function() { + return this.getHours() % 12 || 12; + }; + + Date.prototype.getTwoDigitMonth = function() { + return (this.getMonth() < 9) ? '0' + (this.getMonth() + 1) : (this.getMonth() + 1); + }; + + Date.prototype.getTwoDigitDate = function() { + return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate(); + }; + + Date.prototype.getTwoDigitTwelveHour = function() { + return (this.getTwelveHours() < 10) ? '0' + this.getTwelveHours() : this.getTwelveHours(); + }; + + Date.prototype.getTwoDigitHour = function() { + return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours(); + }; + + Date.prototype.getTwoDigitMinute = function() { + return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes(); + }; + + Date.prototype.getTwoDigitSecond = function() { + return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds(); + }; + + Date.prototype.getAbbrevMonthName = function() { + return typeof window.CalendarNamespace === "undefined" + ? this.getTwoDigitMonth() + : window.CalendarNamespace.monthsOfYearAbbrev[this.getMonth()]; + }; + + Date.prototype.getFullMonthName = function() { + return typeof window.CalendarNamespace === "undefined" + ? this.getTwoDigitMonth() + : window.CalendarNamespace.monthsOfYear[this.getMonth()]; + }; + + Date.prototype.strftime = function(format) { + const fields = { + b: this.getAbbrevMonthName(), + B: this.getFullMonthName(), + c: this.toString(), + d: this.getTwoDigitDate(), + H: this.getTwoDigitHour(), + I: this.getTwoDigitTwelveHour(), + m: this.getTwoDigitMonth(), + M: this.getTwoDigitMinute(), + p: (this.getHours() >= 12) ? 'PM' : 'AM', + S: this.getTwoDigitSecond(), + w: '0' + this.getDay(), + x: this.toLocaleDateString(), + X: this.toLocaleTimeString(), + y: ('' + this.getFullYear()).substr(2, 4), + Y: '' + this.getFullYear(), + '%': '%' + }; + let result = '', i = 0; + while (i < format.length) { + if (format.charAt(i) === '%') { + result += fields[format.charAt(i + 1)]; + ++i; + } + else { + result += format.charAt(i); + } + ++i; + } + return result; + }; + + // ---------------------------------------------------------------------------- + // String object extensions + // ---------------------------------------------------------------------------- + String.prototype.strptime = function(format) { + const split_format = format.split(/[.\-/]/); + const date = this.split(/[.\-/]/); + let i = 0; + let day, month, year; + while (i < split_format.length) { + switch (split_format[i]) { + case "%d": + day = date[i]; + break; + case "%m": + month = date[i] - 1; + break; + case "%Y": + year = date[i]; + break; + case "%y": + // A %y value in the range of [00, 68] is in the current + // century, while [69, 99] is in the previous century, + // according to the Open Group Specification. + if (parseInt(date[i], 10) >= 69) { + year = date[i]; + } else { + year = (new Date(Date.UTC(date[i], 0))).getUTCFullYear() + 100; + } + break; + } + ++i; + } + // Create Date object from UTC since the parsed value is supposed to be + // in UTC, not local time. Also, the calendar uses UTC functions for + // date extraction. + return new Date(Date.UTC(year, month, day)); + }; +} diff --git a/static/admin/js/filters.js b/static/admin/js/filters.js new file mode 100644 index 0000000..f5536eb --- /dev/null +++ b/static/admin/js/filters.js @@ -0,0 +1,30 @@ +/** + * Persist changelist filters state (collapsed/expanded). + */ +'use strict'; +{ + // Init filters. + let filters = JSON.parse(sessionStorage.getItem('django.admin.filtersState')); + + if (!filters) { + filters = {}; + } + + Object.entries(filters).forEach(([key, value]) => { + const detailElement = document.querySelector(`[data-filter-title='${CSS.escape(key)}']`); + + // Check if the filter is present, it could be from other view. + if (detailElement) { + value ? detailElement.setAttribute('open', '') : detailElement.removeAttribute('open'); + } + }); + + // Save filter state when clicks. + const details = document.querySelectorAll('details'); + details.forEach(detail => { + detail.addEventListener('toggle', event => { + filters[`${event.target.dataset.filterTitle}`] = detail.open; + sessionStorage.setItem('django.admin.filtersState', JSON.stringify(filters)); + }); + }); +} diff --git a/static/admin/js/inlines.js b/static/admin/js/inlines.js new file mode 100644 index 0000000..e9a1dfe --- /dev/null +++ b/static/admin/js/inlines.js @@ -0,0 +1,359 @@ +/*global DateTimeShortcuts, SelectFilter*/ +/** + * Django admin inlines + * + * Based on jQuery Formset 1.1 + * @author Stanislaus Madueke (stan DOT madueke AT gmail DOT com) + * @requires jQuery 1.2.6 or later + * + * Copyright (c) 2009, Stanislaus Madueke + * All rights reserved. + * + * Spiced up with Code from Zain Memon's GSoC project 2009 + * and modified for Django by Jannis Leidel, Travis Swicegood and Julien Phalip. + * + * Licensed under the New BSD License + * See: https://opensource.org/licenses/bsd-license.php + */ +'use strict'; +{ + const $ = django.jQuery; + $.fn.formset = function(opts) { + const options = $.extend({}, $.fn.formset.defaults, opts); + const $this = $(this); + const $parent = $this.parent(); + const updateElementIndex = function(el, prefix, ndx) { + const id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))"); + const replacement = prefix + "-" + ndx; + if ($(el).prop("for")) { + $(el).prop("for", $(el).prop("for").replace(id_regex, replacement)); + } + if (el.id) { + el.id = el.id.replace(id_regex, replacement); + } + if (el.name) { + el.name = el.name.replace(id_regex, replacement); + } + }; + const totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off"); + let nextIndex = parseInt(totalForms.val(), 10); + const maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off"); + const minForms = $("#id_" + options.prefix + "-MIN_NUM_FORMS").prop("autocomplete", "off"); + let addButton; + + /** + * The "Add another MyModel" button below the inline forms. + */ + const addInlineAddButton = function() { + if (addButton === null) { + if ($this.prop("tagName") === "TR") { + // If forms are laid out as table rows, insert the + // "add" button in a new table row: + const numCols = $this.eq(-1).children().length; + $parent.append('' + options.addText + ""); + addButton = $parent.find("tr:last a"); + } else { + // Otherwise, insert it immediately after the last form: + $this.filter(":last").after('"); + addButton = $this.filter(":last").next().find("a"); + } + } + addButton.on('click', addInlineClickHandler); + }; + + const addInlineClickHandler = function(e) { + e.preventDefault(); + const template = $("#" + options.prefix + "-empty"); + const row = template.clone(true); + row.removeClass(options.emptyCssClass) + .addClass(options.formCssClass) + .attr("id", options.prefix + "-" + nextIndex); + addInlineDeleteButton(row); + row.find("*").each(function() { + updateElementIndex(this, options.prefix, totalForms.val()); + }); + // Insert the new form when it has been fully edited. + row.insertBefore($(template)); + // Update number of total forms. + $(totalForms).val(parseInt(totalForms.val(), 10) + 1); + nextIndex += 1; + // Hide the add button if there's a limit and it's been reached. + if ((maxForms.val() !== '') && (maxForms.val() - totalForms.val()) <= 0) { + addButton.parent().hide(); + } + // Show the remove buttons if there are more than min_num. + toggleDeleteButtonVisibility(row.closest('.inline-group')); + + // Pass the new form to the post-add callback, if provided. + if (options.added) { + options.added(row); + } + row.get(0).dispatchEvent(new CustomEvent("formset:added", { + bubbles: true, + detail: { + formsetName: options.prefix + } + })); + }; + + /** + * The "X" button that is part of every unsaved inline. + * (When saved, it is replaced with a "Delete" checkbox.) + */ + const addInlineDeleteButton = function(row) { + if (row.is("tr")) { + // If the forms are laid out in table rows, insert + // the remove button into the last table cell: + row.children(":last").append('"); + } else if (row.is("ul") || row.is("ol")) { + // If they're laid out as an ordered/unordered list, + // insert an
  • after the last list item: + row.append('
  • ' + options.deleteText + "
  • "); + } else { + // Otherwise, just insert the remove button as the + // last child element of the form's container: + row.children(":first").append('' + options.deleteText + ""); + } + // Add delete handler for each row. + row.find("a." + options.deleteCssClass).on('click', inlineDeleteHandler.bind(this)); + }; + + const inlineDeleteHandler = function(e1) { + e1.preventDefault(); + const deleteButton = $(e1.target); + const row = deleteButton.closest('.' + options.formCssClass); + const inlineGroup = row.closest('.inline-group'); + // Remove the parent form containing this button, + // and also remove the relevant row with non-field errors: + const prevRow = row.prev(); + if (prevRow.length && prevRow.hasClass('row-form-errors')) { + prevRow.remove(); + } + row.remove(); + nextIndex -= 1; + // Pass the deleted form to the post-delete callback, if provided. + if (options.removed) { + options.removed(row); + } + document.dispatchEvent(new CustomEvent("formset:removed", { + detail: { + formsetName: options.prefix + } + })); + // Update the TOTAL_FORMS form count. + const forms = $("." + options.formCssClass); + $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length); + // Show add button again once below maximum number. + if ((maxForms.val() === '') || (maxForms.val() - forms.length) > 0) { + addButton.parent().show(); + } + // Hide the remove buttons if at min_num. + toggleDeleteButtonVisibility(inlineGroup); + // Also, update names and ids for all remaining form controls so + // they remain in sequence: + let i, formCount; + const updateElementCallback = function() { + updateElementIndex(this, options.prefix, i); + }; + for (i = 0, formCount = forms.length; i < formCount; i++) { + updateElementIndex($(forms).get(i), options.prefix, i); + $(forms.get(i)).find("*").each(updateElementCallback); + } + }; + + const toggleDeleteButtonVisibility = function(inlineGroup) { + if ((minForms.val() !== '') && (minForms.val() - totalForms.val()) >= 0) { + inlineGroup.find('.inline-deletelink').hide(); + } else { + inlineGroup.find('.inline-deletelink').show(); + } + }; + + $this.each(function(i) { + $(this).not("." + options.emptyCssClass).addClass(options.formCssClass); + }); + + // Create the delete buttons for all unsaved inlines: + $this.filter('.' + options.formCssClass + ':not(.has_original):not(.' + options.emptyCssClass + ')').each(function() { + addInlineDeleteButton($(this)); + }); + toggleDeleteButtonVisibility($this); + + // Create the add button, initially hidden. + addButton = options.addButton; + addInlineAddButton(); + + // Show the add button if allowed to add more items. + // Note that max_num = None translates to a blank string. + const showAddButton = maxForms.val() === '' || (maxForms.val() - totalForms.val()) > 0; + if ($this.length && showAddButton) { + addButton.parent().show(); + } else { + addButton.parent().hide(); + } + + return this; + }; + + /* Setup plugin defaults */ + $.fn.formset.defaults = { + prefix: "form", // The form prefix for your django formset + addText: "add another", // Text for the add link + deleteText: "remove", // Text for the delete link + addCssClass: "add-row", // CSS class applied to the add link + deleteCssClass: "delete-row", // CSS class applied to the delete link + emptyCssClass: "empty-row", // CSS class applied to the empty row + formCssClass: "dynamic-form", // CSS class applied to each form in a formset + added: null, // Function called each time a new form is added + removed: null, // Function called each time a form is deleted + addButton: null // Existing add button to use + }; + + + // Tabular inlines --------------------------------------------------------- + $.fn.tabularFormset = function(selector, options) { + const $rows = $(this); + + const reinitDateTimeShortCuts = function() { + // Reinitialize the calendar and clock widgets by force + if (typeof DateTimeShortcuts !== "undefined") { + $(".datetimeshortcuts").remove(); + DateTimeShortcuts.init(); + } + }; + + const updateSelectFilter = function() { + // If any SelectFilter widgets are a part of the new form, + // instantiate a new SelectFilter instance for it. + if (typeof SelectFilter !== 'undefined') { + $('.selectfilter').each(function(index, value) { + SelectFilter.init(value.id, this.dataset.fieldName, false); + }); + $('.selectfilterstacked').each(function(index, value) { + SelectFilter.init(value.id, this.dataset.fieldName, true); + }); + } + }; + + const initPrepopulatedFields = function(row) { + row.find('.prepopulated_field').each(function() { + const field = $(this), + input = field.find('input, select, textarea'), + dependency_list = input.data('dependency_list') || [], + dependencies = []; + $.each(dependency_list, function(i, field_name) { + dependencies.push('#' + row.find('.field-' + field_name).find('input, select, textarea').attr('id')); + }); + if (dependencies.length) { + input.prepopulate(dependencies, input.attr('maxlength')); + } + }); + }; + + $rows.formset({ + prefix: options.prefix, + addText: options.addText, + formCssClass: "dynamic-" + options.prefix, + deleteCssClass: "inline-deletelink", + deleteText: options.deleteText, + emptyCssClass: "empty-form", + added: function(row) { + initPrepopulatedFields(row); + reinitDateTimeShortCuts(); + updateSelectFilter(); + }, + addButton: options.addButton + }); + + return $rows; + }; + + // Stacked inlines --------------------------------------------------------- + $.fn.stackedFormset = function(selector, options) { + const $rows = $(this); + const updateInlineLabel = function(row) { + $(selector).find(".inline_label").each(function(i) { + const count = i + 1; + $(this).html($(this).html().replace(/(#\d+)/g, "#" + count)); + }); + }; + + const reinitDateTimeShortCuts = function() { + // Reinitialize the calendar and clock widgets by force, yuck. + if (typeof DateTimeShortcuts !== "undefined") { + $(".datetimeshortcuts").remove(); + DateTimeShortcuts.init(); + } + }; + + const updateSelectFilter = function() { + // If any SelectFilter widgets were added, instantiate a new instance. + if (typeof SelectFilter !== "undefined") { + $(".selectfilter").each(function(index, value) { + SelectFilter.init(value.id, this.dataset.fieldName, false); + }); + $(".selectfilterstacked").each(function(index, value) { + SelectFilter.init(value.id, this.dataset.fieldName, true); + }); + } + }; + + const initPrepopulatedFields = function(row) { + row.find('.prepopulated_field').each(function() { + const field = $(this), + input = field.find('input, select, textarea'), + dependency_list = input.data('dependency_list') || [], + dependencies = []; + $.each(dependency_list, function(i, field_name) { + // Dependency in a fieldset. + let field_element = row.find('.form-row .field-' + field_name); + // Dependency without a fieldset. + if (!field_element.length) { + field_element = row.find('.form-row.field-' + field_name); + } + dependencies.push('#' + field_element.find('input, select, textarea').attr('id')); + }); + if (dependencies.length) { + input.prepopulate(dependencies, input.attr('maxlength')); + } + }); + }; + + $rows.formset({ + prefix: options.prefix, + addText: options.addText, + formCssClass: "dynamic-" + options.prefix, + deleteCssClass: "inline-deletelink", + deleteText: options.deleteText, + emptyCssClass: "empty-form", + removed: updateInlineLabel, + added: function(row) { + initPrepopulatedFields(row); + reinitDateTimeShortCuts(); + updateSelectFilter(); + updateInlineLabel(row); + }, + addButton: options.addButton + }); + + return $rows; + }; + + $(document).ready(function() { + $(".js-inline-admin-formset").each(function() { + const data = $(this).data(), + inlineOptions = data.inlineFormset; + let selector; + switch(data.inlineType) { + case "stacked": + selector = inlineOptions.name + "-group .inline-related"; + $(selector).stackedFormset(selector, inlineOptions.options); + break; + case "tabular": + selector = inlineOptions.name + "-group .tabular.inline-related tbody:first > tr.form-row"; + $(selector).tabularFormset(selector, inlineOptions.options); + break; + } + }); + }); +} diff --git a/static/admin/js/jquery.init.js b/static/admin/js/jquery.init.js new file mode 100644 index 0000000..f40b27f --- /dev/null +++ b/static/admin/js/jquery.init.js @@ -0,0 +1,8 @@ +/*global jQuery:false*/ +'use strict'; +/* Puts the included jQuery into our own namespace using noConflict and passing + * it 'true'. This ensures that the included jQuery doesn't pollute the global + * namespace (i.e. this preserves pre-existing values for both window.$ and + * window.jQuery). + */ +window.django = {jQuery: jQuery.noConflict(true)}; diff --git a/static/admin/js/nav_sidebar.js b/static/admin/js/nav_sidebar.js new file mode 100644 index 0000000..7e735db --- /dev/null +++ b/static/admin/js/nav_sidebar.js @@ -0,0 +1,79 @@ +'use strict'; +{ + const toggleNavSidebar = document.getElementById('toggle-nav-sidebar'); + if (toggleNavSidebar !== null) { + const navSidebar = document.getElementById('nav-sidebar'); + const main = document.getElementById('main'); + let navSidebarIsOpen = localStorage.getItem('django.admin.navSidebarIsOpen'); + if (navSidebarIsOpen === null) { + navSidebarIsOpen = 'true'; + } + main.classList.toggle('shifted', navSidebarIsOpen === 'true'); + navSidebar.setAttribute('aria-expanded', navSidebarIsOpen); + + toggleNavSidebar.addEventListener('click', function() { + if (navSidebarIsOpen === 'true') { + navSidebarIsOpen = 'false'; + } else { + navSidebarIsOpen = 'true'; + } + localStorage.setItem('django.admin.navSidebarIsOpen', navSidebarIsOpen); + main.classList.toggle('shifted'); + navSidebar.setAttribute('aria-expanded', navSidebarIsOpen); + }); + } + + function initSidebarQuickFilter() { + const options = []; + const navSidebar = document.getElementById('nav-sidebar'); + if (!navSidebar) { + return; + } + navSidebar.querySelectorAll('th[scope=row] a').forEach((container) => { + options.push({title: container.innerHTML, node: container}); + }); + + function checkValue(event) { + let filterValue = event.target.value; + if (filterValue) { + filterValue = filterValue.toLowerCase(); + } + if (event.key === 'Escape') { + filterValue = ''; + event.target.value = ''; // clear input + } + let matches = false; + for (const o of options) { + let displayValue = ''; + if (filterValue) { + if (o.title.toLowerCase().indexOf(filterValue) === -1) { + displayValue = 'none'; + } else { + matches = true; + } + } + // show/hide parent + o.node.parentNode.parentNode.style.display = displayValue; + } + if (!filterValue || matches) { + event.target.classList.remove('no-results'); + } else { + event.target.classList.add('no-results'); + } + sessionStorage.setItem('django.admin.navSidebarFilterValue', filterValue); + } + + const nav = document.getElementById('nav-filter'); + nav.addEventListener('change', checkValue, false); + nav.addEventListener('input', checkValue, false); + nav.addEventListener('keyup', checkValue, false); + + const storedValue = sessionStorage.getItem('django.admin.navSidebarFilterValue'); + if (storedValue) { + nav.value = storedValue; + checkValue({target: nav, key: ''}); + } + } + window.initSidebarQuickFilter = initSidebarQuickFilter; + initSidebarQuickFilter(); +} diff --git a/static/admin/js/popup_response.js b/static/admin/js/popup_response.js new file mode 100644 index 0000000..2b1d3dd --- /dev/null +++ b/static/admin/js/popup_response.js @@ -0,0 +1,16 @@ +/*global opener */ +'use strict'; +{ + const initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse); + switch(initData.action) { + case 'change': + opener.dismissChangeRelatedObjectPopup(window, initData.value, initData.obj, initData.new_value); + break; + case 'delete': + opener.dismissDeleteRelatedObjectPopup(window, initData.value); + break; + default: + opener.dismissAddRelatedObjectPopup(window, initData.value, initData.obj); + break; + } +} diff --git a/static/admin/js/prepopulate.js b/static/admin/js/prepopulate.js new file mode 100644 index 0000000..89e95ab --- /dev/null +++ b/static/admin/js/prepopulate.js @@ -0,0 +1,43 @@ +/*global URLify*/ +'use strict'; +{ + const $ = django.jQuery; + $.fn.prepopulate = function(dependencies, maxLength, allowUnicode) { + /* + Depends on urlify.js + Populates a selected field with the values of the dependent fields, + URLifies and shortens the string. + dependencies - array of dependent fields ids + maxLength - maximum length of the URLify'd string + allowUnicode - Unicode support of the URLify'd string + */ + return this.each(function() { + const prepopulatedField = $(this); + + const populate = function() { + // Bail if the field's value has been changed by the user + if (prepopulatedField.data('_changed')) { + return; + } + + const values = []; + $.each(dependencies, function(i, field) { + field = $(field); + if (field.val().length > 0) { + values.push(field.val()); + } + }); + prepopulatedField.val(URLify(values.join(' '), maxLength, allowUnicode)); + }; + + prepopulatedField.data('_changed', false); + prepopulatedField.on('change', function() { + prepopulatedField.data('_changed', true); + }); + + if (!prepopulatedField.val()) { + $(dependencies.join(',')).on('keyup change focus', populate); + } + }); + }; +} diff --git a/static/admin/js/prepopulate_init.js b/static/admin/js/prepopulate_init.js new file mode 100644 index 0000000..a58841f --- /dev/null +++ b/static/admin/js/prepopulate_init.js @@ -0,0 +1,15 @@ +'use strict'; +{ + const $ = django.jQuery; + const fields = $('#django-admin-prepopulated-fields-constants').data('prepopulatedFields'); + $.each(fields, function(index, field) { + $( + '.empty-form .form-row .field-' + field.name + + ', .empty-form.form-row .field-' + field.name + + ', .empty-form .form-row.field-' + field.name + ).addClass('prepopulated_field'); + $(field.id).data('dependency_list', field.dependency_list).prepopulate( + field.dependency_ids, field.maxLength, field.allowUnicode + ); + }); +} diff --git a/static/admin/js/theme.js b/static/admin/js/theme.js new file mode 100644 index 0000000..794cd15 --- /dev/null +++ b/static/admin/js/theme.js @@ -0,0 +1,56 @@ +'use strict'; +{ + window.addEventListener('load', function(e) { + + function setTheme(mode) { + if (mode !== "light" && mode !== "dark" && mode !== "auto") { + console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`); + mode = "auto"; + } + document.documentElement.dataset.theme = mode; + localStorage.setItem("theme", mode); + } + + function cycleTheme() { + const currentTheme = localStorage.getItem("theme") || "auto"; + const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; + + if (prefersDark) { + // Auto (dark) -> Light -> Dark + if (currentTheme === "auto") { + setTheme("light"); + } else if (currentTheme === "light") { + setTheme("dark"); + } else { + setTheme("auto"); + } + } else { + // Auto (light) -> Dark -> Light + if (currentTheme === "auto") { + setTheme("dark"); + } else if (currentTheme === "dark") { + setTheme("light"); + } else { + setTheme("auto"); + } + } + } + + function initTheme() { + // set theme defined in localStorage if there is one, or fallback to auto mode + const currentTheme = localStorage.getItem("theme"); + currentTheme ? setTheme(currentTheme) : setTheme("auto"); + } + + function setupTheme() { + // Attach event handlers for toggling themes + const buttons = document.getElementsByClassName("theme-toggle"); + Array.from(buttons).forEach((btn) => { + btn.addEventListener("click", cycleTheme); + }); + initTheme(); + } + + setupTheme(); + }); +} diff --git a/static/admin/js/urlify.js b/static/admin/js/urlify.js new file mode 100644 index 0000000..9fc0409 --- /dev/null +++ b/static/admin/js/urlify.js @@ -0,0 +1,169 @@ +/*global XRegExp*/ +'use strict'; +{ + const LATIN_MAP = { + 'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', + 'Ç': 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', + 'Î': 'I', 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', + 'Õ': 'O', 'Ö': 'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', + 'Ü': 'U', 'Ű': 'U', 'Ý': 'Y', 'Þ': 'TH', 'Ÿ': 'Y', 'ß': 'ss', 'à': 'a', + 'á': 'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', + 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e', 'ì': 'i', 'í': 'i', 'î': 'i', + 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o', + 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u', + 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y' + }; + const LATIN_SYMBOLS_MAP = { + '©': '(c)' + }; + const GREEK_MAP = { + 'α': 'a', 'β': 'b', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'h', + 'θ': '8', 'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': '3', + 'ο': 'o', 'π': 'p', 'ρ': 'r', 'σ': 's', 'τ': 't', 'υ': 'y', 'φ': 'f', + 'χ': 'x', 'ψ': 'ps', 'ω': 'w', 'ά': 'a', 'έ': 'e', 'ί': 'i', 'ό': 'o', + 'ύ': 'y', 'ή': 'h', 'ώ': 'w', 'ς': 's', 'ϊ': 'i', 'ΰ': 'y', 'ϋ': 'y', + 'ΐ': 'i', 'Α': 'A', 'Β': 'B', 'Γ': 'G', 'Δ': 'D', 'Ε': 'E', 'Ζ': 'Z', + 'Η': 'H', 'Θ': '8', 'Ι': 'I', 'Κ': 'K', 'Λ': 'L', 'Μ': 'M', 'Ν': 'N', + 'Ξ': '3', 'Ο': 'O', 'Π': 'P', 'Ρ': 'R', 'Σ': 'S', 'Τ': 'T', 'Υ': 'Y', + 'Φ': 'F', 'Χ': 'X', 'Ψ': 'PS', 'Ω': 'W', 'Ά': 'A', 'Έ': 'E', 'Ί': 'I', + 'Ό': 'O', 'Ύ': 'Y', 'Ή': 'H', 'Ώ': 'W', 'Ϊ': 'I', 'Ϋ': 'Y' + }; + const TURKISH_MAP = { + 'ş': 's', 'Ş': 'S', 'ı': 'i', 'İ': 'I', 'ç': 'c', 'Ç': 'C', 'ü': 'u', + 'Ü': 'U', 'ö': 'o', 'Ö': 'O', 'ğ': 'g', 'Ğ': 'G' + }; + const ROMANIAN_MAP = { + 'ă': 'a', 'î': 'i', 'ș': 's', 'ț': 't', 'â': 'a', + 'Ă': 'A', 'Î': 'I', 'Ș': 'S', 'Ț': 'T', 'Â': 'A' + }; + const RUSSIAN_MAP = { + 'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo', + 'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm', + 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u', + 'ф': 'f', 'х': 'h', 'ц': 'c', 'ч': 'ch', 'ш': 'sh', 'щ': 'sh', 'ъ': '', + 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu', 'я': 'ya', + 'А': 'A', 'Б': 'B', 'В': 'V', 'Г': 'G', 'Д': 'D', 'Е': 'E', 'Ё': 'Yo', + 'Ж': 'Zh', 'З': 'Z', 'И': 'I', 'Й': 'J', 'К': 'K', 'Л': 'L', 'М': 'M', + 'Н': 'N', 'О': 'O', 'П': 'P', 'Р': 'R', 'С': 'S', 'Т': 'T', 'У': 'U', + 'Ф': 'F', 'Х': 'H', 'Ц': 'C', 'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Sh', 'Ъ': '', + 'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu', 'Я': 'Ya' + }; + const UKRAINIAN_MAP = { + 'Є': 'Ye', 'І': 'I', 'Ї': 'Yi', 'Ґ': 'G', 'є': 'ye', 'і': 'i', + 'ї': 'yi', 'ґ': 'g' + }; + const CZECH_MAP = { + 'č': 'c', 'ď': 'd', 'ě': 'e', 'ň': 'n', 'ř': 'r', 'š': 's', 'ť': 't', + 'ů': 'u', 'ž': 'z', 'Č': 'C', 'Ď': 'D', 'Ě': 'E', 'Ň': 'N', 'Ř': 'R', + 'Š': 'S', 'Ť': 'T', 'Ů': 'U', 'Ž': 'Z' + }; + const SLOVAK_MAP = { + 'á': 'a', 'ä': 'a', 'č': 'c', 'ď': 'd', 'é': 'e', 'í': 'i', 'ľ': 'l', + 'ĺ': 'l', 'ň': 'n', 'ó': 'o', 'ô': 'o', 'ŕ': 'r', 'š': 's', 'ť': 't', + 'ú': 'u', 'ý': 'y', 'ž': 'z', + 'Á': 'a', 'Ä': 'A', 'Č': 'C', 'Ď': 'D', 'É': 'E', 'Í': 'I', 'Ľ': 'L', + 'Ĺ': 'L', 'Ň': 'N', 'Ó': 'O', 'Ô': 'O', 'Ŕ': 'R', 'Š': 'S', 'Ť': 'T', + 'Ú': 'U', 'Ý': 'Y', 'Ž': 'Z' + }; + const POLISH_MAP = { + 'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's', + 'ź': 'z', 'ż': 'z', + 'Ą': 'A', 'Ć': 'C', 'Ę': 'E', 'Ł': 'L', 'Ń': 'N', 'Ó': 'O', 'Ś': 'S', + 'Ź': 'Z', 'Ż': 'Z' + }; + const LATVIAN_MAP = { + 'ā': 'a', 'č': 'c', 'ē': 'e', 'ģ': 'g', 'ī': 'i', 'ķ': 'k', 'ļ': 'l', + 'ņ': 'n', 'š': 's', 'ū': 'u', 'ž': 'z', + 'Ā': 'A', 'Č': 'C', 'Ē': 'E', 'Ģ': 'G', 'Ī': 'I', 'Ķ': 'K', 'Ļ': 'L', + 'Ņ': 'N', 'Š': 'S', 'Ū': 'U', 'Ž': 'Z' + }; + const ARABIC_MAP = { + 'أ': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'g', 'ح': 'h', 'خ': 'kh', 'د': 'd', + 'ذ': 'th', 'ر': 'r', 'ز': 'z', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': 't', + 'ظ': 'th', 'ع': 'aa', 'غ': 'gh', 'ف': 'f', 'ق': 'k', 'ك': 'k', 'ل': 'l', 'م': 'm', + 'ن': 'n', 'ه': 'h', 'و': 'o', 'ي': 'y' + }; + const LITHUANIAN_MAP = { + 'ą': 'a', 'č': 'c', 'ę': 'e', 'ė': 'e', 'į': 'i', 'š': 's', 'ų': 'u', + 'ū': 'u', 'ž': 'z', + 'Ą': 'A', 'Č': 'C', 'Ę': 'E', 'Ė': 'E', 'Į': 'I', 'Š': 'S', 'Ų': 'U', + 'Ū': 'U', 'Ž': 'Z' + }; + const SERBIAN_MAP = { + 'ђ': 'dj', 'ј': 'j', 'љ': 'lj', 'њ': 'nj', 'ћ': 'c', 'џ': 'dz', + 'đ': 'dj', 'Ђ': 'Dj', 'Ј': 'j', 'Љ': 'Lj', 'Њ': 'Nj', 'Ћ': 'C', + 'Џ': 'Dz', 'Đ': 'Dj' + }; + const AZERBAIJANI_MAP = { + 'ç': 'c', 'ə': 'e', 'ğ': 'g', 'ı': 'i', 'ö': 'o', 'ş': 's', 'ü': 'u', + 'Ç': 'C', 'Ə': 'E', 'Ğ': 'G', 'İ': 'I', 'Ö': 'O', 'Ş': 'S', 'Ü': 'U' + }; + const GEORGIAN_MAP = { + 'ა': 'a', 'ბ': 'b', 'გ': 'g', 'დ': 'd', 'ე': 'e', 'ვ': 'v', 'ზ': 'z', + 'თ': 't', 'ი': 'i', 'კ': 'k', 'ლ': 'l', 'მ': 'm', 'ნ': 'n', 'ო': 'o', + 'პ': 'p', 'ჟ': 'j', 'რ': 'r', 'ს': 's', 'ტ': 't', 'უ': 'u', 'ფ': 'f', + 'ქ': 'q', 'ღ': 'g', 'ყ': 'y', 'შ': 'sh', 'ჩ': 'ch', 'ც': 'c', 'ძ': 'dz', + 'წ': 'w', 'ჭ': 'ch', 'ხ': 'x', 'ჯ': 'j', 'ჰ': 'h' + }; + + const ALL_DOWNCODE_MAPS = [ + LATIN_MAP, + LATIN_SYMBOLS_MAP, + GREEK_MAP, + TURKISH_MAP, + ROMANIAN_MAP, + RUSSIAN_MAP, + UKRAINIAN_MAP, + CZECH_MAP, + SLOVAK_MAP, + POLISH_MAP, + LATVIAN_MAP, + ARABIC_MAP, + LITHUANIAN_MAP, + SERBIAN_MAP, + AZERBAIJANI_MAP, + GEORGIAN_MAP + ]; + + const Downcoder = { + 'Initialize': function() { + if (Downcoder.map) { // already made + return; + } + Downcoder.map = {}; + for (const lookup of ALL_DOWNCODE_MAPS) { + Object.assign(Downcoder.map, lookup); + } + Downcoder.regex = new RegExp(Object.keys(Downcoder.map).join('|'), 'g'); + } + }; + + function downcode(slug) { + Downcoder.Initialize(); + return slug.replace(Downcoder.regex, function(m) { + return Downcoder.map[m]; + }); + } + + + function URLify(s, num_chars, allowUnicode) { + // changes, e.g., "Petty theft" to "petty-theft" + if (!allowUnicode) { + s = downcode(s); + } + s = s.toLowerCase(); // convert to lowercase + // if downcode doesn't hit, the char will be stripped here + if (allowUnicode) { + // Keep Unicode letters including both lowercase and uppercase + // characters, whitespace, and dash; remove other characters. + s = XRegExp.replace(s, XRegExp('[^-_\\p{L}\\p{N}\\s]', 'g'), ''); + } else { + s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars + } + s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces + s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens + s = s.substring(0, num_chars); // trim to first num_chars chars + return s.replace(/-+$/g, ''); // trim any trailing hyphens + } + window.URLify = URLify; +} diff --git a/static/admin/js/vendor/jquery/LICENSE.txt b/static/admin/js/vendor/jquery/LICENSE.txt new file mode 100644 index 0000000..f642c3f --- /dev/null +++ b/static/admin/js/vendor/jquery/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright OpenJS Foundation and other contributors, https://openjsf.org/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/static/admin/js/vendor/jquery/jquery.js b/static/admin/js/vendor/jquery/jquery.js new file mode 100644 index 0000000..7f35c11 --- /dev/null +++ b/static/admin/js/vendor/jquery/jquery.js @@ -0,0 +1,10965 @@ +/*! + * jQuery JavaScript Library v3.6.4 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2023-03-08T15:28Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket trac-14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.4", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.10 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2023-02-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rleadingCombinator = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rleadingCombinator.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + // Support: Chrome 105 - 110+, Safari 15.4 - 16.3+ + // Make sure the the `:has()` argument is parsed unforgivingly. + // We include `*` in the test to detect buggy implementations that are + // _selectively_ forgiving (specifically when the list includes at least + // one valid selector). + // Note that we treat complete lack of support for `:has()` as if it were + // spec-compliant support, which is fine because use of `:has()` in such + // environments will fail in the qSA path and fall back to jQuery traversal + // anyway. + support.cssHas = assert( function() { + try { + document.querySelector( ":has(*,:jqfake)" ); + return false; + } catch ( e ) { + return true; + } + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + if ( !support.cssHas ) { + + // Support: Chrome 105 - 110+, Safari 15.4 - 16.3+ + // Our regular `try-catch` mechanism fails to detect natively-unsupported + // pseudo-classes inside `:has()` (such as `:has(:contains("Foo"))`) + // in browsers that parse the `:has()` argument as a forgiving selector list. + // https://drafts.csswg.org/selectors/#relational now requires the argument + // to be parsed unforgivingly, but browsers have not yet fully adjusted. + rbuggyQSA.push( ":has" ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + + // Support: IE <9 only + // IE doesn't have `contains` on `document` so we need to check for + // `documentElement` presence. + // We need to fall back to `a` when `documentElement` is missing + // as `ownerDocument` of elements within `