From d8f7b928e052fbd72eb7de9c2a407394b423f357 Mon Sep 17 00:00:00 2001 From: robbertuittenbroek Date: Wed, 8 May 2024 16:05:24 +0200 Subject: [PATCH] Add setup for tasks card --- .env | 2 +- .env.test | 2 + .gitignore | 1 + poetry.lock | 960 ++++- pyproject.toml | 5 +- tad/api/main.py | 4 +- tad/api/routes/pages.py | 25 + tad/api/routes/root.py | 2 +- tad/api/routes/tasks.py | 48 + tad/core/config.py | 6 +- tad/core/db.py | 12 +- tad/main.py | 7 +- .../versions/eb2eed884ae9_a_message.py | 67 + tad/models/__init__.py | 5 +- tad/models/status.py | 7 + tad/models/task.py | 30 + tad/models/user.py | 7 + .../styles.css => repositories/__init__.py} | 0 tad/{api => repositories}/deps.py | 11 +- tad/repositories/exceptions.py | 8 + tad/repositories/statuses.py | 56 + tad/repositories/tasks.py | 66 + .../js/main.js => services/__init__.py} | 0 tad/services/statuses.py | 21 + tad/services/tasks.py | 71 + tad/site/static/css/10cols.css | 78 + tad/site/static/css/11cols.css | 84 + tad/site/static/css/12cols.css | 91 + tad/site/static/css/2cols.css | 21 + tad/site/static/css/3cols.css | 29 + tad/site/static/css/4cols.css | 36 + tad/site/static/css/5cols.css | 43 + tad/site/static/css/6cols.css | 50 + tad/site/static/css/7cols.css | 57 + tad/site/static/css/8cols.css | 64 + tad/site/static/css/9cols.css | 71 + tad/site/static/css/col.css | 42 + tad/site/static/css/html5reset.css | 96 + tad/site/static/css/layout.css | 113 + tad/{ => site}/static/favicon.ico | Bin tad/site/static/fonts/ROsanswebtextbold.woff | Bin 0 -> 69467 bytes .../static/fonts/ROsanswebtextitalic.woff | Bin 0 -> 84044 bytes .../static/fonts/ROsanswebtextregular.woff | Bin 0 -> 76489 bytes tad/site/static/images/img_avatar.png | Bin 0 -> 8229 bytes tad/site/static/images/img_avatar2.png | Bin 0 -> 8314 bytes tad/site/static/images/logo.svg | 1 + tad/site/static/js/tad.js | 37 + .../static/vendor/htmx/js}/1.9.12.min.js | 0 tad/site/static/vendor/htmx/js/htmx.min.js | 1 + .../static/vendor/htmx/js/hyperscript.min.js | 1 + .../static/vendor/sortable/js/sortable.js | 3362 +++++++++++++++++ tad/site/templates/default_layout.jinja | 90 + tad/site/templates/error.jinja | 3 + tad/site/templates/root/index.html | 12 + .../templates/root}/layout.html | 0 tad/site/templates/task.jinja | 9 + tad/templates/root/index.html | 8 - tests/api/routes/test_pages.py | 8 + tests/api/routes/test_status.py | 20 + tests/api/routes/test_tasks_move.py | 29 + tests/conftest.py | 79 +- tests/core/test_config.py | 1 + tests/core/test_db.py | 2 +- tests/database_test_utils.py | 121 + tests/e2e/__init__.py | 0 tests/e2e/test_move_task.py | 71 + tests/repositories/test_statuses.py | 63 + tests/repositories/test_tasks.py | 79 + tests/services/test_statuses_service.py | 38 + tests/services/test_tasks_service.py | 115 + 70 files changed, 6377 insertions(+), 71 deletions(-) create mode 100644 tad/api/routes/pages.py create mode 100644 tad/api/routes/tasks.py create mode 100644 tad/migrations/versions/eb2eed884ae9_a_message.py create mode 100644 tad/models/status.py create mode 100644 tad/models/task.py create mode 100644 tad/models/user.py rename tad/{static/css/styles.css => repositories/__init__.py} (100%) rename tad/{api => repositories}/deps.py (51%) create mode 100644 tad/repositories/exceptions.py create mode 100644 tad/repositories/statuses.py create mode 100644 tad/repositories/tasks.py rename tad/{static/js/main.js => services/__init__.py} (100%) create mode 100644 tad/services/statuses.py create mode 100644 tad/services/tasks.py create mode 100644 tad/site/static/css/10cols.css create mode 100644 tad/site/static/css/11cols.css create mode 100644 tad/site/static/css/12cols.css create mode 100644 tad/site/static/css/2cols.css create mode 100644 tad/site/static/css/3cols.css create mode 100644 tad/site/static/css/4cols.css create mode 100644 tad/site/static/css/5cols.css create mode 100644 tad/site/static/css/6cols.css create mode 100644 tad/site/static/css/7cols.css create mode 100644 tad/site/static/css/8cols.css create mode 100644 tad/site/static/css/9cols.css create mode 100644 tad/site/static/css/col.css create mode 100644 tad/site/static/css/html5reset.css create mode 100644 tad/site/static/css/layout.css rename tad/{ => site}/static/favicon.ico (100%) create mode 100644 tad/site/static/fonts/ROsanswebtextbold.woff create mode 100644 tad/site/static/fonts/ROsanswebtextitalic.woff create mode 100644 tad/site/static/fonts/ROsanswebtextregular.woff create mode 100644 tad/site/static/images/img_avatar.png create mode 100644 tad/site/static/images/img_avatar2.png create mode 100644 tad/site/static/images/logo.svg create mode 100644 tad/site/static/js/tad.js rename tad/{static/vendor/htmx => site/static/vendor/htmx/js}/1.9.12.min.js (100%) create mode 100644 tad/site/static/vendor/htmx/js/htmx.min.js create mode 100644 tad/site/static/vendor/htmx/js/hyperscript.min.js create mode 100644 tad/site/static/vendor/sortable/js/sortable.js create mode 100644 tad/site/templates/default_layout.jinja create mode 100644 tad/site/templates/error.jinja create mode 100644 tad/site/templates/root/index.html rename tad/{templates => site/templates/root}/layout.html (100%) create mode 100644 tad/site/templates/task.jinja delete mode 100644 tad/templates/root/index.html create mode 100644 tests/api/routes/test_pages.py create mode 100644 tests/api/routes/test_status.py create mode 100644 tests/api/routes/test_tasks_move.py create mode 100644 tests/database_test_utils.py create mode 100644 tests/e2e/__init__.py create mode 100644 tests/e2e/test_move_task.py create mode 100644 tests/repositories/test_statuses.py create mode 100644 tests/repositories/test_tasks.py create mode 100644 tests/services/test_statuses_service.py create mode 100644 tests/services/test_tasks_service.py diff --git a/.env b/.env index b21bb0ee3..4b36cdf8c 100644 --- a/.env +++ b/.env @@ -8,7 +8,7 @@ PROJECT_NAME="TAD" # TAD backend BACKEND_CORS_ORIGINS="http://localhost,https://localhost,http://127.0.0.1,https://127.0.0.1" SECRET_KEY=changethis -APP_DATABASE_SCHEME="postgresql" +APP_DATABASE_SCHEME="sqlite" APP_DATABASE_USER=tad APP_DATABASE_DB=tad APP_DATABASE_PASSWORD=changethis diff --git a/.env.test b/.env.test index 4b36cdf8c..21e66d393 100644 --- a/.env.test +++ b/.env.test @@ -22,3 +22,5 @@ POSTGRES_PASSWORD=changethis # Database viewer PGADMIN_DEFAULT_PASSWORD=changethis + +APP_DATABASE_FILE=database.sqlite3 diff --git a/.gitignore b/.gitignore index a0cbd2215..b2a562978 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ __pypackages__/ #mypyr .mypy_cache/ +/.idea/ # macos .DS_Store diff --git a/poetry.lock b/poetry.lock index d73683997..a3e454ac5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "alembic" @@ -52,6 +52,55 @@ doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphin test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] trio = ["trio (>=0.23)"] +[[package]] +name = "arrow" +version = "1.3.0" +description = "Better dates & times for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, + {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, +] + +[package.dependencies] +python-dateutil = ">=2.7.0" +types-python-dateutil = ">=2.8.10" + +[package.extras] +doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] +test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] + +[[package]] +name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] + +[[package]] +name = "boolean-py" +version = "4.0" +description = "Define boolean algebras, create and parse boolean expressions and create custom boolean DSL." +optional = false +python-versions = "*" +files = [ + {file = "boolean.py-4.0-py3-none-any.whl", hash = "sha256:2876f2051d7d6394a531d82dc6eb407faa0b01a0a0b3083817ccd7323b8d96bd"}, + {file = "boolean.py-4.0.tar.gz", hash = "sha256:17b9a181630e43dde1851d42bef546d616d5d9b4480357514597e78b203d06e4"}, +] + [[package]] name = "certifi" version = "2024.2.2" @@ -74,6 +123,116 @@ files = [ {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, ] +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = false +python-versions = ">=3.7" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + [[package]] name = "click" version = "8.1.7" @@ -163,6 +322,60 @@ files = [ [package.extras] toml = ["tomli"] +[[package]] +name = "cyclonedx-bom" +version = "4.4.3" +description = "CycloneDX Software Bill of Materials (SBOM) generator for Python projects and environments" +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "cyclonedx_bom-4.4.3-py3-none-any.whl", hash = "sha256:36026f9b222a855772d607032da1991ee1dccf1cbd1e74872af51bd4acfcc397"}, + {file = "cyclonedx_bom-4.4.3.tar.gz", hash = "sha256:088dfff2084e9df60924975ec82b15f5e44ec5bd8ef2a29ed43905ee2b84a6e2"}, +] + +[package.dependencies] +chardet = ">=5.1,<6.0" +cyclonedx-python-lib = {version = ">=7.3.0,<7.3.1 || >7.3.1,<8.0.0", extras = ["validation"]} +packageurl-python = ">=0.11,<2" +packaging = ">=22,<25" +pip-requirements-parser = ">=32.0,<33.0" +tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""} + +[[package]] +name = "cyclonedx-python-lib" +version = "7.3.4" +description = "Python library for CycloneDX" +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "cyclonedx_python_lib-7.3.4-py3-none-any.whl", hash = "sha256:8b6dc39f2281feb7fbf9b174fa5d8d3f8f7b51fd6f1d83e9b4c9bbd60ec2ab91"}, + {file = "cyclonedx_python_lib-7.3.4.tar.gz", hash = "sha256:f374855bd6b736b3a6be4eec93b5ca7f160c8282fe4ba5486518da11dbe83f1b"}, +] + +[package.dependencies] +jsonschema = {version = ">=4.18,<5.0", extras = ["format"], optional = true, markers = "extra == \"validation\" or extra == \"json-validation\""} +license-expression = ">=30,<31" +lxml = {version = ">=4,<6", optional = true, markers = "extra == \"validation\" or extra == \"xml-validation\""} +packageurl-python = ">=0.11,<2" +py-serializable = ">=1.0.3,<2" +sortedcontainers = ">=2.4.0,<3.0.0" + +[package.extras] +json-validation = ["jsonschema[format] (>=4.18,<5.0)"] +validation = ["jsonschema[format] (>=4.18,<5.0)", "lxml (>=4,<6)"] +xml-validation = ["lxml (>=4,<6)"] + +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + [[package]] name = "distlib" version = "0.3.8" @@ -223,6 +436,17 @@ docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1 testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] +[[package]] +name = "fqdn" +version = "1.5.1" +description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" +optional = false +python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" +files = [ + {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, + {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, +] + [[package]] name = "greenlet" version = "3.0.3" @@ -434,6 +658,20 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "isoduration" +version = "20.11.0" +description = "Operations with ISO 8601 durations" +optional = false +python-versions = ">=3.7" +files = [ + {file = "isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042"}, + {file = "isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9"}, +] + +[package.dependencies] +arrow = ">=0.15.0" + [[package]] name = "jinja2" version = "3.1.4" @@ -452,19 +690,234 @@ MarkupSafe = ">=2.0" i18n = ["Babel (>=2.7)"] [[package]] -name = "liccheck" -version = "0.9.2" -description = "Check python packages from requirement.txt and report issues" +name = "jsonpointer" +version = "2.4" +description = "Identify specific nodes in a JSON document (RFC 6901)" optional = false -python-versions = ">=3.5" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, +] + +[[package]] +name = "jsonschema" +version = "4.22.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" files = [ - {file = "liccheck-0.9.2-py2.py3-none-any.whl", hash = "sha256:15cbedd042515945fe9d58b62e0a5af2f2a7795def216f163bb35b3016a16637"}, - {file = "liccheck-0.9.2.tar.gz", hash = "sha256:bdc2190f8e95af3c8f9c19edb784ba7d41ecb2bf9189422eae6112bf84c08cd5"}, + {file = "jsonschema-4.22.0-py3-none-any.whl", hash = "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802"}, + {file = "jsonschema-4.22.0.tar.gz", hash = "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7"}, ] [package.dependencies] -semantic-version = ">=2.7.0" -toml = "*" +attrs = ">=22.2.0" +fqdn = {version = "*", optional = true, markers = "extra == \"format\""} +idna = {version = "*", optional = true, markers = "extra == \"format\""} +isoduration = {version = "*", optional = true, markers = "extra == \"format\""} +jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format\""} +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format\""} +rfc3987 = {version = "*", optional = true, markers = "extra == \"format\""} +rpds-py = ">=0.7.1" +uri-template = {version = "*", optional = true, markers = "extra == \"format\""} +webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format\""} + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + +[[package]] +name = "license-expression" +version = "30.3.0" +description = "license-expression is a comprehensive utility library to parse, compare, simplify and normalize license expressions (such as SPDX license expressions) using boolean logic." +optional = false +python-versions = ">=3.8" +files = [ + {file = "license-expression-30.3.0.tar.gz", hash = "sha256:1295406f736b4f395ff069aec1cebfad53c0fcb3cf57df0f5ec58fc7b905aea5"}, + {file = "license_expression-30.3.0-py3-none-any.whl", hash = "sha256:ae0ba9a829d6909c785dc2f0131f13d10d68318e4a5f28af5ef152d6b52f9b41"}, +] + +[package.dependencies] +"boolean.py" = ">=4.0" + +[package.extras] +docs = ["Sphinx (>=5.0.2)", "doc8 (>=0.11.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-reredirects (>=0.1.2)", "sphinx-rtd-dark-mode (>=1.3.0)", "sphinx-rtd-theme (>=1.0.0)", "sphinxcontrib-apidoc (>=0.4.0)"] +testing = ["black", "isort", "pytest (>=6,!=7.0.0)", "pytest-xdist (>=2)", "twine"] + +[[package]] +name = "lxml" +version = "5.2.2" +description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +optional = false +python-versions = ">=3.6" +files = [ + {file = "lxml-5.2.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:364d03207f3e603922d0d3932ef363d55bbf48e3647395765f9bfcbdf6d23632"}, + {file = "lxml-5.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50127c186f191b8917ea2fb8b206fbebe87fd414a6084d15568c27d0a21d60db"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74e4f025ef3db1c6da4460dd27c118d8cd136d0391da4e387a15e48e5c975147"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981a06a3076997adf7c743dcd0d7a0415582661e2517c7d961493572e909aa1d"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aef5474d913d3b05e613906ba4090433c515e13ea49c837aca18bde190853dff"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e275ea572389e41e8b039ac076a46cb87ee6b8542df3fff26f5baab43713bca"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5b65529bb2f21ac7861a0e94fdbf5dc0daab41497d18223b46ee8515e5ad297"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bcc98f911f10278d1daf14b87d65325851a1d29153caaf146877ec37031d5f36"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:b47633251727c8fe279f34025844b3b3a3e40cd1b198356d003aa146258d13a2"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:fbc9d316552f9ef7bba39f4edfad4a734d3d6f93341232a9dddadec4f15d425f"}, + {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:13e69be35391ce72712184f69000cda04fc89689429179bc4c0ae5f0b7a8c21b"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3b6a30a9ab040b3f545b697cb3adbf3696c05a3a68aad172e3fd7ca73ab3c835"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a233bb68625a85126ac9f1fc66d24337d6e8a0f9207b688eec2e7c880f012ec0"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:dfa7c241073d8f2b8e8dbc7803c434f57dbb83ae2a3d7892dd068d99e96efe2c"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1a7aca7964ac4bb07680d5c9d63b9d7028cace3e2d43175cb50bba8c5ad33316"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ae4073a60ab98529ab8a72ebf429f2a8cc612619a8c04e08bed27450d52103c0"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ffb2be176fed4457e445fe540617f0252a72a8bc56208fd65a690fdb1f57660b"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e290d79a4107d7d794634ce3e985b9ae4f920380a813717adf61804904dc4393"}, + {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:96e85aa09274955bb6bd483eaf5b12abadade01010478154b0ec70284c1b1526"}, + {file = "lxml-5.2.2-cp310-cp310-win32.whl", hash = "sha256:f956196ef61369f1685d14dad80611488d8dc1ef00be57c0c5a03064005b0f30"}, + {file = "lxml-5.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:875a3f90d7eb5c5d77e529080d95140eacb3c6d13ad5b616ee8095447b1d22e7"}, + {file = "lxml-5.2.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545"}, + {file = "lxml-5.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0b3f2df149efb242cee2ffdeb6674b7f30d23c9a7af26595099afaf46ef4e88"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d28cb356f119a437cc58a13f8135ab8a4c8ece18159eb9194b0d269ec4e28083"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:657a972f46bbefdbba2d4f14413c0d079f9ae243bd68193cb5061b9732fa54c1"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b9ea10063efb77a965a8d5f4182806fbf59ed068b3c3fd6f30d2ac7bee734"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07542787f86112d46d07d4f3c4e7c760282011b354d012dc4141cc12a68cef5f"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:303f540ad2dddd35b92415b74b900c749ec2010e703ab3bfd6660979d01fd4ed"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2eb2227ce1ff998faf0cd7fe85bbf086aa41dfc5af3b1d80867ecfe75fb68df3"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:1d8a701774dfc42a2f0b8ccdfe7dbc140500d1049e0632a611985d943fcf12df"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:56793b7a1a091a7c286b5f4aa1fe4ae5d1446fe742d00cdf2ffb1077865db10d"}, + {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a2569a1f15ae6c8c64108a2cd2b4a858fc1e13d25846be0666fc144715e32ab"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:8cf85a6e40ff1f37fe0f25719aadf443686b1ac7652593dc53c7ef9b8492b115"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:d237ba6664b8e60fd90b8549a149a74fcc675272e0e95539a00522e4ca688b04"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0b3f5016e00ae7630a4b83d0868fca1e3d494c78a75b1c7252606a3a1c5fc2ad"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23441e2b5339bc54dc949e9e675fa35efe858108404ef9aa92f0456929ef6fe8"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2fb0ba3e8566548d6c8e7dd82a8229ff47bd8fb8c2da237607ac8e5a1b8312e5"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:79d1fb9252e7e2cfe4de6e9a6610c7cbb99b9708e2c3e29057f487de5a9eaefa"}, + {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6dcc3d17eac1df7859ae01202e9bb11ffa8c98949dcbeb1069c8b9a75917e01b"}, + {file = "lxml-5.2.2-cp311-cp311-win32.whl", hash = "sha256:4c30a2f83677876465f44c018830f608fa3c6a8a466eb223535035fbc16f3438"}, + {file = "lxml-5.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:49095a38eb333aaf44c06052fd2ec3b8f23e19747ca7ec6f6c954ffea6dbf7be"}, + {file = "lxml-5.2.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7429e7faa1a60cad26ae4227f4dd0459efde239e494c7312624ce228e04f6391"}, + {file = "lxml-5.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:50ccb5d355961c0f12f6cf24b7187dbabd5433f29e15147a67995474f27d1776"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc911208b18842a3a57266d8e51fc3cfaccee90a5351b92079beed912a7914c2"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33ce9e786753743159799fdf8e92a5da351158c4bfb6f2db0bf31e7892a1feb5"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec87c44f619380878bd49ca109669c9f221d9ae6883a5bcb3616785fa8f94c97"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08ea0f606808354eb8f2dfaac095963cb25d9d28e27edcc375d7b30ab01abbf6"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75a9632f1d4f698b2e6e2e1ada40e71f369b15d69baddb8968dcc8e683839b18"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74da9f97daec6928567b48c90ea2c82a106b2d500f397eeb8941e47d30b1ca85"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:0969e92af09c5687d769731e3f39ed62427cc72176cebb54b7a9d52cc4fa3b73"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:9164361769b6ca7769079f4d426a41df6164879f7f3568be9086e15baca61466"}, + {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d26a618ae1766279f2660aca0081b2220aca6bd1aa06b2cf73f07383faf48927"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab67ed772c584b7ef2379797bf14b82df9aa5f7438c5b9a09624dd834c1c1aaf"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:3d1e35572a56941b32c239774d7e9ad724074d37f90c7a7d499ab98761bd80cf"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:8268cbcd48c5375f46e000adb1390572c98879eb4f77910c6053d25cc3ac2c67"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e282aedd63c639c07c3857097fc0e236f984ceb4089a8b284da1c526491e3f3d"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfdc2bfe69e9adf0df4915949c22a25b39d175d599bf98e7ddf620a13678585"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4aefd911793b5d2d7a921233a54c90329bf3d4a6817dc465f12ffdfe4fc7b8fe"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8b8df03a9e995b6211dafa63b32f9d405881518ff1ddd775db4e7b98fb545e1c"}, + {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f11ae142f3a322d44513de1018b50f474f8f736bc3cd91d969f464b5bfef8836"}, + {file = "lxml-5.2.2-cp312-cp312-win32.whl", hash = "sha256:16a8326e51fcdffc886294c1e70b11ddccec836516a343f9ed0f82aac043c24a"}, + {file = "lxml-5.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:bbc4b80af581e18568ff07f6395c02114d05f4865c2812a1f02f2eaecf0bfd48"}, + {file = "lxml-5.2.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e3d9d13603410b72787579769469af730c38f2f25505573a5888a94b62b920f8"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38b67afb0a06b8575948641c1d6d68e41b83a3abeae2ca9eed2ac59892b36706"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c689d0d5381f56de7bd6966a4541bff6e08bf8d3871bbd89a0c6ab18aa699573"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:cf2a978c795b54c539f47964ec05e35c05bd045db5ca1e8366988c7f2fe6b3ce"}, + {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:739e36ef7412b2bd940f75b278749106e6d025e40027c0b94a17ef7968d55d56"}, + {file = "lxml-5.2.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d8bbcd21769594dbba9c37d3c819e2d5847656ca99c747ddb31ac1701d0c0ed9"}, + {file = "lxml-5.2.2-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:2304d3c93f2258ccf2cf7a6ba8c761d76ef84948d87bf9664e14d203da2cd264"}, + {file = "lxml-5.2.2-cp36-cp36m-win32.whl", hash = "sha256:02437fb7308386867c8b7b0e5bc4cd4b04548b1c5d089ffb8e7b31009b961dc3"}, + {file = "lxml-5.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:edcfa83e03370032a489430215c1e7783128808fd3e2e0a3225deee278585196"}, + {file = "lxml-5.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:28bf95177400066596cdbcfc933312493799382879da504633d16cf60bba735b"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a745cc98d504d5bd2c19b10c79c61c7c3df9222629f1b6210c0368177589fb8"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b590b39ef90c6b22ec0be925b211298e810b4856909c8ca60d27ffbca6c12e6"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b336b0416828022bfd5a2e3083e7f5ba54b96242159f83c7e3eebaec752f1716"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:c2faf60c583af0d135e853c86ac2735ce178f0e338a3c7f9ae8f622fd2eb788c"}, + {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:4bc6cb140a7a0ad1f7bc37e018d0ed690b7b6520ade518285dc3171f7a117905"}, + {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7ff762670cada8e05b32bf1e4dc50b140790909caa8303cfddc4d702b71ea184"}, + {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:57f0a0bbc9868e10ebe874e9f129d2917750adf008fe7b9c1598c0fbbfdde6a6"}, + {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:a6d2092797b388342c1bc932077ad232f914351932353e2e8706851c870bca1f"}, + {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:60499fe961b21264e17a471ec296dcbf4365fbea611bf9e303ab69db7159ce61"}, + {file = "lxml-5.2.2-cp37-cp37m-win32.whl", hash = "sha256:d9b342c76003c6b9336a80efcc766748a333573abf9350f4094ee46b006ec18f"}, + {file = "lxml-5.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b16db2770517b8799c79aa80f4053cd6f8b716f21f8aca962725a9565ce3ee40"}, + {file = "lxml-5.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7ed07b3062b055d7a7f9d6557a251cc655eed0b3152b76de619516621c56f5d3"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60fdd125d85bf9c279ffb8e94c78c51b3b6a37711464e1f5f31078b45002421"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a7e24cb69ee5f32e003f50e016d5fde438010c1022c96738b04fc2423e61706"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23cfafd56887eaed93d07bc4547abd5e09d837a002b791e9767765492a75883f"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:19b4e485cd07b7d83e3fe3b72132e7df70bfac22b14fe4bf7a23822c3a35bff5"}, + {file = "lxml-5.2.2-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7ce7ad8abebe737ad6143d9d3bf94b88b93365ea30a5b81f6877ec9c0dee0a48"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e49b052b768bb74f58c7dda4e0bdf7b79d43a9204ca584ffe1fb48a6f3c84c66"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d14a0d029a4e176795cef99c056d58067c06195e0c7e2dbb293bf95c08f772a3"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:be49ad33819d7dcc28a309b86d4ed98e1a65f3075c6acd3cd4fe32103235222b"}, + {file = "lxml-5.2.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a6d17e0370d2516d5bb9062c7b4cb731cff921fc875644c3d751ad857ba9c5b1"}, + {file = "lxml-5.2.2-cp38-cp38-win32.whl", hash = "sha256:5b8c041b6265e08eac8a724b74b655404070b636a8dd6d7a13c3adc07882ef30"}, + {file = "lxml-5.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:f61efaf4bed1cc0860e567d2ecb2363974d414f7f1f124b1df368bbf183453a6"}, + {file = "lxml-5.2.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fb91819461b1b56d06fa4bcf86617fac795f6a99d12239fb0c68dbeba41a0a30"}, + {file = "lxml-5.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d4ed0c7cbecde7194cd3228c044e86bf73e30a23505af852857c09c24e77ec5d"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54401c77a63cc7d6dc4b4e173bb484f28a5607f3df71484709fe037c92d4f0ed"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:625e3ef310e7fa3a761d48ca7ea1f9d8718a32b1542e727d584d82f4453d5eeb"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:519895c99c815a1a24a926d5b60627ce5ea48e9f639a5cd328bda0515ea0f10c"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c7079d5eb1c1315a858bbf180000757db8ad904a89476653232db835c3114001"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:343ab62e9ca78094f2306aefed67dcfad61c4683f87eee48ff2fd74902447726"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:cd9e78285da6c9ba2d5c769628f43ef66d96ac3085e59b10ad4f3707980710d3"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:546cf886f6242dff9ec206331209db9c8e1643ae642dea5fdbecae2453cb50fd"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:02f6a8eb6512fdc2fd4ca10a49c341c4e109aa6e9448cc4859af5b949622715a"}, + {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:339ee4a4704bc724757cd5dd9dc8cf4d00980f5d3e6e06d5847c1b594ace68ab"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0a028b61a2e357ace98b1615fc03f76eb517cc028993964fe08ad514b1e8892d"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f90e552ecbad426eab352e7b2933091f2be77115bb16f09f78404861c8322981"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d83e2d94b69bf31ead2fa45f0acdef0757fa0458a129734f59f67f3d2eb7ef32"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a02d3c48f9bb1e10c7788d92c0c7db6f2002d024ab6e74d6f45ae33e3d0288a3"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6d68ce8e7b2075390e8ac1e1d3a99e8b6372c694bbe612632606d1d546794207"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:453d037e09a5176d92ec0fd282e934ed26d806331a8b70ab431a81e2fbabf56d"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:3b019d4ee84b683342af793b56bb35034bd749e4cbdd3d33f7d1107790f8c472"}, + {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb3942960f0beb9f46e2a71a3aca220d1ca32feb5a398656be934320804c0df9"}, + {file = "lxml-5.2.2-cp39-cp39-win32.whl", hash = "sha256:ac6540c9fff6e3813d29d0403ee7a81897f1d8ecc09a8ff84d2eea70ede1cdbf"}, + {file = "lxml-5.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:610b5c77428a50269f38a534057444c249976433f40f53e3b47e68349cca1425"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b537bd04d7ccd7c6350cdaaaad911f6312cbd61e6e6045542f781c7f8b2e99d2"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4820c02195d6dfb7b8508ff276752f6b2ff8b64ae5d13ebe02e7667e035000b9"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a09f6184f17a80897172863a655467da2b11151ec98ba8d7af89f17bf63dae"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76acba4c66c47d27c8365e7c10b3d8016a7da83d3191d053a58382311a8bf4e1"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b128092c927eaf485928cec0c28f6b8bead277e28acf56800e972aa2c2abd7a2"}, + {file = "lxml-5.2.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ae791f6bd43305aade8c0e22f816b34f3b72b6c820477aab4d18473a37e8090b"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a2f6a1bc2460e643785a2cde17293bd7a8f990884b822f7bca47bee0a82fc66b"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e8d351ff44c1638cb6e980623d517abd9f580d2e53bfcd18d8941c052a5a009"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bec4bd9133420c5c52d562469c754f27c5c9e36ee06abc169612c959bd7dbb07"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:55ce6b6d803890bd3cc89975fca9de1dff39729b43b73cb15ddd933b8bc20484"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ab6a358d1286498d80fe67bd3d69fcbc7d1359b45b41e74c4a26964ca99c3f8"}, + {file = "lxml-5.2.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:06668e39e1f3c065349c51ac27ae430719d7806c026fec462e5693b08b95696b"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9cd5323344d8ebb9fb5e96da5de5ad4ebab993bbf51674259dbe9d7a18049525"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89feb82ca055af0fe797a2323ec9043b26bc371365847dbe83c7fd2e2f181c34"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e481bba1e11ba585fb06db666bfc23dbe181dbafc7b25776156120bf12e0d5a6"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d6c6ea6a11ca0ff9cd0390b885984ed31157c168565702959c25e2191674a14"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3d98de734abee23e61f6b8c2e08a88453ada7d6486dc7cdc82922a03968928db"}, + {file = "lxml-5.2.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:69ab77a1373f1e7563e0fb5a29a8440367dec051da6c7405333699d07444f511"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:34e17913c431f5ae01d8658dbf792fdc457073dcdfbb31dc0cc6ab256e664a8d"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05f8757b03208c3f50097761be2dea0aba02e94f0dc7023ed73a7bb14ff11eb0"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a520b4f9974b0a0a6ed73c2154de57cdfd0c8800f4f15ab2b73238ffed0b36e"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5e097646944b66207023bc3c634827de858aebc226d5d4d6d16f0b77566ea182"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b5e4ef22ff25bfd4ede5f8fb30f7b24446345f3e79d9b7455aef2836437bc38a"}, + {file = "lxml-5.2.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff69a9a0b4b17d78170c73abe2ab12084bdf1691550c5629ad1fe7849433f324"}, + {file = "lxml-5.2.2.tar.gz", hash = "sha256:bb2dc4898180bea79863d5487e5f9c7c34297414bad54bcd0f0852aee9cfdb87"}, +] + +[package.extras] +cssselect = ["cssselect (>=0.7)"] +html-clean = ["lxml-html-clean"] +html5 = ["html5lib"] +htmlsoup = ["BeautifulSoup4"] +source = ["Cython (>=3.0.10)"] [[package]] name = "mako" @@ -568,6 +1021,23 @@ files = [ [package.dependencies] setuptools = "*" +[[package]] +name = "packageurl-python" +version = "0.15.0" +description = "A purl aka. Package URL parser and builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packageurl-python-0.15.0.tar.gz", hash = "sha256:f219b2ce6348185a27bd6a72e6fdc9f984e6c9fa157effa7cb93e341c49cdcc2"}, + {file = "packageurl_python-0.15.0-py3-none-any.whl", hash = "sha256:cdc6bd42dc30c4fc7f8f0ccb721fc31f8c33985dbffccb6e6be4c72874de48ca"}, +] + +[package.extras] +build = ["setuptools", "wheel"] +lint = ["black", "isort", "mypy"] +sqlalchemy = ["sqlalchemy (>=2.0.0)"] +test = ["pytest"] + [[package]] name = "packaging" version = "24.0" @@ -579,6 +1049,42 @@ files = [ {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, ] +[[package]] +name = "pip-licenses" +version = "4.4.0" +description = "Dump the software license list of Python packages installed with pip." +optional = false +python-versions = "~=3.8" +files = [ + {file = "pip-licenses-4.4.0.tar.gz", hash = "sha256:996817118375445243a34faafe23c06f6b2d250247c4046571b5a6722d45be69"}, + {file = "pip_licenses-4.4.0-py3-none-any.whl", hash = "sha256:dbad2ac5a25f574cabe2716f2f031a0c5fa359bed9b3ef615301f4e546893b46"}, +] + +[package.dependencies] +prettytable = ">=2.3.0" + +[package.extras] +test = ["docutils", "mypy", "pytest-cov", "pytest-pycodestyle", "pytest-runner"] + +[[package]] +name = "pip-requirements-parser" +version = "32.0.1" +description = "pip requirements parser - a mostly correct pip requirements parsing library because it uses pip's own code." +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "pip-requirements-parser-32.0.1.tar.gz", hash = "sha256:b4fa3a7a0be38243123cf9d1f3518da10c51bdb165a2b2985566247f9155a7d3"}, + {file = "pip_requirements_parser-32.0.1-py3-none-any.whl", hash = "sha256:4659bc2a667783e7a15d190f6fccf8b2486685b6dba4c19c3876314769c57526"}, +] + +[package.dependencies] +packaging = "*" +pyparsing = "*" + +[package.extras] +docs = ["Sphinx (>=3.3.1)", "doc8 (>=0.8.1)", "sphinx-rtd-theme (>=0.5.0)"] +testing = ["aboutcode-toolkit (>=6.0.0)", "black", "pytest (>=6,!=7.0.0)", "pytest-xdist (>=2)"] + [[package]] name = "platformdirs" version = "4.2.2" @@ -595,6 +1101,26 @@ docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx- test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] type = ["mypy (>=1.8)"] +[[package]] +name = "playwright" +version = "1.44.0" +description = "A high-level API to automate web browsers" +optional = false +python-versions = ">=3.8" +files = [ + {file = "playwright-1.44.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:c2317a80896796fdeb03d60f06cc229e775ff2e19b80c64b1bb9b29c8a59d992"}, + {file = "playwright-1.44.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54d44fb634d870839301c2326e1e12a178a1be0de76d0caaec230ab075c2e077"}, + {file = "playwright-1.44.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:64b67194e73b47ae72acf25f1a9cfacfef38ca2b52e4bb8b0abd385c5deeaadf"}, + {file = "playwright-1.44.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:29161b1fae71f7c402df5b15f0bd3deaeecd8b3d1ecd9ff01271700c66210e7b"}, + {file = "playwright-1.44.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8c8a3bfea17576d3f94a2363eee195cbda8dbba86975588c7eaac7792b25eee"}, + {file = "playwright-1.44.0-py3-none-win32.whl", hash = "sha256:235e37832deaa9af8a629d09955396259ab757533cc1922f9b0308b4ee0d9cdf"}, + {file = "playwright-1.44.0-py3-none-win_amd64.whl", hash = "sha256:5b8a4a1d4d50f4ff99b47965576322a8c4e34631854b862a25c1feb824be22a8"}, +] + +[package.dependencies] +greenlet = "3.0.3" +pyee = "11.1.0" + [[package]] name = "pluggy" version = "1.5.0" @@ -628,6 +1154,23 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" +[[package]] +name = "prettytable" +version = "3.10.0" +description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" +optional = false +python-versions = ">=3.8" +files = [ + {file = "prettytable-3.10.0-py3-none-any.whl", hash = "sha256:6536efaf0757fdaa7d22e78b3aac3b69ea1b7200538c2c6995d649365bddab92"}, + {file = "prettytable-3.10.0.tar.gz", hash = "sha256:9665594d137fb08a1117518c25551e0ede1687197cf353a4fdc78d27e1073568"}, +] + +[package.dependencies] +wcwidth = "*" + +[package.extras] +tests = ["pytest", "pytest-cov", "pytest-lazy-fixtures"] + [[package]] name = "psycopg2-binary" version = "2.9.9" @@ -709,6 +1252,20 @@ files = [ {file = "psycopg2_binary-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957"}, ] +[[package]] +name = "py-serializable" +version = "1.0.3" +description = "Library for serializing and deserializing Python Objects to and from JSON and XML." +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "py_serializable-1.0.3-py3-none-any.whl", hash = "sha256:afba815f465b9fe7ab1c1a56d1aa8880c8a9e67a6e28b7ed62d4696fa369caf8"}, + {file = "py_serializable-1.0.3.tar.gz", hash = "sha256:da3cb4b1f3cc5cc5ebecdd3dadbabd5f65d764357366fa64ee9cbaf0d4b70dcf"}, +] + +[package.dependencies] +defusedxml = ">=0.7.1,<0.8.0" + [[package]] name = "pydantic" version = "2.7.1" @@ -838,6 +1395,37 @@ python-dotenv = ">=0.21.0" toml = ["tomli (>=2.0.1)"] yaml = ["pyyaml (>=6.0.1)"] +[[package]] +name = "pyee" +version = "11.1.0" +description = "A rough port of Node.js's EventEmitter to Python with a few tricks of its own" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyee-11.1.0-py3-none-any.whl", hash = "sha256:5d346a7d0f861a4b2e6c47960295bd895f816725b27d656181947346be98d7c1"}, + {file = "pyee-11.1.0.tar.gz", hash = "sha256:b53af98f6990c810edd9b56b87791021a8f54fd13db4edd1142438d44ba2263f"}, +] + +[package.dependencies] +typing-extensions = "*" + +[package.extras] +dev = ["black", "build", "flake8", "flake8-black", "isort", "jupyter-console", "mkdocs", "mkdocs-include-markdown-plugin", "mkdocstrings[python]", "pytest", "pytest-asyncio", "pytest-trio", "sphinx", "toml", "tox", "trio", "trio", "trio-typing", "twine", "twisted", "validate-pyproject[all]"] + +[[package]] +name = "pyparsing" +version = "3.1.2" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, + {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + [[package]] name = "pyright" version = "1.1.363" @@ -878,6 +1466,55 @@ tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +[[package]] +name = "pytest-base-url" +version = "2.1.0" +description = "pytest plugin for URL based testing" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_base_url-2.1.0-py3-none-any.whl", hash = "sha256:3ad15611778764d451927b2a53240c1a7a591b521ea44cebfe45849d2d2812e6"}, + {file = "pytest_base_url-2.1.0.tar.gz", hash = "sha256:02748589a54f9e63fcbe62301d6b0496da0d10231b753e950c63e03aee745d45"}, +] + +[package.dependencies] +pytest = ">=7.0.0" +requests = ">=2.9" + +[package.extras] +test = ["black (>=22.1.0)", "flake8 (>=4.0.1)", "pre-commit (>=2.17.0)", "pytest-localserver (>=0.7.1)", "tox (>=3.24.5)"] + +[[package]] +name = "pytest-playwright" +version = "0.5.0" +description = "A pytest wrapper with fixtures for Playwright to automate web browsers" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-playwright-0.5.0.tar.gz", hash = "sha256:f9f5ae8ade2f773e6e2cd85ec6bfff2ab287f7943108b3956fe5971324151622"}, + {file = "pytest_playwright-0.5.0-py3-none-any.whl", hash = "sha256:b382c870384419c025d66aea14518bab71fb9e79917d4808692cde70d8c5216a"}, +] + +[package.dependencies] +playwright = ">=1.18" +pytest = ">=6.2.4,<9.0.0" +pytest-base-url = ">=1.0.0,<3.0.0" +python-slugify = ">=6.0.0,<9.0.0" + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + [[package]] name = "python-dotenv" version = "1.0.1" @@ -892,6 +1529,23 @@ files = [ [package.extras] cli = ["click (>=5.0)"] +[[package]] +name = "python-slugify" +version = "8.0.4" +description = "A Python slugify application that also handles Unicode" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"}, + {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"}, +] + +[package.dependencies] +text-unidecode = ">=1.3" + +[package.extras] +unidecode = ["Unidecode (>=1.1.1)"] + [[package]] name = "pyyaml" version = "6.0.1" @@ -952,6 +1606,175 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "referencing" +version = "0.35.1" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, + {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[package]] +name = "requests" +version = "2.32.2" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"}, + {file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +description = "A pure python RFC3339 validator" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, + {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "rfc3987" +version = "1.3.8" +description = "Parsing and validation of URIs (RFC 3986) and IRIs (RFC 3987)" +optional = false +python-versions = "*" +files = [ + {file = "rfc3987-1.3.8-py2.py3-none-any.whl", hash = "sha256:10702b1e51e5658843460b189b185c0366d2cf4cff716f13111b0ea9fd2dce53"}, + {file = "rfc3987-1.3.8.tar.gz", hash = "sha256:d3c4d257a560d544e9826b38bc81db676890c79ab9d7ac92b39c7a253d5ca733"}, +] + +[[package]] +name = "rpds-py" +version = "0.18.1" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.18.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53"}, + {file = "rpds_py-0.18.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1"}, + {file = "rpds_py-0.18.1-cp310-none-win32.whl", hash = "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333"}, + {file = "rpds_py-0.18.1-cp310-none-win_amd64.whl", hash = "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a"}, + {file = "rpds_py-0.18.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8"}, + {file = "rpds_py-0.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88"}, + {file = "rpds_py-0.18.1-cp311-none-win32.whl", hash = "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb"}, + {file = "rpds_py-0.18.1-cp311-none-win_amd64.whl", hash = "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2"}, + {file = "rpds_py-0.18.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3"}, + {file = "rpds_py-0.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a"}, + {file = "rpds_py-0.18.1-cp312-none-win32.whl", hash = "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6"}, + {file = "rpds_py-0.18.1-cp312-none-win_amd64.whl", hash = "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72"}, + {file = "rpds_py-0.18.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74"}, + {file = "rpds_py-0.18.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc"}, + {file = "rpds_py-0.18.1-cp38-none-win32.whl", hash = "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9"}, + {file = "rpds_py-0.18.1-cp38-none-win_amd64.whl", hash = "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2"}, + {file = "rpds_py-0.18.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93"}, + {file = "rpds_py-0.18.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26"}, + {file = "rpds_py-0.18.1-cp39-none-win32.whl", hash = "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360"}, + {file = "rpds_py-0.18.1-cp39-none-win_amd64.whl", hash = "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e"}, + {file = "rpds_py-0.18.1.tar.gz", hash = "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f"}, +] + [[package]] name = "ruff" version = "0.4.4" @@ -978,21 +1801,6 @@ files = [ {file = "ruff-0.4.4.tar.gz", hash = "sha256:f87ea42d5cdebdc6a69761a9d0bc83ae9b3b30d0ad78952005ba6568d6c022af"}, ] -[[package]] -name = "semantic-version" -version = "2.10.0" -description = "A library implementing the 'SemVer' scheme." -optional = false -python-versions = ">=2.7" -files = [ - {file = "semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177"}, - {file = "semantic_version-2.10.0.tar.gz", hash = "sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c"}, -] - -[package.extras] -dev = ["Django (>=1.11)", "check-manifest", "colorama (<=0.4.1)", "coverage", "flake8", "nose2", "readme-renderer (<25.0)", "tox", "wheel", "zest.releaser[recommended]"] -doc = ["Sphinx", "sphinx-rtd-theme"] - [[package]] name = "setuptools" version = "69.5.1" @@ -1009,6 +1817,17 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -1020,6 +1839,17 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = false +python-versions = "*" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + [[package]] name = "sqlalchemy" version = "2.0.30" @@ -1140,14 +1970,14 @@ anyio = ">=3.4.0,<5" full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] [[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" +name = "text-unidecode" +version = "1.3" +description = "The most basic Text::Unidecode port" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "*" files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, + {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, + {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, ] [[package]] @@ -1161,6 +1991,17 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20240316" +description = "Typing stubs for python-dateutil" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-python-dateutil-2.9.0.20240316.tar.gz", hash = "sha256:5d2f2e240b86905e40944dd787db6da9263f0deabef1076ddaed797351ec0202"}, + {file = "types_python_dateutil-2.9.0.20240316-py3-none-any.whl", hash = "sha256:6b8cb66d960771ce5ff974e9dd45e38facb81718cc1e208b10b1baccbfdbee3b"}, +] + [[package]] name = "typing-extensions" version = "4.11.0" @@ -1172,6 +2013,37 @@ files = [ {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, ] +[[package]] +name = "uri-template" +version = "1.3.0" +description = "RFC 6570 URI Template Processor" +optional = false +python-versions = ">=3.7" +files = [ + {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, + {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, +] + +[package.extras] +dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "mypy", "pep8-naming", "types-PyYAML"] + +[[package]] +name = "urllib3" +version = "2.2.1" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + [[package]] name = "uvicorn" version = "0.29.0" @@ -1349,6 +2221,32 @@ files = [ [package.dependencies] anyio = ">=3.0.0" +[[package]] +name = "wcwidth" +version = "0.2.13" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, +] + +[[package]] +name = "webcolors" +version = "1.13" +description = "A library for working with the color formats defined by HTML and CSS." +optional = false +python-versions = ">=3.7" +files = [ + {file = "webcolors-1.13-py3-none-any.whl", hash = "sha256:29bc7e8752c0a1bd4a1f03c14d6e6a72e93d82193738fa860cbff59d0fcc11bf"}, + {file = "webcolors-1.13.tar.gz", hash = "sha256:c225b674c83fa923be93d235330ce0300373d02885cef23238813b0d5668304a"}, +] + +[package.extras] +docs = ["furo", "sphinx", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-notfound-page", "sphinxext-opengraph"] +tests = ["pytest", "pytest-cov"] + [[package]] name = "websockets" version = "12.0" @@ -1433,4 +2331,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "2c2107a12597c1805e3008e49e4124975a8b72cb53cc1be4996b1fa47a2e55ea" +content-hash = "149279abad58914170d89552c04d69d35e2d07c9b9b8c7b4b8a49a78cfcb9554" diff --git a/pyproject.toml b/pyproject.toml index 2607198c3..d0450044a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,8 @@ jinja2 = "^3.1.4" pydantic-settings = "^2.2.1" psycopg2-binary = "^2.9.9" uvicorn = {extras = ["standard"], version = "^0.29.0"} +playwright = "^1.44.0" +pytest-playwright = "^0.5.0" [tool.poetry.group.test.dependencies] @@ -77,7 +79,8 @@ reportMissingImports = true reportMissingTypeStubs = true reportUnnecessaryIsInstance = false exclude = [ - "tad/migrations" + "tad/migrations", + ".venv" ] [tool.coverage.run] diff --git a/tad/api/main.py b/tad/api/main.py index 6f604c7ee..5b8437689 100644 --- a/tad/api/main.py +++ b/tad/api/main.py @@ -1,7 +1,9 @@ from fastapi import APIRouter -from tad.api.routes import health, root +from tad.api.routes import health, pages, root, tasks api_router = APIRouter() api_router.include_router(root.router) api_router.include_router(health.router, prefix="/health", tags=["health"]) +api_router.include_router(pages.router, prefix="/pages", tags=["pages"]) +api_router.include_router(tasks.router, prefix="/tasks", tags=["tasks"]) diff --git a/tad/api/routes/pages.py b/tad/api/routes/pages.py new file mode 100644 index 000000000..2f17fc96a --- /dev/null +++ b/tad/api/routes/pages.py @@ -0,0 +1,25 @@ +from typing import Annotated + +from fastapi import APIRouter, Depends, Request +from fastapi.responses import HTMLResponse +from fastapi.templating import Jinja2Templates + +from tad.services.statuses import StatusesService +from tad.services.tasks import TasksService + +router = APIRouter() +templates = Jinja2Templates(directory="tad/site/templates") + + +@router.get("/", response_class=HTMLResponse) +async def default_layout( + request: Request, + status_service: Annotated[StatusesService, Depends(StatusesService)], + tasks_service: Annotated[TasksService, Depends(TasksService)], +): + context = { + "page_title": "This is the page title", + "tasks_service": tasks_service, + "statuses_service": status_service, + } + return templates.TemplateResponse(request=request, name="default_layout.jinja", context=context) diff --git a/tad/api/routes/root.py b/tad/api/routes/root.py index a33a202e5..abe4fb080 100644 --- a/tad/api/routes/root.py +++ b/tad/api/routes/root.py @@ -1,7 +1,7 @@ from fastapi import APIRouter, Request from fastapi.responses import HTMLResponse -from tad.api.deps import templates +from tad.repositories.deps import templates router = APIRouter() diff --git a/tad/api/routes/tasks.py b/tad/api/routes/tasks.py new file mode 100644 index 000000000..e085922c9 --- /dev/null +++ b/tad/api/routes/tasks.py @@ -0,0 +1,48 @@ +from typing import Annotated, Any + +from fastapi import APIRouter, Depends, Request, status +from fastapi.responses import HTMLResponse +from fastapi.templating import Jinja2Templates + +from tad.models.task import MoveTask +from tad.services.tasks import TasksService + +router = APIRouter() +templates = Jinja2Templates(directory="tad/site/templates") + + +@router.post("/move", response_class=HTMLResponse) +async def move_task( + request: Request, move_task: MoveTask, tasks_service: Annotated[TasksService, Depends(TasksService)] +) -> HTMLResponse: + """ + Move a task through an API call. + :param tasks_service: the task service + :param request: the request object + :param move_task: the move task object + :return: a HTMLResponse object, in this case the html code of the card that was moved + """ + try: + task = tasks_service.move_task( + convert_to_int_if_is_int(move_task.id), + convert_to_int_if_is_int(move_task.status_id), + convert_to_int_if_is_int(move_task.previous_sibling_id), + convert_to_int_if_is_int(move_task.next_sibling_id), + ) + # todo(Robbert) add error handling for input error or task error handling + return templates.TemplateResponse(request=request, name="task.jinja", context={"task": task}) + except Exception: + return templates.TemplateResponse( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, request=request, name="error.jinja" + ) + + +def convert_to_int_if_is_int(value: Any) -> int | Any: + """ + If the given value is of type int, return it as int, otherwise return the input value as is. + :param value: the value to convert + :return: the value as int or the original type + """ + if value is not None and isinstance(value, str) and value.isdigit(): + return int(value) + return value diff --git a/tad/core/config.py b/tad/core/config.py index 0023c856d..6f2fea18d 100644 --- a/tad/core/config.py +++ b/tad/core/config.py @@ -15,6 +15,8 @@ # Self type is not available in Python 3.10 so create our own with TypeVar SelfSettings = TypeVar("SelfSettings", bound="Settings") +logger = logging.getLogger(__name__) + class Settings(BaseSettings): # todo(berry): investigate yaml, toml or json file support for SettingsConfigDict @@ -42,8 +44,8 @@ def server_host(self) -> str: PROJECT_NAME: str = "TAD" PROJECT_DESCRIPTION: str = "Transparency of Algorithmic Decision making" - STATIC_DIR: str = "tad/static" - TEMPLATE_DIR: str = "tad/templates" + STATIC_DIR: str = "tad/site/static/" + TEMPLATE_DIR: str = "tad/site/templates" # todo(berry): create submodel for database settings APP_DATABASE_SCHEME: DatabaseSchemaType = "sqlite" diff --git a/tad/core/db.py b/tad/core/db.py index d5317814f..dda4f7c4a 100644 --- a/tad/core/db.py +++ b/tad/core/db.py @@ -1,10 +1,18 @@ +from sqlalchemy.engine.base import Engine from sqlmodel import Session, create_engine, select from tad.core.config import settings -engine = create_engine(settings.SQLALCHEMY_DATABASE_URI) +_engine: None | Engine = None + + +def get_engine() -> Engine: + global _engine + if _engine is None: + _engine = create_engine(settings.SQLALCHEMY_DATABASE_URI) + return _engine async def check_db(): - with Session(engine) as session: + with Session(get_engine()) as session: session.exec(select(1)) diff --git a/tad/main.py b/tad/main.py index 7a2390d2c..68740234f 100644 --- a/tad/main.py +++ b/tad/main.py @@ -18,11 +18,13 @@ validation_exception_handler as tad_validation_exception_handler, ) from tad.core.log import configure_logging -from tad.middleware.route_logging import RequestLoggingMiddleware from tad.utils.mask import Mask +from .middleware.route_logging import RequestLoggingMiddleware + configure_logging(settings.LOGGING_LEVEL, settings.LOGGING_CONFIG) + logger = logging.getLogger(__name__) mask = Mask(mask_keywords=["database_uri"]) @@ -52,7 +54,6 @@ async def lifespan(app: FastAPI): ) app.add_middleware(RequestLoggingMiddleware) - app.mount("/static", StaticFiles(directory=settings.STATIC_DIR), name="static") @@ -67,3 +68,5 @@ async def validation_exception_handler(request: Request, exc: RequestValidationE app.include_router(api_router) + +# todo (robbert) add init code for example tasks and statuses diff --git a/tad/migrations/versions/eb2eed884ae9_a_message.py b/tad/migrations/versions/eb2eed884ae9_a_message.py new file mode 100644 index 000000000..0fc315225 --- /dev/null +++ b/tad/migrations/versions/eb2eed884ae9_a_message.py @@ -0,0 +1,67 @@ +"""a message + +Revision ID: eb2eed884ae9 +Revises: +Create Date: 2024-05-14 13:36:23.551663 + +""" + +from collections.abc import Sequence + +import sqlalchemy as sa +import sqlmodel.sql.sqltypes +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "eb2eed884ae9" +down_revision: str | None = None +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "hero", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "status", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("sort_order", sa.Float(), nullable=False), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "user", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("avatar", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "task", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("title", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column("sort_order", sa.Float(), nullable=False), + sa.Column("status_id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table("task") + op.drop_table("user") + op.drop_table("status") + op.drop_table("hero") + # ### end Alembic commands ### diff --git a/tad/models/__init__.py b/tad/models/__init__.py index e8084bec2..629df5cdc 100644 --- a/tad/models/__init__.py +++ b/tad/models/__init__.py @@ -1,3 +1,6 @@ from .hero import Hero +from .status import Status +from .task import Task +from .user import User -__all__ = ["Hero"] +__all__ = ["Hero", "Task", "Status", "User"] diff --git a/tad/models/status.py b/tad/models/status.py new file mode 100644 index 000000000..d8af1819e --- /dev/null +++ b/tad/models/status.py @@ -0,0 +1,7 @@ +from sqlmodel import Field, SQLModel # type: ignore + + +class Status(SQLModel, table=True): + id: int = Field(default=None, primary_key=True) + name: str + sort_order: float diff --git a/tad/models/task.py b/tad/models/task.py new file mode 100644 index 000000000..a652aaa03 --- /dev/null +++ b/tad/models/task.py @@ -0,0 +1,30 @@ +from pydantic import BaseModel, ValidationInfo, field_validator +from pydantic import Field as PydanticField # type: ignore +from sqlmodel import Field as SQLField # type: ignore +from sqlmodel import SQLModel + + +class Task(SQLModel, table=True): + id: int = SQLField(default=None, primary_key=True) + title: str + description: str + sort_order: float + status_id: int | None = SQLField(default=None, foreign_key="status.id") + user_id: int | None = SQLField(default=None, foreign_key="user.id") + # todo(robbert) Tasks probably are grouped (and sub-grouped), so we probably need a reference to a group_id + + +class MoveTask(BaseModel): + # todo(robbert) values from htmx json are all strings, using type int does not work for + # sibling variables (they are optional) + id: str = PydanticField(None, alias="taskId", strict=False) + status_id: str = PydanticField(None, alias="statusId", strict=False) + previous_sibling_id: str | None = PydanticField(None, alias="previousSiblingId", strict=False) + next_sibling_id: str | None = PydanticField(None, alias="nextSiblingId", strict=False) + + @field_validator("id", "status_id", "previous_sibling_id", "next_sibling_id") + @classmethod + def check_is_int(cls, value: str, info: ValidationInfo) -> str: + if isinstance(value, str) and value.isdigit(): + assert value.isdigit(), f"{info.field_name} must be an integer" # noqa: S101 + return value diff --git a/tad/models/user.py b/tad/models/user.py new file mode 100644 index 000000000..7b3d273c3 --- /dev/null +++ b/tad/models/user.py @@ -0,0 +1,7 @@ +from sqlmodel import Field, SQLModel # type: ignore + + +class User(SQLModel, table=True): + id: int = Field(default=None, primary_key=True) + name: str + avatar: str | None diff --git a/tad/static/css/styles.css b/tad/repositories/__init__.py similarity index 100% rename from tad/static/css/styles.css rename to tad/repositories/__init__.py diff --git a/tad/api/deps.py b/tad/repositories/deps.py similarity index 51% rename from tad/api/deps.py rename to tad/repositories/deps.py index 1a7c86223..988da5f84 100644 --- a/tad/api/deps.py +++ b/tad/repositories/deps.py @@ -1,19 +1,14 @@ from collections.abc import Generator -from typing import Annotated -from fastapi import Depends from fastapi.templating import Jinja2Templates from sqlmodel import Session from tad.core.config import settings -from tad.core.db import engine +from tad.core.db import get_engine templates = Jinja2Templates(directory=settings.TEMPLATE_DIR) -def get_db() -> Generator[Session, None, None]: - with Session(engine) as session: +def get_session() -> Generator[Session, None, None]: + with Session(get_engine()) as session: yield session - - -SessionDep = Annotated[Session, Depends(get_db)] diff --git a/tad/repositories/exceptions.py b/tad/repositories/exceptions.py new file mode 100644 index 000000000..863e32ea3 --- /dev/null +++ b/tad/repositories/exceptions.py @@ -0,0 +1,8 @@ +from tad.core.exceptions import TADError + + +class RepositoryError(TADError): + def __init__(self, message: str = "Repository error"): + self.message: str = message + exception_name: str = self.__class__.__name__ + super().__init__(f"{exception_name}: {self.message}") diff --git a/tad/repositories/statuses.py b/tad/repositories/statuses.py new file mode 100644 index 000000000..1855bdf6d --- /dev/null +++ b/tad/repositories/statuses.py @@ -0,0 +1,56 @@ +import logging +from collections.abc import Sequence +from typing import Annotated + +from fastapi import Depends +from sqlalchemy.exc import NoResultFound +from sqlmodel import Session, select + +from tad.models import Status +from tad.repositories.deps import get_session +from tad.repositories.exceptions import RepositoryError + +logger = logging.getLogger(__name__) + + +class StatusesRepository: + """ + The StatusRepository provides access to the repository layer. + """ + + def __init__(self, session: Annotated[Session, Depends(get_session)]): + self.session = session + + def find_all(self) -> Sequence[Status]: + """ + Returns a list of all statuses in the repository. + :return: the list of all statuses + """ + return self.session.exec(select(Status)).all() + + def save(self, status: Status) -> Status: + """ + Stores the given status in the repository. + :param status: the status to store + :return: the updated status after storing + """ + self.session.add(status) + try: + self.session.commit() + self.session.refresh(status) + except Exception as e: + self.session.rollback() + raise RepositoryError from e + return status + + def find_by_id(self, status_id: int) -> Status: + """ + Returns the status with the given id or an exception if the id does not exist. + :param status_id: the id of the status + :return: the status with the given id or an exception + """ + try: + statement = select(Status).where(Status.id == status_id) + return self.session.exec(statement).one() + except NoResultFound as e: + raise RepositoryError from e diff --git a/tad/repositories/tasks.py b/tad/repositories/tasks.py new file mode 100644 index 000000000..6de4f4df8 --- /dev/null +++ b/tad/repositories/tasks.py @@ -0,0 +1,66 @@ +import logging +from collections.abc import Sequence +from typing import Annotated + +from fastapi import Depends +from sqlalchemy.exc import NoResultFound +from sqlmodel import Session, select + +from tad.models import Task +from tad.repositories.deps import get_session +from tad.repositories.exceptions import RepositoryError + +logger = logging.getLogger(__name__) + + +class TasksRepository: + """ + The TasksRepository provides access to the repository layer. + """ + + def __init__(self, session: Annotated[Session, Depends(get_session)]): + self.session = session + + def find_all(self) -> Sequence[Task]: + """ + Returns all tasks in the repository. + :return: all tasks in the repository + """ + return self.session.exec(select(Task)).all() + + def find_by_status_id(self, status_id: int) -> Sequence[Task]: + """ + Returns all tasks in the repository for the given status_id. + :param status_id: the status_id to filter on + :return: a list of tasks in the repository for the given status_id + """ + # todo (Robbert): we 'type ignore' Task.sort_order because it works correctly, but pyright does not agree + statement = select(Task).where(Task.status_id == status_id).order_by(Task.sort_order) # type: ignore + return self.session.exec(statement).all() + + def save(self, task: Task) -> Task: + """ + Stores the given task in the repository or throws a RepositoryException + :param task: the task to store + :return: the updated task after storing + """ + try: + self.session.add(task) + self.session.commit() + self.session.refresh(task) + except Exception as e: + self.session.rollback() + raise RepositoryError from e + return task + + def find_by_id(self, task_id: int) -> Task: + """ + Returns the task with the given id. + :param task_id: the id of the task to find + :return: the task with the given id or an exception if no task was found + """ + statement = select(Task).where(Task.id == task_id) + try: + return self.session.exec(statement).one() + except NoResultFound as e: + raise RepositoryError from e diff --git a/tad/static/js/main.js b/tad/services/__init__.py similarity index 100% rename from tad/static/js/main.js rename to tad/services/__init__.py diff --git a/tad/services/statuses.py b/tad/services/statuses.py new file mode 100644 index 000000000..ea0bea7de --- /dev/null +++ b/tad/services/statuses.py @@ -0,0 +1,21 @@ +import logging +from collections.abc import Sequence +from typing import Annotated + +from fastapi import Depends + +from tad.models import Status +from tad.repositories.statuses import StatusesRepository + +logger = logging.getLogger(__name__) + + +class StatusesService: + def __init__(self, repository: Annotated[StatusesRepository, Depends(StatusesRepository)]): + self.repository = repository + + def get_status(self, status_id: int) -> Status: + return self.repository.find_by_id(status_id) + + def get_statuses(self) -> Sequence[Status]: + return self.repository.find_all() diff --git a/tad/services/tasks.py b/tad/services/tasks.py new file mode 100644 index 000000000..fc52b66c7 --- /dev/null +++ b/tad/services/tasks.py @@ -0,0 +1,71 @@ +import logging +from collections.abc import Sequence +from typing import Annotated + +from fastapi import Depends + +from tad.models.task import Task +from tad.models.user import User +from tad.repositories.tasks import TasksRepository +from tad.services.statuses import StatusesService + +logger = logging.getLogger(__name__) + + +class TasksService: + def __init__( + self, + statuses_service: Annotated[StatusesService, Depends(StatusesService)], + repository: Annotated[TasksRepository, Depends(TasksRepository)], + ): + self.repository = repository + self.statuses_service = statuses_service + + def get_tasks(self, status_id: int) -> Sequence[Task]: + return self.repository.find_by_status_id(status_id) + + def assign_task(self, task: Task, user: User) -> Task: + task.user_id = user.id + return self.repository.save(task) + + def move_task( + self, task_id: int, status_id: int, previous_sibling_id: int | None = None, next_sibling_id: int | None = None + ) -> Task: + """ + Updates the task with the given task_id + :param task_id: the id of the task + :param status_id: the id of the status of the task + :param previous_sibling_id: the id of the previous sibling of the task + :param next_sibling_id: the id of the next sibling of the task + :return: the updated task + """ + status = self.statuses_service.get_status(status_id) + task = self.repository.find_by_id(task_id) + + if status.name == "done": + # TODO implement logic for done + logging.warning("Task is done, we need to update a system card") + + # assign the task to the current user + if status.name == "in_progress": + task.user_id = 1 + + # update the status for the task (this may not be needed if the status has not changed) + task.status_id = status_id + + # update order position of the card + if not previous_sibling_id and not next_sibling_id: + task.sort_order = 10 + elif previous_sibling_id and next_sibling_id: + previous_task = self.repository.find_by_id(previous_sibling_id) + next_task = self.repository.find_by_id(next_sibling_id) + new_sort_order = previous_task.sort_order + ((next_task.sort_order - previous_task.sort_order) / 2) + task.sort_order = new_sort_order + elif previous_sibling_id and not next_sibling_id: + previous_task = self.repository.find_by_id(previous_sibling_id) + task.sort_order = previous_task.sort_order + 10 + elif not previous_sibling_id and next_sibling_id: + next_task = self.repository.find_by_id(next_sibling_id) + task.sort_order = next_task.sort_order / 2 + + return self.repository.save(task) diff --git a/tad/site/static/css/10cols.css b/tad/site/static/css/10cols.css new file mode 100644 index 000000000..332c07085 --- /dev/null +++ b/tad/site/static/css/10cols.css @@ -0,0 +1,78 @@ +/* GRID OF TEN ============================================================================= */ + + +.span_10_of_10 { + width: 100%; +} + +.span_9_of_10 { + width: 89.84%; +} + +.span_8_of_10 { + width: 79.68%; +} + +.span_7_of_10 { + width: 69.52%; +} + +.span_6_of_10 { + width: 59.36%; +} + +.span_5_of_10 { + width: 49.2%; +} + +.span_4_of_10 { + width: 39.04%; +} + +.span_3_of_10 { + width: 28.88%; +} + +.span_2_of_10 { + width: 18.72%; +} + +.span_1_of_10 { + width: 8.56%; +} + + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_10_of_10 { + width: 100%; + } + .span_9_of_10 { + width: 100%; + } + .span_8_of_10 { + width: 100%; + } + .span_7_of_10 { + width: 100%; + } + .span_6_of_10 { + width: 100%; + } + .span_5_of_10 { + width: 100%; + } + .span_4_of_10 { + width: 100%; + } + .span_3_of_10 { + width: 100%; + } + .span_2_of_10 { + width: 100%; + } + .span_1_of_10 { + width: 100%; + } +} diff --git a/tad/site/static/css/11cols.css b/tad/site/static/css/11cols.css new file mode 100644 index 000000000..a5624a7a9 --- /dev/null +++ b/tad/site/static/css/11cols.css @@ -0,0 +1,84 @@ +/* GRID OF ELEVEN ============================================================================= */ + +.span_11_of_11 { + width: 100%; +} + +.span_10_of_11 { + width: 90.76%; +} + +.span_9_of_11 { + width: 81.52%; +} + +.span_8_of_11 { + width: 72.29%; +} + +.span_7_of_11 { + width: 63.05%; +} + +.span_6_of_11 { + width: 53.81%; +} + +.span_5_of_11 { + width: 44.58%; +} + +.span_4_of_11 { + width: 35.34%; +} + +.span_3_of_11 { + width: 26.1%; +} + +.span_2_of_11 { + width: 16.87%; +} + +.span_1_of_11 { + width: 7.63%; +} + + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_11_of_11 { + width: 100%; + } + .span_10_of_11 { + width: 100%; + } + .span_9_of_11 { + width: 100%; + } + .span_8_of_11 { + width: 100%; + } + .span_7_of_11 { + width: 100%; + } + .span_6_of_11 { + width: 100%; + } + .span_5_of_11 { + width: 100%; + } + .span_4_of_11 { + width: 100%; + } + .span_3_of_11 { + width: 100%; + } + .span_2_of_11 { + width: 100%; + } + .span_1_of_11 { + width: 100%; + } +} diff --git a/tad/site/static/css/12cols.css b/tad/site/static/css/12cols.css new file mode 100644 index 000000000..58299ba09 --- /dev/null +++ b/tad/site/static/css/12cols.css @@ -0,0 +1,91 @@ +/* GRID OF TWELVE ============================================================================= */ + +.span_12_of_12 { + width: 100%; +} + +.span_11_of_12 { + width: 91.53%; +} + +.span_10_of_12 { + width: 83.06%; +} + +.span_9_of_12 { + width: 74.6%; +} + +.span_8_of_12 { + width: 66.13%; +} + +.span_7_of_12 { + width: 57.66%; +} + +.span_6_of_12 { + width: 49.2%; +} + +.span_5_of_12 { + width: 40.73%; +} + +.span_4_of_12 { + width: 32.26%; +} + +.span_3_of_12 { + width: 23.8%; +} + +.span_2_of_12 { + width: 15.33%; +} + +.span_1_of_12 { + width: 6.86%; +} + + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_12_of_12 { + width: 100%; + } + .span_11_of_12 { + width: 100%; + } + .span_10_of_12 { + width: 100%; + } + .span_9_of_12 { + width: 100%; + } + .span_8_of_12 { + width: 100%; + } + .span_7_of_12 { + width: 100%; + } + .span_6_of_12 { + width: 100%; + } + .span_5_of_12 { + width: 100%; + } + .span_4_of_12 { + width: 100%; + } + .span_3_of_12 { + width: 100%; + } + .span_2_of_12 { + width: 100%; + } + .span_1_of_12 { + width: 100%; + } +} diff --git a/tad/site/static/css/2cols.css b/tad/site/static/css/2cols.css new file mode 100644 index 000000000..995dc0cb4 --- /dev/null +++ b/tad/site/static/css/2cols.css @@ -0,0 +1,21 @@ +/* GRID OF TWO ============================================================================= */ + + +.span_2_of_2 { + width: 100%; +} + +.span_1_of_2 { + width: 49.2%; +} + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_2_of_2 { + width: 100%; + } + .span_1_of_2 { + width: 100%; + } +} diff --git a/tad/site/static/css/3cols.css b/tad/site/static/css/3cols.css new file mode 100644 index 000000000..4a07902d2 --- /dev/null +++ b/tad/site/static/css/3cols.css @@ -0,0 +1,29 @@ +/* GRID OF THREE ============================================================================= */ + + +.span_3_of_3 { + width: 100%; +} + +.span_2_of_3 { + width: 66.13%; +} + +.span_1_of_3 { + width: 32.26%; +} + + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_3_of_3 { + width: 100%; + } + .span_2_of_3 { + width: 100%; + } + .span_1_of_3 { + width: 100%; + } +} diff --git a/tad/site/static/css/4cols.css b/tad/site/static/css/4cols.css new file mode 100644 index 000000000..0f693919f --- /dev/null +++ b/tad/site/static/css/4cols.css @@ -0,0 +1,36 @@ +/* GRID OF FOUR ============================================================================= */ + + +.span_4_of_4 { + width: 100%; +} + +.span_3_of_4 { + width: 74.6%; +} + +.span_2_of_4 { + width: 49.2%; +} + +.span_1_of_4 { + width: 23.8%; +} + + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_4_of_4 { + width: 100%; + } + .span_3_of_4 { + width: 100%; + } + .span_2_of_4 { + width: 100%; + } + .span_1_of_4 { + width: 100%; + } +} diff --git a/tad/site/static/css/5cols.css b/tad/site/static/css/5cols.css new file mode 100644 index 000000000..cd62f96ff --- /dev/null +++ b/tad/site/static/css/5cols.css @@ -0,0 +1,43 @@ +/* GRID OF FIVE ============================================================================= */ + + +.span_5_of_5 { + width: 100%; +} + +.span_4_of_5 { + width: 79.68%; +} + +.span_3_of_5 { + width: 59.36%; +} + +.span_2_of_5 { + width: 39.04%; +} + +.span_1_of_5 { + width: 18.72%; +} + + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_5_of_5 { + width: 100%; + } + .span_4_of_5 { + width: 100%; + } + .span_3_of_5 { + width: 100%; + } + .span_2_of_5 { + width: 100%; + } + .span_1_of_5 { + width: 100%; + } +} diff --git a/tad/site/static/css/6cols.css b/tad/site/static/css/6cols.css new file mode 100644 index 000000000..7c46d9ab4 --- /dev/null +++ b/tad/site/static/css/6cols.css @@ -0,0 +1,50 @@ +/* GRID OF SIX ============================================================================= */ + + +.span_6_of_6 { + width: 100%; +} + +.span_5_of_6 { + width: 83.06%; +} + +.span_4_of_6 { + width: 66.13%; +} + +.span_3_of_6 { + width: 49.2%; +} + +.span_2_of_6 { + width: 32.26%; +} + +.span_1_of_6 { + width: 15.33%; +} + + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_6_of_6 { + width: 100%; + } + .span_5_of_6 { + width: 100%; + } + .span_4_of_6 { + width: 100%; + } + .span_3_of_6 { + width: 100%; + } + .span_2_of_6 { + width: 100%; + } + .span_1_of_6 { + width: 100%; + } +} diff --git a/tad/site/static/css/7cols.css b/tad/site/static/css/7cols.css new file mode 100644 index 000000000..ae81184e3 --- /dev/null +++ b/tad/site/static/css/7cols.css @@ -0,0 +1,57 @@ +/* GRID OF SEVEN ============================================================================= */ + + +.span_7_of_7 { + width: 100%; +} + +.span_6_of_7 { + width: 85.48%; +} + +.span_5_of_7 { + width: 70.97%; +} + +.span_4_of_7 { + width: 56.45%; +} + +.span_3_of_7 { + width: 41.94%; +} + +.span_2_of_7 { + width: 27.42%; +} + +.span_1_of_7 { + width: 12.91%; +} + + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_7_of_7 { + width: 100%; + } + .span_6_of_7 { + width: 100%; + } + .span_5_of_7 { + width: 100%; + } + .span_4_of_7 { + width: 100%; + } + .span_3_of_7 { + width: 100%; + } + .span_2_of_7 { + width: 100%; + } + .span_1_of_7 { + width: 100%; + } +} diff --git a/tad/site/static/css/8cols.css b/tad/site/static/css/8cols.css new file mode 100644 index 000000000..0ac2a476d --- /dev/null +++ b/tad/site/static/css/8cols.css @@ -0,0 +1,64 @@ +/* GRID OF EIGHT ============================================================================= */ + + +.span_8_of_8 { + width: 100%; +} + +.span_7_of_8 { + width: 87.3%; +} + +.span_6_of_8 { + width: 74.6%; +} + +.span_5_of_8 { + width: 61.9%; +} + +.span_4_of_8 { + width: 49.2%; +} + +.span_3_of_8 { + width: 36.5%; +} + +.span_2_of_8 { + width: 23.8%; +} + +.span_1_of_8 { + width: 11.1%; +} + + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_8_of_8 { + width: 100%; + } + .span_7_of_8 { + width: 100%; + } + .span_6_of_8 { + width: 100%; + } + .span_5_of_8 { + width: 100%; + } + .span_4_of_8 { + width: 100%; + } + .span_3_of_8 { + width: 100%; + } + .span_2_of_8 { + width: 100%; + } + .span_1_of_8 { + width: 100%; + } +} diff --git a/tad/site/static/css/9cols.css b/tad/site/static/css/9cols.css new file mode 100644 index 000000000..25e834a5a --- /dev/null +++ b/tad/site/static/css/9cols.css @@ -0,0 +1,71 @@ +/* GRID OF NINE ============================================================================= */ + + +.span_9_of_9 { + width: 100%; +} + +.span_8_of_9 { + width: 88.71%; +} + +.span_7_of_9 { + width: 77.42%; +} + +.span_6_of_9 { + width: 66.13%; +} + +.span_5_of_9 { + width: 54.84%; +} + +.span_4_of_9 { + width: 43.55%; +} + +.span_3_of_9 { + width: 32.26%; +} + +.span_2_of_9 { + width: 20.97%; +} + +.span_1_of_9 { + width: 9.68%; +} + + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .span_9_of_9 { + width: 100%; + } + .span_8_of_9 { + width: 100%; + } + .span_7_of_9 { + width: 100%; + } + .span_6_of_9 { + width: 100%; + } + .span_5_of_9 { + width: 100%; + } + .span_4_of_9 { + width: 100%; + } + .span_3_of_9 { + width: 100%; + } + .span_2_of_9 { + width: 100%; + } + .span_1_of_9 { + width: 100%; + } +} diff --git a/tad/site/static/css/col.css b/tad/site/static/css/col.css new file mode 100644 index 000000000..e07140a90 --- /dev/null +++ b/tad/site/static/css/col.css @@ -0,0 +1,42 @@ + +/* SECTIONS ============================================================================= */ + +.section { + clear: both; + padding: 0px; + margin: 0px; +} + +/* GROUPING ============================================================================= */ + + +.group:before, +.group:after { + content:""; + display:table; +} +.group:after { + clear:both; +} +.group { + zoom:1; /* For IE 6/7 (trigger hasLayout) */ +} + +/* GRID COLUMN SETUP ==================================================================== */ + +.col { + display: block; + float:left; + margin: 1% 0 1% 1.6%; +} + +.col:first-child { margin-left: 0; } /* all browsers except IE6 and lower */ + + +/* REMOVE MARGINS AS ALL GO FULL WIDTH AT 480 PIXELS */ + +@media only screen and (max-width: 480px) { + .col { + margin: 1% 0 1% 0%; + } +} diff --git a/tad/site/static/css/html5reset.css b/tad/site/static/css/html5reset.css new file mode 100644 index 000000000..1b135a09c --- /dev/null +++ b/tad/site/static/css/html5reset.css @@ -0,0 +1,96 @@ +/* html5reset.css - 01/11/2011 */ + +html, body, div, span, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +abbr, address, cite, code, +del, dfn, em, img, ins, kbd, q, samp, +small, strong, sub, sup, var, +b, i, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, figcaption, figure, +footer, header, hgroup, menu, nav, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + outline: 0; + /*font-size: 100%;*/ + vertical-align: baseline; + background: transparent; +} + +body { + line-height: 1; +} + +article,aside,details,figcaption,figure, +footer,header,hgroup,menu,nav,section { + display: block; +} + +nav ul { + list-style: none; +} + +blockquote, q { + quotes: none; +} + +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} + +a { + margin: 0; + padding: 0; + font-size: 100%; + vertical-align: baseline; + background: transparent; +} + +/* change colours to suit your needs */ +ins { + background-color: #ff9; + color: #000; + text-decoration: none; +} + +/* change colours to suit your needs */ +mark { + background-color: #ff9; + color: #000; + font-style: italic; + font-weight: bold; +} + +del { + text-decoration: line-through; +} + +abbr[title], dfn[title] { + border-bottom: 1px dotted; + cursor: help; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +/* change border colour to suit your needs */ +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #cccccc; + margin: 1em 0; + padding: 0; +} + +input, select { + vertical-align: middle; +} diff --git a/tad/site/static/css/layout.css b/tad/site/static/css/layout.css new file mode 100644 index 000000000..ba95ff452 --- /dev/null +++ b/tad/site/static/css/layout.css @@ -0,0 +1,113 @@ +@font-face { + font-family: "Rijksoverheid Sans"; + src: url(../fonts/ROsanswebtextregular.woff) format("opentype"); + font-style: normal; + font-weight: 400 +} + +@font-face { + font-family: "Rijksoverheid Sans"; + src: url(../fonts/ROsanswebtextitalic.woff) format("opentype"); + font-style: italic; + font-weight: 400 +} + +@font-face { + font-family: "Rijksoverheid Sans"; + src: url(../fonts/ROsanswebtextbold.woff) format("opentype"); + font-weight: 700; + font-style: normal +} + +body, html { + padding: 0; + margin: 0; + background-color: #FFFFFF; + font-family: "Rijksoverheid Sans", sans-serif; +} + +.header { + margin-bottom: 2em; + border-bottom-color: rgb(178, 215, 238); + border-bottom-style: solid; + border-bottom-width: 0.5em; +} + +.header_logo_container { + padding: 0.75em 0; +} + +.header_subtitle_container { + color: #154273; + font-size: 1.125em; + line-height: 1.5em; +} + +.header_logo_image { + width: 180px; + max-width: 180px; +} + +.container { + max-width: 74em; + margin: 0 auto; + padding: 0 1em; +} + +.header_nav { + background-color: rgb(0, 123, 199); + height: 50px; +} + +.visually-hidden { + display: none; +} + +.margin-bottom--large { + margin-bottom: 1em; +} + +.margin-bottom--small { + margin-bottom: 0.5em; +} + +.margin-bottom--extra-small { + margin-bottom: 0.25em; +} + +.progress_cards_container { + min-height: 30em; + background-color: rgb(229, 241, 249); + border-radius: 10px; + margin: 0 0.5em; + overflow: hidden; +} + +.progress_card_container { + margin: 0.5em; + border: 1px solid rgb(21, 66, 115); + padding: 0.5em; + border-radius: 10px; + background-color: #ffffff; + box-shadow: rgba(00, 00, 00, 0.12) 0 3px 6px 0; + cursor: move; + user-select: none; +} + +.progress_card_assignees_container { + display: flex; + justify-content: flex-end; +} + +.progress_card_assignees_image { + border-radius: 50%; + height: 35px; +} + +.text-center-horizontal { + text-align: center; +} + +.as-inline-block { + display: inline-block; +} diff --git a/tad/static/favicon.ico b/tad/site/static/favicon.ico similarity index 100% rename from tad/static/favicon.ico rename to tad/site/static/favicon.ico diff --git a/tad/site/static/fonts/ROsanswebtextbold.woff b/tad/site/static/fonts/ROsanswebtextbold.woff new file mode 100644 index 0000000000000000000000000000000000000000..6f0e3c819eca6311a8fa8d4e7c9e7dcb436cfdc9 GIT binary patch literal 69467 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 Z)i#~}|8=^LsxAs;>-qm=_a8qGLmyP-&%6Kt literal 0 HcmV?d00001 diff --git a/tad/site/static/fonts/ROsanswebtextitalic.woff b/tad/site/static/fonts/ROsanswebtextitalic.woff new file mode 100644 index 0000000000000000000000000000000000000000..7e74d6692834f0061b2a9d8f904cc5566d2c1f09 GIT binary patch literal 84044 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%0A^tJtbs}qGM5GQbB=py!+TZ0 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�tIG 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 Cil=V? literal 0 HcmV?d00001 diff --git a/tad/site/static/fonts/ROsanswebtextregular.woff b/tad/site/static/fonts/ROsanswebtextregular.woff new file mode 100644 index 0000000000000000000000000000000000000000..624c3f89a784358d6a72548ce60260b154783505 GIT binary patch literal 76489 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�AQav)eo_m)+_OR9EsBN&%nOZt?hn{H9SZlJQxHWignF2&b~s@q^zH!m!m|MGcr^4Z z0%&Q_*a`*O?i9apy!mgkiI41iV(yI2>iCRv8XC{+jKpW0TVkCi5^ha<+{rwf6jB~@ zbjHGI(=VSLkM=C=?!J6Z;6D4{;UTxB5*HGsXxr ze1SC?C>%|ctzflnN$~cx|^~fN-OUAa$;Xf@tcEx;Wl7mtnjX9)eRM~0$a2l;nf@b8k6SJ&yS4n+-COdIih{ZB*AQV6+Z3dP)*EsKVA~S@O zz4CGA^MD9@7y3xaX;9Eslw`6_y14*LR?1627`VT*BzOx78KY;H9*;dA6BZ6s#WJzZ zn8*gD7_vmf*2M0NL0*l~n^Q5eS!Pm7UfLxvRV>Cb`UZ$e{b;-EL2f`Pu7~|>HAp{v z-%DiuKm?b(8e|ouEsCK!0XQO$cz(x<1XBW5=H8quW za~l2jP<>>cBj9lw`L>Zeyn0V0Q#IRLU8%_Uu}F;n*<6E3FS=7L)xm~zTuPW+9$$rc z$_#gHvZf+wtEvi0QqXM`^hWSVZ1ijy?n|)>1*ge9DcDQYF_DGWz( zIhrK>!Ovkx{6~;ZtYsf-m{K@#u>-asRpb#if`~j#2ua>Wi|SnIf#hRw$KDC7$5^sC zDO}f=@(h<=O}&$14ZkFHOX?1kEQO8`O(p3wqU@ zU*$(Z-UgSr5kf$DasG<#Cs->HbSd@maS`F4hq(2Ok?w|3Xx699X3%C35 zpjB`YUJUXVg#Ph>O{xTW0^Ij72!XR8$yO8c}_mv+nR9-hH$n! znLBrS%}igWBN}R~@#=IYqe1Ah*A`~iD)UZ;@#7o(5jL)R`HFr=)QqT)s1d%Hh!%7p z;6g{Du}*TQs5L5`Q+_*N7UG4WbDKSV?0zhD4Tf-jOXbMl}ZraM_93$u#~C- zSpttBMTd;WKa94}VMg;!^d(W8Fhh#PB~I`OLzKZONV95w1V` z+8J|BfxO|(bR`_&P^f}GH0PJRAOu?H)wf?dD?T&O*prO3)Ks!_0^dk|p@+#}FAG26 zVq6!0Re!oV42xuSGixypJh1`u%_2tF;G=4f7ool-R^NzdF%8NRmgH}Qm3P7N7U2kCJ!p7jC9>rpL9_gk2lci_>Ff?zRRdN#Kg&MNz$ z?cLo9-&7AZo^K-3Af!pLLU4N~OOpR*PH)4hU0EA%4}`0w`uT04aA84x?zHw$(?vHt z$P2uyrZE((k2qb4rm(X*=ofy{>uWrvNibRrVlaP3Q`sbgUp|pcl}if>w-XI+!;871vb4ShQ8Ic0L!T8Bd(jW5vAuEshzNP75!n zYX8dgk*E1XvwMDg=RIegb;qs$JWFINm~Pf5UKj4-GTaRAJmJp%xrDMJMb2V0M{C+H zTBR(aRSK}2ku(lDi;y)gnrq7GSkD3DaFD@^*jrQvOt9oAH$v9Z4YSgLz zWK)vexd^L_MM!a31le$wmiDpx#AP7qb*og-;KRpAhkHmxAjm!OujSEZn5Oa zFSeIX%4ulcB5l3O(z&lrB=`PPX=O~&u>_wXhtYTzjCh}7#G_!fedtHeL-AJ$=$vXO z^@6~8eXZwRxOZ8QU(J6WZafbSzKVc6K=f$(#n`(YF}H7u@4*L1hvl6IWK&rP+6}S^ zBl=;?p+_*7FY~X(a>Ih<#u5Lg*e8Iy-6+p)l!sEu9R$%qGJx{Qb5A5!Fqvr@B>Vl}g6R1cVP>`OTw|5>B5}rL{?-}flhmbh$ zNsth}^fR_s+H&4jsH5*W54z3sPGCR8KAzVE`pJpl)G!%e8K+JW@?GgMfEgU~Qtj-f zKt;GQnhB-+mT31G*~ZiJp^ECJnpkB(GKJgbMt$j!WMsqdEMJY!DuwH;r}^Vvt1I3V z4&>r4qbniY<*Vz6gjyPET|OxmPkNFwa{*s{cOux_ka77dLa~Imrl&d7BZZRQ%CO&K z%{XI;jL(w@RE#`Q=cq}hz5d#;!x4(RoWWpNnUlW4zr_Dlos*iYUC3!vokowtbObSG zY&zo57&IqsU__mh5c{pnNgT~in3JStH3Wkjn}#On3fKUoOh|rCoseK=W|h6C949+r zLQ*FqxVp5%HN3uEos$TSV^?`v31MP7j3M#_h#ezl2qMSJ@X>T(MzO#h?PKu&K~hT4 ztoAX86+_)Kc+6&l=Jm7=Gtm){U04#m0rCv^bT5bnfrTe96K%o#^I~QQdf2UXC=SRj zc=Nph@(kvrml^RXf<+-c(IE;<cGuYjdsVQyvVMMEossgGksc7( zlvG)h!;~bskh8BkusT?1zoxm*9jljOFvm5DpRxoi4 zb~q9pu|vLe@(Q*h8Ovet2!PR=V1YQm_WEjS*&>UKrvxI0>lCM|$FXer7$gW21OYt% z9>jt}EWS$VYyk_L`?C}D5i`ciKJBW?#XsD~`G))Ws$m?OT-YcRCzJB07bW&)KT^#U zow;HqJ5fm|`dqGI+3O+(^fJ-ed(0~=?DJTM0f!nGltUh`>O&bHloNCv8Gi?=5}8D2 zLZn%A7&G!_kQ+gQsI~vX-d{0I{SvNO&qy!9HOmEGEJ~<+7z($;6g~egc0+7oJ3&+A zg~s;wo~=$H+HrdJwx96f)>@zN&1RiR zC$g2qB3{%@i=22j!rwCTr}nRWrLJ+|IWwe@KmDha>z>2rX7I#kDo@PhKU6t_xIpEI z>U0OA8N`l%0bh(FVc7vjiXAGbqqo_EEt;+eN`pr*`qwvP zsCMDlT>!YI1!M)1hW?&1hl1P>^8V~8*@4Xb{~zp-oy-ndsjtd4+&A4ajNLlxu&7l@?Qt0x4ou4<+k~gRmsXg zrG@|F$X{%{%^UU9yQ-XKn=j_F`@H_C_;Y5bPOlTB>TJNBsEIoLRRV-ZKl z&cy5rhu>-DX)x0;!sa0T)j8lQFN5n<~(KPG9$lYM+Zunv(;NZO? z&-gu0ZoADn?2y4+UeV4kRD9}SgLwpaxd%Yt{MXmR#>|e+9x7ai;(OOSSnSQoch1N7 zIG;WC_t;wj62#%h^D$h`FU-eqIe&rq~iuOTJV(C1`rL?~~qbg38Uzs|q!*m4IK#qN918Zd^hW&=oY;(} zbfFbrhPMN`)lgW}vmi$(L~Ax==8v&*f>loeG*l4X@v6{lbgkAe*2sO%IN$qTh1nB` zx`WxUBhqnJV@IK;z&ch{DqwOtofd0NXG7G?U;KF!z~VxyHy-v`1)V#b@>aLkdh>SH z`J5qlg{U*Kj#h7~ie;*rKX+Kl7iB4zgLoO*SYF2mop;CJhL2iU)-GttaNrRqhve)BUYgBbY(XeULR4rHbW=V` z{J(eQUvq6Py&<_^%xl&Z$q!+I1Go;C^PE$yqlpf{~ zUQpIUvNd8;vwW*v(;M!^-rI~6C=0c+cJRd;#b$S^BQY!4o^rXE3LfZZ3uJ2rP zMMLxDU;kEj%eDXTja|rypQba17Q&LK$ zS4t(ZQb|-QUbdn{gcY}sP-+NF4iIhy%?1h%ZLJm$Q{fVYq}!8jR|+?*7VheQ=x)9C z+H&D|?yIBcaK~BMjNEzsx?1ReqpIqc%A_tZkdId0HHNq)7tP=gLvF(Ix=&!^6ViiW z^40+X#Dy3G_V?A>F1qM8VMF1w#&+OBvUhH#cb?wQ)rzb>M0F*jw$(24KD^{zEKij; zak(+cp$ozDoDz@9-dKJaBzPzL+l-ezQV{-tcLhdI23E1ZZ-uN++O(KKIeWFcJo((fcpVt2t&{d_v}}L?=VrK*RiyI zP5qtq57s|k|9t&x^+r~^2!oMNz~*jqhv4h}J6M5{?Z-c`iO(A#2O40KI!SIx|mxKL`NXuf6iGYnX>Z3FkT<%xS}GZoJ`uh-qIyH&SI zSJLg!y{tQ^GqEA`c^7gQeB{zCESX$>7eIKQ_q^tL*YlAFr#yZSPVEZr3my)B5@e?= z!2oO8UgwhfTk7wqf1v)c`seC_>_89ec&+2zj*mKUXNSK-xQ^>}-YEW1yhnUkd{W#k zz9AkFaosbnmt1eU-or~pmy2HdjQb_`o9_4AIOTS^>6GUs&zqk2P!7@KqH??#910!{ zohU}{BZQ0G)N3+jn_h#S9vgbP&*RQU>z5f3Cf%={GuhhRyW!us5a>v1r zVU$hR;bvtklwJSxn7v6Wly4M?m*SeNOyfD@vXUd5@)2YCYut>nni*q795#O(+(wM$ zw1w)U(fW{W^|QoR3S)VlPZ48@f<%nvXN(2Ig1sv4-NP8m#TcuCF&5bwe2jFnaZltT zLOWZv0TI_$3-8XV+5lmF0euMByJgNq#_{!D%}HPs0?K-jK@h=fC6qxcMd!C^iNY0A z8JyXVLI1mm5jLbwXJe{gZVM0yZh(|G%Hu7{?dxIw8U=ytmD~+7h{N>|m%9<*Yqxn6 z{J&zwV6h@c>L9i-o6c5dep#X)Wv6nDM*})s0mb4}t1iwNH7szlt*O z1OsH;3uxMi?ICtYnB5U(cU04lazrWn8cJ(m&S^mnq&V*ykBm84(>uWpLVkozC~Q&O z$6459rKr*RD%s*unSdx50(EGn8PE(DG0cW+5h@KryEYkP|`3 zu$fy)otY@Zi>)jJs;c0knB8I&nZlzh0CxjDuzfa%69wwCenk} zunoJien^(s!lbX44*O13G8x~6`XMk&z$y3Iw{TmzUEDtIF!u>(SSagJbISpG^sKNK z5kMYP8+7^d2Otj!8Z@#GIF5cqG@6jgOIg&sil;9H@#7UA5)L_#p%)ug17C9uI`uN3 z5H6F}BAN1H?`k-CnK3k2p@fBPucVK7U{}#2JX)XhB$*UpsSDI0Q72YWtC0y5DDnW} zg9>R~2f`RSj*agY(7t((M27C+xOwJOGD{g?bM z7z-mG6gpxZ8DF5GJ6co7_^KMZL++^GZudt$u9)9$^Tqfr$^~7qu?u{5yD#c-;{tz7 z_=WeggbA z{YSTUeE;FT!QCj%nb3#6MZITk!xBa>R{PVH6Z=ys!L=b$QRy>NbQkI*V|`|-0z+m%%=HtyGI|->|1xOUJi7V%#v#^fSG#8x(s1bY4LSJJ2 zhn40&xcRTpeEsE>SK_f(;;~mYU5UqDdEm<9SF*?M`4(>aR`grwfJ^YqCDA2KOYqDk zxaa%uG6q@p{V(o&I5?FZoH}JkJoUfP5uuQ%m-^0Ey5rxmO|R7V_iXcbQt`VqeBX?Y zvkZiKDWGjj=$YVZE{Ik+f%E@_F>N!*vt`V4vcPQyd3GG`E%n=1%ANNXOy<;YO%VNk zU&S7X?{e&c7{3m34GzD9AC@D0(!}}kazgfA1$l8X$XfK}<><@HrFGC!FT<2^1KzP3 zFdT{;C%f@JJ(02QOabAt6^fL_jjJ2k&C8(yU55orxkt);84YO9wVw>gj*Ue{} zWv8z_9d86o;X1$+EVe5ko{1GdVJFyb?s1lSO4u%$1hu*8=(KKG@yN zS~7)kYRPGUu#m8{Pq!LRv7Ke(-`ul@$+ql0e2U&<}!SSS=2i9bUWLE1CT9h#}Ktu$pv2rQPSWn4SI#sl6k0gJ`ii z6g^P`|1viqJkH8`b-yLS=7bW$*99$neV}OBZW*+Q3(G|v*zY*z7k4POz9Z%sADJdo3$G$XsL=`mp z%b^e^1^-r%7YG6jL}<{ehEQzBwIcL`Oul!}E1U@FnW9~Ne?voW{F~a|G-drVUf?ez zUdZx%e>8!NkHi!53UVB0HCl!@kR7OBgfGi0pv;yK$P8u?Ce`(R>6kQ%x^_sBvAQ0B z{dCle)7}UovWwB}QFiNuI^Lf;mKsGJJ5rIcIxaoY@B#u^$7-1>ee=W$o`Uzr*D;%W z2lm+x+di?e$6IUx8)Nl-HHT|HsljngphmdvBt}h7K5^i0tNvwwQ}v@Sj{cMz;1;v` z|E5~+P&qP=q&|okY5iD~_}|tUUzpeT%!ZNQHHMc`H z{V|qF7g~+JgTMI2MZfq(;+0qa{SB05J}b*iD$C{le7z2Huv!dy<$y9SW4u&y87gl_ z2~REnbn-(=jtfao1rR0_z~w{Ajr*to{Gd_-@FVKuJt~8h+tF{ShptPhmz7XTePNYA zLYY__rA3yN7GXT665!9ke$z42DDw7@&!v)=V3Bd95tkYzBfHcj^_lC*Mqp*%^aPe{xVkY%9jgN_aCd@ zUF13DUyyMErer3;}lg)~+k4IC* zZ?J7ddTI%gqACD}T%kN$f@y6!8$|p{Ho#9nEKqQC2DA~TjQeFAlARtU>kYf1*Lsih zVds<1-Oe|hY+&nxKgY*xRW)FCRyi|H5#J?CPUU*|q6mYs%ShTxv$CmhnbqWdxP%Jk>vAo}->6xDd*@a{l7Eizm-d5(UOxgZ6fv`gUcx;At&*(s7R~?#joFd0*=z zVyBo`v?!r&gqGE-le%`X{j=TP>dp1}*d>9F(wnaxYPPAHD4gZ$pNt93NYX{kPHqv z&x8d62_%NeQW{$U^q3sJiV7w)m?UpSh0kFsRQQ}`ljL{UeG=PxC&`mb{}<%R3>?O{ zL7pVZGJr!8FS-AH@lsIgk$;V1l)w4KH3|EPo1h1(2Nf+7EZp)6kPHqvKp1M?4RKb+ zIBYUdGGJxkFep%FhRKUlR?p5atM|#r{9Th8V&vD8TZZIj_1iMsL;ckWWJ}?y+2X2L zy}f#{S|q1O6;ZBcxYxRk+rugAE`1qRF5+f`GhpKcx|&SD1N-C0;-hi2UOW8k4~x_{^YivqJE}YT!^gw zPY4%sOR4?4x##*@YHHzQTI0qV1KdzTjR=UBfLkc}-VniJ^bwFAbh6_}IjKl+>gtsI z3`z&8k5@xrtCp(q3#)gC1VHzT))JGoY;PHCInZ*v1x$ui_EC^+0O#eVPwu1>7;7Si zoDq(Jl2^Y{Ny}&=@=;uOgL|Qs#C5TV<@BkXACbP5@hFDmwuNmvMChxi95u z2XbG^+wKJ>T*lBjhOMPyrIj)joq*I*lFyV<&UR-R$Gw#DxBJvxBlv`T3y*%xZv zIzFjevtg0-Yoy#_HHV;S$eqgkt0c3Usx~L!xR88_ST1y38wLKjS*1Dv5v#%Lk3%3! z>Dqxn_BYoOr>4c71UQy4ccNXCgtcYBvC4L|OUl*mnxsa-uwiuN3l~hT%*$B~^Zk>m z^0TdGK0BaObqy!@YZ!m#xdo!3p9{y>IAEpBNsG!UreF;&ZL{vNGNwhQG{&^vvfEwl zaIbm0q-g$hn&wYl1R;gflIM-(#SZvSr^%A4^ZtorJJW%g` z^|Iz#b{c!_EvMaanwBkzvTJKxK9?QL#hlp98pSyz>zkeAgMfU;OZ2w@U^cBU0Kt@N zR&oIAos{0lT3}VGxuExYu9a?-ekk1|JuE#b?UvqliU&(Idi1*rSTW-kd$jse_wPBtG`?DiSK~ikMG<`?rZq0 z`$K#=D+Rd)>yiH9hSpUG0Pp~e&`sfgh0X##q@%L~n;D%mu<7aS!S~E;pNY+^_F34> zZ=a9Ng7yUhB`|~2J^2$EmDscKp7&Ztgvqd^{54i@+}~k!S`DJntnW42%zBeE=<1NX zc0)xVT_r_hF=u5>JmsnFt@n+5deX>e_SYqAoM}^KrORS*S2|64qs!~HIHRFZMXk;2 zt8!F^JyxC3Vw{C!Deh$3NX6t~684+X3;CrqPA(9>-JcI*Zm)|*ps%T86<4g=UdQU` zID)4*K>FAHZNujZI1;WT0vDF!ARJPf79-mujKS+PyaL>mkt&J|&`=?BbaiQI zZVdvJ3pw_MbEUp6*7x$cE{ZkHwU;m)0bQ>wY5YyT5k(N!RO8??M0J3-zCIf&r3oglA*JdIo*n@ zFPP8&_va4TgOV9R-beA)pir-Y97cI|gB(Ip_JQmM`4mO@7)7xl4M7BCIS}Z62ogq- zLi72PW+ic4-$@q~AAGHEjYoglJ-ILZg!+=rY1L2YO9dv387hM4OVLaCtQaY!hqr*B&yzIYszj12g_~;6i^Ijq0(YuH5`WqG~WY` z9D-m&=Y!oNgWbZWfC=9{{OHR@-u@0d5bh(ASmfPKeLr|_jIWrc2mR3151VxGF3D^;RoQS^%nHk17$xC0~BQsq4)t&@m}Da6!P%^0yj9G zyLj|m?oRRpo!!sZVl{oB9C&en@IO#NBYHKtbZMXdFl_SM^{PUCJQu;o-Wk8Rr$^Xu z;%PRHk3HMSeP#U9@nC$sW;B;a;7+sxR`z}7!?3b%pUS5n=7&MFFjT}t@_s!+ckoK5 z@>;xjaQRxbwKb7k2fZO5UwstFB|TJ#s$zxc0)w6(a+8YOm@T zfaLJS^P#|!B}^{oBZq@5eGN(D;0&|v8aNMu)Zx$v^7b{_OrXU`&_RwJSmx%QrGR1)qChl989CZ$gS=hj_gxG~ecj?PJMOzgNt<&OnG=}Ga+}=8f2?^5X6LJO%EY$(-wqZ-UBiUGK|r8 zGsxp0{fI`}0pdkSTIqCvpu)39kMweZg>Wo<9v}0X}2WbN!5)XRymR;lsD!n=SbI2l2TdfqaZF{Vm92_|oUg5qN*a z=WYUVpAIJ}kO3T)Pz5$rfuB`@-g9zTI4KF@lk#U2oRh#y#^>A^e=O8g#*^7V?+usc z7p&ZT@wq>|x==g&+*)5eSg8}8@pP>>+?@2JXPsSZc2!oIW*O{GYq(G!Xt-d>f(7fo z)ssE_$_{sJs>W+{GNCWnTI;iULQ+L_H2$4tprF=W{G-3S_R;?{x9zf3XV3ZGIa#Z> z#^;H7t={IdI%a?8j9OmQ3HFfBF~3A z&TXsfj8&K_L$E83eklA>xQm<1AMQ_vC1lMF!_Q}CWSW|XN6XK#9gfV~Rs2e26}O0D z#HFkX$4zQu*%1Je*&v0O%g0;rfEEd#GO4YL;?p`Qc3Q zpyhG&V{1JH4+oU%*s4CtlhLlg1CgwN-)1Pk&B&ED&L}dL?3>QUh+gt9d>vE55lZ5N z$gPhtC>+)hm7W1_a)ucu4FzI%7z@F{DN#{G#rE=77SGYtH)Ewn2|g0+vcj=oNTDAA!ZWI!9-&)F|#=+=nT3!NFL<~rM=blp^7=~cw<$l zAu7e^T{CyqtaE?x)kbCh$&b$Gp*wSN-w_x0TcVAOKO@ywLpO0XY&BOSHWBWSi?9^A z^y&y&>r%Fii4K!||ot^>z{JboSKvgyjqdoAP1YY`iC(X|Lj zFJ6?Bw_SuB?2IQf%Bf6_AcEY=(X~=vfbrpUsc$~xLr-8nMZIS(q8ze-4r^8RAH+(2 z7TqJyR<1htq73~4gp~&_ee6=kNS7-Y-+wv9=$1BxOPGVU0R82|I5NJ*eR0+o7qjj> zphN~S;pZuI-Cwr!x3Kx)rIt658t>*7E$85Ok#q2ut^HVNQwqgZAlD&(>c8gu^6ZvB z(fi>(E>oVN8eOgCpk5$Vo=wkM)*DiS%8Ge^t0yry>yDwu;eetrP%Z^^g3ViS7IJ$i3@}rlt zqhI4__Z4qkapVg2#(S^$)fMas`>s5ECENVw$``K$E*spPAHM3ztJtYGt~$at^6!w0 z_K~mS1%Hn$01t(qKvlg5ux_!&g`^07L5=ZoC#$j2AF_YSBI7*9L1cFv*irv-{Xx{; zbEv%sTOLR4z1H$BHV?Eu#;R-J{`^3GXI@-5uq1y={tmWNdNuz}9zZ%>Z*(0&^*nIe zW2l}Js2v)~j}1 zg-`i=griP^?;1B+j6?h~jv@A>$0xWRn^4E4p}XA~%~n-qqm`A)*2z0e&gw|4vZg)h z(wQpE7O&55uRWzTj2tWg)sN5oN}DH@NVt9JRMMU3%y@N1tI32EcI>i{&TKQ=Ty|r0 z+WBp+cr@~1RRdca#u}=s8fq#lYwG!Br-*t{kU}Y+-RqK!28&S)wal%pOw@#J7JsnX z3D6for`Ih2{;xAq7qGaUl2ONQ3bN}Qkxuxu>{eElyqM7m9)4wy9 zi58V??Xp>no!HMe193Sv?>ndUeq(-$=V8O;j&P6h-(chUv@fyYlI50cxPdYAts|!x zZCzhxJmhO9n__@H{2T5={xQSxK}d7*viX&3i{)X;EFc z97BlDwB99Rf%}5^x~N~s^;&Ni?-vKeo#HF(u-AI4ag(uR++lp#h@*S#58I!#@3y~T zr=xLhDU-h>3C)H-9jd4ZrTtauULhv8^Th^BnF<{`dT!IV*QfzrF#v zz9^GdR7*(t@K1u^cz!sSyC3tTwXVlU&=1VtO`7&aIS?8uTl zROE)H_|l2rD58k;ots!e&G^(`{9@!oR$#KD&fzX&W&R7}Cm)yPd;2X(@biA{qt)C) z12B{3ATiCG?V>F!ChS{zd9_mZGhyO>(zJhrK zj>ki-ly9qg8qBhFkuK!hs!Mhu9IQSyjq+{Pw$|c?OgBUfi6lb7VSbx zulm?Dq!o+DTQPYi6M0H2R+q2C$!u%(WNVg@)&68_;Tr~<(`t1hNtCj^gJ1XFSS^0=;6dAv6z$kq{(SP;nG6Yql0lLZujD%G~p{pik zqZdpR;vn@IG6ZX@I08|Q3E4_NQU_CY#T*=OxFIs8Yf7tY0>a)cde3v(j$^uUX%RY{|p2ln@nHQUiUeaZolXH}do~==h3TYPx{bu|8w^2f5X&*}tY+82z5I zpIf~uw@Q)M=WxGfePR>otG=d;0@U|u6d*4G8WhL_tq8I~Q1n>(L1nfgy`DZN@4;mh zgW9BGLjde{h3Y_|(?$@zGK!2WW*zkM*|SSZ-{iToxO4d@_)*TtFOrRVQ3JLlH%q-ZN@bWt8U?S z;gImLfa*qjY^B8YP|>G^b~wq7wT1^b3xv%?rM=8Qc?oeGzGjJlWZ%et4cCNF}}68#Xw4+DuGYEC}P%B<_% zhhDdRQrD9^&|DY_g$doQ^qTHn9pKB+*9toR^E;XR&cv>y0Lq(;^o@NcC7s4gXpHyJ zL?WBuS&i<1<>oeSGxsQZ(MxEB_duvC=|J#U`9ZkZ%ZG9I+xXdlUtC}qSa(XBg-5YA z*jqO85X7q$TDYQskL%}h2S(FZb?=~>#`W#eYx;M=804N%AQAX;dbDg3`0<^VLJO3(zgx4^$-e># zp-X;-Jx957?nc`NvG*B|2G`-2w{VRIdpl_;#m@nd|H9Qzph~uY>;w4(gmOQ>h&?l! zy-w_6EHF@|L!TB|V`CIM400pL_t5Nbfvjd^z^g}}7a8Xm@@V}M*myI@UXb@e2r?YQ zjy4A9J+VB0>Bz?+{_K%rh+oEL&WnZbPv2a>Y5JvTe)xxSKjmNMpXMTr4}LE5PEmCr z-vE;nFKGrtc>@IOMXIB;hUdtp@+b-CvB6@Dz%-gD%7=jWO2CX`C0#oc&D@?VaqUt& zJ01iKABp(A)@_D8hW&CCQ=o>QlFKH43d@NP^Fv}M^Jj(`GFHaOHMDay4s~;_s~G3JJ;RQ&7K-< z@5bfP9Q%Oj>KLVuf($+Pt!a}YDR46qvm1DyvLYv+l(eFZf#${cIp_IDBQ{?+?(w7xHI){h z*JFv=s-tn2H}cDe%7MiFEYh)FqXw$ogoNa!{?kR27Gst$1u%9V5=yOh_wKnVLFX6PVpM}jN3 zzjKr2Q*9}!8>G=`LiX?#O5_iiv1lJ+Yt`v&vFb;>l7rTMPKqCSQ5=Gz=(vtPL38=? zP{=mM-S+?u@S3K+z!Q*)* zfzM_y8SbNJ$GNYI(}gNFs{fO$hn{64yOn(#X(Tq{vv|r4aucEL7b!YS8Iw!b3pZnW zybUAbCd`-P)0B&xGM!)!F%GJM7d)D>qoKGs$-%-vI#G1ygS1LCI#MIc0Mr5Usi#>!7Hplu)=G$%Akx+%lzbtvGQA2J zR+BWV*McHMa2C)C%D9R?RMRaxSu7t>j-ezzfe51_0Mt-UL37x!g{hqK7J8A0$iS1> z^2wO;oWf76_{j-WTZzyJ#S_9?)BOQC}r;BPxnmEBx4~6l-8m^ zJAiN>w9#T=qHikK@`d>=op72pTm)>T{4(wibZ~TKK?fVmPr!Y9BevBN;qt4whk);? z;yM`CiEqK|`3XG16S&hOh1^c}n$_xRYe~_+41f8^NOmP^>2^LeqE(%`hA`1DI&*R@ zvSYB+Ix92_m^-L;4Aw=6K`s;_Q#OTV7f~>1!;7v$OlGz+#Ja(huEDxXQP&_vgp{;v zD2GtO252{4Xm`NTM-bd}OM!{@C6&M5`^wgW; z?_s6zqFbEMTCg|swT5oPgu41)X!gH{%Hd6JtOnMay78eUTmLc2`fdmxyZg;>4<%)nY1ycN$nYu{5kkCg&ZV z1Q3&t!PmangMKAu2kjVQM0-Ieifo9v4=rvbbP3iA_=%C`S~kdtyfz6b%z+47(&pG$ zW~Z-oP+1DF#m!Eb)mq@|GT7MWVHnevVa4IZO%Z)yWp#QVMg*K)i7aY$mwW(Oq?o4r7d2BG(iO_9a1@nm)goj)dhj8|C?O*(|9WeEp^c=*@BM17z9IG%g;!)R0=M5&%1(LM|LKlz_= zmE0^cCs&1>I=OVB8D2rdD&!+>X8Fz>P6JEIU9}1@?69GVu_b1EOnu=M;r{T(u!sbh zj92zw<{wmtXdBE5qe|G9Wh9MBwOcp` zr;|~oeR@_?=^vvo*^=U8AijsE3Z88DF?c4I!ee<8-~+3HMc4+++HQy;aCh$lKwto9 zz+V6-{3+&nN*rUbfa{I2^$FKDq@f(ah5jAlUR)@LpKpiA;TkVM7-ml3Ra7*V>Uoxm zsPT)_lxEbgCo+|KQn8T5U`{trFL8!L5r-odi#ggaUrVJf{#ny7EWWLn!0dzgXPd@~Sq#-> z$$X3HEJZDYv}T7>10)3_ggX*3~~+{>qeDs@DtRq z1Tid0t4)0gfxd(Qpq9-!Xhp(Ot4-B~g9f@M8?3rHqg0^xnyiKbwS5>P{|H8a47P~O zOiP{(tct{bshHXMXuc6Rluhf%W8|mgB|JM!$mlDe_$GvoqN)6*-AebPGiy3jiXtGw(_z$$}Z zG;iWU9M+4U;GW@ja|bzbQT{q|Gf>t`F-E^Gyn{hIR4{EVuu`89b_@KXGeF7Ae#vkj zaQ{fY$$7Y^bLK34wjnjHLs*pW=QhGx>NjtMRjH2KS}dpHz*Lvbe3!EMt|O~(bfP(E zi2NyT$UoYhIMpqfk!)TopdMIguzGD0sjzzOvSjz#tRD7>dKnx4ly4LaoQb@nVd156 zFsHPj#g{TF*Y>B!{ypCZ-;-$hGH@Qg}4`8%!Ho18C&ShoU#NLyB8OGO#CU9yml7WI*V^{CyeVGA@*WAdMCt<5Jxdc z9l_-vhPa1K!bqt=2W(FhIoUln)^q2jjt7iawoG{zB#e!Ij+J;LE%ABU_B^_6Zk)#=3)PRL`jJvU zvR(K!l2p`#F?Hibm`g*1!KpZQDWDe+6_>)+&twN@(lOd_P|0GUgwgYuGX@>BsV z76U`c?5(#NMWEn4Y3VL zb#_BUacvf6^eW)*TVl@xPv-+<$&2J*dob>Afp`JJ2R?z1aVr@&6{q9Q0Dzwa*{=b& z{}i`3)7z5*UR#<1*luc5Z36=^+HDg^wKVJoX#$tV-x;WEi3aPc%WNcKi<*P ze$2|_Sh+XSToD|rv- z7Go6YNL{r3MV*5g+Ip<63~R|zmM6R<XY+gqVdS0v~qF1VEp;iOWj_^gUMFk_wEgx0ZBI@86#BC65h(B0d$oj+L zQ#y*-SeT|isD=J3QktmP`N4XEd_99Um_hYynL5C}%P$Vx8lY!>f@F@SKnR(6w;~23 z6QI3xM_?bmbO+ckGJu7*x*3TyGRiBlG)w7TqTgkp>|p-qWiO*+SFvMCwR*1(b*}<= z@%9cxPIuhe0R(BszK)|Ev}?E2cd!#$z$M?o9&AVFzD|0fo=*1D9VoZ}ko&zPtu>RQ zh$&nLu?)fj!Y0Olz7*-Q9tI!nQxG44vv@6nKaN5iL4Oa@o}b@7YtJlti@Skae-+|d zh?|jgOt}G*~m;AAOow;p0A#2pY8A%%wbxx0|`BG^^=A4B4ABXk`R61W6+@V zfUs2#4^(EAB_OYU1Y%2rYE~luiUXm!6P@B&j2jyZxpjF5o2XjZ2Ua}nv=Q51M!b?& zKgPiFS?6FG1Ix3daFyyuRo0=k#!U!+zlRBs5(G*xfGsVg-SxmWxgKi*VHj)?WKCok z+f6t-0ty2k{fVKp<#Vf64`h|d1)Y_1nxgUMIpv-9U?^xcIl`fkEk3O}6sl=Y*<;a& z)e;Ct?7l0ErQKg`Z@Oegh5YTyXr&6XftC%{&8f`JtM$=or_f7lnkUSbZ=hm7e-GD2 zEIASSPC2ac?s3Bf_PzYe{2_Qt4#$vfL4)@yCNZEP!PE@K;31+X)uVueG4@?dC!0b* zH}+EOqP4>Vwe~Gg1O;l}{p$aZ@MoM0iVJRd?mXVJQ@;u|t zFwqLrm?`O&i9KgfPryLnKUQkgA7-3`jkH>88%?Ytl{IM?ndw{7Ag8AK2>FOuhbqJo zr&^k(3oVFRDOdzPt(Fd~UvDtmO;0!z@u=MrikAh(Udvis7Q+|67|iz8+QXrM#S)4{ zZK3jzjr{$rzG!taWELcoah_48m0=DgDng5AeWzkZO#q#29y%EkgQz@#-zK}rJ9Mr! zkNiHzWe{&)moX!w0s|2v&Lrej<4l|b;e&-JsVFIR`2Z4rJ(e8TwtNda#mZ ztE)f|C6W|nSm0tgBhZMlz^RCHVCFEAZOj@Tn3Y9t&)LJu=JQcEsjSkk^KcAw9#j%g ze;c6)`#KSXB8(2CoP!QwRH;mLYBviFgRCQSaG-)dM+G$}j#qqIftf)?81T^YidOo8 zh_8YzTCV=K9OPw6le*JMAL^hMV%bbD)C_PIOU9f((tNU+UeD0%Lu%$$^?WtEUNd`% zCcFVU?r98twm=L+AF|NrEx||-^LLOKh*e%BG59@ll=9VXuxES#a(tn|1K;}x2*VH> zJ%~R$HJj+U3^?T@Tu2HAaG~GBGUa3L7%qy|C8oV#RR0JUk{SZI&?)3Nvb05z;|Mv9 z^VS(r&;=k8F)z;!(u;bg#7IaiXK|Yr9s%T}ruhSs77&r46O}q)lOtN@^OZ#%`sYkR zvPjdiZDwBp^x^@(xvjokGD{-D)b-=GV8CZ?%TA-G3Z$a==lE2AMZYcjl|K-)vR}1k z+wiNRyQpggF4~BBzMl(_4{}cMeCMP(BY0ry(1ukX6~qJv1T$K71*;W0v=jn!WaWJ$ z^A=(kYkpM_@9X@QMLEQi5Hew*xhD3JUt#Wt1EB?7rWAq&ZUKCsUt#ITjJgyG`Y`6% z&q8!zajFuukxrc!P^AlWGIBry#I@1^&IofT970`!N@N$rN(j(NC`&?9; zObcu242d|xFo`I--(YIJM%sj_^%OJ@h+I`9VW*^fGvSCFT5sNL-e$&R45juSO6_&a zJ8*HVw`@k??JGE5;dbJbr*I{SUZkxF8dGTU&_4k>RZE4~`=cK%d-Bij7k>2RC%=FH z{r4~Y(Y7zmBD2Q+l{Ak1%d9WWTC#+-oyhpdzSwwI&GYo4)P1{MY(Zzfv(}xG9XO#{_g5Hk6 z(8@wM=%nmHI#ZaEmf9HJAPqAfspz>hbGoKg0MQ_!`p?SF0hrrON2NA8qoyN|&0V8` zp#$v3^cktaUQSPMVBaW>Z7k7I7mm}%Vu^@h4H;kv0olW`P`j_cfQ<@%^HkIf z(lGRv6)s*iF{O_R(j=7%r5*ryv>KM`_!3sdB(h9e(mcQAqDzcIv}Rh$;&!{ulEv+! z`X?T+^W>N9r+4zL?Hy(96+S`)zKc$mErC*%tFoT_ki5lj;0#0n;dFKWu;G1RBoQ2> z3>b9$^^;g&IKk+v4W!`KBn7~vmP^av)KN|h?XBDnCGv@+tIz_`1b24xL9mZkvGf-{yH3;FADpyB+eSp z99GIffufi1bNoPIW*k?s6 z;{9*M>wXNa{|>}$UIeQy6YqfQ{$2SLyd2kgZ$|RS>wM&M5rXGL0+O$M9-!;WJye1LzJ9|rwPz4p{YIm2^?R}J*YlhE60)>+nH z)Q*5mCk$ZtB;0sOW4#fHJ&ey9hmFFbK?$!-EhId1J}J}-JUG#NJU4JFx%FIevM|%4 zo)oxgfM1!ko1O=l8qi0KNZ;x#jscAJcnKVT<2Va##l=K-}~Dyt@t(l zN25fur0ueXwxfBp9Z6hYPD;RsL`NX80B2+lqyd4!8JQ!9S3d?Agp=jQQH<;(zfl^1 zA$OQ*NrARw*C>n66*L$;BU$24!u_J=nxaod+jOZ^^X-c+zp%^Mji>tRSLrj+5uKdR zp6TkGh-l*+mq3=^0YoSC3mb(2=()q}sRT}Sld>SOesQBX0DsP5QH?rakEebNNb2Y} zD7myOJcCA--!A_ye+my};Un~+2y*fSn%cklA29^B?y?@iv--iN$-uR*m-KX*vz4Vc{ih|`&@4O)=lTnd;1 zp@`j`s_|Q7r^CVb*V()d$q~01Ob%0>&F7HWwoNVP1$;A^&i^&lyR}6*#DA`*9#0n7 zggM>+I!I&|$JgXr@H@V_y{{{2(4ov0>l3oAcDD)`f8H?$$tZqmXB3?aoP^o@Db9*|AMu{+j8D2i~#W} zv&M_7VJO%VMZVv=5e64lzLmpqb$NR*WP>+X1AZ}o?qI3yb6>y5bG>wnbdU6~G$iRE zgC=VCNq(tNHgqVo-E3Q9+hp5fd)~I!cEonlM$a+We6~Maa6O)7?mOJ~xgU2w?cU`+ z;C|PA%1wW0aYx)|lxmOXd%_QdyM+gZoba6Rs_+}(1A(3^2p$1nUMt-sO^_P^N=UyH zC9m{{>!ZiB)ONdVo$WE(Pi-&RUbnqt`vi|}vW0Ag%KC#(`8hQ?m7QdbEs${0Ns-MK zh`U^gfUVkSb;zt|2W{(r>x%nrR_$w?ZgN^A$pZ37Gzgae=gRS!Br$%N3lUe& znDmI%$n>GES~%%kE#Gh3XyX^*AX~OjvRFuRhExiL9$O!`fdX@w1sfc~~~AI!rg2R+}C& zs@)LD-eRlg=qkg1sMs6oMI_!0V$(Tu> zjL~26D|rB6w(&dp5&k&;DUVAK!?a0;}M4KMb*vih=Vq zdO5`bpYF@>>8_w+pkjESBCD(dN!3P(!&D4(W3{e(U^+GT3>QyIY^N{$6taY%&l;SA zrKVA3S}F3Z4@{%?m`1hvY|E%pryi=yDqI~sw16I}n7x2`A*V6VPPh6oogHLcJ6NO8 zn1##4W^p2VJ~$CJuIz*%xD#u&FHSH>?{0VZ}3 zR4vcBQ6wroahazXrqDzFyq{WmqTh=okq_*&6bvLF6-^3pUt%kuj=Ty@{2XK3$N_x zxN2c7x!dmZ1syf#x5i33F08WpydJCQ@VMR9cymR-pJ`6my&gZA*SicC`Tm?aW(+^-dFe{`>{Z-w#SitiEi+v=npR7qwrre-&St-B9whV^YY zs|{zt`_?~wBltj*fM@hg$ALK;=gL|y^Q~R zVD7N;A=Jfwh@}u)3p}ZY^ZvtHpk3|q?Nkc@sMf0Pwr2Cgt%uPgLF{2z|m`QB4mhK`4N2=pm0oJON<;L+C48Aec7z9+3Rs119F0 z0vKllqo74OFQeTdf9Ko{bNN4@8N$*ZR1fYV_3%8jU4?y`9ow#{YC&=1eFQ%gmVXO! z-S5C#ZpRBU&EScGv@DvBf))U}VVkZI@|I*IiC8kc@vj)L15Th{!RfoXd>hmORD%+O z$aTW~*0~8Nr=@uH{dnOUW}my)xA_WtlCRWNV8;uTX3pK=4>ShLf>yIX>F?@XLc6Ei z>Q8w3&b#8AUHls>P41}28F0zZtRpu&qM4vS9rGCIA3ujP_7DVPv|H}hmw4!O z3g6q*vjgg$U;VHL{4D-j{cx(MxYX~w>YmSQ)>;3R<8as>fVdyRj$_Q7djl2upN3x2 za{`>D8#D4ReWyS$P5Uz^kE+qE%KQ3ykml#01tAS9_sWdOVImgcI3UaiAWk6w&TI;s z3Vi!LrrS*SnjST6HHmCN$ug|?ofb8Pn&R-QF=>u$FrRU>(HZg3QpfF%bq-T$Hj$O)044&{wwG_Sk@jvcci3PY=a{eozw= zDC^*Me+Ob4#E277o6b9sXr4t~{R#)FU7gS#2av_7($@|T+ zYNk!|jlDzu@{KpfHju!6w9_i`mt+yYmW@A8Qd(5?QM9^@YTk+)N-#XNw^)KWm|S^0i?IW&X{;6MJE~X3=-y+ANeT?h_JwZNLAnrLOsiC-LJsqc!P0~fcD^S5K zwZe;feuccqd$DSSls%|r7W~hMT%Liri%jqhfT2ZSWWsEm*JtCCL;4HR%Em^F(eD{Q zGtx6{##m7*(EG65{RGCo6Vf<{dBB>4uPrTD9r>+g3@nFW|as}AS`@Ylo=GbTI>{AUS0$) zJgYjt8POBV0*jCoocsWc{>LB|TZ^(1=-EISGLV6Z7^}lUMdVqfj~lg21;Z-2Pu4I4 z?l;NAyeef%3*E&P$-IARn;=rSx%j$$wiS{KsjuoS1nau%yEFSD=n zWpXpZ%}i`hxxY{fJFHW4GoTdAj6_5c)w2zPnO(xrjCap^W<(Iv$ONnawlsJGP7#fYqJ6f z>o7L0dvH@r0Xp-Lsxu3%gf$Pnl~fx#4U;+O5XGBMO7*M+1oPxpVo14=_nQ8-k?)M{ zF1-IQE+Z|!)O!ZTsb#qz2<%SgA+XDcc|_EV`w~AUabcEwuPO zl`Tf)@iY!A5{vRv3+N*hkR%0Y0S&1O?gAT=WY8vvy1_T3E`L(n>|@w_vMC5cil;2V zq9`ArwnfzY+mc4uq?k?QY9f>ho+csCmf^{f_|dl$TQ@(tnOrcog-$A0$V?|-Lq z@SGy^$Sh9aLaM(E9x~=CQz?ZAlDsm0OX1YKd1}9$H6G+Pjt_G_Zj0)JDR^FrlBugW zZ`JKmNHYs4f+5SG3xh7hsB#FtO~=6@HN~W`s3_kRJmv*bIi1JQ@;%!RY9D zeTK$qOf*xnPgR*ZOcNuVo_)&JN=LCkk*Ophv*|3!=C+ufR>|b_SxQ4jvm{<_b=xIG zc{<9rGptp!vR4M?6CU4QmYB3mUn`N)Fz&9K<;OJo4q@*-@*c7v6^dQa@-APS5BhE*+Ke3b2 z@vw*u0JkqH%B+W83v5C0`SH^@2Ap z?CJ{E&#MpD*3^ZKp_-c7aH2YFeS^F=<|U7hT|yq8J}uLc@e*F(XYv9eW^YNbgDaHn ztE_B)mvbe&XDeIH7p~%KU0N$shPC9I>U((gpo9N-$rfmTuoI&@F@48QckFt}vgQA? z7PFh~xUmysv(}K0d zVljKXGGw{&Mq0%Fnz?nhcrsz-pFZ8oU(546vG|jLj_GO%mvvP5QNn7u&K$RM|IGU9 z;QyKa%0guRANAFlw69vtF4|XJK1*2`0Q0}JdT3v@du)zOMXB|hqRes(10VJZ`L1vo z9Rw^nz6N6`2Jt*coWQ&lKv&Gp26rT{VZ?;2O7F^0UiBD4Fpm6R0ZlP%+J7ySsepWY zg+YuM_U#ptVddn~ux||ZHskErw;3o9VBeJ21T}dW%QB!WhX78-3WDVIwwvgw^UV=n%th9)a zq)7|uC6|yZ$eHJ`(mK~U*XXc5;WCsKaDA_kpP;NbiJxAK>&qino?let58ZQuWqR8?9{_%^@2J?BtcKGWL72*AK8hy4nrlI_l5k1Z!54;~g8SSUG;{Ur1 z_`gwqe?02%6^8l)=I<3UkG3(1_fEq6X{jOrTGH`<|7qx-W{rbAN?DFGCs5-Y6)e%h ze|0kvod6%IwD9y+!b)Miuvyq9>=Z_X}bN!+kDC7vMN2^rt$pEdqW1nt?un`P@zZhfu|^ zcJt4`e5#BrKox3Mvkn41UHe;yfn z>YT_>6&t#bdst|t^|$3egAG+{3RRQm98OGs{(l9C3dX4bQPytP@XwPj;XAC|Zq_iO z=Bl`c5oJ9=C)?84F&Rb_J}V70ng@QFUo=r9hbEQFA3%|w4MU{Q06mN4TjjO#Bl1)7 z4tbw^RQ^Z?GE5H03^ZuF$+p_|kS%Y6_wX&-D4>|4&1;*;YkoFdL67G~_g(HExqssR znfq7nH{Ad3J`H@P%^hPX(n;R`b6^^;m2Z+)%MZzUdAqzveoG$3E+3X}`3C;xalV5aJnCA~W!s&q7Ti%jtYW753vcVQ~2jT`E zFi%fO(B39WW}`ut47|Wi#(4%*oG0U!E&_Wdiol*LBKo4xxxt>quY*0mFWf0?5S|b~ zg?CVRPxuV>o@*jTVwZS8d{>kgDd8ab98{!YrC(9Q^m^eIVIqy&+ro$JQWJ3+J49rh zkQY(QIk+;oKDar!Ex0o{5Nc_rxEL55-@IzZQQx{$ZS6>8zm3 z&qZ5a;7|I@XGL4u!lB^jpe?!aajuNExpsa&U(W5KRbV9F{)ppD`Qh@z<@}=h2DM#w za;M2W{wG{D`C87NLA?yt(ek+%1)-P6)I06+BwM%Dz}29>djic`q}#4 zbP!%zMiqf$KBle0i*Uo1FwM;P z9oX5GQ*cK_@RNNw@hP166g`KUIMm#dd}nqedXySpZ9N~@O}=o_8>x;t64MseO=~M@ zEB9JMc=#7>8G2Y~Jv0Lhp|U&&1Xb@>3; zl?EU}VLvO-5G~N9z)QYaKZ!j7wN_!{;;7?* zd`054GY_d_i?C?uI{9XK4NT*YZK#u?jHME-hbCVNRnazG&~^V@dpI1n(W!>l8cc`M z?y%cT-WdCxl~`$qtnq|gCMzv|TfiUWuWT1-`8(s)VQ*PU(iOD$gJDN&qc@#OIHESM zFKBlJT_$7;WjV>{ly8*wIXm~IoLpg|V}VJpiy^>o);b>n9*6Nie+Xefn>y?~qkPT5 z(LpXSI!HpSoMjKQr|F9!O(%VWg^pw@VXK^B356s4l?|dS3S(a(eMAtMen^bl$#407 zsvj<= zabzxGw^6SboVcF$Jc0a)`Q!5eqL`nUPlx!v`77r0+Vi*2cb&Ko-t`~og{+EWK0>+Y z6ICJdTr>UlZT@arH-2tB=Sb4p$&rLpTenuD;6dR^un4Fe0yf3TJe8~9^IPR$i6R^Y z`j2*u1fK@s4#ZYP5P-$tmLNYhO1{`nq$RkZnm2z)I6<}CATMY!qB_@Tz@!GnJBAgv zK~4VWKIZ<|jd*!fTnJ+E1ezK>Wj{R3vX^lUfQWmq^$2)llvf-*cgu15C&<@bV25s2lnVv;)J)hu#M<0MQSzq>`Mipco^I z%9lFmCCp6{CrpzE{NS|*ktuz%-(b>w5@I4F5@S6Xfp{0n;xmXNSQB^#;&GIi*&oK- z>Iwfdz?Hs>vCRuK>89uwph@$LxDG&4W6}>GDI*7a3wm`kV6snBL5fUDjNyUeOzKp< z5NF+j_C)E7FV5r5nF|@jqNzQ@-%;F8Rt2 zzEa&=GUtk!bH6n+QQG^hnY~x^XxzT@sMyJ`p?dzVoFzsze9oVw+Fm(<=jkif^Fy#9 z49lSVuO-QIh3%~%Lw|8LY9DsNSy>T0R?H~7oS$^+qwh@BTD^tGL3#=Zp5iE;yYch4DhzTh8Ax)$)_;zzK4d4p>u_~(z~ z@*}W!M$qcLxX}nY{cZ>m^fY^Mw-+F8hd2)L4tl*A81iMWro#o*rjzfpuRyC|a8@Up zj>#VU+@|yU0ubkVbmb+i;$VmGZ$?{r8*Sw!h=ULe9LL;uyC9-yGc4)BafqiOBDmHy zdL|BasMw1M%O13jC>qPPxQUq5TjkpjJ0T8WkT{Y$nc^1>c2GeUPwrQOnweyQD7Wj7Nfe|Jhr{x7U8Nc5JuRLoHRcWprlrmO;3`q59-J*+L?XQq!&5VKNDI4^($_(c_o&C0TmtyoCCI>g z$yx230)J*R2O3PJy&2YIGad|ERS@g2`y#{)^`xCMfIx#V&%pQCs=!uD^9(kcwzRj< zm+4`9N(OYj=9V68C)AG$JZ>PZ@*7tPjH+|Kiki6vesV_Wej6ffmcX!m5urjyp$LLa z2p7ct_AS8fmoO?Ls51XO{s%C~Ms>1zmhDsnR4XE!<35N787Dc!X3VD}m{~s$8vV_d zZQ!kA6YMCM|2{?J)8p2sVZa`T(RMuWDS{m>n55o`XS)H&Q6r5R#2-Y1H$Vc!AfnhkelcG4 z;-@dhJJ8ZpHe8JFA>wqG6atI1ez4SU_LS7e!gZw{*;~r5 z3skiwqK&nc9>1%kH0@2#%!UKiU1gC5dMIFxmQ(~%-3`$h&S;s}6A$?;m9A7-Wyn_= zvXA}GD%!I%{$NGa;fR!aoRLV3({dAXv~Txw4muN)fHlqWHQ*;^=^a_3#{me=rr}+t zWD{42jn{K=smSb?WtG!dMXVufqVhn2WB4$(DiDPVtMn|rkx>e2LzIJ>wLIrwJqUNU zIanh2X*M<8LKwdM5bO|^g$r!LoFd>vmeJ6MtrxKMAZ91e!HKsC;vtMm525X|6iVA6 zeryF~JwR)%lu-_+=8#(*-QVbpEeN%Jb^6#Z`Tp56{_&ps7A{!3detlzQ-3kli9e&| zmgdHCwixuGkSr6c^TWbn^tV0@zpirY9U>@XmDeP#5lGMzGyO$aK` zQC`TLwQvgHJ0xfafjQ@9iTUXGEw6w<&Y-)<=Bo%Y`^rt{ZdAF*&cOs7$;*ZZ%Chwh z>dU_cu?1o;#0v=WdC-!hDq!e&%U;V73mr$dV-Dw|>N;--_&^IgiVp8ZCpSRcLwAWU z<(tko7KT!4b@_|9SzYAeu`#pT>9l4Sw8d+__}%Gq=GJ~;TEbV^QRaw7qjtW(_s4V; z4L8oKnf8sDB{NAV+f$ZkEOCQ`o@7-H?T=V4ooX_Yv&XQ0+BbRWG_Eh5V#1{dF!dF$ zl`1n3Y4~$GZ5&!&zN-9za$%9SQYs7SNh_t#7Oj*n#!6{|x&`<3SA)V4H(ytc$z19WFW_EEF7(ma zcWo@wUFol0_?;OS&aeN%w3s{HQDOE60##c?2W-=miJtXy59mf=XK9fKlLb3Sx9Rg^HJl+GWn zd%q4`NOjIST8?#k9thUH@>q!H7Y$~Tqxr+N@7LnIT4yc1@SyU(6;}C65cfme2vLC< z-VtmKcTMWj3;9ig zY?0^7W`l5{JyH>NN5f$^d2ej7$!0PTsw_IO5)5yR)n%rYYLnX|HDx6pS0YsvY?Ri6?p)Bg^XNL zN3|^1mLOFPft*c4eZCdGejn8$8pvH)u2J%6M+xzkF5HC<)alYbp34clwJaAkML$?|ZzqsOSwN+of@uKX)o+iIIi_YVz`NYrWe+Yam zxiDv_1B*8Y7VrFWZWV?fl|GFe#=yT(O?t&Tq@aF?Y>hczW9S0r6^WYj!-m6HT0!tx zez|cKq8m$%O+dd&>Vh=O=(Jpqdr_0Lg-m*LVF|9zSRw*fw#0Lckr|m;WChhFF2;XdJnMLm`YNTWf^XvGL+RbZj=AuOxCu&myOK-M&69Ry1U z?1gQ{GHZVblgkY&?HKH?*C7tz4eiD_AQToUf}p8GEP5_TZMIa3G)Y2A;Afv6A%?2> zV`Sk!^FQ1$_64HA$DrwK-bmInABEPp>HdB2d2o&6r-jY@JkG@Vxy!lRxPIc+#X)hndn$z*ib*0)z8e)&<%!(uCokDYXk3D6!I_g{7k8M{P}Y zLPjza6V%gbL!iF3wQ=%wn_F8O=&9OVfxp`F(N!`Jqv!U7w>(XT>{aCq8NZ+PA)C_WA-A{abumeF?XFIoL)FW~*d0n~Z#%k2lRMOLo*o_|-%( zi11+wg25>CNDik{PIc9VLUmmYtBKtoclVG_QeCw;kTUx`Zj(>6*zFP?Lj4sO?hS}! zaoTMLuQTK}(^JVEkzqo9G1HQ$s15RhAn-5i&x5QQ3oZzWzV4;o69(BJ=wIM7P@5^S zR{n%H(1($%RErx;hO!y;5pS?+T9RIe==Zx>5CtC3gopi~zKW8l`KBks+CDwW&_D~q zE0e+x@Cn<|?DqI=b(VN(#*0(`H-b~QJb2ozR$Xt@MiiZ};WMG)2~|~9%^O5D&hDZ> zNTiB@M1TquWz+EN^^Vs=ydG<2yvy=G`ckP6RsT-^Lf`rmDph^!nLFc+H-rFEW5qeX zb3e{KbH@&2?Aw)Nw!-MA^By;kR~W~W$CudE&MyIX*!P{^0$ycbcm4?YGTZ6=74Q|t zSHBDRD%^eu_!_&pz}H)Njon`TG2rzUzS-h)i)wY)%Ib9#_;|1;q0Exg8}^?w3hZ{eFQKDS)0 zLpjc^+2K#-d?HI}tk5zkxY8q`xypF&0e@MSg7>@KZGLxOO@%HeqO^QJc`vN>3lT3> z%zM49jfmS^@PSRRf@t^fTHvmWq#PN3_Z8L9bGNuJN}*9}FUu0C%?3wWp~Z+NJXO_P zJ7!!9BlI+}Qk4-;44yNgos(5umfVQcE%Dygu&MWS5xbXK-h0&RN61&EATG->xzt8* z@Zm{S6*8sdE;N>gJ|j^HfqJOZb*s7Fnq zOqJI75SKF-a>NHvIHTY*_M|lN4Swe5D3_)!0v{=1Ah#v*b0YG@PbxM%uY31fbwg41$}h|g8c zO|I%ky$(c#bixZCaRKHEEdzWcF= zdribg){ljD8^e97g8}cy-Cf9uQ!(YexEnw0?oN^up==fxa@dcz;;rrb{YU(h6%PbX zEI)SZb&*?J?QCw&X0td;bS{e`E{jce$Rr!HoLOer4&&?zo8vx#wZyN1T`&!lumW}k zJR*z38SXvy0QZ-yhQ9#nvo5Y}pu21zK2!28kx}4oVc$ot_jt0D`!pf~E)fw^)*jnp z8)UO!=lljhNr>^ao0Zp;EvHHad`fUM#Nbt{4^5r<$bDkt{C!`0ux7v#7K6Gxuyq~+ z**MlXOA%cmi(Y8PY2A?Dl-No5l*BtB4sJc8^(K>r2Pa;fBGW|_r>=(|^!N0fx_cDo zA|BzlPZd+jk_N?Hg>frOP1ShN$NjBv74S=2%$wS2P@qw0e9m6pp$^Aqw5(7`bhe%1YRT3AAexsmMiq#rxXFJM>u_YF#RT`eoM^cqRnBlBd z`C@OSfyr;L$kXu3R&)W?SZ$EQR z(PnR(nae-97md%wd*W5st$Fg3oKgqwj5WKY;NiRV6F#L3O@}^5qnD%(O_<>cy?+cY zuc7Z@NYy__iI~nuN&d?$lVJ5dOcp$R?q=2H@e>fyo1h4%R1+J=H40uSXOL zHRV=hH%qhGOw16zBAosqy=Ub@_l)XKzCimUnyYrEi&!{a<}@vC9&$p((i`gZoHR3f z{+Hzi{x&LFIbQ5vS*mPL-ri# zOKaTwpvITQACr$+^xS53fEf3kb(Y;Qo&H-fr7wuH$Lt}kI^|A~%lTxm7BqJ*c8h+u zk-3j=4*wr|JfQEk|8L@W5${%Wn%@flk!<3c(G}AdTGL4=aK&^2Hva>}x<6U~0C?JM zRCjO`brk+SlH4V^gf3N45Tr>+E+io+O3IN!NF*f0gu1!g+%386#=YHK5AFJte$*FV%zXDoO7TawL;J9GEm@4fGRzxUp^cjyJ{`S%`p@jnmu$G#HS z3!`xo&*2%ILL>Z4U?P(+2InDwzv-eI|6(kYF%B<4#Oki*P!9MJZ ziR_2-@d{qVOL&?6Ie-Is2L8e%4nhV8V={+uD2E{vS!m*Lp2@RfeZ7uX@fvPJkRy0D z&p|e(AcrG4isvGiqd5j&Adlx^D&E2ycoQLxw4nH!7xy<8Ke8zm-&S@ydQYdIf3&K!&0Waiq_%IV1{^3Qum_P|< zpcI#(6*?j;U?GcGOdrZn&YAd=B`n1(mZ1VB474H2a?WA}XJa-iQOPP)@ey% zv~wIhJuA>v$>Vq6W3BX9MSB9v5&SzC;}t;Zm%?6}S>taWR)rVk7+w zpdJmB*~B12n2!bc0S{8)QY>UM!}uEea3j`XKfc2O{6w+^Z&Rg)&)Le$a0hipu!jas zwlT_fcCeF|a~YTO3jBs&@jD997kA<=c#wvRFawLQ1TG}wX`~_v_u@X>jeGDUp2DMe z499RB>9`t?qaXU-h?Ud@%*iQU-6Ra}k3xE_1q#wx7FBiO+;ID!I5*n}c{jCb%U-p9Lm z51a7;KEy}(1RJm(8?lnta4pwyJvZP1ZsaCz<`!Pd>v%o4avQgE2XEj`?&5Cl;a=|J zjl7Bbd4Moxl-pF5%*=vJcR`Ef z*EQ8u(5TC8vb#VFYO37qDe^12-)w0L%k8N}0nL#7epxkK#eOLUcKhripH-CV>jJoa zqTc1RfSwWuO-UCjt;Dajv`FIMDecC%$_ynOklkfAf0<~i%xQbBRsH>4t4z9Q~|Lb*)EcW$a1&HvMsVK zL=HM=g54qqog#-EGbmz9ip{TxrWCuWr4Esso!bu!MZ!H|V(+R*sm_!trqJwLG$FFq zLu6gl>CQS`P)3Bv5l7#K$e5yi(fNOF^A>cUal1SX=iTbM{}FxB#8B^WX+kg5ox6iL^$XjpDC+?Hpyrdn2y zBSkWxMOEQ7YDOsDlGmG+W83^hpQ&ppc5Ohl!ddybw#~EcRNLm;e^|xokygnsFOHwG zy}1cZiHoe35O-CRJ;gr*P0_MH(Sh8c-nexE9UfO71*}W#*2Jb&P?0- z?EGoGwWrMN!XjY{L_9lxip?w5p5@I=YEon)@*kpS&OHDC000001ONyC0ss^M0RUhC z1ONX30(jb;R#|9MK@>grC27)_rZsKSG*xleN+}}liuxhqj$nU85CwNdv{VuCx9<4i zmx@#c@y9AEg0)C-DHYu4hiLs!YZZiA>sAy+yqp3aY`_?lhMedircUjGdqaRm!tS_`pzp-`dS3N=dNxvcEqYw0@w)5Sg zPiZUBgGW2fHvi#iLvJ6K@xa~&r(aiZXdQ8p?Y`FQ9=@-zwfr7GL|s$GwQ7^LP|X&` zeb;JzNYC@Gb+jf;T!Yqf{svpGf$N>uM&{79-r>}7-D261b|{`9G=XxIVlswe8OF0_ z|D3fY+5T6+UL!Gp4H(m{46PR2dirnVT!zSPY5dh0;?`%(sfn#FEkE}Z7o?57n!?wk z{o~%ZYQtZix>VV8&HFpA%yYN@n~y%|L1vA=DmJ-4tlL9>ji1)j-I%3S+x1Cz>NZtX z^yFM?{m-l}X>BiNI#1n?r5$#7Lfl&zyn&;v2=^|EU@RsgA2YC!=W8)f&1-i#MmfH&yC5(!EOOC>J- zu}p@^aIBOPDZy$flQOK4y|Nc;WxwplI_5Xr^2=j>`RL1vjq?5<%Pb;1&&e!j(=&$< z%q6^-$Gi(HZy)nsg)FQl9IPP+zj5#y2d{C+Hx2>gkZl}-#vy7PvW-K)IE2aJ33Bn2 zh~gRf$k?$H5-=^rR20)sOgTXtA;wkkju3oAC*%j49B7>Y0C?I(jXe&+ zFcgFBw5d>qI6wzRCI-aB0T2@-BTFZQR0>1OIrxW+T!0f6!b?)ALq6xl_6rCg#S90i z`C_@kpvbEdL&Wk9YY~YknYx*BG?HSw$uVkK);o*?_m0y*skr@)%F}gwm|*SqQSLc6OU=($j?47OvE`-X>o!-amVpyxyH; z9g8ZJsNv0@YH+aEBisJLe z!gHx5OdoVNaD()jg*|T!}Ez`fMW&3oJrv~A{2hT+#D86s$(m9`V^~qERXDY;-5*+H=qLh{}xu z!vd>fM8a{ga~N1f)O%+qMJNAa>$oeIwjnuI^C2+{g|4SQI=7FuV`@ZO%Bap&ap{Qe zKM*kBJSvT3(iDnDA6!P|n$dBzDf&P8>88p{!8x)9m_dVF#ddZdwztyF%f3b4+|d6&A&8d!`P1P!ftkB6pE8s7~;HYKE$6xLgu|(Z55ur^G>0 z*Uh5u8GZn4<5{#ReT#&ad)fh4!9dr#XrOUAW-;0`Oe~DE-U!x)gMY_2!}21?3fEtG dT{rUR)i#~}-#Xn#RTqV__57Ez`yZuOL~xaM(g^?n literal 0 HcmV?d00001 diff --git a/tad/site/static/images/img_avatar.png b/tad/site/static/images/img_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..2b8318559062626e0f4ffe02a52004d0f32d421c GIT binary patch literal 8229 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 z zd1mAkHnUb^j3FR7Tdn;_wN^&J9M(yZG}x(d-ZHp8FQ%(w3Z1>*z36{*X90#$HKDc@ z8p=7&D~Z82aE?-mzq3t}y%!0Gb!3fqv)}0axTKgeWR>5)J=^;BRkg-xMyuC+Vwx`w zA+vn{Fh^-e@t!jL(*K5eH2T*Y!y+eGF0I2KKNk>=>d2bxp8InrG#3Fd_&9z)p1(K( zJzRcDI&tS5DzY^~efj=T2y3D59YiF`B3%p>S^1T4U#He&_xBq+?Q5fRq0oW6Fh z-c_TFoj0BUl!BG+Pa<|ITH{860g@Jvb<|Ka!E|=cRRu!Rci!+ci8g*9ltRSe?St{y zQiwF`m~g(q0r%=KOzF;{A=$T|uS6oK46E)=(YG{*!aber$m~AC!%z$X9W{=O7-oK< zSX!3E^YVsZD$!@=vOdZZoM!Ne_Q#I?240N(XyJ89jwd;)yvR5NtS44LAgra2>m1Dqbww+T!idsCnl;u>WF+emrwsyPEg{kP?|4U9k`GjimPe&v z7u8x%YS&xtqN%OzAvi}l%UjS$)77^GImjXQ5h$H-o*2h2BXj~@K}!Nqv_cp(kKPNZ z4~6E_%f18rE#`Je>lpABcnMJ2;$}TQ5+sP=2~9;S;DtcFSP+L$Miek+#l{HSoG;?x z{4i)Ly^ISlC|$Y1yv4jh?uC>>MBw540YI5kWdo&xGL?PbY0}h-SbO_8!~ujGqi}cR zLOf7t3(Yd)6_5{jLR-<&V3nptTfxR5><}r8{h%_Ojc4EqHAQQKUM6jv77PRyN8o|L zZwY6J;7m0|^WDGVB$#o_jNK=2y;*{yQ>%A$NWu#*`x*H#=)Ik_GDCi-y~^yFn~c_2S`3!SHEjbO*C?N;ops=^M(IxlFPDz8yThcGrRF+)ER>RAnFJIPA}$=V?554Zx8)jSTC4$lD(~rWW;TrMCddOJuNh($iJZ(67AU%h)a&q z8HAqeP_xo*(UI_RS!$N;xX5i5Z@QVxrya26c>H>Y72^D6xsQTj*@H~ngyAZ&`G*hl zj2k4QRL>K7ToXCkjm+=RzPWuUF&-8~kz}0CI)@NmcG2D29ab{)o&$EltB_OSVUoQ$ zdT+$y8iCF8ly$<(*)_i2vK|Q(wgX!xD<=>#`-Zk!vy~64X+4clBAqPAqz>yWM5}IB z6#i;Ps1~_4YNXw)5RFpGtHeE?u6(w-Ss>8X;Mj+!9SKha3L!7Ge!XUHnNV{D{)uxL*!_I@CL&5VIF+XOX0302TjKh} zB2Dlv4ZB`Ky8J$BY)jwWvHkZ71di}$*nj$N1L{yeRJFTOJTBKd;Z5=g$}jUax`Xla z^14VDNRb-ai9XYXb%L=t6%bnMGaPI+u<(F@|+c= z6REVkFW5R=Q={FlQl5N6zVgzBH+5|`-2+Q}bo`vCV&%FB+ug61`^{-C-?_M2UI|?I zE)yE(+y4hy9SP&7l&!=YF6Uig|G1SEn4Ia*zwJ)-K10UUCd0zW0+-S^rDRS=u14sq z7%b)u`Z?KlD_@?H0ZO)5X?xs%{LKlh`hQ%Y+Q|M)JD6#0Yjy2-G2l$@e}o$Y4O zHD2KQgw4X`%8K0HYgyj$V|3*&nqbr2XRfF0!Y;BqqUZB}%x}FN^mCb(rz!KZsK+_3 zpypS~?Z?3pn@%A`fvPbv3gd4smQFWpQV(!k>rOt-OhPrP2vw#Pct)KQ_C&3E-E$=0 zEo8o8_^lWzIiJ2}=V6(Z=T0cJiEKLy{m?VmcZ(`k+S4g<4qW;814(MLH(Y4b!E2NoQmY*}p>50uefKBWhO`Sy=uG`mBa zmWncE#y$zZ)(`c!wn#9Vdv9x}bsixaKN4hX7hpgx43}@h^B%LHZhroI*$ z0=!TIDgvnyxbW+xY7^7eO587LB=hKn*V7>I3myZ)ch$c0BA-OKIS0j1QZX9o9XDsg z?~(opxIZ0$R6!W|LsGv!tWSf5X96i!rC@EQK@$H`K2!G<6K_9wz&XZ;ZFcx&d*##q zOtB$p+QBEfql%eLKT>Se-*9b@W%z4KWg@O2I%ms+3%Qz!@A39VF25E_4*^{5&&O{d zAN}q0(~0m^Q8(RFQw;BG;{g)}@To5%ZA*5HzmoNM3`!;Kr)E=6EWKjtRx!_iY!kjk z+e)XczZPKDjC)31$(-^(7`9ldfC5DXRA^nFbU&pl&nJfC0z9xog}!PEdu9lto>x~} zNx08w9C2YnE+E9=%bF!1dy$48hsNXSIEZbHMlbTyXK{QhzTwBuasBT@Vsaz6vnct9 zpb9O=$wimIx2m91w``*xZ89(3#q*xtLVR^x!<}d@{e*rtQ;On$=TR8$9$1dA0StX~qvyaH0@VHY0E5~!m>5NLL9uA{%X`Jw|740aBxXquxY`ggN zBv){s9Ky7A%kjl1+DH_<_Qk_+1gAsH(k#*FhdoLTvAl|$7eZ@nUb#j4hT*+*1^f|T zT0hwQj;DpTBu)E9mgF9y$rgJXf6{Br{UGO2wtfI_BXOu$+ow+zW)S9Ep?zg!9Ri+! zMm<8WO~-RHtDnCZdzbOr>|+;rE?K=qzLlGgIuIDLzEnj88$1@j=sV?s?0R=YVB_*F zHG#5byJYOgI!)N^M^uCq^Ap2d*3cp_N8b14;bLa)SlkQ_f02FQjmPen*+cy7rfSXb zhXx0zWA||%zn6U|?C;4N=t&F@y&4BMSWX|jaVVXGc}aXTPY=|&!oz+#=@!^n?fP|T z!Rwl5QBP02=~l4usK+ncLNe{W4x>AZ3G{|q*Vp_k?4Nq8!einBSL(L% z(^$5&Dh_`V@eB&|%1?zgl5zjt=Z1GO1ZzaO3Z?;V+>k`}ST^4{OpP$WkkMWf9<17% zTOeFc&%Hh#_AG~6hAnP~ux6zmC?pO$L^?_h5O=;Q^YG>9I{rTId$5T3#b+&YSw`0E zQZhxa-cQA5SN&ChO4NI+!>>HTPK5=`Np(6$!dP>9%~Be?kN~rXp@})^?$2}lSd~O& zDGlLm`qYEnyA`honqBBPO(Nw}OJKzzwQ!)H&c#ir5Fw<(Ur{X6{T?f0!wQ>{^Z_3v@{ZBNwQ{wOIW=a7R-ZLo$BEOxQ8t)z6( z$fZ^2FmjAmN2V3W$VXPk7iav6{gd`hR-Ot(unwzk|B!ub^?A_xlfm`YrfV11Yzxpo z40HhE*;O7S_OH-%Je@xcrAPesN#*yh+nvb7*1y!WFT2?Rn>_LCyR5c$T4np8mmg)G zrt-h&f0ozRsR5k*qCLz#qbki`>2ba6_f?%lM$yd4Ip<#U{JMF)OW?g#Sb6I$l{MRJ z`lkq${<9_HGlqE~bcfLLkfG0|XNc*a`r2FDnSFJkvj=8%I^I-_f`nxglbRkL6W+>T z4h%hMoCt`$GodCd3-+8U8uZ(`Y33D@giaiElQe9-qhb{ndn(NO@6fwDH94g)Dd_r3 z&##C^W)0(!@O%`NS9lB3t4MdzQaL_%Czp~hTG=3PD}C@{pf6#eOa1s)n{ADoaD%-`2O{l&4|MLSQvvYoY2 zi(62+8z?sTsYR_y!-o~Dn@3(AbC_vW3%F1m!#P-fq|jYtX!G#KgCTW~8;h9U_74Kf zwhz!#p9EX~C}el{a!rftDaqD z4y#)}YqwGDS9gHh3=n7UgqpCY-Q{e$HX#uY9XIk5#TzRJ%^q@kS|F83eD- znEhT*xlq)eSB+z95&h_UBSNpQ2^ zaD6em+RaEBN+Z{=N~j+6pc~#Rvwy9>6SVm@3nj#U%@}pgD@jsWJ3aR3ML7IyYqSZgT2*3(8ujIfcvzaZ(Y#{GWbRSRaDca zdn{?lj9lru$5S=v`3{YFW6Xu;(h-zOTv@mb%N4C~^2+#rn?85_Dgp=Gzx;k%-uBb+ zHUoOKNWIcBeke(guoEC%RkXZVu=FQGJ5uoB)o!ZxvH$dn%TbXx#{)W{h}^xEU!L?< z9(nc!7MCLP)}ZH5&%tX`<@8pd3l~^QLW=zdn>yNa2LU2CK}zZF7aY0P7@5x%STNF#2TJ-1y9UYn*^w|8+h-h3&=-X+h82 zKis{V!r=?9mx<5MLX}3i2J0qb7I*PeW_GuYU~LQ+`d_~C6}PLCdbLhd;tANCa% zS7yISZKwTX<$)JvotFnSg~55U$S-e#_An4MQ`#O*^r zIvY8Ar|l3&*vSmlO9#izDzCX^guL53WrrA1zzpX1Tk-k}#@o<#5+6Sz1__dU$=*%- ph)2LmwBKTX!#=pRcj)*5Ohfa}CZUUbz<2)x*5**N7L!{k{|Cj1gthlph!_ECytEBn682xA+O?8eLx#$>Iuj>^^`5;Bt+ zOGL6&?uN>e8PPEDz5D#G>-Wd~xaak}pXZ#{IoG*f_kEpfa-5yu0*6l>-m_xa;!^KU~K#~WWXLX|0v%88QX|!K>-&6uKA;5XaR;` zi!^74i&n@xR+lbaN_+0$bIYKi;aP08b>3@d24gUwz$7UibvfAf{c~L61KY?li)$!H zLUA$rzD@EY+Yr3jHghEWw)x${glM8=Tpc`=V9uRvz35|O?_zPi!hy4~&RP4u{kb>g zi5>E`!`$c3t}#Xz!%STh^phUh24PKY94)Wc!sGASxO$wowy_LKb9C}G_Ve+$oT7)W zalFysh_1J>va(8f;Q06b1I$y0f;ZTa|w&SZDqH*>K_3-5Tj@ccE{OoxG)R|scE`!!lkNA=BIbf~B6 z`IXgQ%-0oB!M-Kw(cH18jvi*2t%$9q*;}pP&~}+Eh-fS#qsb|iY=?Pff3pP5tJ&;57I)|VUa0XW^@eqa9IYUK+UF0jY zU1b@UVn!4ke?7kemHjO2 zMZ44ys#Qfja2mjaiUhJ7^axQr*~Joho=?zrh1O~x3>Ew3MMEp`^7w%z+FhUwkOQ3; zkvX7KjbaKq%RRjXO7VV#JS_xmgmw?i@DK0?oW(wt^rK>KEiO+JL9?YQg1R=44(f79 z7}!>Xa*|z4%JU7@hdJL3sf2-hPF%O|NJ$0(vdZ%T1thw@(iDziN=vWN|bi|mj<5~-=u~x z&eOUEcn_ZUjw>XMNtAL=zs`B1*iTgkbrWxaXTH}b&mzrH9yIv zrO}@%tuAbm4S2sKK_ z?(yDhv3F$Z&%xz(Uz+|%>3Gm?>U6cxq7!{Q+Om5uG8uK8#X!D3es5}=P*>qsG^fIw z91}YghYUyUXPM~i8`raFEs>a%xWS!A9?Lduy)7{zaic^0SO2jYZ&sDcW9sh3gZso5 zPZ0cw@lfNbV3p!Hr+Rkep*VUQqVXDw6)Qn;iD*NP_@9y~mb_bWF*%)-HL zX%aQbs(kNj!<1o#lpc}o;P6kjg}#Nuxi}lCC#g}2uv@TwXxU?8-xhT7yXKRooni+I z-YfFczA!YT9`E<9i=!DMqfz-;^#K&7+3(8h0LJ+%4Rc4>L27z^b<$ceywGe`z_S0x zx1`&+9-?1S-p?+_*xBtxS6l|MP9pvc@B6wqj=C$(f>>7s?IrL*f2PFdQTH;=Q%wZV zWWT_0)KB1g%I7=UoL_VsUfxtUY08qIOJsF~@uE%IH%FezW@+}z?nZtPWT(b$s_#~u z1x%SX4YEoJO)o~1nwy$>+}f*Z1|V4)aJep#O>vWik|+VWq4F8*$XOXajsCDR0vcTE{}bV2xEGjg)L@iMrNzsnI4l^wSKS|GCLLF zSm5S)^dr|V_B(KknE;H8CU@zmZk!x=X}rb%1qftjZ+42T(TVzamtlzhg!tRA;D#3Gbw}_!wA}+C^S1Osom&4V|4XI2W}XCbB z3H#Cf>c7!s$XsrrVquQAiAAYBIifJh1=XuP7uI*E&?;p{+Dz1r95%RB=RWD$@o`y0 zC-BxHv=^^>1E?BWZCYJw`Fh~5@bAW)6`vhb6^f8e=ONrAc0K?bQJXcQh*L#_wyqbH zNxS1?E`O72v9)<}ZY(O4iFwHJXFe@$YHzuOIox&zsaVKmb0Q|ZRbzmodK-)Ki*KkU zdaS8uqa?#_tkb$*YzSa?3f*h{bmD#PjGLiwN}5`sr>%UK&jHm>Jp=la?zu0dtwrJF zyEr#yRcPdQzVbw!{2iP&QZb*q!}U+2?hf zg11WT+WS7F%8haM%j)#_-VzD_$*|Fp z%p%qEz$X94hkrX@tz8z)UItdB=44CUoR6Z-@^M(FF|XGVijY-jjz=@%L~PQeBwi&l zZO1|xuoFV}GCL;UWWV~$ldcjeafje(E4RDJ@c|y6xB!&C##*~A)HUK&&4A6lN2v;A z;D+d?JVr`iog!o@h5PiS6xDkMGg_4~=s@0&gWuf<6d-b(ACZ{!k^A9Co z-K=uLDs<3H>ch?X$x88AUuX7w%_ttBwIH*r8Cw6g#Ry6%`a#8J zIyo5kkutdh=|;@8h7(@D=c`=^2qL=(BZfA^v?vN2?IKrAQD!FA5J=TIaC8pwN(-b$ zQA<3f2rLykqU(FN)M>PSMme=>nv|j&7zMB7a3t4y$lZ}HC^P9=7Xr2%h1-o8NA9qe zjN$Igry0&AxCyV}p^@*@9%eY;^K{TaP{&dzw9D^! ztF^8XtHN?Yxv~ZW*XKt&^w?Z8)mxl4Y4JO`++I>?hfDU_pIA2{XW*AA;fC#hP|IE3 z|2WTKTIdCvb$NEewc!#N93m@CL=kq~|Hz|+*{>1lPUgnv7L-=QshH$PQQnT}JA8*( zoiGD*{g)SL#)LUsVHfumvRdppxD4+U)K}t!qx4yWp`RlKL|cVLt>KDQAx<`_kmyP7 z{VEB`(&XDPS#kexEg%KxkS&v+e!&ZzE;tTK2 zLiV}52?-xp8ooyBr;AYyS~~9PLWx^Z3h+7}LKXu?g@z}5pZ14MOg_mRuAx~lC4f7Q zEvi$t`kFaaPaLZ=2v}lcQT(Y3>Y4UJ+glUwENglQ*fMreJabMSbv274h^Jt9Z*Zqc zIUO#yQ!UCuLJ?f;>q`2^IOQ-=G~`&!c@x+9OI^xZIf7QHp@Y_`&>w9Nyf}b*0r^N? zo}hKA@1XVUWOf_;ZF-BtnAL?#(t9KexgSYb!`krH+T5v`ZXM}b9{f>;7|j3|f0H&> z3-^|EWfzRd()gGp;0{&Qd`sj$oM-@1f+l)#R+&7{S}h9-dx0FHV!vaF|`Ra zgAw43{pO71VfOdMMBo}Kk=3q24}f0vd9>^GZGI9fhRF!3n79u+$Kb)Vq7WFfCo zZcuIs*ByGB(@pLxmwcBj;Z>2`OUmH7%ipFKlGWu#0%N|7<*{gb*5Va_4SwHB@2AN}`Godstk(U+ z4QW7RCNxBcbEitLt@w<~S4B9Pk^NGyg3mRpOtEmVzTWigCv_naq)#LC{$W2nSX^bh z9{Y7hd3+E|2=rA;^kj)KwSgSz=h?vnOG-Pv0ag2qbUCpoIiwM41?Ysl;~p_G=3GRn zARST6$|RTDoI{EGSRqV*fXM7PdXatO99uR~h^5So1=^TTCXRL3?Vz#A;p>(Ffq4_~ z2_s5hZiZ!{;W5UEa;!rrJERwCP$g3RSg>)9F*bRcRO~rLdY=0;M_U?RWxs>!v)Qqk zAT{I;{7nAz2$64GWf<<{K#m&Rs1ERX#5tX~AFPr@&pFc1A30u65gwbiBXv|bgGT$! zptOY9Uy&Z)R34G1!Rg;=0`#L#CLfHHOV_~(RTWxA;$`gciH#=X&`F3T)(qS{W|6*w ztP`U*qEWj@32^J2KnkM@Q89_5B;O=so)mpf4(uoe2kTi~*7;VEH5^nVU7>|DX*>Q= zdxTAtZu-Hl9+CsA9?m53pOoZUR#h{kAYI1BiI=+|VrN36{uuLZg@a{Jo>TY2O4uu& z*svwBh@xW1dNk>hrSiq3wyGCPTGd1H($IRvT{+RqS|dkeO}@1arGYC$CzWyYZsA}7 zT24vCie0-57j`8Ocf{vVe7bQ7cZ`&i{L{|`mHYQoWp{u3_if+dhMRN>l_46N zJ{PKS`t#+s=*E8%=byyYTq&W|du-mT_Bm9pg^xNbUg6g|!?uudi}iYb0-NW4n7`kk24uxWPeZL5}ai zw8lTBJ~2XBDCH4Mn&ZlIwYCdiKFJ|2qeeuaobhGT$hbKz?qztVWo)0L;DtWfk{I>) zBPOmNO0&ryX=ab~B-r;}7mOL-0wa^{C%_{PPF=`rjeu!cdW4=4%_0Ax$ttzkurJMl zzxNmMIK<+ZIzCEmLZ&;*t%{Nv;TiVzd#PNebA9D+lDvW`Ll-WB^0eVviG(LnMYoJD{JHji;g00S{#yv z(pPMlMtt?0m*9SxhbW?%4HBO!hRy{kVvzmSaqz@U+jeCa_F0VuMGWh1ZIs%Qw&!GP zFR6k{Bizzvd+}*)KY*EV2#~hTfojQg!)WzJY?-|bhGpOw+tljP>}}|?xqPnFY^U8I z@u^tT9AgF*UZESRcGFW-a@p~AsUW_pEKhcKIcjw=e00s*9FbVcW)P#YC^D>6pts2% zA0P1U`kWxj9Y9pYxn+ibz^@DsT$*d`@jS&DtrtHedY#_B*Kc+F-Osq}qx5gM&AN(3 zMxWe#L>hG9+wb3@%_~#Fb_$?%E*ABCGB1K|!1n_6G=<;dkm4>An(^SGN`bY!n+ijf zIU%UQ@ZeY76(0ODeg#`Lpt#EbPlViHJLrCw7yrObG|)2jX`b7fo<7A& zH9XSKMnIv^-S&d8oonrP)_!za)PyTZzulFsXeGByxi>KJlx1Ld5)#$*RvR-K*^uD< zaHW{S0D3}ZcaDuFKi@ri+-PV3<{zoU*=-qNZ1X2>KbwU6JZ|#^7545aqWaepE6ZkL z&}_W;_4XNHrl*FZvot+xylxmYR>A;Q4^PI48&SH%cKG{*W22rj$&_T)3b7QX;nO?w zxH;?Iwma}6l9&f+2;c1bTO!PU{8DjR=7s#C_e0nCAy0j@BJ|IXq-EVLOCLjysHV5x zQh=K)UOF$ydyUTh5jH)R>fJXvL|&4|Ow1VneXkX(&Ui|<*t>ph;D=zGuN zb_yCu6@Dcv6N5W9@}ctK6)W#lSOst67N?|S;qO+YD|dOaW=W^rwdYE7fK^@oDLjW0bq|@KB?8UC3|HrH2;37Lhl>Z8X&%O0fi`zKDn6Z zhv{5YEWAK=Es0P|Pv%7U#hU0E5FPPG5Be=f3xm# zpH1rHS`CUkW6G_eXJc~jiSInKp9+uQq3oa4MiaQpdo(x4f9#_lqDASn zTn&J0Cehh$ILCseM7e$aSUWI%l)ia;|~2d2dK7^ za6?(U6F>S9H{&CuPsPt2k*?2Goh@kwG{6~(7Dzq5dSb=FzD@4aU355ejsFiVtA0Q8 z2q?&QWttkd&yXie@*d2d(+xAUZ>yE*YJ3|e#s4?)NmuMalR}jYSSt3_XN`*f;CEhF zPU+|V=hjh$h}qvC8S-=Cx%Psu+~=t)hpV^*oxRMcG^z&uVOV_TZifV<^NbPZh9p$zur!^nRi*U2Te4*| zh&B5bF+v9PG95aX4rx@SK$a>jG0bB@=dLTE@`cH~8q5h{l3)EyHTWXUwBH#Q_UjDx z?%Mlm;EmCU$O>#D0>&H_U7v6x5QCmpEgmlE_(IdDYO97ko;$}l1ZjJt&_7lGz08MC zmd`}T%w$A_X%O;Y)bKe+{1}pS|HyYsw`}0$zxdKIq#;}4A?$rc{r_T1B&N=yaICn7 zw0IaRfhIzr7{3+`ICN;FyzVdaA%xC-w9=?8hkBGl{zX3i@phn;zTSUHeyL?x_ryvM zP`MQB@Mo?knQGqb<#HO>FEahS``vfjd*0~_XQI~Wh`e}Dwonah(UBpb!VZ7$wA6fe zH2Lm_#0&jjh{6|R4u3tHW%G64)7ZW_pMEGtJJn{*VC$ z!{24)r)7&66WR0|4WHGE%7QG~@4sZa2^(7o@Hc#}nBV+*d>=;=`_^#Y5%BtRaFu@G zuUSu z-E{YNlN8fTjHu$&y&LSB(Vu(+^qfh&4TqJqGU=>mvrY@D()mzNRCMmY>;pdMXs@Rs?iBl&s12xGLcwI46a(W{6GOe=S#WlH-_Q_+^(& zGE$maWUlIkePk*Da&e*0yvp-$ei@5l6j0~*W%)dZ^Mr1>Sm;3IL|?e@cnvp#(Hm{3 z{J&`V9rYwaa%j4UTLV$59(?zNdeTXNF3E~ae)6H2+M<>0yqP9c zNwm?0$8)&R{H=?X1{8u>J(LTcr|RVcWEtwWrLoT^)_IkC+%3-W$zZ&T{3~M~-t77K zRQVul0Z+YgV!gI(ZETqCNQGLJ_ncWY8kz*id#F`V|8n)0qc}6$mBVRVPRki~EjY3{ z(rpj08i30#A-!gj1tdPeVdtSC za-KKE>|?@s8bg5Q6U$44-nlYZLul7j#GF4C9NAVKbg!WPKxCx3S_};8J=|ANzds_< zvhxgX`q|$$nJClOOlv@{6g9dLW<8tmsG1oFs3SEQT25ydp0(=)*zA}qQAQ${oxi4? zqwCP1nMCN!l|i%kuy^@fD~ksdTIAEyF@~^cloztxK&J@(MaQ8vfSgY)HR_I8 z9Ci|D5~+8fMrkWl1d;5P)4){BQ{^F(9smE4Nr?k_GS>rVP_6%fBE>0i9APH*PirCj z2^rcG3Z<_|VM?1%rq`bACH}u_iT4YS`?XUSaYc>8WL$U#PU=Lr5wS?kwgDT>hmdMPW+$m6XGpDxxm zas(;Wy4!Y@5gq!B8AFS>GU%tYS*z2de1q7p)EWZAwpy7q1?%0X{f*jpWY1kQ9hqsh T1U2x_1bb|)oGi)aSJVFw2UzAA literal 0 HcmV?d00001 diff --git a/tad/site/static/images/logo.svg b/tad/site/static/images/logo.svg new file mode 100644 index 000000000..f7cfde292 --- /dev/null +++ b/tad/site/static/images/logo.svg @@ -0,0 +1 @@ + diff --git a/tad/site/static/js/tad.js b/tad/site/static/js/tad.js new file mode 100644 index 000000000..7971e06f9 --- /dev/null +++ b/tad/site/static/js/tad.js @@ -0,0 +1,37 @@ +window.onload = function () { + + const columns = document.getElementsByClassName("progress_cards_container"); + for (var i = 0; i < columns.length; i++) { + new Sortable(columns[i], { + group: 'shared', // set both lists to same group + animation: 150, + onEnd: function (evt) { + console.log(evt); + let previousSiblingId = evt.item.previousElementSibling ? evt.item.previousElementSibling.getAttribute("data-id") : ""; + let nextSiblingId = evt.item.nextElementSibling ? evt.item.nextElementSibling.getAttribute("data-id") : ""; + let data = { + "taskId": evt.item.getAttribute("data-id"), + "statusId": evt.to.getAttribute("data-id"), + "previousSiblingId": previousSiblingId, + "nextSiblingId": nextSiblingId + } + + let headers = { + 'Content-Type': 'application/json' + }; + let targetId = "#" + evt.item.getAttribute("id"); + let form = document.getElementById("cardMovedForm"); + document.getElementsByName("taskId")[0].value = evt.item.getAttribute("data-id"); + document.getElementsByName("statusId")[0].value = evt.to.getAttribute("data-id"); + document.getElementsByName("previousSiblingId")[0].value = previousSiblingId; + document.getElementsByName("nextSiblingId")[0].value = nextSiblingId; + form.setAttribute("hx-target", targetId); + htmx.trigger("#cardMovedForm", "cardmoved"); + + // TODO: this must be a JSON post, but I can not get it to work with HTMX... + // https://htmx.org/api/#ajax + //htmx.ajax('POST', "/tasks/move", {values: JSON.stringify({ data: data }), headers: headers, target: targetId, swap: 'outerHTML'}) + } + }); + } +} diff --git a/tad/static/vendor/htmx/1.9.12.min.js b/tad/site/static/vendor/htmx/js/1.9.12.min.js similarity index 100% rename from tad/static/vendor/htmx/1.9.12.min.js rename to tad/site/static/vendor/htmx/js/1.9.12.min.js diff --git a/tad/site/static/vendor/htmx/js/htmx.min.js b/tad/site/static/vendor/htmx/js/htmx.min.js new file mode 100644 index 000000000..2519eec50 --- /dev/null +++ b/tad/site/static/vendor/htmx/js/htmx.min.js @@ -0,0 +1 @@ +(function(e,t){if(typeof define==="function"&&define.amd){define([],t)}else if(typeof module==="object"&&module.exports){module.exports=t()}else{e.htmx=e.htmx||t()}})(typeof self!=="undefined"?self:this,function(){return function(){"use strict";var Q={onLoad:B,process:zt,on:de,off:ge,trigger:ce,ajax:Nr,find:C,findAll:f,closest:v,values:function(e,t){var r=dr(e,t||"post");return r.values},remove:_,addClass:z,removeClass:n,toggleClass:$,takeClass:W,defineExtension:Ur,removeExtension:Fr,logAll:V,logNone:j,logger:null,config:{historyEnabled:true,historyCacheSize:10,refreshOnHistoryMiss:false,defaultSwapStyle:"innerHTML",defaultSwapDelay:0,defaultSettleDelay:20,includeIndicatorStyles:true,indicatorClass:"htmx-indicator",requestClass:"htmx-request",addedClass:"htmx-added",settlingClass:"htmx-settling",swappingClass:"htmx-swapping",allowEval:true,allowScriptTags:true,inlineScriptNonce:"",attributesToSettle:["class","style","width","height"],withCredentials:false,timeout:0,wsReconnectDelay:"full-jitter",wsBinaryType:"blob",disableSelector:"[hx-disable], [data-hx-disable]",useTemplateFragments:false,scrollBehavior:"smooth",defaultFocusScroll:false,getCacheBusterParam:false,globalViewTransitions:false,methodsThatUseUrlParams:["get"],selfRequestsOnly:false,ignoreTitle:false,scrollIntoViewOnBoost:true,triggerSpecsCache:null},parseInterval:d,_:t,createEventSource:function(e){return new EventSource(e,{withCredentials:true})},createWebSocket:function(e){var t=new WebSocket(e,[]);t.binaryType=Q.config.wsBinaryType;return t},version:"1.9.11"};var r={addTriggerHandler:Lt,bodyContains:se,canAccessLocalStorage:U,findThisElement:xe,filterValues:yr,hasAttribute:o,getAttributeValue:te,getClosestAttributeValue:ne,getClosestMatch:c,getExpressionVars:Hr,getHeaders:xr,getInputValues:dr,getInternalData:ae,getSwapSpecification:wr,getTriggerSpecs:it,getTarget:ye,makeFragment:l,mergeObjects:le,makeSettleInfo:T,oobSwap:Ee,querySelectorExt:ue,selectAndSwap:je,settleImmediately:nr,shouldCancel:ut,triggerEvent:ce,triggerErrorEvent:fe,withExtensions:R};var w=["get","post","put","delete","patch"];var i=w.map(function(e){return"[hx-"+e+"], [data-hx-"+e+"]"}).join(", ");var S=e("head"),q=e("title"),H=e("svg",true);function e(e,t=false){return new RegExp(`<${e}(\\s[^>]*>|>)([\\s\\S]*?)<\\/${e}>`,t?"gim":"im")}function d(e){if(e==undefined){return undefined}let t=NaN;if(e.slice(-2)=="ms"){t=parseFloat(e.slice(0,-2))}else if(e.slice(-1)=="s"){t=parseFloat(e.slice(0,-1))*1e3}else if(e.slice(-1)=="m"){t=parseFloat(e.slice(0,-1))*1e3*60}else{t=parseFloat(e)}return isNaN(t)?undefined:t}function ee(e,t){return e.getAttribute&&e.getAttribute(t)}function o(e,t){return e.hasAttribute&&(e.hasAttribute(t)||e.hasAttribute("data-"+t))}function te(e,t){return ee(e,t)||ee(e,"data-"+t)}function u(e){return e.parentElement}function re(){return document}function c(e,t){while(e&&!t(e)){e=u(e)}return e?e:null}function L(e,t,r){var n=te(t,r);var i=te(t,"hx-disinherit");if(e!==t&&i&&(i==="*"||i.split(" ").indexOf(r)>=0)){return"unset"}else{return n}}function ne(t,r){var n=null;c(t,function(e){return n=L(t,e,r)});if(n!=="unset"){return n}}function h(e,t){var r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector;return r&&r.call(e,t)}function A(e){var t=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i;var r=t.exec(e);if(r){return r[1].toLowerCase()}else{return""}}function s(e,t){var r=new DOMParser;var n=r.parseFromString(e,"text/html");var i=n.body;while(t>0){t--;i=i.firstChild}if(i==null){i=re().createDocumentFragment()}return i}function N(e){return/",0);var a=i.querySelector("template").content;if(Q.config.allowScriptTags){oe(a.querySelectorAll("script"),function(e){if(Q.config.inlineScriptNonce){e.nonce=Q.config.inlineScriptNonce}e.htmxExecuted=navigator.userAgent.indexOf("Firefox")===-1})}else{oe(a.querySelectorAll("script"),function(e){_(e)})}return a}switch(r){case"thead":case"tbody":case"tfoot":case"colgroup":case"caption":return s(""+n+"
",1);case"col":return s(""+n+"
",2);case"tr":return s(""+n+"
",2);case"td":case"th":return s(""+n+"
",3);case"script":case"style":return s("

"+n+"
",1);default:return s(n,0)}}function ie(e){if(e){e()}}function I(e,t){return Object.prototype.toString.call(e)==="[object "+t+"]"}function k(e){return I(e,"Function")}function P(e){return I(e,"Object")}function ae(e){var t="htmx-internal-data";var r=e[t];if(!r){r=e[t]={}}return r}function M(e){var t=[];if(e){for(var r=0;r=0}function se(e){if(e.getRootNode&&e.getRootNode()instanceof window.ShadowRoot){return re().body.contains(e.getRootNode().host)}else{return re().body.contains(e)}}function D(e){return e.trim().split(/\s+/)}function le(e,t){for(var r in t){if(t.hasOwnProperty(r)){e[r]=t[r]}}return e}function E(e){try{return JSON.parse(e)}catch(e){b(e);return null}}function U(){var e="htmx:localStorageTest";try{localStorage.setItem(e,e);localStorage.removeItem(e);return true}catch(e){return false}}function F(t){try{var e=new URL(t);if(e){t=e.pathname+e.search}if(!/^\/$/.test(t)){t=t.replace(/\/+$/,"")}return t}catch(e){return t}}function t(e){return Tr(re().body,function(){return eval(e)})}function B(t){var e=Q.on("htmx:load",function(e){t(e.detail.elt)});return e}function V(){Q.logger=function(e,t,r){if(console){console.log(t,e,r)}}}function j(){Q.logger=null}function C(e,t){if(t){return e.querySelector(t)}else{return C(re(),e)}}function f(e,t){if(t){return e.querySelectorAll(t)}else{return f(re(),e)}}function _(e,t){e=p(e);if(t){setTimeout(function(){_(e);e=null},t)}else{e.parentElement.removeChild(e)}}function z(e,t,r){e=p(e);if(r){setTimeout(function(){z(e,t);e=null},r)}else{e.classList&&e.classList.add(t)}}function n(e,t,r){e=p(e);if(r){setTimeout(function(){n(e,t);e=null},r)}else{if(e.classList){e.classList.remove(t);if(e.classList.length===0){e.removeAttribute("class")}}}}function $(e,t){e=p(e);e.classList.toggle(t)}function W(e,t){e=p(e);oe(e.parentElement.children,function(e){n(e,t)});z(e,t)}function v(e,t){e=p(e);if(e.closest){return e.closest(t)}else{do{if(e==null||h(e,t)){return e}}while(e=e&&u(e));return null}}function g(e,t){return e.substring(0,t.length)===t}function G(e,t){return e.substring(e.length-t.length)===t}function J(e){var t=e.trim();if(g(t,"<")&&G(t,"/>")){return t.substring(1,t.length-2)}else{return t}}function Z(e,t){if(t.indexOf("closest ")===0){return[v(e,J(t.substr(8)))]}else if(t.indexOf("find ")===0){return[C(e,J(t.substr(5)))]}else if(t==="next"){return[e.nextElementSibling]}else if(t.indexOf("next ")===0){return[K(e,J(t.substr(5)))]}else if(t==="previous"){return[e.previousElementSibling]}else if(t.indexOf("previous ")===0){return[Y(e,J(t.substr(9)))]}else if(t==="document"){return[document]}else if(t==="window"){return[window]}else if(t==="body"){return[document.body]}else{return re().querySelectorAll(J(t))}}var K=function(e,t){var r=re().querySelectorAll(t);for(var n=0;n=0;n--){var i=r[n];if(i.compareDocumentPosition(e)===Node.DOCUMENT_POSITION_FOLLOWING){return i}}};function ue(e,t){if(t){return Z(e,t)[0]}else{return Z(re().body,e)[0]}}function p(e){if(I(e,"String")){return C(e)}else{return e}}function ve(e,t,r){if(k(t)){return{target:re().body,event:e,listener:t}}else{return{target:p(e),event:t,listener:r}}}function de(t,r,n){jr(function(){var e=ve(t,r,n);e.target.addEventListener(e.event,e.listener)});var e=k(r);return e?r:n}function ge(t,r,n){jr(function(){var e=ve(t,r,n);e.target.removeEventListener(e.event,e.listener)});return k(r)?r:n}var pe=re().createElement("output");function me(e,t){var r=ne(e,t);if(r){if(r==="this"){return[xe(e,t)]}else{var n=Z(e,r);if(n.length===0){b('The selector "'+r+'" on '+t+" returned no matches!");return[pe]}else{return n}}}}function xe(e,t){return c(e,function(e){return te(e,t)!=null})}function ye(e){var t=ne(e,"hx-target");if(t){if(t==="this"){return xe(e,"hx-target")}else{return ue(e,t)}}else{var r=ae(e);if(r.boosted){return re().body}else{return e}}}function be(e){var t=Q.config.attributesToSettle;for(var r=0;r0){o=e.substr(0,e.indexOf(":"));t=e.substr(e.indexOf(":")+1,e.length)}else{o=e}var r=re().querySelectorAll(t);if(r){oe(r,function(e){var t;var r=i.cloneNode(true);t=re().createDocumentFragment();t.appendChild(r);if(!Se(o,e)){t=r}var n={shouldSwap:true,target:e,fragment:t};if(!ce(e,"htmx:oobBeforeSwap",n))return;e=n.target;if(n["shouldSwap"]){Be(o,e,e,t,a)}oe(a.elts,function(e){ce(e,"htmx:oobAfterSwap",n)})});i.parentNode.removeChild(i)}else{i.parentNode.removeChild(i);fe(re().body,"htmx:oobErrorNoTarget",{content:i})}return e}function Ce(e,t,r){var n=ne(e,"hx-select-oob");if(n){var i=n.split(",");for(var a=0;a0){var r=t.replace("'","\\'");var n=e.tagName.replace(":","\\:");var i=o.querySelector(n+"[id='"+r+"']");if(i&&i!==o){var a=e.cloneNode();we(e,i);s.tasks.push(function(){we(e,a)})}}})}function Oe(e){return function(){n(e,Q.config.addedClass);zt(e);Nt(e);qe(e);ce(e,"htmx:load")}}function qe(e){var t="[autofocus]";var r=h(e,t)?e:e.querySelector(t);if(r!=null){r.focus()}}function a(e,t,r,n){Te(e,r,n);while(r.childNodes.length>0){var i=r.firstChild;z(i,Q.config.addedClass);e.insertBefore(i,t);if(i.nodeType!==Node.TEXT_NODE&&i.nodeType!==Node.COMMENT_NODE){n.tasks.push(Oe(i))}}}function He(e,t){var r=0;while(r-1){var t=e.replace(H,"");var r=t.match(q);if(r){return r[2]}}}function je(e,t,r,n,i,a){i.title=Ve(n);var o=l(n);if(o){Ce(r,o,i);o=Fe(r,o,a);Re(o);return Be(e,r,t,o,i)}}function _e(e,t,r){var n=e.getResponseHeader(t);if(n.indexOf("{")===0){var i=E(n);for(var a in i){if(i.hasOwnProperty(a)){var o=i[a];if(!P(o)){o={value:o}}ce(r,a,o)}}}else{var s=n.split(",");for(var l=0;l0){var o=t[0];if(o==="]"){n--;if(n===0){if(a===null){i=i+"true"}t.shift();i+=")})";try{var s=Tr(e,function(){return Function(i)()},function(){return true});s.source=i;return s}catch(e){fe(re().body,"htmx:syntax:error",{error:e,source:i});return null}}}else if(o==="["){n++}if(Qe(o,a,r)){i+="(("+r+"."+o+") ? ("+r+"."+o+") : (window."+o+"))"}else{i=i+o}a=t.shift()}}}function y(e,t){var r="";while(e.length>0&&!t.test(e[0])){r+=e.shift()}return r}function tt(e){var t;if(e.length>0&&Ze.test(e[0])){e.shift();t=y(e,Ke).trim();e.shift()}else{t=y(e,x)}return t}var rt="input, textarea, select";function nt(e,t,r){var n=[];var i=Ye(t);do{y(i,Je);var a=i.length;var o=y(i,/[,\[\s]/);if(o!==""){if(o==="every"){var s={trigger:"every"};y(i,Je);s.pollInterval=d(y(i,/[,\[\s]/));y(i,Je);var l=et(e,i,"event");if(l){s.eventFilter=l}n.push(s)}else if(o.indexOf("sse:")===0){n.push({trigger:"sse",sseEvent:o.substr(4)})}else{var u={trigger:o};var l=et(e,i,"event");if(l){u.eventFilter=l}while(i.length>0&&i[0]!==","){y(i,Je);var f=i.shift();if(f==="changed"){u.changed=true}else if(f==="once"){u.once=true}else if(f==="consume"){u.consume=true}else if(f==="delay"&&i[0]===":"){i.shift();u.delay=d(y(i,x))}else if(f==="from"&&i[0]===":"){i.shift();if(Ze.test(i[0])){var c=tt(i)}else{var c=y(i,x);if(c==="closest"||c==="find"||c==="next"||c==="previous"){i.shift();var h=tt(i);if(h.length>0){c+=" "+h}}}u.from=c}else if(f==="target"&&i[0]===":"){i.shift();u.target=tt(i)}else if(f==="throttle"&&i[0]===":"){i.shift();u.throttle=d(y(i,x))}else if(f==="queue"&&i[0]===":"){i.shift();u.queue=y(i,x)}else if(f==="root"&&i[0]===":"){i.shift();u[f]=tt(i)}else if(f==="threshold"&&i[0]===":"){i.shift();u[f]=y(i,x)}else{fe(e,"htmx:syntax:error",{token:i.shift()})}}n.push(u)}}if(i.length===a){fe(e,"htmx:syntax:error",{token:i.shift()})}y(i,Je)}while(i[0]===","&&i.shift());if(r){r[t]=n}return n}function it(e){var t=te(e,"hx-trigger");var r=[];if(t){var n=Q.config.triggerSpecsCache;r=n&&n[t]||nt(e,t,n)}if(r.length>0){return r}else if(h(e,"form")){return[{trigger:"submit"}]}else if(h(e,'input[type="button"], input[type="submit"]')){return[{trigger:"click"}]}else if(h(e,rt)){return[{trigger:"change"}]}else{return[{trigger:"click"}]}}function at(e){ae(e).cancelled=true}function ot(e,t,r){var n=ae(e);n.timeout=setTimeout(function(){if(se(e)&&n.cancelled!==true){if(!ct(r,e,Wt("hx:poll:trigger",{triggerSpec:r,target:e}))){t(e)}ot(e,t,r)}},r.pollInterval)}function st(e){return location.hostname===e.hostname&&ee(e,"href")&&ee(e,"href").indexOf("#")!==0}function lt(t,r,e){if(t.tagName==="A"&&st(t)&&(t.target===""||t.target==="_self")||t.tagName==="FORM"){r.boosted=true;var n,i;if(t.tagName==="A"){n="get";i=ee(t,"href")}else{var a=ee(t,"method");n=a?a.toLowerCase():"get";if(n==="get"){}i=ee(t,"action")}e.forEach(function(e){ht(t,function(e,t){if(v(e,Q.config.disableSelector)){m(e);return}he(n,i,e,t)},r,e,true)})}}function ut(e,t){if(e.type==="submit"||e.type==="click"){if(t.tagName==="FORM"){return true}if(h(t,'input[type="submit"], button')&&v(t,"form")!==null){return true}if(t.tagName==="A"&&t.href&&(t.getAttribute("href")==="#"||t.getAttribute("href").indexOf("#")!==0)){return true}}return false}function ft(e,t){return ae(e).boosted&&e.tagName==="A"&&t.type==="click"&&(t.ctrlKey||t.metaKey)}function ct(e,t,r){var n=e.eventFilter;if(n){try{return n.call(t,r)!==true}catch(e){fe(re().body,"htmx:eventFilter:error",{error:e,source:n.source});return true}}return false}function ht(a,o,e,s,l){var u=ae(a);var t;if(s.from){t=Z(a,s.from)}else{t=[a]}if(s.changed){t.forEach(function(e){var t=ae(e);t.lastValue=e.value})}oe(t,function(n){var i=function(e){if(!se(a)){n.removeEventListener(s.trigger,i);return}if(ft(a,e)){return}if(l||ut(e,a)){e.preventDefault()}if(ct(s,a,e)){return}var t=ae(e);t.triggerSpec=s;if(t.handledFor==null){t.handledFor=[]}if(t.handledFor.indexOf(a)<0){t.handledFor.push(a);if(s.consume){e.stopPropagation()}if(s.target&&e.target){if(!h(e.target,s.target)){return}}if(s.once){if(u.triggeredOnce){return}else{u.triggeredOnce=true}}if(s.changed){var r=ae(n);if(r.lastValue===n.value){return}r.lastValue=n.value}if(u.delayed){clearTimeout(u.delayed)}if(u.throttle){return}if(s.throttle>0){if(!u.throttle){o(a,e);u.throttle=setTimeout(function(){u.throttle=null},s.throttle)}}else if(s.delay>0){u.delayed=setTimeout(function(){o(a,e)},s.delay)}else{ce(a,"htmx:trigger");o(a,e)}}};if(e.listenerInfos==null){e.listenerInfos=[]}e.listenerInfos.push({trigger:s.trigger,listener:i,on:n});n.addEventListener(s.trigger,i)})}var vt=false;var dt=null;function gt(){if(!dt){dt=function(){vt=true};window.addEventListener("scroll",dt);setInterval(function(){if(vt){vt=false;oe(re().querySelectorAll("[hx-trigger='revealed'],[data-hx-trigger='revealed']"),function(e){pt(e)})}},200)}}function pt(t){if(!o(t,"data-hx-revealed")&&X(t)){t.setAttribute("data-hx-revealed","true");var e=ae(t);if(e.initHash){ce(t,"revealed")}else{t.addEventListener("htmx:afterProcessNode",function(e){ce(t,"revealed")},{once:true})}}}function mt(e,t,r){var n=D(r);for(var i=0;i=0){var t=wt(n);setTimeout(function(){xt(s,r,n+1)},t)}};t.onopen=function(e){n=0};ae(s).webSocket=t;t.addEventListener("message",function(e){if(yt(s)){return}var t=e.data;R(s,function(e){t=e.transformResponse(t,null,s)});var r=T(s);var n=l(t);var i=M(n.children);for(var a=0;a0){ce(u,"htmx:validation:halted",i);return}t.send(JSON.stringify(l));if(ut(e,u)){e.preventDefault()}})}else{fe(u,"htmx:noWebSocketSourceError")}}function wt(e){var t=Q.config.wsReconnectDelay;if(typeof t==="function"){return t(e)}if(t==="full-jitter"){var r=Math.min(e,6);var n=1e3*Math.pow(2,r);return n*Math.random()}b('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"')}function St(e,t,r){var n=D(r);for(var i=0;i0){setTimeout(i,n)}else{i()}}function Ht(t,i,e){var a=false;oe(w,function(r){if(o(t,"hx-"+r)){var n=te(t,"hx-"+r);a=true;i.path=n;i.verb=r;e.forEach(function(e){Lt(t,e,i,function(e,t){if(v(e,Q.config.disableSelector)){m(e);return}he(r,n,e,t)})})}});return a}function Lt(n,e,t,r){if(e.sseEvent){Rt(n,r,e.sseEvent)}else if(e.trigger==="revealed"){gt();ht(n,r,t,e);pt(n)}else if(e.trigger==="intersect"){var i={};if(e.root){i.root=ue(n,e.root)}if(e.threshold){i.threshold=parseFloat(e.threshold)}var a=new IntersectionObserver(function(e){for(var t=0;t0){t.polling=true;ot(n,r,e)}else{ht(n,r,t,e)}}function At(e){if(!e.htmxExecuted&&Q.config.allowScriptTags&&(e.type==="text/javascript"||e.type==="module"||e.type==="")){var t=re().createElement("script");oe(e.attributes,function(e){t.setAttribute(e.name,e.value)});t.textContent=e.textContent;t.async=false;if(Q.config.inlineScriptNonce){t.nonce=Q.config.inlineScriptNonce}var r=e.parentElement;try{r.insertBefore(t,e)}catch(e){b(e)}finally{if(e.parentElement){e.parentElement.removeChild(e)}}}}function Nt(e){if(h(e,"script")){At(e)}oe(f(e,"script"),function(e){At(e)})}function It(e){var t=e.attributes;for(var r=0;r0){var o=n.shift();var s=o.match(/^\s*([a-zA-Z:\-\.]+:)(.*)/);if(a===0&&s){o.split(":");i=s[1].slice(0,-1);r[i]=s[2]}else{r[i]+=o}a+=Ft(o)}for(var l in r){Bt(e,l,r[l])}}}function jt(e){Ae(e);for(var t=0;tQ.config.historyCacheSize){i.shift()}while(i.length>0){try{localStorage.setItem("htmx-history-cache",JSON.stringify(i));break}catch(e){fe(re().body,"htmx:historyCacheError",{cause:e,cache:i});i.shift()}}}function Yt(e){if(!U()){return null}e=F(e);var t=E(localStorage.getItem("htmx-history-cache"))||[];for(var r=0;r=200&&this.status<400){ce(re().body,"htmx:historyCacheMissLoad",o);var e=l(this.response);e=e.querySelector("[hx-history-elt],[data-hx-history-elt]")||e;var t=Zt();var r=T(t);var n=Ve(this.response);if(n){var i=C("title");if(i){i.innerHTML=n}else{window.document.title=n}}Ue(t,e,r);nr(r.tasks);Jt=a;ce(re().body,"htmx:historyRestore",{path:a,cacheMiss:true,serverResponse:this.response})}else{fe(re().body,"htmx:historyCacheMissLoadError",o)}};e.send()}function ar(e){er();e=e||location.pathname+location.search;var t=Yt(e);if(t){var r=l(t.content);var n=Zt();var i=T(n);Ue(n,r,i);nr(i.tasks);document.title=t.title;setTimeout(function(){window.scrollTo(0,t.scroll)},0);Jt=e;ce(re().body,"htmx:historyRestore",{path:e,item:t})}else{if(Q.config.refreshOnHistoryMiss){window.location.reload(true)}else{ir(e)}}}function or(e){var t=me(e,"hx-indicator");if(t==null){t=[e]}oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)+1;e.classList["add"].call(e.classList,Q.config.requestClass)});return t}function sr(e){var t=me(e,"hx-disabled-elt");if(t==null){t=[]}oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)+1;e.setAttribute("disabled","")});return t}function lr(e,t){oe(e,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)-1;if(t.requestCount===0){e.classList["remove"].call(e.classList,Q.config.requestClass)}});oe(t,function(e){var t=ae(e);t.requestCount=(t.requestCount||0)-1;if(t.requestCount===0){e.removeAttribute("disabled")}})}function ur(e,t){for(var r=0;r=0}function wr(e,t){var r=t?t:ne(e,"hx-swap");var n={swapStyle:ae(e).boosted?"innerHTML":Q.config.defaultSwapStyle,swapDelay:Q.config.defaultSwapDelay,settleDelay:Q.config.defaultSettleDelay};if(Q.config.scrollIntoViewOnBoost&&ae(e).boosted&&!br(e)){n["show"]="top"}if(r){var i=D(r);if(i.length>0){for(var a=0;a0?l.join(":"):null;n["scroll"]=u;n["scrollTarget"]=f}else if(o.indexOf("show:")===0){var c=o.substr(5);var l=c.split(":");var h=l.pop();var f=l.length>0?l.join(":"):null;n["show"]=h;n["showTarget"]=f}else if(o.indexOf("focus-scroll:")===0){var v=o.substr("focus-scroll:".length);n["focusScroll"]=v=="true"}else if(a==0){n["swapStyle"]=o}else{b("Unknown modifier in hx-swap: "+o)}}}}return n}function Sr(e){return ne(e,"hx-encoding")==="multipart/form-data"||h(e,"form")&&ee(e,"enctype")==="multipart/form-data"}function Er(t,r,n){var i=null;R(r,function(e){if(i==null){i=e.encodeParameters(t,n,r)}});if(i!=null){return i}else{if(Sr(r)){return mr(n)}else{return pr(n)}}}function T(e){return{tasks:[],elts:[e]}}function Cr(e,t){var r=e[0];var n=e[e.length-1];if(t.scroll){var i=null;if(t.scrollTarget){i=ue(r,t.scrollTarget)}if(t.scroll==="top"&&(r||i)){i=i||r;i.scrollTop=0}if(t.scroll==="bottom"&&(n||i)){i=i||n;i.scrollTop=i.scrollHeight}}if(t.show){var i=null;if(t.showTarget){var a=t.showTarget;if(t.showTarget==="window"){a="body"}i=ue(r,a)}if(t.show==="top"&&(r||i)){i=i||r;i.scrollIntoView({block:"start",behavior:Q.config.scrollBehavior})}if(t.show==="bottom"&&(n||i)){i=i||n;i.scrollIntoView({block:"end",behavior:Q.config.scrollBehavior})}}}function Rr(e,t,r,n){if(n==null){n={}}if(e==null){return n}var i=te(e,t);if(i){var a=i.trim();var o=r;if(a==="unset"){return null}if(a.indexOf("javascript:")===0){a=a.substr(11);o=true}else if(a.indexOf("js:")===0){a=a.substr(3);o=true}if(a.indexOf("{")!==0){a="{"+a+"}"}var s;if(o){s=Tr(e,function(){return Function("return ("+a+")")()},{})}else{s=E(a)}for(var l in s){if(s.hasOwnProperty(l)){if(n[l]==null){n[l]=s[l]}}}}return Rr(u(e),t,r,n)}function Tr(e,t,r){if(Q.config.allowEval){return t()}else{fe(e,"htmx:evalDisallowedError");return r}}function Or(e,t){return Rr(e,"hx-vars",true,t)}function qr(e,t){return Rr(e,"hx-vals",false,t)}function Hr(e){return le(Or(e),qr(e))}function Lr(t,r,n){if(n!==null){try{t.setRequestHeader(r,n)}catch(e){t.setRequestHeader(r,encodeURIComponent(n));t.setRequestHeader(r+"-URI-AutoEncoded","true")}}}function Ar(t){if(t.responseURL&&typeof URL!=="undefined"){try{var e=new URL(t.responseURL);return e.pathname+e.search}catch(e){fe(re().body,"htmx:badResponseUrl",{url:t.responseURL})}}}function O(e,t){return t.test(e.getAllResponseHeaders())}function Nr(e,t,r){e=e.toLowerCase();if(r){if(r instanceof Element||I(r,"String")){return he(e,t,null,null,{targetOverride:p(r),returnPromise:true})}else{return he(e,t,p(r.source),r.event,{handler:r.handler,headers:r.headers,values:r.values,targetOverride:p(r.target),swapOverride:r.swap,select:r.select,returnPromise:true})}}else{return he(e,t,null,null,{returnPromise:true})}}function Ir(e){var t=[];while(e){t.push(e);e=e.parentElement}return t}function kr(e,t,r){var n;var i;if(typeof URL==="function"){i=new URL(t,document.location.href);var a=document.location.origin;n=a===i.origin}else{i=t;n=g(t,document.location.origin)}if(Q.config.selfRequestsOnly){if(!n){return false}}return ce(e,"htmx:validateUrl",le({url:i,sameHost:n},r))}function he(t,r,n,i,a,e){var o=null;var s=null;a=a!=null?a:{};if(a.returnPromise&&typeof Promise!=="undefined"){var l=new Promise(function(e,t){o=e;s=t})}if(n==null){n=re().body}var M=a.handler||Mr;var X=a.select||null;if(!se(n)){ie(o);return l}var u=a.targetOverride||ye(n);if(u==null||u==pe){fe(n,"htmx:targetError",{target:te(n,"hx-target")});ie(s);return l}var f=ae(n);var c=f.lastButtonClicked;if(c){var h=ee(c,"formaction");if(h!=null){r=h}var v=ee(c,"formmethod");if(v!=null){if(v.toLowerCase()!=="dialog"){t=v}}}var d=ne(n,"hx-confirm");if(e===undefined){var D=function(e){return he(t,r,n,i,a,!!e)};var U={target:u,elt:n,path:r,verb:t,triggeringEvent:i,etc:a,issueRequest:D,question:d};if(ce(n,"htmx:confirm",U)===false){ie(o);return l}}var g=n;var p=ne(n,"hx-sync");var m=null;var x=false;if(p){var F=p.split(":");var B=F[0].trim();if(B==="this"){g=xe(n,"hx-sync")}else{g=ue(n,B)}p=(F[1]||"drop").trim();f=ae(g);if(p==="drop"&&f.xhr&&f.abortable!==true){ie(o);return l}else if(p==="abort"){if(f.xhr){ie(o);return l}else{x=true}}else if(p==="replace"){ce(g,"htmx:abort")}else if(p.indexOf("queue")===0){var V=p.split(" ");m=(V[1]||"last").trim()}}if(f.xhr){if(f.abortable){ce(g,"htmx:abort")}else{if(m==null){if(i){var y=ae(i);if(y&&y.triggerSpec&&y.triggerSpec.queue){m=y.triggerSpec.queue}}if(m==null){m="last"}}if(f.queuedRequests==null){f.queuedRequests=[]}if(m==="first"&&f.queuedRequests.length===0){f.queuedRequests.push(function(){he(t,r,n,i,a)})}else if(m==="all"){f.queuedRequests.push(function(){he(t,r,n,i,a)})}else if(m==="last"){f.queuedRequests=[];f.queuedRequests.push(function(){he(t,r,n,i,a)})}ie(o);return l}}var b=new XMLHttpRequest;f.xhr=b;f.abortable=x;var w=function(){f.xhr=null;f.abortable=false;if(f.queuedRequests!=null&&f.queuedRequests.length>0){var e=f.queuedRequests.shift();e()}};var j=ne(n,"hx-prompt");if(j){var S=prompt(j);if(S===null||!ce(n,"htmx:prompt",{prompt:S,target:u})){ie(o);w();return l}}if(d&&!e){if(!confirm(d)){ie(o);w();return l}}var E=xr(n,u,S);if(t!=="get"&&!Sr(n)){E["Content-Type"]="application/x-www-form-urlencoded"}if(a.headers){E=le(E,a.headers)}var _=dr(n,t);var C=_.errors;var R=_.values;if(a.values){R=le(R,a.values)}var z=Hr(n);var $=le(R,z);var T=yr($,n);if(Q.config.getCacheBusterParam&&t==="get"){T["org.htmx.cache-buster"]=ee(u,"id")||"true"}if(r==null||r===""){r=re().location.href}var O=Rr(n,"hx-request");var W=ae(n).boosted;var q=Q.config.methodsThatUseUrlParams.indexOf(t)>=0;var H={boosted:W,useUrlParams:q,parameters:T,unfilteredParameters:$,headers:E,target:u,verb:t,errors:C,withCredentials:a.credentials||O.credentials||Q.config.withCredentials,timeout:a.timeout||O.timeout||Q.config.timeout,path:r,triggeringEvent:i};if(!ce(n,"htmx:configRequest",H)){ie(o);w();return l}r=H.path;t=H.verb;E=H.headers;T=H.parameters;C=H.errors;q=H.useUrlParams;if(C&&C.length>0){ce(n,"htmx:validation:halted",H);ie(o);w();return l}var G=r.split("#");var J=G[0];var L=G[1];var A=r;if(q){A=J;var Z=Object.keys(T).length!==0;if(Z){if(A.indexOf("?")<0){A+="?"}else{A+="&"}A+=pr(T);if(L){A+="#"+L}}}if(!kr(n,A,H)){fe(n,"htmx:invalidPath",H);ie(s);return l}b.open(t.toUpperCase(),A,true);b.overrideMimeType("text/html");b.withCredentials=H.withCredentials;b.timeout=H.timeout;if(O.noHeaders){}else{for(var N in E){if(E.hasOwnProperty(N)){var K=E[N];Lr(b,N,K)}}}var I={xhr:b,target:u,requestConfig:H,etc:a,boosted:W,select:X,pathInfo:{requestPath:r,finalRequestPath:A,anchor:L}};b.onload=function(){try{var e=Ir(n);I.pathInfo.responsePath=Ar(b);M(n,I);lr(k,P);ce(n,"htmx:afterRequest",I);ce(n,"htmx:afterOnLoad",I);if(!se(n)){var t=null;while(e.length>0&&t==null){var r=e.shift();if(se(r)){t=r}}if(t){ce(t,"htmx:afterRequest",I);ce(t,"htmx:afterOnLoad",I)}}ie(o);w()}catch(e){fe(n,"htmx:onLoadError",le({error:e},I));throw e}};b.onerror=function(){lr(k,P);fe(n,"htmx:afterRequest",I);fe(n,"htmx:sendError",I);ie(s);w()};b.onabort=function(){lr(k,P);fe(n,"htmx:afterRequest",I);fe(n,"htmx:sendAbort",I);ie(s);w()};b.ontimeout=function(){lr(k,P);fe(n,"htmx:afterRequest",I);fe(n,"htmx:timeout",I);ie(s);w()};if(!ce(n,"htmx:beforeRequest",I)){ie(o);w();return l}var k=or(n);var P=sr(n);oe(["loadstart","loadend","progress","abort"],function(t){oe([b,b.upload],function(e){e.addEventListener(t,function(e){ce(n,"htmx:xhr:"+t,{lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total})})})});ce(n,"htmx:beforeSend",I);var Y=q?null:Er(b,n,T);b.send(Y);return l}function Pr(e,t){var r=t.xhr;var n=null;var i=null;if(O(r,/HX-Push:/i)){n=r.getResponseHeader("HX-Push");i="push"}else if(O(r,/HX-Push-Url:/i)){n=r.getResponseHeader("HX-Push-Url");i="push"}else if(O(r,/HX-Replace-Url:/i)){n=r.getResponseHeader("HX-Replace-Url");i="replace"}if(n){if(n==="false"){return{}}else{return{type:i,path:n}}}var a=t.pathInfo.finalRequestPath;var o=t.pathInfo.responsePath;var s=ne(e,"hx-push-url");var l=ne(e,"hx-replace-url");var u=ae(e).boosted;var f=null;var c=null;if(s){f="push";c=s}else if(l){f="replace";c=l}else if(u){f="push";c=o||a}if(c){if(c==="false"){return{}}if(c==="true"){c=o||a}if(t.pathInfo.anchor&&c.indexOf("#")===-1){c=c+"#"+t.pathInfo.anchor}return{type:f,path:c}}else{return{}}}function Mr(l,u){var f=u.xhr;var c=u.target;var e=u.etc;var t=u.requestConfig;var h=u.select;if(!ce(l,"htmx:beforeOnLoad",u))return;if(O(f,/HX-Trigger:/i)){_e(f,"HX-Trigger",l)}if(O(f,/HX-Location:/i)){er();var r=f.getResponseHeader("HX-Location");var v;if(r.indexOf("{")===0){v=E(r);r=v["path"];delete v["path"]}Nr("GET",r,v).then(function(){tr(r)});return}var n=O(f,/HX-Refresh:/i)&&"true"===f.getResponseHeader("HX-Refresh");if(O(f,/HX-Redirect:/i)){location.href=f.getResponseHeader("HX-Redirect");n&&location.reload();return}if(n){location.reload();return}if(O(f,/HX-Retarget:/i)){if(f.getResponseHeader("HX-Retarget")==="this"){u.target=l}else{u.target=ue(l,f.getResponseHeader("HX-Retarget"))}}var d=Pr(l,u);var i=f.status>=200&&f.status<400&&f.status!==204;var g=f.response;var a=f.status>=400;var p=Q.config.ignoreTitle;var o=le({shouldSwap:i,serverResponse:g,isError:a,ignoreTitle:p},u);if(!ce(c,"htmx:beforeSwap",o))return;c=o.target;g=o.serverResponse;a=o.isError;p=o.ignoreTitle;u.target=c;u.failed=a;u.successful=!a;if(o.shouldSwap){if(f.status===286){at(l)}R(l,function(e){g=e.transformResponse(g,f,l)});if(d.type){er()}var s=e.swapOverride;if(O(f,/HX-Reswap:/i)){s=f.getResponseHeader("HX-Reswap")}var v=wr(l,s);if(v.hasOwnProperty("ignoreTitle")){p=v.ignoreTitle}c.classList.add(Q.config.swappingClass);var m=null;var x=null;var y=function(){try{var e=document.activeElement;var t={};try{t={elt:e,start:e?e.selectionStart:null,end:e?e.selectionEnd:null}}catch(e){}var r;if(h){r=h}if(O(f,/HX-Reselect:/i)){r=f.getResponseHeader("HX-Reselect")}if(d.type){ce(re().body,"htmx:beforeHistoryUpdate",le({history:d},u));if(d.type==="push"){tr(d.path);ce(re().body,"htmx:pushedIntoHistory",{path:d.path})}else{rr(d.path);ce(re().body,"htmx:replacedInHistory",{path:d.path})}}var n=T(c);je(v.swapStyle,c,l,g,n,r);if(t.elt&&!se(t.elt)&&ee(t.elt,"id")){var i=document.getElementById(ee(t.elt,"id"));var a={preventScroll:v.focusScroll!==undefined?!v.focusScroll:!Q.config.defaultFocusScroll};if(i){if(t.start&&i.setSelectionRange){try{i.setSelectionRange(t.start,t.end)}catch(e){}}i.focus(a)}}c.classList.remove(Q.config.swappingClass);oe(n.elts,function(e){if(e.classList){e.classList.add(Q.config.settlingClass)}ce(e,"htmx:afterSwap",u)});if(O(f,/HX-Trigger-After-Swap:/i)){var o=l;if(!se(l)){o=re().body}_e(f,"HX-Trigger-After-Swap",o)}var s=function(){oe(n.tasks,function(e){e.call()});oe(n.elts,function(e){if(e.classList){e.classList.remove(Q.config.settlingClass)}ce(e,"htmx:afterSettle",u)});if(u.pathInfo.anchor){var e=re().getElementById(u.pathInfo.anchor);if(e){e.scrollIntoView({block:"start",behavior:"auto"})}}if(n.title&&!p){var t=C("title");if(t){t.innerHTML=n.title}else{window.document.title=n.title}}Cr(n.elts,v);if(O(f,/HX-Trigger-After-Settle:/i)){var r=l;if(!se(l)){r=re().body}_e(f,"HX-Trigger-After-Settle",r)}ie(m)};if(v.settleDelay>0){setTimeout(s,v.settleDelay)}else{s()}}catch(e){fe(l,"htmx:swapError",u);ie(x);throw e}};var b=Q.config.globalViewTransitions;if(v.hasOwnProperty("transition")){b=v.transition}if(b&&ce(l,"htmx:beforeTransition",u)&&typeof Promise!=="undefined"&&document.startViewTransition){var w=new Promise(function(e,t){m=e;x=t});var S=y;y=function(){document.startViewTransition(function(){S();return w})}}if(v.swapDelay>0){setTimeout(y,v.swapDelay)}else{y()}}if(a){fe(l,"htmx:responseError",le({error:"Response Status Error Code "+f.status+" from "+u.pathInfo.requestPath},u))}}var Xr={};function Dr(){return{init:function(e){return null},onEvent:function(e,t){return true},transformResponse:function(e,t,r){return e},isInlineSwap:function(e){return false},handleSwap:function(e,t,r,n){return false},encodeParameters:function(e,t,r){return null}}}function Ur(e,t){if(t.init){t.init(r)}Xr[e]=le(Dr(),t)}function Fr(e){delete Xr[e]}function Br(e,r,n){if(e==undefined){return r}if(r==undefined){r=[]}if(n==undefined){n=[]}var t=te(e,"hx-ext");if(t){oe(t.split(","),function(e){e=e.replace(/ /g,"");if(e.slice(0,7)=="ignore:"){n.push(e.slice(7));return}if(n.indexOf(e)<0){var t=Xr[e];if(t&&r.indexOf(t)<0){r.push(t)}}})}return Br(u(e),r,n)}var Vr=false;re().addEventListener("DOMContentLoaded",function(){Vr=true});function jr(e){if(Vr||re().readyState==="complete"){e()}else{re().addEventListener("DOMContentLoaded",e)}}function _r(){if(Q.config.includeIndicatorStyles!==false){re().head.insertAdjacentHTML("beforeend","")}}function zr(){var e=re().querySelector('meta[name="htmx-config"]');if(e){return E(e.content)}else{return null}}function $r(){var e=zr();if(e){Q.config=le(Q.config,e)}}jr(function(){$r();_r();var e=re().body;zt(e);var t=re().querySelectorAll("[hx-trigger='restored'],[data-hx-trigger='restored']");e.addEventListener("htmx:abort",function(e){var t=e.target;var r=ae(t);if(r&&r.xhr){r.xhr.abort()}});const r=window.onpopstate?window.onpopstate.bind(window):null;window.onpopstate=function(e){if(e.state&&e.state.htmx){ar();oe(t,function(e){ce(e,"htmx:restored",{document:re(),triggerEvent:ce})})}else{if(r){r(e)}}};setTimeout(function(){ce(e,"htmx:load",{});e=null},0)});return Q}()}); diff --git a/tad/site/static/vendor/htmx/js/hyperscript.min.js b/tad/site/static/vendor/htmx/js/hyperscript.min.js new file mode 100644 index 000000000..9e11f0b5e --- /dev/null +++ b/tad/site/static/vendor/htmx/js/hyperscript.min.js @@ -0,0 +1 @@ +(function(e,r){if(typeof define==="function"&&define.amd){define([],r)}else{e._hyperscript=r()}})(typeof self!=="undefined"?self:this,function(){return function(){"use strict";function M(e,r){for(var t in r){if(r.hasOwnProperty(t)){e[t]=r[t]}}return e}function r(e){try{return JSON.parse(e)}catch(e){t(e);return null}}function t(e){if(console.error){console.error(e)}else if(console.log){console.log("ERROR: ",e)}}function u(e,r){return new(e.bind.apply(e,[e].concat(r)))}var _=typeof self!=="undefined"?self:typeof global!=="undefined"?global:this;var j=function(){var b={"+":"PLUS","-":"MINUS","*":"MULTIPLY","/":"DIVIDE",".":"PERIOD","..":"ELLIPSIS","\\":"BACKSLASH",":":"COLON","%":"PERCENT","|":"PIPE","!":"EXCLAMATION","?":"QUESTION","#":"POUND","&":"AMPERSAND",$:"DOLLAR",";":"SEMI",",":"COMMA","(":"L_PAREN",")":"R_PAREN","<":"L_ANG",">":"R_ANG","<=":"LTE_ANG",">=":"GTE_ANG","==":"EQ","===":"EQQ","!=":"NEQ","!==":"NEQQ","{":"L_BRACE","}":"R_BRACE","[":"L_BRACKET","]":"R_BRACKET","=":"EQUALS"};function w(e){return R(e)||C(e)||e==="-"||e==="_"||e===":"}function N(e){return R(e)||C(e)||e==="-"||e==="_"||e===":"}function I(e){return e===" "||e==="\t"||A(e)}function O(e){return"[Line: "+e.line+", Column: "+e.col+"]"}function A(e){return e==="\r"||e==="\n"}function C(e){return e>="0"&&e<="9"}function R(e){return e>="a"&&e<="z"||e>="A"&&e<="Z"}function S(e){return e==="_"||e==="$"}function L(e){return e==="`"||e==="^"}function P(i,o,e){u();var r=null;function u(){while(y(0,true).type==="WHITESPACE"){o.push(i.shift())}}function s(e,r){D.raiseParseError(e,r)}function t(e){var r=l(e);if(r){return r}else{s(this,"Expected '"+e+"' but found '"+k().value+"'")}}function n(e,r,t){for(var n=0;n=0){return v()}}function p(e,r){var t=m(e,r);if(t){return t}else{s(this,"Expected '"+e+"' but found '"+k().value+"'")}}function m(e,r){var r=r||"IDENTIFIER";if(k()&&k().value===e&&k().type===r){return v()}}function v(){var e=i.shift();o.push(e);r=e;u();return e}function h(e,r){var t=[];var n=y(0,true);while((r==null||n.type!==r)&&(e==null||n.value!==e)&&n.type!=="EOF"){var a=i.shift();o.push(a);t.push(n);n=y(0,true)}u();return t}function d(){if(o[o.length-1]&&o[o.length-1].type==="WHITESPACE"){return o[o.length-1].value}else{return""}}function E(){return h(null,"WHITESPACE")}function T(){return i.length>0}function y(e,r){var t;var n=0;do{if(!r){while(i[n]&&i[n].type==="WHITESPACE"){n++}}t=i[n];e--;n++}while(e>-1);if(t){return t}else{return{type:"EOF",value:"<<>>"}}}function k(){return y(0)}function x(){return r}function g(){return e.substring(this.startToken.start,this.endToken.end)}function q(){return e.split("\n")[this.startToken.line-1]}return{matchAnyToken:a,matchAnyOpToken:n,matchOpToken:l,requireOpToken:t,matchTokenType:f,requireTokenType:c,consumeToken:v,matchToken:m,requireToken:p,list:i,consumed:o,source:e,hasMore:T,currentToken:k,lastMatch:x,token:y,consumeUntil:h,consumeUntilWhitespace:E,lastWhitespace:d,sourceFor:g,lineFor:q}}function F(e){if(e.length>0){var r=e[e.length-1];if(r.type==="IDENTIFIER"||r.type==="CLASS_REF"||r.type==="ID_REF"){return false}if(r.op&&(r.value===">"||r.value===")")){return false}}return true}function e(e,r){var t=[];var n=e;var a=0;var i=0;var o=1;var u="";var s=0;function l(){return r&&s===0}while(a0){var i=r.shift();var o=a[i];if(o==null){o={};a[i]=o}a=o}a[t]=n}function C(e,r){var t=[];var n=e;while(n.meta.caller){n=n.meta.caller}if(n.meta.traceMap){return n.meta.traceMap.get(r,t)}}function R(e,r){var a=[];var t=null;while(e!=null){a.push(e);t=e;e=e.meta.caller}if(t.meta.traceMap==null){t.meta.traceMap=new Map}if(!t.meta.traceMap.get(r)){var n={trace:a,print:function(e){e=e||console.error;e("hypertrace /// ");var r=0;for(var t=0;t",n.meta.feature.displayName.padEnd(r+2),"-",n.meta.owner)}}};t.meta.traceMap.set(r,n)}}function S(e){return e.replace(/:/g,function(e){return"\\"+e})}function L(e,r){if(e==null){throw new Error(r.sourceFor()+" is null")}}function P(e){return e==undefined||e.length===0}var F="document"in _?document.currentScript.src:null;return{typeCheck:w,forEach:n,triggerEvent:o,matchesSelector:t,getScript:c,processNode:g,evaluate:x,parse:k,getScriptSelector:E,resolveSymbol:N,makeContext:d,findNext:I,unifiedEval:e,convertValue:T,unifiedExec:v,resolveProperty:O,assignToNamespace:A,registerHyperTrace:R,getHyperTrace:C,getInternalData:b,escapeSelector:S,nullCheck:L,isEmpty:P,hyperscriptUrl:F,HALT:l}}();{D.addLeafExpression("parenthesized",function(e,r,t){if(t.matchOpToken("(")){var n=e.requireElement("expression",t);t.requireOpToken(")");return{type:"parenthesized",expr:n,evaluate:function(e){return n.evaluate(e)}}}});D.addLeafExpression("string",function(e,r,t){var n=t.matchTokenType("STRING");if(n){var a=n.value;if(n.template){var i=j.tokenize(a,true);var o=e.parseStringTemplate(i)}else{var o=[]}return{type:"string",token:n,args:o,op:function(e){var r="";for(var t=1;t");var i=a.map(function(e){if(e.type==="STRING"){return'"'+e.value+'"'}else{return e.value}}).join("");return{type:"queryRef",css:i,evaluate:function(){return document.querySelectorAll(this.css)}}}});D.addGrammarElement("attributeRef",function(e,r,t){if(t.matchOpToken("[")){var n=t.consumeUntil("]");var a=n.map(function(e){return e.value}).join("");var i=a.split("=");var o=i[0];var u=i[1];t.requireOpToken("]");return{type:"attribute_expression",name:o,value:u,args:[u],op:function(e,r){if(this.value){return{name:this.name,value:r}}else{return{name:this.name}}},evaluate:function(e){return r.unifiedEval(this,e)}}}});D.addGrammarElement("objectKey",function(e,r,t){var n;if(n=t.matchTokenType("STRING")){return{type:"objectKey",key:n.value,evaluate:function(){return this.key}}}else if(t.matchOpToken("[")){var a=e.parseElement("expression",t);t.requireOpToken("]");return{type:"objectKey",expr:a,args:[a],op:function(e,r){return r},evaluate:function(e){return r.unifiedEval(this,e)}}}else{var i="";do{n=t.matchTokenType("IDENTIFIER")||t.matchOpToken("-");if(n)i+=n.value}while(n);return{type:"objectKey",key:i,evaluate:function(){return this.key}}}});D.addLeafExpression("objectLiteral",function(e,r,t){if(t.matchOpToken("{")){var n=[];var a=[];if(!t.matchOpToken("}")){do{var i=e.requireElement("objectKey",t);t.requireOpToken(":");var o=e.requireElement("expression",t);a.push(o);n.push(i)}while(t.matchOpToken(","));t.requireOpToken("}")}return{type:"objectLiteral",args:[n,a],op:function(e,r,t){var n={};for(var a=0;a");var i=e.requireElement("expression",t);return{type:"blockLiteral",args:n,expr:i,evaluate:function(r){var e=function(){for(var e=0;e0){return n}else{return null}},evaluate:function(e){return a.unifiedEval(this,e)}};return e.parseElement("indirectExpression",r,n)}});D.addIndirectExpression("asExpression",function(e,t,r,n){if(r.matchToken("as")){var a=e.requireElement("dotOrColonPath",r).evaluate();var i={type:"asExpression",root:n,args:[n],op:function(e,r){return t.convertValue(r,a)},evaluate:function(e){return t.unifiedEval(this,e)}};return e.parseElement("indirectExpression",r,i)}});D.addIndirectExpression("functionCall",function(e,a,r,i){if(r.matchOpToken("(")){var t=[];if(!r.matchOpToken(")")){do{t.push(e.requireElement("expression",r))}while(r.matchOpToken(","));r.requireOpToken(")")}if(i.root){var n={type:"functionCall",root:i,argExressions:t,args:[i.root,t],op:function(e,r,t){a.nullCheck(r,i.root);var n=r[i.prop.value];a.nullCheck(n,i);if(n.hyperfunc){t.push(e)}return n.apply(r,t)},evaluate:function(e){return a.unifiedEval(this,e)}}}else{var n={type:"functionCall",root:i,argExressions:t,args:[i,t],op:function(e,r,t){a.nullCheck(r,i);if(r.hyperfunc){t.push(e)}var n=r.apply(null,t);return n},evaluate:function(e){return a.unifiedEval(this,e)}}}return e.parseElement("indirectExpression",r,n)}});D.addIndirectExpression("arrayIndex",function(e,r,t,n){if(t.matchOpToken("[")){var a=false;var i=false;var o=null;var u=null;if(t.matchOpToken("..")){a=true;o=e.requireElement("expression",t)}else{o=e.requireElement("expression",t);if(t.matchOpToken("..")){i=true;var s=t.currentToken();if(s.type!=="R_BRACKET"){u=e.parseElement("expression",t)}}}t.requireOpToken("]");var l={type:"arrayIndex",root:n,firstIndex:o,secondIndex:u,args:[n,o,u],op:function(e,r,t,n){if(a){return r.slice(0,t+1)}else if(i){if(n!=null){return r.slice(t,n+1)}else{return r.slice(t)}}else{return r[t]}},evaluate:function(e){return G.unifiedEval(this,e,o,u)}};return D.parseElement("indirectExpression",t,l)}});D.addGrammarElement("postfixExpression",function(e,n,r){var t=e.parseElement("primaryExpression",r);if(r.matchOpToken(":")){var a=r.requireTokenType("IDENTIFIER");var i=!r.matchOpToken("!");return{type:"typeCheck",typeName:a,root:t,nullOk:i,args:[t],op:function(e,r){var t=n.typeCheck(r,this.typeName.value,this.nullOk);if(t){return r}else{throw new Error("Typecheck failed! Expected: "+this.typeName.value)}},evaluate:function(e){return n.unifiedEval(this,e)}}}else{return t}});D.addGrammarElement("logicalNot",function(e,r,t){if(t.matchToken("not")){var n=e.requireElement("unaryExpression",t);return{type:"logicalNot",root:n,args:[n],op:function(e,r){return!r},evaluate:function(e){return r.unifiedEval(this,e)}}}});D.addGrammarElement("noExpression",function(e,t,r){if(r.matchToken("no")){var n=e.requireElement("unaryExpression",r);return{type:"noExpression",root:n,args:[n],op:function(e,r){return t.isEmpty(r)},evaluate:function(e){return t.unifiedEval(this,e)}}}});D.addGrammarElement("negativeNumber",function(e,r,t){if(t.matchOpToken("-")){var n=e.requireElement("unaryExpression",t);return{type:"negativeNumber",root:n,args:[n],op:function(e,r){return-1*r},evaluate:function(e){return r.unifiedEval(this,e)}}}});D.addGrammarElement("unaryExpression",function(e,r,t){return e.parseAnyOf(["logicalNot","positionalExpression","noExpression","negativeNumber","postfixExpression"],t)});D.addGrammarElement("positionalExpression",function(e,r,t){var n=t.matchAnyToken("first","last","random");if(n){t.matchAnyToken("in","from","of");var a=e.requireElement("unaryExpression",t);return{type:"positionalExpression",rhs:a,operator:n.value,args:[a],op:function(e,r){if(!Array.isArray(r)){if(r.children){r=r.children}else{r=Array.from(r)}}if(this.operator==="first"){return r[0]}else if(this.operator==="last"){return r[r.length-1]}else if(this.operator==="random"){return r[Math.floor(Math.random()*r.length)]}},evaluate:function(e){return r.unifiedEval(this,e)}}}});D.addGrammarElement("mathOperator",function(e,r,t){var n=e.parseElement("unaryExpression",t);var a,i=null;a=t.matchAnyOpToken("+","-","*","/","%");while(a){i=i||a;var o=a.value;if(i.value!==o){e.raiseParseError(t,"You must parenthesize math operations with different operators")}var u=e.parseElement("unaryExpression",t);n={type:"mathOperator",lhs:n,rhs:u,operator:o,args:[n,u],op:function(e,r,t){if(this.operator==="+"){return r+t}else if(this.operator==="-"){return r-t}else if(this.operator==="*"){return r*t}else if(this.operator==="/"){return r/t}else if(this.operator==="%"){return r%t}},evaluate:function(e){return r.unifiedEval(this,e)}};a=t.matchAnyOpToken("+","-","*","/","%")}return n});D.addGrammarElement("mathExpression",function(e,r,t){return e.parseAnyOf(["mathOperator","unaryExpression"],t)});D.addGrammarElement("comparisonOperator",function(e,n,r){var t=e.parseElement("mathExpression",r);var a=r.matchAnyOpToken("<",">","<=",">=","==","===","!=","!==");var i=a?a.value:null;var o=true;var u=false;if(i==null){if(r.matchToken("is")||r.matchToken("am")){if(r.matchToken("not")){if(r.matchToken("in")){i="not in"}else if(r.matchToken("a")){i="not a";u=true}else if(r.matchToken("empty")){i="not empty";o=false}else{i="!="}}else if(r.matchToken("in")){i="in"}else if(r.matchToken("a")){i="a";u=true}else if(r.matchToken("empty")){i="empty";o=false}else{i="=="}}else if(r.matchToken("matches")||r.matchToken("match")){i="match"}else if(r.matchToken("contains")||r.matchToken("contain")){i="contain"}else if(r.matchToken("do")||r.matchToken("does")){r.requireToken("not");if(r.matchToken("matches")||r.matchToken("match")){i="not match"}else if(r.matchToken("contains")||r.matchToken("contain")){i="not contain"}else{e.raiseParseError(r,"Expected matches or contains")}}}if(i){if(u){var s=r.requireTokenType("IDENTIFIER");var l=!r.matchOpToken("!")}else if(o){var c=e.requireElement("mathExpression",r);if(i==="match"||i==="not match"){c=c.css?c.css:c}}t={type:"comparisonOperator",operator:i,typeName:s,nullOk:l,lhs:t,rhs:c,args:[t,c],op:function(e,r,t){if(this.operator==="=="){return r==t}else if(this.operator==="!="){return r!=t}if(this.operator==="in"){return t!=null&&Array.from(t).indexOf(r)>=0}if(this.operator==="not in"){return t==null||Array.from(t).indexOf(r)<0}if(this.operator==="match"){return r!=null&&r.matches(t)}if(this.operator==="not match"){return r==null||!r.matches(t)}if(this.operator==="contain"){return r!=null&&r.contains(t)}if(this.operator==="not contain"){return r==null||!r.contains(t)}if(this.operator==="==="){return r===t}else if(this.operator==="!=="){return r!==t}else if(this.operator==="<"){return r"){return r>t}else if(this.operator==="<="){return r<=t}else if(this.operator===">="){return r>=t}else if(this.operator==="empty"){return n.isEmpty(r)}else if(this.operator==="not empty"){return!n.isEmpty(r)}else if(this.operator==="a"){return n.typeCheck(r,this.typeName.value,this.nullOk)}else if(this.operator==="not a"){return!n.typeCheck(r,this.typeName.value,this.nullOk)}else{throw"Unknown comparison : "+this.operator}},evaluate:function(e){return n.unifiedEval(this,e)}}}return t});D.addGrammarElement("comparisonExpression",function(e,r,t){return e.parseAnyOf(["comparisonOperator","mathExpression"],t)});D.addGrammarElement("logicalOperator",function(e,r,t){var n=e.parseElement("comparisonExpression",t);var a,i=null;a=t.matchToken("and")||t.matchToken("or");while(a){i=i||a;if(i.value!==a.value){e.raiseParseError(t,"You must parenthesize logical operations with different operators")}var o=e.requireElement("comparisonExpression",t);n={type:"logicalOperator",operator:a.value,lhs:n,rhs:o,args:[n,o],op:function(e,r,t){if(this.operator==="and"){return r&&t}else{return r||t}},evaluate:function(e){return r.unifiedEval(this,e)}};a=t.matchToken("and")||t.matchToken("or")}return n});D.addGrammarElement("logicalExpression",function(e,r,t){return e.parseAnyOf(["logicalOperator","mathExpression"],t)});D.addGrammarElement("asyncExpression",function(e,r,t){if(t.matchToken("async")){var n=e.requireElement("logicalExpression",t);var a={type:"asyncExpression",value:n,evaluate:function(e){return{asyncWrapper:true,value:this.value.evaluate(e)}}};return a}else{return e.parseElement("logicalExpression",t)}});D.addGrammarElement("expression",function(e,r,t){t.matchToken("the");return e.parseElement("asyncExpression",t)});D.addGrammarElement("targetExpression",function(e,r,t){t.matchToken("the");var n=e.parseElement("primaryExpression",t);if(n.type==="symbol"||n.type==="idRef"||n.type==="inExpression"||n.type==="queryRef"||n.type==="classRef"||n.type==="ofExpression"||n.type==="propertyAccess"||n.type==="closestExpr"||n.type==="possessive"){return n}else{D.raiseParseError(t,"A target expression must be writable")}return n});D.addGrammarElement("hyperscript",function(e,r,t){var n=[];if(t.hasMore()){do{var a=e.requireElement("feature",t);n.push(a);t.matchToken("end")}while(e.featureStart(t.currentToken())||t.currentToken().value==="(");if(t.hasMore()){e.raiseParseError(t)}}return{type:"hyperscript",features:n,apply:function(r,t){G.forEach(n,function(e){e.install(r,t)})}}});var C=function(e){var r=[];if(e.token(0).value==="("&&(e.token(1).value===")"||e.token(2).value===","||e.token(2).value===")")){e.matchOpToken("(");do{r.push(e.requireTokenType("IDENTIFIER"))}while(e.matchOpToken(","));e.requireOpToken(")")}return r};D.addFeature("on",function(e,s,r){if(r.matchToken("on")){var t=false;if(r.matchToken("every")){t=true}var n=[];var a=null;do{var i=e.requireElement("dotOrColonPath",r,"Expected event name");var o=i.evaluate();if(a){a=a+" or "+o}else{a="on "+o}var u=C(r);var l=null;if(r.matchOpToken("[")){l=e.requireElement("expression",r);r.requireOpToken("]")}if(r.currentToken().type==="NUMBER"){var c=r.consumeToken();var f=parseInt(c.value);if(r.matchToken("to")){var p=r.consumeToken();var m=parseInt(p.value)}else if(r.matchToken("and")){var v=true;r.requireToken("on")}}var h=null;var d=false;if(r.matchToken("from")){if(r.matchToken("elsewhere")){d=true}else{h=e.parseElement("targetExpression",r);if(!h){e.raiseParseError('Expected either target value or "elsewhere".',r)}}}if(h===null&&d===false&&r.matchToken("elsewhere")){d=true}if(r.matchToken("in")){var E=e.parseAnyOf(["idRef","queryRef","classRef"],r)}if(r.matchToken("debounced")){r.requireToken("at");var T=e.requireElement("timeExpression",r);var y=T.evaluate({})}else if(r.matchToken("throttled")){r.requireToken("at");var T=e.requireElement("timeExpression",r);var k=T.evaluate({})}n.push({execCount:0,every:t,on:o,args:u,filter:l,from:h,inExpr:E,elsewhere:d,startCount:f,endCount:m,unbounded:v,debounceTime:y,throttleTime:k})}while(r.matchToken("or"));var x=[];var g=true;if(!t){if(r.matchToken("queue")){if(r.matchToken("all")){var q=true;var g=false}else if(r.matchToken("first")){var b=true}else if(r.matchToken("none")){var w=true}else{r.requireToken("last")}}}var N=e.requireElement("commandList",r);var I={type:"implicitReturn",op:function(e){e.meta.resolve();return s.HALT},execute:function(e){}};if(N){var O=N;while(O.next){O=O.next}O.next=I}else{N=I}var A={displayName:a,events:n,start:N,every:t,executing:false,execCount:0,queue:x,execute:function(n){if(this.executing&&this.every===false){if(w||b&&x.length>0){return}if(g){A.queue.length=0}A.queue.push(n);return}this.execCount++;this.executing=true;n.meta.resolve=function(){A.executing=false;var e=A.queue.shift();if(e){setTimeout(function(){A.execute(e)},1)}};n.meta.reject=function(e){console.error(e.message?e.message:e);var r=s.getHyperTrace(n,e);if(r){r.print()}s.triggerEvent(n.me,"exception",{error:e});A.executing=false;var t=A.queue.shift();if(t){setTimeout(function(){A.execute(t)},1)}};N.execute(n)},install:function(u,e){s.forEach(A.events,function(o){var e;if(o.elsewhere){e=[document]}else if(o.from){e=o.from.evaluate({me:u})}else{e=[u]}s.forEach(e,function(i){i.addEventListener(o.on,function(e){var r=s.makeContext(u,A,u,e);if(o.elsewhere&&u.contains(e.target)){return}if(o.from){r.result=i}s.forEach(o.args,function(e){r[e.value]=r.event[e.value]||(r.event.detail?r.event.detail[e.value]:null)});if(o.filter){var t=r.meta.context;r.meta.context=r.event;try{var n=o.filter.evaluate(r);if(n){}else{return}}finally{r.meta.context=t}}if(o.inExpr){var a=e.target;while(true){if(a.matches&&a.matches(o.inExpr.css)){r.result=a;break}else{a=a.parentElement;if(a==null){return}}}}o.execCount++;if(o.startCount){if(o.endCount){if(o.execCounto.endCount){return}}else if(o.unbounded){if(o.execCount + * @author owenm + * @license MIT + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.Sortable = factory()); +}(this, (function () { 'use strict'; + + function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + if (enumerableOnly) { + symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + }); + } + keys.push.apply(keys, symbols); + } + return keys; + } + function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + if (i % 2) { + ownKeys(Object(source), true).forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } else if (Object.getOwnPropertyDescriptors) { + Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); + } else { + ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + } + return target; + } + function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + return _typeof(obj); + } + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + return obj; + } + function _extends() { + _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + return target; + }; + return _extends.apply(this, arguments); + } + function _objectWithoutPropertiesLoose(source, excluded) { + if (source == null) return {}; + var target = {}; + var sourceKeys = Object.keys(source); + var key, i; + for (i = 0; i < sourceKeys.length; i++) { + key = sourceKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + target[key] = source[key]; + } + return target; + } + function _objectWithoutProperties(source, excluded) { + if (source == null) return {}; + var target = _objectWithoutPropertiesLoose(source, excluded); + var key, i; + if (Object.getOwnPropertySymbols) { + var sourceSymbolKeys = Object.getOwnPropertySymbols(source); + for (i = 0; i < sourceSymbolKeys.length; i++) { + key = sourceSymbolKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; + target[key] = source[key]; + } + } + return target; + } + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var version = "1.15.2"; + + function userAgent(pattern) { + if (typeof window !== 'undefined' && window.navigator) { + return !! /*@__PURE__*/navigator.userAgent.match(pattern); + } + } + var IE11OrLess = userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i); + var Edge = userAgent(/Edge/i); + var FireFox = userAgent(/firefox/i); + var Safari = userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i); + var IOS = userAgent(/iP(ad|od|hone)/i); + var ChromeForAndroid = userAgent(/chrome/i) && userAgent(/android/i); + + var captureMode = { + capture: false, + passive: false + }; + function on(el, event, fn) { + el.addEventListener(event, fn, !IE11OrLess && captureMode); + } + function off(el, event, fn) { + el.removeEventListener(event, fn, !IE11OrLess && captureMode); + } + function matches( /**HTMLElement*/el, /**String*/selector) { + if (!selector) return; + selector[0] === '>' && (selector = selector.substring(1)); + if (el) { + try { + if (el.matches) { + return el.matches(selector); + } else if (el.msMatchesSelector) { + return el.msMatchesSelector(selector); + } else if (el.webkitMatchesSelector) { + return el.webkitMatchesSelector(selector); + } + } catch (_) { + return false; + } + } + return false; + } + function getParentOrHost(el) { + return el.host && el !== document && el.host.nodeType ? el.host : el.parentNode; + } + function closest( /**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx, includeCTX) { + if (el) { + ctx = ctx || document; + do { + if (selector != null && (selector[0] === '>' ? el.parentNode === ctx && matches(el, selector) : matches(el, selector)) || includeCTX && el === ctx) { + return el; + } + if (el === ctx) break; + /* jshint boss:true */ + } while (el = getParentOrHost(el)); + } + return null; + } + var R_SPACE = /\s+/g; + function toggleClass(el, name, state) { + if (el && name) { + if (el.classList) { + el.classList[state ? 'add' : 'remove'](name); + } else { + var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' '); + el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' '); + } + } + } + function css(el, prop, val) { + var style = el && el.style; + if (style) { + if (val === void 0) { + if (document.defaultView && document.defaultView.getComputedStyle) { + val = document.defaultView.getComputedStyle(el, ''); + } else if (el.currentStyle) { + val = el.currentStyle; + } + return prop === void 0 ? val : val[prop]; + } else { + if (!(prop in style) && prop.indexOf('webkit') === -1) { + prop = '-webkit-' + prop; + } + style[prop] = val + (typeof val === 'string' ? '' : 'px'); + } + } + } + function matrix(el, selfOnly) { + var appliedTransforms = ''; + if (typeof el === 'string') { + appliedTransforms = el; + } else { + do { + var transform = css(el, 'transform'); + if (transform && transform !== 'none') { + appliedTransforms = transform + ' ' + appliedTransforms; + } + /* jshint boss:true */ + } while (!selfOnly && (el = el.parentNode)); + } + var matrixFn = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix; + /*jshint -W056 */ + return matrixFn && new matrixFn(appliedTransforms); + } + function find(ctx, tagName, iterator) { + if (ctx) { + var list = ctx.getElementsByTagName(tagName), + i = 0, + n = list.length; + if (iterator) { + for (; i < n; i++) { + iterator(list[i], i); + } + } + return list; + } + return []; + } + function getWindowScrollingElement() { + var scrollingElement = document.scrollingElement; + if (scrollingElement) { + return scrollingElement; + } else { + return document.documentElement; + } + } + + /** + * Returns the "bounding client rect" of given element + * @param {HTMLElement} el The element whose boundingClientRect is wanted + * @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container + * @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr + * @param {[Boolean]} undoScale Whether the container's scale() should be undone + * @param {[HTMLElement]} container The parent the element will be placed in + * @return {Object} The boundingClientRect of el, with specified adjustments + */ + function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) { + if (!el.getBoundingClientRect && el !== window) return; + var elRect, top, left, bottom, right, height, width; + if (el !== window && el.parentNode && el !== getWindowScrollingElement()) { + elRect = el.getBoundingClientRect(); + top = elRect.top; + left = elRect.left; + bottom = elRect.bottom; + right = elRect.right; + height = elRect.height; + width = elRect.width; + } else { + top = 0; + left = 0; + bottom = window.innerHeight; + right = window.innerWidth; + height = window.innerHeight; + width = window.innerWidth; + } + if ((relativeToContainingBlock || relativeToNonStaticParent) && el !== window) { + // Adjust for translate() + container = container || el.parentNode; + + // solves #1123 (see: https://stackoverflow.com/a/37953806/6088312) + // Not needed on <= IE11 + if (!IE11OrLess) { + do { + if (container && container.getBoundingClientRect && (css(container, 'transform') !== 'none' || relativeToNonStaticParent && css(container, 'position') !== 'static')) { + var containerRect = container.getBoundingClientRect(); + + // Set relative to edges of padding box of container + top -= containerRect.top + parseInt(css(container, 'border-top-width')); + left -= containerRect.left + parseInt(css(container, 'border-left-width')); + bottom = top + elRect.height; + right = left + elRect.width; + break; + } + /* jshint boss:true */ + } while (container = container.parentNode); + } + } + if (undoScale && el !== window) { + // Adjust for scale() + var elMatrix = matrix(container || el), + scaleX = elMatrix && elMatrix.a, + scaleY = elMatrix && elMatrix.d; + if (elMatrix) { + top /= scaleY; + left /= scaleX; + width /= scaleX; + height /= scaleY; + bottom = top + height; + right = left + width; + } + } + return { + top: top, + left: left, + bottom: bottom, + right: right, + width: width, + height: height + }; + } + + /** + * Checks if a side of an element is scrolled past a side of its parents + * @param {HTMLElement} el The element who's side being scrolled out of view is in question + * @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom') + * @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom') + * @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element + */ + function isScrolledPast(el, elSide, parentSide) { + var parent = getParentAutoScrollElement(el, true), + elSideVal = getRect(el)[elSide]; + + /* jshint boss:true */ + while (parent) { + var parentSideVal = getRect(parent)[parentSide], + visible = void 0; + if (parentSide === 'top' || parentSide === 'left') { + visible = elSideVal >= parentSideVal; + } else { + visible = elSideVal <= parentSideVal; + } + if (!visible) return parent; + if (parent === getWindowScrollingElement()) break; + parent = getParentAutoScrollElement(parent, false); + } + return false; + } + + /** + * Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible) + * and non-draggable elements + * @param {HTMLElement} el The parent element + * @param {Number} childNum The index of the child + * @param {Object} options Parent Sortable's options + * @return {HTMLElement} The child at index childNum, or null if not found + */ + function getChild(el, childNum, options, includeDragEl) { + var currentChild = 0, + i = 0, + children = el.children; + while (i < children.length) { + if (children[i].style.display !== 'none' && children[i] !== Sortable.ghost && (includeDragEl || children[i] !== Sortable.dragged) && closest(children[i], options.draggable, el, false)) { + if (currentChild === childNum) { + return children[i]; + } + currentChild++; + } + i++; + } + return null; + } + + /** + * Gets the last child in the el, ignoring ghostEl or invisible elements (clones) + * @param {HTMLElement} el Parent element + * @param {selector} selector Any other elements that should be ignored + * @return {HTMLElement} The last child, ignoring ghostEl + */ + function lastChild(el, selector) { + var last = el.lastElementChild; + while (last && (last === Sortable.ghost || css(last, 'display') === 'none' || selector && !matches(last, selector))) { + last = last.previousElementSibling; + } + return last || null; + } + + /** + * Returns the index of an element within its parent for a selected set of + * elements + * @param {HTMLElement} el + * @param {selector} selector + * @return {number} + */ + function index(el, selector) { + var index = 0; + if (!el || !el.parentNode) { + return -1; + } + + /* jshint boss:true */ + while (el = el.previousElementSibling) { + if (el.nodeName.toUpperCase() !== 'TEMPLATE' && el !== Sortable.clone && (!selector || matches(el, selector))) { + index++; + } + } + return index; + } + + /** + * Returns the scroll offset of the given element, added with all the scroll offsets of parent elements. + * The value is returned in real pixels. + * @param {HTMLElement} el + * @return {Array} Offsets in the format of [left, top] + */ + function getRelativeScrollOffset(el) { + var offsetLeft = 0, + offsetTop = 0, + winScroller = getWindowScrollingElement(); + if (el) { + do { + var elMatrix = matrix(el), + scaleX = elMatrix.a, + scaleY = elMatrix.d; + offsetLeft += el.scrollLeft * scaleX; + offsetTop += el.scrollTop * scaleY; + } while (el !== winScroller && (el = el.parentNode)); + } + return [offsetLeft, offsetTop]; + } + + /** + * Returns the index of the object within the given array + * @param {Array} arr Array that may or may not hold the object + * @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find + * @return {Number} The index of the object in the array, or -1 + */ + function indexOfObject(arr, obj) { + for (var i in arr) { + if (!arr.hasOwnProperty(i)) continue; + for (var key in obj) { + if (obj.hasOwnProperty(key) && obj[key] === arr[i][key]) return Number(i); + } + } + return -1; + } + function getParentAutoScrollElement(el, includeSelf) { + // skip to window + if (!el || !el.getBoundingClientRect) return getWindowScrollingElement(); + var elem = el; + var gotSelf = false; + do { + // we don't need to get elem css if it isn't even overflowing in the first place (performance) + if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) { + var elemCSS = css(elem); + if (elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') || elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')) { + if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement(); + if (gotSelf || includeSelf) return elem; + gotSelf = true; + } + } + /* jshint boss:true */ + } while (elem = elem.parentNode); + return getWindowScrollingElement(); + } + function extend(dst, src) { + if (dst && src) { + for (var key in src) { + if (src.hasOwnProperty(key)) { + dst[key] = src[key]; + } + } + } + return dst; + } + function isRectEqual(rect1, rect2) { + return Math.round(rect1.top) === Math.round(rect2.top) && Math.round(rect1.left) === Math.round(rect2.left) && Math.round(rect1.height) === Math.round(rect2.height) && Math.round(rect1.width) === Math.round(rect2.width); + } + var _throttleTimeout; + function throttle(callback, ms) { + return function () { + if (!_throttleTimeout) { + var args = arguments, + _this = this; + if (args.length === 1) { + callback.call(_this, args[0]); + } else { + callback.apply(_this, args); + } + _throttleTimeout = setTimeout(function () { + _throttleTimeout = void 0; + }, ms); + } + }; + } + function cancelThrottle() { + clearTimeout(_throttleTimeout); + _throttleTimeout = void 0; + } + function scrollBy(el, x, y) { + el.scrollLeft += x; + el.scrollTop += y; + } + function clone(el) { + var Polymer = window.Polymer; + var $ = window.jQuery || window.Zepto; + if (Polymer && Polymer.dom) { + return Polymer.dom(el).cloneNode(true); + } else if ($) { + return $(el).clone(true)[0]; + } else { + return el.cloneNode(true); + } + } + function setRect(el, rect) { + css(el, 'position', 'absolute'); + css(el, 'top', rect.top); + css(el, 'left', rect.left); + css(el, 'width', rect.width); + css(el, 'height', rect.height); + } + function unsetRect(el) { + css(el, 'position', ''); + css(el, 'top', ''); + css(el, 'left', ''); + css(el, 'width', ''); + css(el, 'height', ''); + } + function getChildContainingRectFromElement(container, options, ghostEl) { + var rect = {}; + Array.from(container.children).forEach(function (child) { + var _rect$left, _rect$top, _rect$right, _rect$bottom; + if (!closest(child, options.draggable, container, false) || child.animated || child === ghostEl) return; + var childRect = getRect(child); + rect.left = Math.min((_rect$left = rect.left) !== null && _rect$left !== void 0 ? _rect$left : Infinity, childRect.left); + rect.top = Math.min((_rect$top = rect.top) !== null && _rect$top !== void 0 ? _rect$top : Infinity, childRect.top); + rect.right = Math.max((_rect$right = rect.right) !== null && _rect$right !== void 0 ? _rect$right : -Infinity, childRect.right); + rect.bottom = Math.max((_rect$bottom = rect.bottom) !== null && _rect$bottom !== void 0 ? _rect$bottom : -Infinity, childRect.bottom); + }); + rect.width = rect.right - rect.left; + rect.height = rect.bottom - rect.top; + rect.x = rect.left; + rect.y = rect.top; + return rect; + } + var expando = 'Sortable' + new Date().getTime(); + + function AnimationStateManager() { + var animationStates = [], + animationCallbackId; + return { + captureAnimationState: function captureAnimationState() { + animationStates = []; + if (!this.options.animation) return; + var children = [].slice.call(this.el.children); + children.forEach(function (child) { + if (css(child, 'display') === 'none' || child === Sortable.ghost) return; + animationStates.push({ + target: child, + rect: getRect(child) + }); + var fromRect = _objectSpread2({}, animationStates[animationStates.length - 1].rect); + + // If animating: compensate for current animation + if (child.thisAnimationDuration) { + var childMatrix = matrix(child, true); + if (childMatrix) { + fromRect.top -= childMatrix.f; + fromRect.left -= childMatrix.e; + } + } + child.fromRect = fromRect; + }); + }, + addAnimationState: function addAnimationState(state) { + animationStates.push(state); + }, + removeAnimationState: function removeAnimationState(target) { + animationStates.splice(indexOfObject(animationStates, { + target: target + }), 1); + }, + animateAll: function animateAll(callback) { + var _this = this; + if (!this.options.animation) { + clearTimeout(animationCallbackId); + if (typeof callback === 'function') callback(); + return; + } + var animating = false, + animationTime = 0; + animationStates.forEach(function (state) { + var time = 0, + target = state.target, + fromRect = target.fromRect, + toRect = getRect(target), + prevFromRect = target.prevFromRect, + prevToRect = target.prevToRect, + animatingRect = state.rect, + targetMatrix = matrix(target, true); + if (targetMatrix) { + // Compensate for current animation + toRect.top -= targetMatrix.f; + toRect.left -= targetMatrix.e; + } + target.toRect = toRect; + if (target.thisAnimationDuration) { + // Could also check if animatingRect is between fromRect and toRect + if (isRectEqual(prevFromRect, toRect) && !isRectEqual(fromRect, toRect) && + // Make sure animatingRect is on line between toRect & fromRect + (animatingRect.top - toRect.top) / (animatingRect.left - toRect.left) === (fromRect.top - toRect.top) / (fromRect.left - toRect.left)) { + // If returning to same place as started from animation and on same axis + time = calculateRealTime(animatingRect, prevFromRect, prevToRect, _this.options); + } + } + + // if fromRect != toRect: animate + if (!isRectEqual(toRect, fromRect)) { + target.prevFromRect = fromRect; + target.prevToRect = toRect; + if (!time) { + time = _this.options.animation; + } + _this.animate(target, animatingRect, toRect, time); + } + if (time) { + animating = true; + animationTime = Math.max(animationTime, time); + clearTimeout(target.animationResetTimer); + target.animationResetTimer = setTimeout(function () { + target.animationTime = 0; + target.prevFromRect = null; + target.fromRect = null; + target.prevToRect = null; + target.thisAnimationDuration = null; + }, time); + target.thisAnimationDuration = time; + } + }); + clearTimeout(animationCallbackId); + if (!animating) { + if (typeof callback === 'function') callback(); + } else { + animationCallbackId = setTimeout(function () { + if (typeof callback === 'function') callback(); + }, animationTime); + } + animationStates = []; + }, + animate: function animate(target, currentRect, toRect, duration) { + if (duration) { + css(target, 'transition', ''); + css(target, 'transform', ''); + var elMatrix = matrix(this.el), + scaleX = elMatrix && elMatrix.a, + scaleY = elMatrix && elMatrix.d, + translateX = (currentRect.left - toRect.left) / (scaleX || 1), + translateY = (currentRect.top - toRect.top) / (scaleY || 1); + target.animatingX = !!translateX; + target.animatingY = !!translateY; + css(target, 'transform', 'translate3d(' + translateX + 'px,' + translateY + 'px,0)'); + this.forRepaintDummy = repaint(target); // repaint + + css(target, 'transition', 'transform ' + duration + 'ms' + (this.options.easing ? ' ' + this.options.easing : '')); + css(target, 'transform', 'translate3d(0,0,0)'); + typeof target.animated === 'number' && clearTimeout(target.animated); + target.animated = setTimeout(function () { + css(target, 'transition', ''); + css(target, 'transform', ''); + target.animated = false; + target.animatingX = false; + target.animatingY = false; + }, duration); + } + } + }; + } + function repaint(target) { + return target.offsetWidth; + } + function calculateRealTime(animatingRect, fromRect, toRect, options) { + return Math.sqrt(Math.pow(fromRect.top - animatingRect.top, 2) + Math.pow(fromRect.left - animatingRect.left, 2)) / Math.sqrt(Math.pow(fromRect.top - toRect.top, 2) + Math.pow(fromRect.left - toRect.left, 2)) * options.animation; + } + + var plugins = []; + var defaults = { + initializeByDefault: true + }; + var PluginManager = { + mount: function mount(plugin) { + // Set default static properties + for (var option in defaults) { + if (defaults.hasOwnProperty(option) && !(option in plugin)) { + plugin[option] = defaults[option]; + } + } + plugins.forEach(function (p) { + if (p.pluginName === plugin.pluginName) { + throw "Sortable: Cannot mount plugin ".concat(plugin.pluginName, " more than once"); + } + }); + plugins.push(plugin); + }, + pluginEvent: function pluginEvent(eventName, sortable, evt) { + var _this = this; + this.eventCanceled = false; + evt.cancel = function () { + _this.eventCanceled = true; + }; + var eventNameGlobal = eventName + 'Global'; + plugins.forEach(function (plugin) { + if (!sortable[plugin.pluginName]) return; + // Fire global events if it exists in this sortable + if (sortable[plugin.pluginName][eventNameGlobal]) { + sortable[plugin.pluginName][eventNameGlobal](_objectSpread2({ + sortable: sortable + }, evt)); + } + + // Only fire plugin event if plugin is enabled in this sortable, + // and plugin has event defined + if (sortable.options[plugin.pluginName] && sortable[plugin.pluginName][eventName]) { + sortable[plugin.pluginName][eventName](_objectSpread2({ + sortable: sortable + }, evt)); + } + }); + }, + initializePlugins: function initializePlugins(sortable, el, defaults, options) { + plugins.forEach(function (plugin) { + var pluginName = plugin.pluginName; + if (!sortable.options[pluginName] && !plugin.initializeByDefault) return; + var initialized = new plugin(sortable, el, sortable.options); + initialized.sortable = sortable; + initialized.options = sortable.options; + sortable[pluginName] = initialized; + + // Add default options from plugin + _extends(defaults, initialized.defaults); + }); + for (var option in sortable.options) { + if (!sortable.options.hasOwnProperty(option)) continue; + var modified = this.modifyOption(sortable, option, sortable.options[option]); + if (typeof modified !== 'undefined') { + sortable.options[option] = modified; + } + } + }, + getEventProperties: function getEventProperties(name, sortable) { + var eventProperties = {}; + plugins.forEach(function (plugin) { + if (typeof plugin.eventProperties !== 'function') return; + _extends(eventProperties, plugin.eventProperties.call(sortable[plugin.pluginName], name)); + }); + return eventProperties; + }, + modifyOption: function modifyOption(sortable, name, value) { + var modifiedValue; + plugins.forEach(function (plugin) { + // Plugin must exist on the Sortable + if (!sortable[plugin.pluginName]) return; + + // If static option listener exists for this option, call in the context of the Sortable's instance of this plugin + if (plugin.optionListeners && typeof plugin.optionListeners[name] === 'function') { + modifiedValue = plugin.optionListeners[name].call(sortable[plugin.pluginName], value); + } + }); + return modifiedValue; + } + }; + + function dispatchEvent(_ref) { + var sortable = _ref.sortable, + rootEl = _ref.rootEl, + name = _ref.name, + targetEl = _ref.targetEl, + cloneEl = _ref.cloneEl, + toEl = _ref.toEl, + fromEl = _ref.fromEl, + oldIndex = _ref.oldIndex, + newIndex = _ref.newIndex, + oldDraggableIndex = _ref.oldDraggableIndex, + newDraggableIndex = _ref.newDraggableIndex, + originalEvent = _ref.originalEvent, + putSortable = _ref.putSortable, + extraEventProperties = _ref.extraEventProperties; + sortable = sortable || rootEl && rootEl[expando]; + if (!sortable) return; + var evt, + options = sortable.options, + onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); + // Support for new CustomEvent feature + if (window.CustomEvent && !IE11OrLess && !Edge) { + evt = new CustomEvent(name, { + bubbles: true, + cancelable: true + }); + } else { + evt = document.createEvent('Event'); + evt.initEvent(name, true, true); + } + evt.to = toEl || rootEl; + evt.from = fromEl || rootEl; + evt.item = targetEl || rootEl; + evt.clone = cloneEl; + evt.oldIndex = oldIndex; + evt.newIndex = newIndex; + evt.oldDraggableIndex = oldDraggableIndex; + evt.newDraggableIndex = newDraggableIndex; + evt.originalEvent = originalEvent; + evt.pullMode = putSortable ? putSortable.lastPutMode : undefined; + var allEventProperties = _objectSpread2(_objectSpread2({}, extraEventProperties), PluginManager.getEventProperties(name, sortable)); + for (var option in allEventProperties) { + evt[option] = allEventProperties[option]; + } + if (rootEl) { + rootEl.dispatchEvent(evt); + } + if (options[onName]) { + options[onName].call(sortable, evt); + } + } + + var _excluded = ["evt"]; + var pluginEvent = function pluginEvent(eventName, sortable) { + var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, + originalEvent = _ref.evt, + data = _objectWithoutProperties(_ref, _excluded); + PluginManager.pluginEvent.bind(Sortable)(eventName, sortable, _objectSpread2({ + dragEl: dragEl, + parentEl: parentEl, + ghostEl: ghostEl, + rootEl: rootEl, + nextEl: nextEl, + lastDownEl: lastDownEl, + cloneEl: cloneEl, + cloneHidden: cloneHidden, + dragStarted: moved, + putSortable: putSortable, + activeSortable: Sortable.active, + originalEvent: originalEvent, + oldIndex: oldIndex, + oldDraggableIndex: oldDraggableIndex, + newIndex: newIndex, + newDraggableIndex: newDraggableIndex, + hideGhostForTarget: _hideGhostForTarget, + unhideGhostForTarget: _unhideGhostForTarget, + cloneNowHidden: function cloneNowHidden() { + cloneHidden = true; + }, + cloneNowShown: function cloneNowShown() { + cloneHidden = false; + }, + dispatchSortableEvent: function dispatchSortableEvent(name) { + _dispatchEvent({ + sortable: sortable, + name: name, + originalEvent: originalEvent + }); + } + }, data)); + }; + function _dispatchEvent(info) { + dispatchEvent(_objectSpread2({ + putSortable: putSortable, + cloneEl: cloneEl, + targetEl: dragEl, + rootEl: rootEl, + oldIndex: oldIndex, + oldDraggableIndex: oldDraggableIndex, + newIndex: newIndex, + newDraggableIndex: newDraggableIndex + }, info)); + } + var dragEl, + parentEl, + ghostEl, + rootEl, + nextEl, + lastDownEl, + cloneEl, + cloneHidden, + oldIndex, + newIndex, + oldDraggableIndex, + newDraggableIndex, + activeGroup, + putSortable, + awaitingDragStarted = false, + ignoreNextClick = false, + sortables = [], + tapEvt, + touchEvt, + lastDx, + lastDy, + tapDistanceLeft, + tapDistanceTop, + moved, + lastTarget, + lastDirection, + pastFirstInvertThresh = false, + isCircumstantialInvert = false, + targetMoveDistance, + // For positioning ghost absolutely + ghostRelativeParent, + ghostRelativeParentInitialScroll = [], + // (left, top) + + _silent = false, + savedInputChecked = []; + + /** @const */ + var documentExists = typeof document !== 'undefined', + PositionGhostAbsolutely = IOS, + CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float', + // This will not pass for IE9, because IE9 DnD only works on anchors + supportDraggable = documentExists && !ChromeForAndroid && !IOS && 'draggable' in document.createElement('div'), + supportCssPointerEvents = function () { + if (!documentExists) return; + // false when <= IE11 + if (IE11OrLess) { + return false; + } + var el = document.createElement('x'); + el.style.cssText = 'pointer-events:auto'; + return el.style.pointerEvents === 'auto'; + }(), + _detectDirection = function _detectDirection(el, options) { + var elCSS = css(el), + elWidth = parseInt(elCSS.width) - parseInt(elCSS.paddingLeft) - parseInt(elCSS.paddingRight) - parseInt(elCSS.borderLeftWidth) - parseInt(elCSS.borderRightWidth), + child1 = getChild(el, 0, options), + child2 = getChild(el, 1, options), + firstChildCSS = child1 && css(child1), + secondChildCSS = child2 && css(child2), + firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width, + secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width; + if (elCSS.display === 'flex') { + return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse' ? 'vertical' : 'horizontal'; + } + if (elCSS.display === 'grid') { + return elCSS.gridTemplateColumns.split(' ').length <= 1 ? 'vertical' : 'horizontal'; + } + if (child1 && firstChildCSS["float"] && firstChildCSS["float"] !== 'none') { + var touchingSideChild2 = firstChildCSS["float"] === 'left' ? 'left' : 'right'; + return child2 && (secondChildCSS.clear === 'both' || secondChildCSS.clear === touchingSideChild2) ? 'vertical' : 'horizontal'; + } + return child1 && (firstChildCSS.display === 'block' || firstChildCSS.display === 'flex' || firstChildCSS.display === 'table' || firstChildCSS.display === 'grid' || firstChildWidth >= elWidth && elCSS[CSSFloatProperty] === 'none' || child2 && elCSS[CSSFloatProperty] === 'none' && firstChildWidth + secondChildWidth > elWidth) ? 'vertical' : 'horizontal'; + }, + _dragElInRowColumn = function _dragElInRowColumn(dragRect, targetRect, vertical) { + var dragElS1Opp = vertical ? dragRect.left : dragRect.top, + dragElS2Opp = vertical ? dragRect.right : dragRect.bottom, + dragElOppLength = vertical ? dragRect.width : dragRect.height, + targetS1Opp = vertical ? targetRect.left : targetRect.top, + targetS2Opp = vertical ? targetRect.right : targetRect.bottom, + targetOppLength = vertical ? targetRect.width : targetRect.height; + return dragElS1Opp === targetS1Opp || dragElS2Opp === targetS2Opp || dragElS1Opp + dragElOppLength / 2 === targetS1Opp + targetOppLength / 2; + }, + /** + * Detects first nearest empty sortable to X and Y position using emptyInsertThreshold. + * @param {Number} x X position + * @param {Number} y Y position + * @return {HTMLElement} Element of the first found nearest Sortable + */ + _detectNearestEmptySortable = function _detectNearestEmptySortable(x, y) { + var ret; + sortables.some(function (sortable) { + var threshold = sortable[expando].options.emptyInsertThreshold; + if (!threshold || lastChild(sortable)) return; + var rect = getRect(sortable), + insideHorizontally = x >= rect.left - threshold && x <= rect.right + threshold, + insideVertically = y >= rect.top - threshold && y <= rect.bottom + threshold; + if (insideHorizontally && insideVertically) { + return ret = sortable; + } + }); + return ret; + }, + _prepareGroup = function _prepareGroup(options) { + function toFn(value, pull) { + return function (to, from, dragEl, evt) { + var sameGroup = to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name; + if (value == null && (pull || sameGroup)) { + // Default pull value + // Default pull and put value if same group + return true; + } else if (value == null || value === false) { + return false; + } else if (pull && value === 'clone') { + return value; + } else if (typeof value === 'function') { + return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt); + } else { + var otherGroup = (pull ? to : from).options.group.name; + return value === true || typeof value === 'string' && value === otherGroup || value.join && value.indexOf(otherGroup) > -1; + } + }; + } + var group = {}; + var originalGroup = options.group; + if (!originalGroup || _typeof(originalGroup) != 'object') { + originalGroup = { + name: originalGroup + }; + } + group.name = originalGroup.name; + group.checkPull = toFn(originalGroup.pull, true); + group.checkPut = toFn(originalGroup.put); + group.revertClone = originalGroup.revertClone; + options.group = group; + }, + _hideGhostForTarget = function _hideGhostForTarget() { + if (!supportCssPointerEvents && ghostEl) { + css(ghostEl, 'display', 'none'); + } + }, + _unhideGhostForTarget = function _unhideGhostForTarget() { + if (!supportCssPointerEvents && ghostEl) { + css(ghostEl, 'display', ''); + } + }; + + // #1184 fix - Prevent click event on fallback if dragged but item not changed position + if (documentExists && !ChromeForAndroid) { + document.addEventListener('click', function (evt) { + if (ignoreNextClick) { + evt.preventDefault(); + evt.stopPropagation && evt.stopPropagation(); + evt.stopImmediatePropagation && evt.stopImmediatePropagation(); + ignoreNextClick = false; + return false; + } + }, true); + } + var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent(evt) { + if (dragEl) { + evt = evt.touches ? evt.touches[0] : evt; + var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY); + if (nearest) { + // Create imitation event + var event = {}; + for (var i in evt) { + if (evt.hasOwnProperty(i)) { + event[i] = evt[i]; + } + } + event.target = event.rootEl = nearest; + event.preventDefault = void 0; + event.stopPropagation = void 0; + nearest[expando]._onDragOver(event); + } + } + }; + var _checkOutsideTargetEl = function _checkOutsideTargetEl(evt) { + if (dragEl) { + dragEl.parentNode[expando]._isOutsideThisEl(evt.target); + } + }; + + /** + * @class Sortable + * @param {HTMLElement} el + * @param {Object} [options] + */ + function Sortable(el, options) { + if (!(el && el.nodeType && el.nodeType === 1)) { + throw "Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(el)); + } + this.el = el; // root element + this.options = options = _extends({}, options); + + // Export instance + el[expando] = this; + var defaults = { + group: null, + sort: true, + disabled: false, + store: null, + handle: null, + draggable: /^[uo]l$/i.test(el.nodeName) ? '>li' : '>*', + swapThreshold: 1, + // percentage; 0 <= x <= 1 + invertSwap: false, + // invert always + invertedSwapThreshold: null, + // will be set to same as swapThreshold if default + removeCloneOnHide: true, + direction: function direction() { + return _detectDirection(el, this.options); + }, + ghostClass: 'sortable-ghost', + chosenClass: 'sortable-chosen', + dragClass: 'sortable-drag', + ignore: 'a, img', + filter: null, + preventOnFilter: true, + animation: 0, + easing: null, + setData: function setData(dataTransfer, dragEl) { + dataTransfer.setData('Text', dragEl.textContent); + }, + dropBubble: false, + dragoverBubble: false, + dataIdAttr: 'data-id', + delay: 0, + delayOnTouchOnly: false, + touchStartThreshold: (Number.parseInt ? Number : window).parseInt(window.devicePixelRatio, 10) || 1, + forceFallback: false, + fallbackClass: 'sortable-fallback', + fallbackOnBody: false, + fallbackTolerance: 0, + fallbackOffset: { + x: 0, + y: 0 + }, + supportPointer: Sortable.supportPointer !== false && 'PointerEvent' in window && !Safari, + emptyInsertThreshold: 5 + }; + PluginManager.initializePlugins(this, el, defaults); + + // Set default options + for (var name in defaults) { + !(name in options) && (options[name] = defaults[name]); + } + _prepareGroup(options); + + // Bind all private methods + for (var fn in this) { + if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { + this[fn] = this[fn].bind(this); + } + } + + // Setup drag mode + this.nativeDraggable = options.forceFallback ? false : supportDraggable; + if (this.nativeDraggable) { + // Touch start threshold cannot be greater than the native dragstart threshold + this.options.touchStartThreshold = 1; + } + + // Bind events + if (options.supportPointer) { + on(el, 'pointerdown', this._onTapStart); + } else { + on(el, 'mousedown', this._onTapStart); + on(el, 'touchstart', this._onTapStart); + } + if (this.nativeDraggable) { + on(el, 'dragover', this); + on(el, 'dragenter', this); + } + sortables.push(this.el); + + // Restore sorting + options.store && options.store.get && this.sort(options.store.get(this) || []); + + // Add animation state manager + _extends(this, AnimationStateManager()); + } + Sortable.prototype = /** @lends Sortable.prototype */{ + constructor: Sortable, + _isOutsideThisEl: function _isOutsideThisEl(target) { + if (!this.el.contains(target) && target !== this.el) { + lastTarget = null; + } + }, + _getDirection: function _getDirection(evt, target) { + return typeof this.options.direction === 'function' ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction; + }, + _onTapStart: function _onTapStart( /** Event|TouchEvent */evt) { + if (!evt.cancelable) return; + var _this = this, + el = this.el, + options = this.options, + preventOnFilter = options.preventOnFilter, + type = evt.type, + touch = evt.touches && evt.touches[0] || evt.pointerType && evt.pointerType === 'touch' && evt, + target = (touch || evt).target, + originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0] || evt.composedPath && evt.composedPath()[0]) || target, + filter = options.filter; + _saveInputCheckedState(el); + + // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group. + if (dragEl) { + return; + } + if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) { + return; // only left button and enabled + } + + // cancel dnd if original target is content editable + if (originalTarget.isContentEditable) { + return; + } + + // Safari ignores further event handling after mousedown + if (!this.nativeDraggable && Safari && target && target.tagName.toUpperCase() === 'SELECT') { + return; + } + target = closest(target, options.draggable, el, false); + if (target && target.animated) { + return; + } + if (lastDownEl === target) { + // Ignoring duplicate `down` + return; + } + + // Get the index of the dragged element within its parent + oldIndex = index(target); + oldDraggableIndex = index(target, options.draggable); + + // Check filter + if (typeof filter === 'function') { + if (filter.call(this, evt, target, this)) { + _dispatchEvent({ + sortable: _this, + rootEl: originalTarget, + name: 'filter', + targetEl: target, + toEl: el, + fromEl: el + }); + pluginEvent('filter', _this, { + evt: evt + }); + preventOnFilter && evt.cancelable && evt.preventDefault(); + return; // cancel dnd + } + } else if (filter) { + filter = filter.split(',').some(function (criteria) { + criteria = closest(originalTarget, criteria.trim(), el, false); + if (criteria) { + _dispatchEvent({ + sortable: _this, + rootEl: criteria, + name: 'filter', + targetEl: target, + fromEl: el, + toEl: el + }); + pluginEvent('filter', _this, { + evt: evt + }); + return true; + } + }); + if (filter) { + preventOnFilter && evt.cancelable && evt.preventDefault(); + return; // cancel dnd + } + } + if (options.handle && !closest(originalTarget, options.handle, el, false)) { + return; + } + + // Prepare `dragstart` + this._prepareDragStart(evt, touch, target); + }, + _prepareDragStart: function _prepareDragStart( /** Event */evt, /** Touch */touch, /** HTMLElement */target) { + var _this = this, + el = _this.el, + options = _this.options, + ownerDocument = el.ownerDocument, + dragStartFn; + if (target && !dragEl && target.parentNode === el) { + var dragRect = getRect(target); + rootEl = el; + dragEl = target; + parentEl = dragEl.parentNode; + nextEl = dragEl.nextSibling; + lastDownEl = target; + activeGroup = options.group; + Sortable.dragged = dragEl; + tapEvt = { + target: dragEl, + clientX: (touch || evt).clientX, + clientY: (touch || evt).clientY + }; + tapDistanceLeft = tapEvt.clientX - dragRect.left; + tapDistanceTop = tapEvt.clientY - dragRect.top; + this._lastX = (touch || evt).clientX; + this._lastY = (touch || evt).clientY; + dragEl.style['will-change'] = 'all'; + dragStartFn = function dragStartFn() { + pluginEvent('delayEnded', _this, { + evt: evt + }); + if (Sortable.eventCanceled) { + _this._onDrop(); + return; + } + // Delayed drag has been triggered + // we can re-enable the events: touchmove/mousemove + _this._disableDelayedDragEvents(); + if (!FireFox && _this.nativeDraggable) { + dragEl.draggable = true; + } + + // Bind the events: dragstart/dragend + _this._triggerDragStart(evt, touch); + + // Drag start event + _dispatchEvent({ + sortable: _this, + name: 'choose', + originalEvent: evt + }); + + // Chosen item + toggleClass(dragEl, options.chosenClass, true); + }; + + // Disable "draggable" + options.ignore.split(',').forEach(function (criteria) { + find(dragEl, criteria.trim(), _disableDraggable); + }); + on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent); + on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent); + on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent); + on(ownerDocument, 'mouseup', _this._onDrop); + on(ownerDocument, 'touchend', _this._onDrop); + on(ownerDocument, 'touchcancel', _this._onDrop); + + // Make dragEl draggable (must be before delay for FireFox) + if (FireFox && this.nativeDraggable) { + this.options.touchStartThreshold = 4; + dragEl.draggable = true; + } + pluginEvent('delayStart', this, { + evt: evt + }); + + // Delay is impossible for native DnD in Edge or IE + if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) { + if (Sortable.eventCanceled) { + this._onDrop(); + return; + } + // If the user moves the pointer or let go the click or touch + // before the delay has been reached: + // disable the delayed drag + on(ownerDocument, 'mouseup', _this._disableDelayedDrag); + on(ownerDocument, 'touchend', _this._disableDelayedDrag); + on(ownerDocument, 'touchcancel', _this._disableDelayedDrag); + on(ownerDocument, 'mousemove', _this._delayedDragTouchMoveHandler); + on(ownerDocument, 'touchmove', _this._delayedDragTouchMoveHandler); + options.supportPointer && on(ownerDocument, 'pointermove', _this._delayedDragTouchMoveHandler); + _this._dragStartTimer = setTimeout(dragStartFn, options.delay); + } else { + dragStartFn(); + } + } + }, + _delayedDragTouchMoveHandler: function _delayedDragTouchMoveHandler( /** TouchEvent|PointerEvent **/e) { + var touch = e.touches ? e.touches[0] : e; + if (Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1))) { + this._disableDelayedDrag(); + } + }, + _disableDelayedDrag: function _disableDelayedDrag() { + dragEl && _disableDraggable(dragEl); + clearTimeout(this._dragStartTimer); + this._disableDelayedDragEvents(); + }, + _disableDelayedDragEvents: function _disableDelayedDragEvents() { + var ownerDocument = this.el.ownerDocument; + off(ownerDocument, 'mouseup', this._disableDelayedDrag); + off(ownerDocument, 'touchend', this._disableDelayedDrag); + off(ownerDocument, 'touchcancel', this._disableDelayedDrag); + off(ownerDocument, 'mousemove', this._delayedDragTouchMoveHandler); + off(ownerDocument, 'touchmove', this._delayedDragTouchMoveHandler); + off(ownerDocument, 'pointermove', this._delayedDragTouchMoveHandler); + }, + _triggerDragStart: function _triggerDragStart( /** Event */evt, /** Touch */touch) { + touch = touch || evt.pointerType == 'touch' && evt; + if (!this.nativeDraggable || touch) { + if (this.options.supportPointer) { + on(document, 'pointermove', this._onTouchMove); + } else if (touch) { + on(document, 'touchmove', this._onTouchMove); + } else { + on(document, 'mousemove', this._onTouchMove); + } + } else { + on(dragEl, 'dragend', this); + on(rootEl, 'dragstart', this._onDragStart); + } + try { + if (document.selection) { + // Timeout neccessary for IE9 + _nextTick(function () { + document.selection.empty(); + }); + } else { + window.getSelection().removeAllRanges(); + } + } catch (err) {} + }, + _dragStarted: function _dragStarted(fallback, evt) { + awaitingDragStarted = false; + if (rootEl && dragEl) { + pluginEvent('dragStarted', this, { + evt: evt + }); + if (this.nativeDraggable) { + on(document, 'dragover', _checkOutsideTargetEl); + } + var options = this.options; + + // Apply effect + !fallback && toggleClass(dragEl, options.dragClass, false); + toggleClass(dragEl, options.ghostClass, true); + Sortable.active = this; + fallback && this._appendGhost(); + + // Drag start event + _dispatchEvent({ + sortable: this, + name: 'start', + originalEvent: evt + }); + } else { + this._nulling(); + } + }, + _emulateDragOver: function _emulateDragOver() { + if (touchEvt) { + this._lastX = touchEvt.clientX; + this._lastY = touchEvt.clientY; + _hideGhostForTarget(); + var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY); + var parent = target; + while (target && target.shadowRoot) { + target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY); + if (target === parent) break; + parent = target; + } + dragEl.parentNode[expando]._isOutsideThisEl(target); + if (parent) { + do { + if (parent[expando]) { + var inserted = void 0; + inserted = parent[expando]._onDragOver({ + clientX: touchEvt.clientX, + clientY: touchEvt.clientY, + target: target, + rootEl: parent + }); + if (inserted && !this.options.dragoverBubble) { + break; + } + } + target = parent; // store last element + } + /* jshint boss:true */ while (parent = parent.parentNode); + } + _unhideGhostForTarget(); + } + }, + _onTouchMove: function _onTouchMove( /**TouchEvent*/evt) { + if (tapEvt) { + var options = this.options, + fallbackTolerance = options.fallbackTolerance, + fallbackOffset = options.fallbackOffset, + touch = evt.touches ? evt.touches[0] : evt, + ghostMatrix = ghostEl && matrix(ghostEl, true), + scaleX = ghostEl && ghostMatrix && ghostMatrix.a, + scaleY = ghostEl && ghostMatrix && ghostMatrix.d, + relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent), + dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1), + dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1); + + // only set the status to dragging, when we are actually dragging + if (!Sortable.active && !awaitingDragStarted) { + if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) { + return; + } + this._onDragStart(evt, true); + } + if (ghostEl) { + if (ghostMatrix) { + ghostMatrix.e += dx - (lastDx || 0); + ghostMatrix.f += dy - (lastDy || 0); + } else { + ghostMatrix = { + a: 1, + b: 0, + c: 0, + d: 1, + e: dx, + f: dy + }; + } + var cssMatrix = "matrix(".concat(ghostMatrix.a, ",").concat(ghostMatrix.b, ",").concat(ghostMatrix.c, ",").concat(ghostMatrix.d, ",").concat(ghostMatrix.e, ",").concat(ghostMatrix.f, ")"); + css(ghostEl, 'webkitTransform', cssMatrix); + css(ghostEl, 'mozTransform', cssMatrix); + css(ghostEl, 'msTransform', cssMatrix); + css(ghostEl, 'transform', cssMatrix); + lastDx = dx; + lastDy = dy; + touchEvt = touch; + } + evt.cancelable && evt.preventDefault(); + } + }, + _appendGhost: function _appendGhost() { + // Bug if using scale(): https://stackoverflow.com/questions/2637058 + // Not being adjusted for + if (!ghostEl) { + var container = this.options.fallbackOnBody ? document.body : rootEl, + rect = getRect(dragEl, true, PositionGhostAbsolutely, true, container), + options = this.options; + + // Position absolutely + if (PositionGhostAbsolutely) { + // Get relatively positioned parent + ghostRelativeParent = container; + while (css(ghostRelativeParent, 'position') === 'static' && css(ghostRelativeParent, 'transform') === 'none' && ghostRelativeParent !== document) { + ghostRelativeParent = ghostRelativeParent.parentNode; + } + if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) { + if (ghostRelativeParent === document) ghostRelativeParent = getWindowScrollingElement(); + rect.top += ghostRelativeParent.scrollTop; + rect.left += ghostRelativeParent.scrollLeft; + } else { + ghostRelativeParent = getWindowScrollingElement(); + } + ghostRelativeParentInitialScroll = getRelativeScrollOffset(ghostRelativeParent); + } + ghostEl = dragEl.cloneNode(true); + toggleClass(ghostEl, options.ghostClass, false); + toggleClass(ghostEl, options.fallbackClass, true); + toggleClass(ghostEl, options.dragClass, true); + css(ghostEl, 'transition', ''); + css(ghostEl, 'transform', ''); + css(ghostEl, 'box-sizing', 'border-box'); + css(ghostEl, 'margin', 0); + css(ghostEl, 'top', rect.top); + css(ghostEl, 'left', rect.left); + css(ghostEl, 'width', rect.width); + css(ghostEl, 'height', rect.height); + css(ghostEl, 'opacity', '0.8'); + css(ghostEl, 'position', PositionGhostAbsolutely ? 'absolute' : 'fixed'); + css(ghostEl, 'zIndex', '100000'); + css(ghostEl, 'pointerEvents', 'none'); + Sortable.ghost = ghostEl; + container.appendChild(ghostEl); + + // Set transform-origin + css(ghostEl, 'transform-origin', tapDistanceLeft / parseInt(ghostEl.style.width) * 100 + '% ' + tapDistanceTop / parseInt(ghostEl.style.height) * 100 + '%'); + } + }, + _onDragStart: function _onDragStart( /**Event*/evt, /**boolean*/fallback) { + var _this = this; + var dataTransfer = evt.dataTransfer; + var options = _this.options; + pluginEvent('dragStart', this, { + evt: evt + }); + if (Sortable.eventCanceled) { + this._onDrop(); + return; + } + pluginEvent('setupClone', this); + if (!Sortable.eventCanceled) { + cloneEl = clone(dragEl); + cloneEl.removeAttribute("id"); + cloneEl.draggable = false; + cloneEl.style['will-change'] = ''; + this._hideClone(); + toggleClass(cloneEl, this.options.chosenClass, false); + Sortable.clone = cloneEl; + } + + // #1143: IFrame support workaround + _this.cloneId = _nextTick(function () { + pluginEvent('clone', _this); + if (Sortable.eventCanceled) return; + if (!_this.options.removeCloneOnHide) { + rootEl.insertBefore(cloneEl, dragEl); + } + _this._hideClone(); + _dispatchEvent({ + sortable: _this, + name: 'clone' + }); + }); + !fallback && toggleClass(dragEl, options.dragClass, true); + + // Set proper drop events + if (fallback) { + ignoreNextClick = true; + _this._loopId = setInterval(_this._emulateDragOver, 50); + } else { + // Undo what was set in _prepareDragStart before drag started + off(document, 'mouseup', _this._onDrop); + off(document, 'touchend', _this._onDrop); + off(document, 'touchcancel', _this._onDrop); + if (dataTransfer) { + dataTransfer.effectAllowed = 'move'; + options.setData && options.setData.call(_this, dataTransfer, dragEl); + } + on(document, 'drop', _this); + + // #1276 fix: + css(dragEl, 'transform', 'translateZ(0)'); + } + awaitingDragStarted = true; + _this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt)); + on(document, 'selectstart', _this); + moved = true; + if (Safari) { + css(document.body, 'user-select', 'none'); + } + }, + // Returns true - if no further action is needed (either inserted or another condition) + _onDragOver: function _onDragOver( /**Event*/evt) { + var el = this.el, + target = evt.target, + dragRect, + targetRect, + revert, + options = this.options, + group = options.group, + activeSortable = Sortable.active, + isOwner = activeGroup === group, + canSort = options.sort, + fromSortable = putSortable || activeSortable, + vertical, + _this = this, + completedFired = false; + if (_silent) return; + function dragOverEvent(name, extra) { + pluginEvent(name, _this, _objectSpread2({ + evt: evt, + isOwner: isOwner, + axis: vertical ? 'vertical' : 'horizontal', + revert: revert, + dragRect: dragRect, + targetRect: targetRect, + canSort: canSort, + fromSortable: fromSortable, + target: target, + completed: completed, + onMove: function onMove(target, after) { + return _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after); + }, + changed: changed + }, extra)); + } + + // Capture animation state + function capture() { + dragOverEvent('dragOverAnimationCapture'); + _this.captureAnimationState(); + if (_this !== fromSortable) { + fromSortable.captureAnimationState(); + } + } + + // Return invocation when dragEl is inserted (or completed) + function completed(insertion) { + dragOverEvent('dragOverCompleted', { + insertion: insertion + }); + if (insertion) { + // Clones must be hidden before folding animation to capture dragRectAbsolute properly + if (isOwner) { + activeSortable._hideClone(); + } else { + activeSortable._showClone(_this); + } + if (_this !== fromSortable) { + // Set ghost class to new sortable's ghost class + toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false); + toggleClass(dragEl, options.ghostClass, true); + } + if (putSortable !== _this && _this !== Sortable.active) { + putSortable = _this; + } else if (_this === Sortable.active && putSortable) { + putSortable = null; + } + + // Animation + if (fromSortable === _this) { + _this._ignoreWhileAnimating = target; + } + _this.animateAll(function () { + dragOverEvent('dragOverAnimationComplete'); + _this._ignoreWhileAnimating = null; + }); + if (_this !== fromSortable) { + fromSortable.animateAll(); + fromSortable._ignoreWhileAnimating = null; + } + } + + // Null lastTarget if it is not inside a previously swapped element + if (target === dragEl && !dragEl.animated || target === el && !target.animated) { + lastTarget = null; + } + + // no bubbling and not fallback + if (!options.dragoverBubble && !evt.rootEl && target !== document) { + dragEl.parentNode[expando]._isOutsideThisEl(evt.target); + + // Do not detect for empty insert if already inserted + !insertion && nearestEmptyInsertDetectEvent(evt); + } + !options.dragoverBubble && evt.stopPropagation && evt.stopPropagation(); + return completedFired = true; + } + + // Call when dragEl has been inserted + function changed() { + newIndex = index(dragEl); + newDraggableIndex = index(dragEl, options.draggable); + _dispatchEvent({ + sortable: _this, + name: 'change', + toEl: el, + newIndex: newIndex, + newDraggableIndex: newDraggableIndex, + originalEvent: evt + }); + } + if (evt.preventDefault !== void 0) { + evt.cancelable && evt.preventDefault(); + } + target = closest(target, options.draggable, el, true); + dragOverEvent('dragOver'); + if (Sortable.eventCanceled) return completedFired; + if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) { + return completed(false); + } + ignoreNextClick = false; + if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = parentEl !== rootEl) // Reverting item into the original list + : putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) { + vertical = this._getDirection(evt, target) === 'vertical'; + dragRect = getRect(dragEl); + dragOverEvent('dragOverValid'); + if (Sortable.eventCanceled) return completedFired; + if (revert) { + parentEl = rootEl; // actualization + capture(); + this._hideClone(); + dragOverEvent('revert'); + if (!Sortable.eventCanceled) { + if (nextEl) { + rootEl.insertBefore(dragEl, nextEl); + } else { + rootEl.appendChild(dragEl); + } + } + return completed(true); + } + var elLastChild = lastChild(el, options.draggable); + if (!elLastChild || _ghostIsLast(evt, vertical, this) && !elLastChild.animated) { + // Insert to end of list + + // If already at end of list: Do not insert + if (elLastChild === dragEl) { + return completed(false); + } + + // if there is a last element, it is the target + if (elLastChild && el === evt.target) { + target = elLastChild; + } + if (target) { + targetRect = getRect(target); + } + if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) { + capture(); + if (elLastChild && elLastChild.nextSibling) { + // the last draggable element is not the last node + el.insertBefore(dragEl, elLastChild.nextSibling); + } else { + el.appendChild(dragEl); + } + parentEl = el; // actualization + + changed(); + return completed(true); + } + } else if (elLastChild && _ghostIsFirst(evt, vertical, this)) { + // Insert to start of list + var firstChild = getChild(el, 0, options, true); + if (firstChild === dragEl) { + return completed(false); + } + target = firstChild; + targetRect = getRect(target); + if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, false) !== false) { + capture(); + el.insertBefore(dragEl, firstChild); + parentEl = el; // actualization + + changed(); + return completed(true); + } + } else if (target.parentNode === el) { + targetRect = getRect(target); + var direction = 0, + targetBeforeFirstSwap, + differentLevel = dragEl.parentNode !== el, + differentRowCol = !_dragElInRowColumn(dragEl.animated && dragEl.toRect || dragRect, target.animated && target.toRect || targetRect, vertical), + side1 = vertical ? 'top' : 'left', + scrolledPastTop = isScrolledPast(target, 'top', 'top') || isScrolledPast(dragEl, 'top', 'top'), + scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0; + if (lastTarget !== target) { + targetBeforeFirstSwap = targetRect[side1]; + pastFirstInvertThresh = false; + isCircumstantialInvert = !differentRowCol && options.invertSwap || differentLevel; + } + direction = _getSwapDirection(evt, target, targetRect, vertical, differentRowCol ? 1 : options.swapThreshold, options.invertedSwapThreshold == null ? options.swapThreshold : options.invertedSwapThreshold, isCircumstantialInvert, lastTarget === target); + var sibling; + if (direction !== 0) { + // Check if target is beside dragEl in respective direction (ignoring hidden elements) + var dragIndex = index(dragEl); + do { + dragIndex -= direction; + sibling = parentEl.children[dragIndex]; + } while (sibling && (css(sibling, 'display') === 'none' || sibling === ghostEl)); + } + // If dragEl is already beside target: Do not insert + if (direction === 0 || sibling === target) { + return completed(false); + } + lastTarget = target; + lastDirection = direction; + var nextSibling = target.nextElementSibling, + after = false; + after = direction === 1; + var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after); + if (moveVector !== false) { + if (moveVector === 1 || moveVector === -1) { + after = moveVector === 1; + } + _silent = true; + setTimeout(_unsilent, 30); + capture(); + if (after && !nextSibling) { + el.appendChild(dragEl); + } else { + target.parentNode.insertBefore(dragEl, after ? nextSibling : target); + } + + // Undo chrome's scroll adjustment (has no effect on other browsers) + if (scrolledPastTop) { + scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop); + } + parentEl = dragEl.parentNode; // actualization + + // must be done before animation + if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) { + targetMoveDistance = Math.abs(targetBeforeFirstSwap - getRect(target)[side1]); + } + changed(); + return completed(true); + } + } + if (el.contains(dragEl)) { + return completed(false); + } + } + return false; + }, + _ignoreWhileAnimating: null, + _offMoveEvents: function _offMoveEvents() { + off(document, 'mousemove', this._onTouchMove); + off(document, 'touchmove', this._onTouchMove); + off(document, 'pointermove', this._onTouchMove); + off(document, 'dragover', nearestEmptyInsertDetectEvent); + off(document, 'mousemove', nearestEmptyInsertDetectEvent); + off(document, 'touchmove', nearestEmptyInsertDetectEvent); + }, + _offUpEvents: function _offUpEvents() { + var ownerDocument = this.el.ownerDocument; + off(ownerDocument, 'mouseup', this._onDrop); + off(ownerDocument, 'touchend', this._onDrop); + off(ownerDocument, 'pointerup', this._onDrop); + off(ownerDocument, 'touchcancel', this._onDrop); + off(document, 'selectstart', this); + }, + _onDrop: function _onDrop( /**Event*/evt) { + var el = this.el, + options = this.options; + + // Get the index of the dragged element within its parent + newIndex = index(dragEl); + newDraggableIndex = index(dragEl, options.draggable); + pluginEvent('drop', this, { + evt: evt + }); + parentEl = dragEl && dragEl.parentNode; + + // Get again after plugin event + newIndex = index(dragEl); + newDraggableIndex = index(dragEl, options.draggable); + if (Sortable.eventCanceled) { + this._nulling(); + return; + } + awaitingDragStarted = false; + isCircumstantialInvert = false; + pastFirstInvertThresh = false; + clearInterval(this._loopId); + clearTimeout(this._dragStartTimer); + _cancelNextTick(this.cloneId); + _cancelNextTick(this._dragStartId); + + // Unbind events + if (this.nativeDraggable) { + off(document, 'drop', this); + off(el, 'dragstart', this._onDragStart); + } + this._offMoveEvents(); + this._offUpEvents(); + if (Safari) { + css(document.body, 'user-select', ''); + } + css(dragEl, 'transform', ''); + if (evt) { + if (moved) { + evt.cancelable && evt.preventDefault(); + !options.dropBubble && evt.stopPropagation(); + } + ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl); + if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') { + // Remove clone(s) + cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl); + } + if (dragEl) { + if (this.nativeDraggable) { + off(dragEl, 'dragend', this); + } + _disableDraggable(dragEl); + dragEl.style['will-change'] = ''; + + // Remove classes + // ghostClass is added in dragStarted + if (moved && !awaitingDragStarted) { + toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : this.options.ghostClass, false); + } + toggleClass(dragEl, this.options.chosenClass, false); + + // Drag stop event + _dispatchEvent({ + sortable: this, + name: 'unchoose', + toEl: parentEl, + newIndex: null, + newDraggableIndex: null, + originalEvent: evt + }); + if (rootEl !== parentEl) { + if (newIndex >= 0) { + // Add event + _dispatchEvent({ + rootEl: parentEl, + name: 'add', + toEl: parentEl, + fromEl: rootEl, + originalEvent: evt + }); + + // Remove event + _dispatchEvent({ + sortable: this, + name: 'remove', + toEl: parentEl, + originalEvent: evt + }); + + // drag from one list and drop into another + _dispatchEvent({ + rootEl: parentEl, + name: 'sort', + toEl: parentEl, + fromEl: rootEl, + originalEvent: evt + }); + _dispatchEvent({ + sortable: this, + name: 'sort', + toEl: parentEl, + originalEvent: evt + }); + } + putSortable && putSortable.save(); + } else { + if (newIndex !== oldIndex) { + if (newIndex >= 0) { + // drag & drop within the same list + _dispatchEvent({ + sortable: this, + name: 'update', + toEl: parentEl, + originalEvent: evt + }); + _dispatchEvent({ + sortable: this, + name: 'sort', + toEl: parentEl, + originalEvent: evt + }); + } + } + } + if (Sortable.active) { + /* jshint eqnull:true */ + if (newIndex == null || newIndex === -1) { + newIndex = oldIndex; + newDraggableIndex = oldDraggableIndex; + } + _dispatchEvent({ + sortable: this, + name: 'end', + toEl: parentEl, + originalEvent: evt + }); + + // Save sorting + this.save(); + } + } + } + this._nulling(); + }, + _nulling: function _nulling() { + pluginEvent('nulling', this); + rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable.dragged = Sortable.ghost = Sortable.clone = Sortable.active = null; + savedInputChecked.forEach(function (el) { + el.checked = true; + }); + savedInputChecked.length = lastDx = lastDy = 0; + }, + handleEvent: function handleEvent( /**Event*/evt) { + switch (evt.type) { + case 'drop': + case 'dragend': + this._onDrop(evt); + break; + case 'dragenter': + case 'dragover': + if (dragEl) { + this._onDragOver(evt); + _globalDragOver(evt); + } + break; + case 'selectstart': + evt.preventDefault(); + break; + } + }, + /** + * Serializes the item into an array of string. + * @returns {String[]} + */ + toArray: function toArray() { + var order = [], + el, + children = this.el.children, + i = 0, + n = children.length, + options = this.options; + for (; i < n; i++) { + el = children[i]; + if (closest(el, options.draggable, this.el, false)) { + order.push(el.getAttribute(options.dataIdAttr) || _generateId(el)); + } + } + return order; + }, + /** + * Sorts the elements according to the array. + * @param {String[]} order order of the items + */ + sort: function sort(order, useAnimation) { + var items = {}, + rootEl = this.el; + this.toArray().forEach(function (id, i) { + var el = rootEl.children[i]; + if (closest(el, this.options.draggable, rootEl, false)) { + items[id] = el; + } + }, this); + useAnimation && this.captureAnimationState(); + order.forEach(function (id) { + if (items[id]) { + rootEl.removeChild(items[id]); + rootEl.appendChild(items[id]); + } + }); + useAnimation && this.animateAll(); + }, + /** + * Save the current sorting + */ + save: function save() { + var store = this.options.store; + store && store.set && store.set(this); + }, + /** + * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. + * @param {HTMLElement} el + * @param {String} [selector] default: `options.draggable` + * @returns {HTMLElement|null} + */ + closest: function closest$1(el, selector) { + return closest(el, selector || this.options.draggable, this.el, false); + }, + /** + * Set/get option + * @param {string} name + * @param {*} [value] + * @returns {*} + */ + option: function option(name, value) { + var options = this.options; + if (value === void 0) { + return options[name]; + } else { + var modifiedValue = PluginManager.modifyOption(this, name, value); + if (typeof modifiedValue !== 'undefined') { + options[name] = modifiedValue; + } else { + options[name] = value; + } + if (name === 'group') { + _prepareGroup(options); + } + } + }, + /** + * Destroy + */ + destroy: function destroy() { + pluginEvent('destroy', this); + var el = this.el; + el[expando] = null; + off(el, 'mousedown', this._onTapStart); + off(el, 'touchstart', this._onTapStart); + off(el, 'pointerdown', this._onTapStart); + if (this.nativeDraggable) { + off(el, 'dragover', this); + off(el, 'dragenter', this); + } + // Remove draggable attributes + Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) { + el.removeAttribute('draggable'); + }); + this._onDrop(); + this._disableDelayedDragEvents(); + sortables.splice(sortables.indexOf(this.el), 1); + this.el = el = null; + }, + _hideClone: function _hideClone() { + if (!cloneHidden) { + pluginEvent('hideClone', this); + if (Sortable.eventCanceled) return; + css(cloneEl, 'display', 'none'); + if (this.options.removeCloneOnHide && cloneEl.parentNode) { + cloneEl.parentNode.removeChild(cloneEl); + } + cloneHidden = true; + } + }, + _showClone: function _showClone(putSortable) { + if (putSortable.lastPutMode !== 'clone') { + this._hideClone(); + return; + } + if (cloneHidden) { + pluginEvent('showClone', this); + if (Sortable.eventCanceled) return; + + // show clone at dragEl or original position + if (dragEl.parentNode == rootEl && !this.options.group.revertClone) { + rootEl.insertBefore(cloneEl, dragEl); + } else if (nextEl) { + rootEl.insertBefore(cloneEl, nextEl); + } else { + rootEl.appendChild(cloneEl); + } + if (this.options.group.revertClone) { + this.animate(dragEl, cloneEl); + } + css(cloneEl, 'display', ''); + cloneHidden = false; + } + } + }; + function _globalDragOver( /**Event*/evt) { + if (evt.dataTransfer) { + evt.dataTransfer.dropEffect = 'move'; + } + evt.cancelable && evt.preventDefault(); + } + function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) { + var evt, + sortable = fromEl[expando], + onMoveFn = sortable.options.onMove, + retVal; + // Support for new CustomEvent feature + if (window.CustomEvent && !IE11OrLess && !Edge) { + evt = new CustomEvent('move', { + bubbles: true, + cancelable: true + }); + } else { + evt = document.createEvent('Event'); + evt.initEvent('move', true, true); + } + evt.to = toEl; + evt.from = fromEl; + evt.dragged = dragEl; + evt.draggedRect = dragRect; + evt.related = targetEl || toEl; + evt.relatedRect = targetRect || getRect(toEl); + evt.willInsertAfter = willInsertAfter; + evt.originalEvent = originalEvent; + fromEl.dispatchEvent(evt); + if (onMoveFn) { + retVal = onMoveFn.call(sortable, evt, originalEvent); + } + return retVal; + } + function _disableDraggable(el) { + el.draggable = false; + } + function _unsilent() { + _silent = false; + } + function _ghostIsFirst(evt, vertical, sortable) { + var firstElRect = getRect(getChild(sortable.el, 0, sortable.options, true)); + var childContainingRect = getChildContainingRectFromElement(sortable.el, sortable.options, ghostEl); + var spacer = 10; + return vertical ? evt.clientX < childContainingRect.left - spacer || evt.clientY < firstElRect.top && evt.clientX < firstElRect.right : evt.clientY < childContainingRect.top - spacer || evt.clientY < firstElRect.bottom && evt.clientX < firstElRect.left; + } + function _ghostIsLast(evt, vertical, sortable) { + var lastElRect = getRect(lastChild(sortable.el, sortable.options.draggable)); + var childContainingRect = getChildContainingRectFromElement(sortable.el, sortable.options, ghostEl); + var spacer = 10; + return vertical ? evt.clientX > childContainingRect.right + spacer || evt.clientY > lastElRect.bottom && evt.clientX > lastElRect.left : evt.clientY > childContainingRect.bottom + spacer || evt.clientX > lastElRect.right && evt.clientY > lastElRect.top; + } + function _getSwapDirection(evt, target, targetRect, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) { + var mouseOnAxis = vertical ? evt.clientY : evt.clientX, + targetLength = vertical ? targetRect.height : targetRect.width, + targetS1 = vertical ? targetRect.top : targetRect.left, + targetS2 = vertical ? targetRect.bottom : targetRect.right, + invert = false; + if (!invertSwap) { + // Never invert or create dragEl shadow when target movemenet causes mouse to move past the end of regular swapThreshold + if (isLastTarget && targetMoveDistance < targetLength * swapThreshold) { + // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2 + // check if past first invert threshold on side opposite of lastDirection + if (!pastFirstInvertThresh && (lastDirection === 1 ? mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2 : mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2)) { + // past first invert threshold, do not restrict inverted threshold to dragEl shadow + pastFirstInvertThresh = true; + } + if (!pastFirstInvertThresh) { + // dragEl shadow (target move distance shadow) + if (lastDirection === 1 ? mouseOnAxis < targetS1 + targetMoveDistance // over dragEl shadow + : mouseOnAxis > targetS2 - targetMoveDistance) { + return -lastDirection; + } + } else { + invert = true; + } + } else { + // Regular + if (mouseOnAxis > targetS1 + targetLength * (1 - swapThreshold) / 2 && mouseOnAxis < targetS2 - targetLength * (1 - swapThreshold) / 2) { + return _getInsertDirection(target); + } + } + } + invert = invert || invertSwap; + if (invert) { + // Invert of regular + if (mouseOnAxis < targetS1 + targetLength * invertedSwapThreshold / 2 || mouseOnAxis > targetS2 - targetLength * invertedSwapThreshold / 2) { + return mouseOnAxis > targetS1 + targetLength / 2 ? 1 : -1; + } + } + return 0; + } + + /** + * Gets the direction dragEl must be swapped relative to target in order to make it + * seem that dragEl has been "inserted" into that element's position + * @param {HTMLElement} target The target whose position dragEl is being inserted at + * @return {Number} Direction dragEl must be swapped + */ + function _getInsertDirection(target) { + if (index(dragEl) < index(target)) { + return 1; + } else { + return -1; + } + } + + /** + * Generate id + * @param {HTMLElement} el + * @returns {String} + * @private + */ + function _generateId(el) { + var str = el.tagName + el.className + el.src + el.href + el.textContent, + i = str.length, + sum = 0; + while (i--) { + sum += str.charCodeAt(i); + } + return sum.toString(36); + } + function _saveInputCheckedState(root) { + savedInputChecked.length = 0; + var inputs = root.getElementsByTagName('input'); + var idx = inputs.length; + while (idx--) { + var el = inputs[idx]; + el.checked && savedInputChecked.push(el); + } + } + function _nextTick(fn) { + return setTimeout(fn, 0); + } + function _cancelNextTick(id) { + return clearTimeout(id); + } + + // Fixed #973: + if (documentExists) { + on(document, 'touchmove', function (evt) { + if ((Sortable.active || awaitingDragStarted) && evt.cancelable) { + evt.preventDefault(); + } + }); + } + + // Export utils + Sortable.utils = { + on: on, + off: off, + css: css, + find: find, + is: function is(el, selector) { + return !!closest(el, selector, el, false); + }, + extend: extend, + throttle: throttle, + closest: closest, + toggleClass: toggleClass, + clone: clone, + index: index, + nextTick: _nextTick, + cancelNextTick: _cancelNextTick, + detectDirection: _detectDirection, + getChild: getChild + }; + + /** + * Get the Sortable instance of an element + * @param {HTMLElement} element The element + * @return {Sortable|undefined} The instance of Sortable + */ + Sortable.get = function (element) { + return element[expando]; + }; + + /** + * Mount a plugin to Sortable + * @param {...SortablePlugin|SortablePlugin[]} plugins Plugins being mounted + */ + Sortable.mount = function () { + for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) { + plugins[_key] = arguments[_key]; + } + if (plugins[0].constructor === Array) plugins = plugins[0]; + plugins.forEach(function (plugin) { + if (!plugin.prototype || !plugin.prototype.constructor) { + throw "Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(plugin)); + } + if (plugin.utils) Sortable.utils = _objectSpread2(_objectSpread2({}, Sortable.utils), plugin.utils); + PluginManager.mount(plugin); + }); + }; + + /** + * Create sortable instance + * @param {HTMLElement} el + * @param {Object} [options] + */ + Sortable.create = function (el, options) { + return new Sortable(el, options); + }; + + // Export + Sortable.version = version; + + var autoScrolls = [], + scrollEl, + scrollRootEl, + scrolling = false, + lastAutoScrollX, + lastAutoScrollY, + touchEvt$1, + pointerElemChangedInterval; + function AutoScrollPlugin() { + function AutoScroll() { + this.defaults = { + scroll: true, + forceAutoScrollFallback: false, + scrollSensitivity: 30, + scrollSpeed: 10, + bubbleScroll: true + }; + + // Bind all private methods + for (var fn in this) { + if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { + this[fn] = this[fn].bind(this); + } + } + } + AutoScroll.prototype = { + dragStarted: function dragStarted(_ref) { + var originalEvent = _ref.originalEvent; + if (this.sortable.nativeDraggable) { + on(document, 'dragover', this._handleAutoScroll); + } else { + if (this.options.supportPointer) { + on(document, 'pointermove', this._handleFallbackAutoScroll); + } else if (originalEvent.touches) { + on(document, 'touchmove', this._handleFallbackAutoScroll); + } else { + on(document, 'mousemove', this._handleFallbackAutoScroll); + } + } + }, + dragOverCompleted: function dragOverCompleted(_ref2) { + var originalEvent = _ref2.originalEvent; + // For when bubbling is canceled and using fallback (fallback 'touchmove' always reached) + if (!this.options.dragOverBubble && !originalEvent.rootEl) { + this._handleAutoScroll(originalEvent); + } + }, + drop: function drop() { + if (this.sortable.nativeDraggable) { + off(document, 'dragover', this._handleAutoScroll); + } else { + off(document, 'pointermove', this._handleFallbackAutoScroll); + off(document, 'touchmove', this._handleFallbackAutoScroll); + off(document, 'mousemove', this._handleFallbackAutoScroll); + } + clearPointerElemChangedInterval(); + clearAutoScrolls(); + cancelThrottle(); + }, + nulling: function nulling() { + touchEvt$1 = scrollRootEl = scrollEl = scrolling = pointerElemChangedInterval = lastAutoScrollX = lastAutoScrollY = null; + autoScrolls.length = 0; + }, + _handleFallbackAutoScroll: function _handleFallbackAutoScroll(evt) { + this._handleAutoScroll(evt, true); + }, + _handleAutoScroll: function _handleAutoScroll(evt, fallback) { + var _this = this; + var x = (evt.touches ? evt.touches[0] : evt).clientX, + y = (evt.touches ? evt.touches[0] : evt).clientY, + elem = document.elementFromPoint(x, y); + touchEvt$1 = evt; + + // IE does not seem to have native autoscroll, + // Edge's autoscroll seems too conditional, + // MACOS Safari does not have autoscroll, + // Firefox and Chrome are good + if (fallback || this.options.forceAutoScrollFallback || Edge || IE11OrLess || Safari) { + autoScroll(evt, this.options, elem, fallback); + + // Listener for pointer element change + var ogElemScroller = getParentAutoScrollElement(elem, true); + if (scrolling && (!pointerElemChangedInterval || x !== lastAutoScrollX || y !== lastAutoScrollY)) { + pointerElemChangedInterval && clearPointerElemChangedInterval(); + // Detect for pointer elem change, emulating native DnD behaviour + pointerElemChangedInterval = setInterval(function () { + var newElem = getParentAutoScrollElement(document.elementFromPoint(x, y), true); + if (newElem !== ogElemScroller) { + ogElemScroller = newElem; + clearAutoScrolls(); + } + autoScroll(evt, _this.options, newElem, fallback); + }, 10); + lastAutoScrollX = x; + lastAutoScrollY = y; + } + } else { + // if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll + if (!this.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) { + clearAutoScrolls(); + return; + } + autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false); + } + } + }; + return _extends(AutoScroll, { + pluginName: 'scroll', + initializeByDefault: true + }); + } + function clearAutoScrolls() { + autoScrolls.forEach(function (autoScroll) { + clearInterval(autoScroll.pid); + }); + autoScrolls = []; + } + function clearPointerElemChangedInterval() { + clearInterval(pointerElemChangedInterval); + } + var autoScroll = throttle(function (evt, options, rootEl, isFallback) { + // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521 + if (!options.scroll) return; + var x = (evt.touches ? evt.touches[0] : evt).clientX, + y = (evt.touches ? evt.touches[0] : evt).clientY, + sens = options.scrollSensitivity, + speed = options.scrollSpeed, + winScroller = getWindowScrollingElement(); + var scrollThisInstance = false, + scrollCustomFn; + + // New scroll root, set scrollEl + if (scrollRootEl !== rootEl) { + scrollRootEl = rootEl; + clearAutoScrolls(); + scrollEl = options.scroll; + scrollCustomFn = options.scrollFn; + if (scrollEl === true) { + scrollEl = getParentAutoScrollElement(rootEl, true); + } + } + var layersOut = 0; + var currentParent = scrollEl; + do { + var el = currentParent, + rect = getRect(el), + top = rect.top, + bottom = rect.bottom, + left = rect.left, + right = rect.right, + width = rect.width, + height = rect.height, + canScrollX = void 0, + canScrollY = void 0, + scrollWidth = el.scrollWidth, + scrollHeight = el.scrollHeight, + elCSS = css(el), + scrollPosX = el.scrollLeft, + scrollPosY = el.scrollTop; + if (el === winScroller) { + canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll' || elCSS.overflowX === 'visible'); + canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll' || elCSS.overflowY === 'visible'); + } else { + canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll'); + canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll'); + } + var vx = canScrollX && (Math.abs(right - x) <= sens && scrollPosX + width < scrollWidth) - (Math.abs(left - x) <= sens && !!scrollPosX); + var vy = canScrollY && (Math.abs(bottom - y) <= sens && scrollPosY + height < scrollHeight) - (Math.abs(top - y) <= sens && !!scrollPosY); + if (!autoScrolls[layersOut]) { + for (var i = 0; i <= layersOut; i++) { + if (!autoScrolls[i]) { + autoScrolls[i] = {}; + } + } + } + if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) { + autoScrolls[layersOut].el = el; + autoScrolls[layersOut].vx = vx; + autoScrolls[layersOut].vy = vy; + clearInterval(autoScrolls[layersOut].pid); + if (vx != 0 || vy != 0) { + scrollThisInstance = true; + /* jshint loopfunc:true */ + autoScrolls[layersOut].pid = setInterval(function () { + // emulate drag over during autoscroll (fallback), emulating native DnD behaviour + if (isFallback && this.layer === 0) { + Sortable.active._onTouchMove(touchEvt$1); // To move ghost if it is positioned absolutely + } + var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0; + var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0; + if (typeof scrollCustomFn === 'function') { + if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== 'continue') { + return; + } + } + scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY); + }.bind({ + layer: layersOut + }), 24); + } + } + layersOut++; + } while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false))); + scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not + }, 30); + + var drop = function drop(_ref) { + var originalEvent = _ref.originalEvent, + putSortable = _ref.putSortable, + dragEl = _ref.dragEl, + activeSortable = _ref.activeSortable, + dispatchSortableEvent = _ref.dispatchSortableEvent, + hideGhostForTarget = _ref.hideGhostForTarget, + unhideGhostForTarget = _ref.unhideGhostForTarget; + if (!originalEvent) return; + var toSortable = putSortable || activeSortable; + hideGhostForTarget(); + var touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent; + var target = document.elementFromPoint(touch.clientX, touch.clientY); + unhideGhostForTarget(); + if (toSortable && !toSortable.el.contains(target)) { + dispatchSortableEvent('spill'); + this.onSpill({ + dragEl: dragEl, + putSortable: putSortable + }); + } + }; + function Revert() {} + Revert.prototype = { + startIndex: null, + dragStart: function dragStart(_ref2) { + var oldDraggableIndex = _ref2.oldDraggableIndex; + this.startIndex = oldDraggableIndex; + }, + onSpill: function onSpill(_ref3) { + var dragEl = _ref3.dragEl, + putSortable = _ref3.putSortable; + this.sortable.captureAnimationState(); + if (putSortable) { + putSortable.captureAnimationState(); + } + var nextSibling = getChild(this.sortable.el, this.startIndex, this.options); + if (nextSibling) { + this.sortable.el.insertBefore(dragEl, nextSibling); + } else { + this.sortable.el.appendChild(dragEl); + } + this.sortable.animateAll(); + if (putSortable) { + putSortable.animateAll(); + } + }, + drop: drop + }; + _extends(Revert, { + pluginName: 'revertOnSpill' + }); + function Remove() {} + Remove.prototype = { + onSpill: function onSpill(_ref4) { + var dragEl = _ref4.dragEl, + putSortable = _ref4.putSortable; + var parentSortable = putSortable || this.sortable; + parentSortable.captureAnimationState(); + dragEl.parentNode && dragEl.parentNode.removeChild(dragEl); + parentSortable.animateAll(); + }, + drop: drop + }; + _extends(Remove, { + pluginName: 'removeOnSpill' + }); + + var lastSwapEl; + function SwapPlugin() { + function Swap() { + this.defaults = { + swapClass: 'sortable-swap-highlight' + }; + } + Swap.prototype = { + dragStart: function dragStart(_ref) { + var dragEl = _ref.dragEl; + lastSwapEl = dragEl; + }, + dragOverValid: function dragOverValid(_ref2) { + var completed = _ref2.completed, + target = _ref2.target, + onMove = _ref2.onMove, + activeSortable = _ref2.activeSortable, + changed = _ref2.changed, + cancel = _ref2.cancel; + if (!activeSortable.options.swap) return; + var el = this.sortable.el, + options = this.options; + if (target && target !== el) { + var prevSwapEl = lastSwapEl; + if (onMove(target) !== false) { + toggleClass(target, options.swapClass, true); + lastSwapEl = target; + } else { + lastSwapEl = null; + } + if (prevSwapEl && prevSwapEl !== lastSwapEl) { + toggleClass(prevSwapEl, options.swapClass, false); + } + } + changed(); + completed(true); + cancel(); + }, + drop: function drop(_ref3) { + var activeSortable = _ref3.activeSortable, + putSortable = _ref3.putSortable, + dragEl = _ref3.dragEl; + var toSortable = putSortable || this.sortable; + var options = this.options; + lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false); + if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) { + if (dragEl !== lastSwapEl) { + toSortable.captureAnimationState(); + if (toSortable !== activeSortable) activeSortable.captureAnimationState(); + swapNodes(dragEl, lastSwapEl); + toSortable.animateAll(); + if (toSortable !== activeSortable) activeSortable.animateAll(); + } + } + }, + nulling: function nulling() { + lastSwapEl = null; + } + }; + return _extends(Swap, { + pluginName: 'swap', + eventProperties: function eventProperties() { + return { + swapItem: lastSwapEl + }; + } + }); + } + function swapNodes(n1, n2) { + var p1 = n1.parentNode, + p2 = n2.parentNode, + i1, + i2; + if (!p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1)) return; + i1 = index(n1); + i2 = index(n2); + if (p1.isEqualNode(p2) && i1 < i2) { + i2++; + } + p1.insertBefore(n2, p1.children[i1]); + p2.insertBefore(n1, p2.children[i2]); + } + + var multiDragElements = [], + multiDragClones = [], + lastMultiDragSelect, + // for selection with modifier key down (SHIFT) + multiDragSortable, + initialFolding = false, + // Initial multi-drag fold when drag started + folding = false, + // Folding any other time + dragStarted = false, + dragEl$1, + clonesFromRect, + clonesHidden; + function MultiDragPlugin() { + function MultiDrag(sortable) { + // Bind all private methods + for (var fn in this) { + if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { + this[fn] = this[fn].bind(this); + } + } + if (!sortable.options.avoidImplicitDeselect) { + if (sortable.options.supportPointer) { + on(document, 'pointerup', this._deselectMultiDrag); + } else { + on(document, 'mouseup', this._deselectMultiDrag); + on(document, 'touchend', this._deselectMultiDrag); + } + } + on(document, 'keydown', this._checkKeyDown); + on(document, 'keyup', this._checkKeyUp); + this.defaults = { + selectedClass: 'sortable-selected', + multiDragKey: null, + avoidImplicitDeselect: false, + setData: function setData(dataTransfer, dragEl) { + var data = ''; + if (multiDragElements.length && multiDragSortable === sortable) { + multiDragElements.forEach(function (multiDragElement, i) { + data += (!i ? '' : ', ') + multiDragElement.textContent; + }); + } else { + data = dragEl.textContent; + } + dataTransfer.setData('Text', data); + } + }; + } + MultiDrag.prototype = { + multiDragKeyDown: false, + isMultiDrag: false, + delayStartGlobal: function delayStartGlobal(_ref) { + var dragged = _ref.dragEl; + dragEl$1 = dragged; + }, + delayEnded: function delayEnded() { + this.isMultiDrag = ~multiDragElements.indexOf(dragEl$1); + }, + setupClone: function setupClone(_ref2) { + var sortable = _ref2.sortable, + cancel = _ref2.cancel; + if (!this.isMultiDrag) return; + for (var i = 0; i < multiDragElements.length; i++) { + multiDragClones.push(clone(multiDragElements[i])); + multiDragClones[i].sortableIndex = multiDragElements[i].sortableIndex; + multiDragClones[i].draggable = false; + multiDragClones[i].style['will-change'] = ''; + toggleClass(multiDragClones[i], this.options.selectedClass, false); + multiDragElements[i] === dragEl$1 && toggleClass(multiDragClones[i], this.options.chosenClass, false); + } + sortable._hideClone(); + cancel(); + }, + clone: function clone(_ref3) { + var sortable = _ref3.sortable, + rootEl = _ref3.rootEl, + dispatchSortableEvent = _ref3.dispatchSortableEvent, + cancel = _ref3.cancel; + if (!this.isMultiDrag) return; + if (!this.options.removeCloneOnHide) { + if (multiDragElements.length && multiDragSortable === sortable) { + insertMultiDragClones(true, rootEl); + dispatchSortableEvent('clone'); + cancel(); + } + } + }, + showClone: function showClone(_ref4) { + var cloneNowShown = _ref4.cloneNowShown, + rootEl = _ref4.rootEl, + cancel = _ref4.cancel; + if (!this.isMultiDrag) return; + insertMultiDragClones(false, rootEl); + multiDragClones.forEach(function (clone) { + css(clone, 'display', ''); + }); + cloneNowShown(); + clonesHidden = false; + cancel(); + }, + hideClone: function hideClone(_ref5) { + var _this = this; + var sortable = _ref5.sortable, + cloneNowHidden = _ref5.cloneNowHidden, + cancel = _ref5.cancel; + if (!this.isMultiDrag) return; + multiDragClones.forEach(function (clone) { + css(clone, 'display', 'none'); + if (_this.options.removeCloneOnHide && clone.parentNode) { + clone.parentNode.removeChild(clone); + } + }); + cloneNowHidden(); + clonesHidden = true; + cancel(); + }, + dragStartGlobal: function dragStartGlobal(_ref6) { + var sortable = _ref6.sortable; + if (!this.isMultiDrag && multiDragSortable) { + multiDragSortable.multiDrag._deselectMultiDrag(); + } + multiDragElements.forEach(function (multiDragElement) { + multiDragElement.sortableIndex = index(multiDragElement); + }); + + // Sort multi-drag elements + multiDragElements = multiDragElements.sort(function (a, b) { + return a.sortableIndex - b.sortableIndex; + }); + dragStarted = true; + }, + dragStarted: function dragStarted(_ref7) { + var _this2 = this; + var sortable = _ref7.sortable; + if (!this.isMultiDrag) return; + if (this.options.sort) { + // Capture rects, + // hide multi drag elements (by positioning them absolute), + // set multi drag elements rects to dragRect, + // show multi drag elements, + // animate to rects, + // unset rects & remove from DOM + + sortable.captureAnimationState(); + if (this.options.animation) { + multiDragElements.forEach(function (multiDragElement) { + if (multiDragElement === dragEl$1) return; + css(multiDragElement, 'position', 'absolute'); + }); + var dragRect = getRect(dragEl$1, false, true, true); + multiDragElements.forEach(function (multiDragElement) { + if (multiDragElement === dragEl$1) return; + setRect(multiDragElement, dragRect); + }); + folding = true; + initialFolding = true; + } + } + sortable.animateAll(function () { + folding = false; + initialFolding = false; + if (_this2.options.animation) { + multiDragElements.forEach(function (multiDragElement) { + unsetRect(multiDragElement); + }); + } + + // Remove all auxiliary multidrag items from el, if sorting enabled + if (_this2.options.sort) { + removeMultiDragElements(); + } + }); + }, + dragOver: function dragOver(_ref8) { + var target = _ref8.target, + completed = _ref8.completed, + cancel = _ref8.cancel; + if (folding && ~multiDragElements.indexOf(target)) { + completed(false); + cancel(); + } + }, + revert: function revert(_ref9) { + var fromSortable = _ref9.fromSortable, + rootEl = _ref9.rootEl, + sortable = _ref9.sortable, + dragRect = _ref9.dragRect; + if (multiDragElements.length > 1) { + // Setup unfold animation + multiDragElements.forEach(function (multiDragElement) { + sortable.addAnimationState({ + target: multiDragElement, + rect: folding ? getRect(multiDragElement) : dragRect + }); + unsetRect(multiDragElement); + multiDragElement.fromRect = dragRect; + fromSortable.removeAnimationState(multiDragElement); + }); + folding = false; + insertMultiDragElements(!this.options.removeCloneOnHide, rootEl); + } + }, + dragOverCompleted: function dragOverCompleted(_ref10) { + var sortable = _ref10.sortable, + isOwner = _ref10.isOwner, + insertion = _ref10.insertion, + activeSortable = _ref10.activeSortable, + parentEl = _ref10.parentEl, + putSortable = _ref10.putSortable; + var options = this.options; + if (insertion) { + // Clones must be hidden before folding animation to capture dragRectAbsolute properly + if (isOwner) { + activeSortable._hideClone(); + } + initialFolding = false; + // If leaving sort:false root, or already folding - Fold to new location + if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) { + // Fold: Set all multi drag elements's rects to dragEl's rect when multi-drag elements are invisible + var dragRectAbsolute = getRect(dragEl$1, false, true, true); + multiDragElements.forEach(function (multiDragElement) { + if (multiDragElement === dragEl$1) return; + setRect(multiDragElement, dragRectAbsolute); + + // Move element(s) to end of parentEl so that it does not interfere with multi-drag clones insertion if they are inserted + // while folding, and so that we can capture them again because old sortable will no longer be fromSortable + parentEl.appendChild(multiDragElement); + }); + folding = true; + } + + // Clones must be shown (and check to remove multi drags) after folding when interfering multiDragElements are moved out + if (!isOwner) { + // Only remove if not folding (folding will remove them anyways) + if (!folding) { + removeMultiDragElements(); + } + if (multiDragElements.length > 1) { + var clonesHiddenBefore = clonesHidden; + activeSortable._showClone(sortable); + + // Unfold animation for clones if showing from hidden + if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) { + multiDragClones.forEach(function (clone) { + activeSortable.addAnimationState({ + target: clone, + rect: clonesFromRect + }); + clone.fromRect = clonesFromRect; + clone.thisAnimationDuration = null; + }); + } + } else { + activeSortable._showClone(sortable); + } + } + } + }, + dragOverAnimationCapture: function dragOverAnimationCapture(_ref11) { + var dragRect = _ref11.dragRect, + isOwner = _ref11.isOwner, + activeSortable = _ref11.activeSortable; + multiDragElements.forEach(function (multiDragElement) { + multiDragElement.thisAnimationDuration = null; + }); + if (activeSortable.options.animation && !isOwner && activeSortable.multiDrag.isMultiDrag) { + clonesFromRect = _extends({}, dragRect); + var dragMatrix = matrix(dragEl$1, true); + clonesFromRect.top -= dragMatrix.f; + clonesFromRect.left -= dragMatrix.e; + } + }, + dragOverAnimationComplete: function dragOverAnimationComplete() { + if (folding) { + folding = false; + removeMultiDragElements(); + } + }, + drop: function drop(_ref12) { + var evt = _ref12.originalEvent, + rootEl = _ref12.rootEl, + parentEl = _ref12.parentEl, + sortable = _ref12.sortable, + dispatchSortableEvent = _ref12.dispatchSortableEvent, + oldIndex = _ref12.oldIndex, + putSortable = _ref12.putSortable; + var toSortable = putSortable || this.sortable; + if (!evt) return; + var options = this.options, + children = parentEl.children; + + // Multi-drag selection + if (!dragStarted) { + if (options.multiDragKey && !this.multiDragKeyDown) { + this._deselectMultiDrag(); + } + toggleClass(dragEl$1, options.selectedClass, !~multiDragElements.indexOf(dragEl$1)); + if (!~multiDragElements.indexOf(dragEl$1)) { + multiDragElements.push(dragEl$1); + dispatchEvent({ + sortable: sortable, + rootEl: rootEl, + name: 'select', + targetEl: dragEl$1, + originalEvent: evt + }); + + // Modifier activated, select from last to dragEl + if (evt.shiftKey && lastMultiDragSelect && sortable.el.contains(lastMultiDragSelect)) { + var lastIndex = index(lastMultiDragSelect), + currentIndex = index(dragEl$1); + if (~lastIndex && ~currentIndex && lastIndex !== currentIndex) { + // Must include lastMultiDragSelect (select it), in case modified selection from no selection + // (but previous selection existed) + var n, i; + if (currentIndex > lastIndex) { + i = lastIndex; + n = currentIndex; + } else { + i = currentIndex; + n = lastIndex + 1; + } + for (; i < n; i++) { + if (~multiDragElements.indexOf(children[i])) continue; + toggleClass(children[i], options.selectedClass, true); + multiDragElements.push(children[i]); + dispatchEvent({ + sortable: sortable, + rootEl: rootEl, + name: 'select', + targetEl: children[i], + originalEvent: evt + }); + } + } + } else { + lastMultiDragSelect = dragEl$1; + } + multiDragSortable = toSortable; + } else { + multiDragElements.splice(multiDragElements.indexOf(dragEl$1), 1); + lastMultiDragSelect = null; + dispatchEvent({ + sortable: sortable, + rootEl: rootEl, + name: 'deselect', + targetEl: dragEl$1, + originalEvent: evt + }); + } + } + + // Multi-drag drop + if (dragStarted && this.isMultiDrag) { + folding = false; + // Do not "unfold" after around dragEl if reverted + if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) { + var dragRect = getRect(dragEl$1), + multiDragIndex = index(dragEl$1, ':not(.' + this.options.selectedClass + ')'); + if (!initialFolding && options.animation) dragEl$1.thisAnimationDuration = null; + toSortable.captureAnimationState(); + if (!initialFolding) { + if (options.animation) { + dragEl$1.fromRect = dragRect; + multiDragElements.forEach(function (multiDragElement) { + multiDragElement.thisAnimationDuration = null; + if (multiDragElement !== dragEl$1) { + var rect = folding ? getRect(multiDragElement) : dragRect; + multiDragElement.fromRect = rect; + + // Prepare unfold animation + toSortable.addAnimationState({ + target: multiDragElement, + rect: rect + }); + } + }); + } + + // Multi drag elements are not necessarily removed from the DOM on drop, so to reinsert + // properly they must all be removed + removeMultiDragElements(); + multiDragElements.forEach(function (multiDragElement) { + if (children[multiDragIndex]) { + parentEl.insertBefore(multiDragElement, children[multiDragIndex]); + } else { + parentEl.appendChild(multiDragElement); + } + multiDragIndex++; + }); + + // If initial folding is done, the elements may have changed position because they are now + // unfolding around dragEl, even though dragEl may not have his index changed, so update event + // must be fired here as Sortable will not. + if (oldIndex === index(dragEl$1)) { + var update = false; + multiDragElements.forEach(function (multiDragElement) { + if (multiDragElement.sortableIndex !== index(multiDragElement)) { + update = true; + return; + } + }); + if (update) { + dispatchSortableEvent('update'); + dispatchSortableEvent('sort'); + } + } + } + + // Must be done after capturing individual rects (scroll bar) + multiDragElements.forEach(function (multiDragElement) { + unsetRect(multiDragElement); + }); + toSortable.animateAll(); + } + multiDragSortable = toSortable; + } + + // Remove clones if necessary + if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') { + multiDragClones.forEach(function (clone) { + clone.parentNode && clone.parentNode.removeChild(clone); + }); + } + }, + nullingGlobal: function nullingGlobal() { + this.isMultiDrag = dragStarted = false; + multiDragClones.length = 0; + }, + destroyGlobal: function destroyGlobal() { + this._deselectMultiDrag(); + off(document, 'pointerup', this._deselectMultiDrag); + off(document, 'mouseup', this._deselectMultiDrag); + off(document, 'touchend', this._deselectMultiDrag); + off(document, 'keydown', this._checkKeyDown); + off(document, 'keyup', this._checkKeyUp); + }, + _deselectMultiDrag: function _deselectMultiDrag(evt) { + if (typeof dragStarted !== "undefined" && dragStarted) return; + + // Only deselect if selection is in this sortable + if (multiDragSortable !== this.sortable) return; + + // Only deselect if target is not item in this sortable + if (evt && closest(evt.target, this.options.draggable, this.sortable.el, false)) return; + + // Only deselect if left click + if (evt && evt.button !== 0) return; + while (multiDragElements.length) { + var el = multiDragElements[0]; + toggleClass(el, this.options.selectedClass, false); + multiDragElements.shift(); + dispatchEvent({ + sortable: this.sortable, + rootEl: this.sortable.el, + name: 'deselect', + targetEl: el, + originalEvent: evt + }); + } + }, + _checkKeyDown: function _checkKeyDown(evt) { + if (evt.key === this.options.multiDragKey) { + this.multiDragKeyDown = true; + } + }, + _checkKeyUp: function _checkKeyUp(evt) { + if (evt.key === this.options.multiDragKey) { + this.multiDragKeyDown = false; + } + } + }; + return _extends(MultiDrag, { + // Static methods & properties + pluginName: 'multiDrag', + utils: { + /** + * Selects the provided multi-drag item + * @param {HTMLElement} el The element to be selected + */ + select: function select(el) { + var sortable = el.parentNode[expando]; + if (!sortable || !sortable.options.multiDrag || ~multiDragElements.indexOf(el)) return; + if (multiDragSortable && multiDragSortable !== sortable) { + multiDragSortable.multiDrag._deselectMultiDrag(); + multiDragSortable = sortable; + } + toggleClass(el, sortable.options.selectedClass, true); + multiDragElements.push(el); + }, + /** + * Deselects the provided multi-drag item + * @param {HTMLElement} el The element to be deselected + */ + deselect: function deselect(el) { + var sortable = el.parentNode[expando], + index = multiDragElements.indexOf(el); + if (!sortable || !sortable.options.multiDrag || !~index) return; + toggleClass(el, sortable.options.selectedClass, false); + multiDragElements.splice(index, 1); + } + }, + eventProperties: function eventProperties() { + var _this3 = this; + var oldIndicies = [], + newIndicies = []; + multiDragElements.forEach(function (multiDragElement) { + oldIndicies.push({ + multiDragElement: multiDragElement, + index: multiDragElement.sortableIndex + }); + + // multiDragElements will already be sorted if folding + var newIndex; + if (folding && multiDragElement !== dragEl$1) { + newIndex = -1; + } else if (folding) { + newIndex = index(multiDragElement, ':not(.' + _this3.options.selectedClass + ')'); + } else { + newIndex = index(multiDragElement); + } + newIndicies.push({ + multiDragElement: multiDragElement, + index: newIndex + }); + }); + return { + items: _toConsumableArray(multiDragElements), + clones: [].concat(multiDragClones), + oldIndicies: oldIndicies, + newIndicies: newIndicies + }; + }, + optionListeners: { + multiDragKey: function multiDragKey(key) { + key = key.toLowerCase(); + if (key === 'ctrl') { + key = 'Control'; + } else if (key.length > 1) { + key = key.charAt(0).toUpperCase() + key.substr(1); + } + return key; + } + } + }); + } + function insertMultiDragElements(clonesInserted, rootEl) { + multiDragElements.forEach(function (multiDragElement, i) { + var target = rootEl.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)]; + if (target) { + rootEl.insertBefore(multiDragElement, target); + } else { + rootEl.appendChild(multiDragElement); + } + }); + } + + /** + * Insert multi-drag clones + * @param {[Boolean]} elementsInserted Whether the multi-drag elements are inserted + * @param {HTMLElement} rootEl + */ + function insertMultiDragClones(elementsInserted, rootEl) { + multiDragClones.forEach(function (clone, i) { + var target = rootEl.children[clone.sortableIndex + (elementsInserted ? Number(i) : 0)]; + if (target) { + rootEl.insertBefore(clone, target); + } else { + rootEl.appendChild(clone); + } + }); + } + function removeMultiDragElements() { + multiDragElements.forEach(function (multiDragElement) { + if (multiDragElement === dragEl$1) return; + multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement); + }); + } + + Sortable.mount(new AutoScrollPlugin()); + Sortable.mount(Remove, Revert); + + Sortable.mount(new SwapPlugin()); + Sortable.mount(new MultiDragPlugin()); + + return Sortable; + +}))); diff --git a/tad/site/templates/default_layout.jinja b/tad/site/templates/default_layout.jinja new file mode 100644 index 000000000..d3e248c58 --- /dev/null +++ b/tad/site/templates/default_layout.jinja @@ -0,0 +1,90 @@ +{% macro render_task_card(task) -%} + {% include "task.jinja" %} +{%- endmacro -%} + +{% macro render_task_column(status) -%} +
+

{{ status.name }}

+
+ {% for task in tasks_service.get_tasks(status.id) %} + {{ render_task_card(task) }} + {% endfor %} +
+
+{% endmacro -%} + + + + + {{ page_title }} + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ Transparency of Algorithmic Decision making (TAD) +
+
+
+ +
+
+
+ + + + +
+

Project X

+
+ +
+
+ + {% for status in statuses_service.get_statuses() %} + {{ render_task_column(status) }} + {% endfor %} +{#
#} +{#

In progress

#} +{#
#} +{#
#} +{#
#} +{#
#} +{#

Review

#} +{#
#} +{#
#} +{#
#} +{#
#} +{#

Done

#} +{#
#} +{#
#} +{#
#} +
+
+ + + diff --git a/tad/site/templates/error.jinja b/tad/site/templates/error.jinja new file mode 100644 index 000000000..ea51d2618 --- /dev/null +++ b/tad/site/templates/error.jinja @@ -0,0 +1,3 @@ +
+

This is an error message

+
diff --git a/tad/site/templates/root/index.html b/tad/site/templates/root/index.html new file mode 100644 index 000000000..682bb0157 --- /dev/null +++ b/tad/site/templates/root/index.html @@ -0,0 +1,12 @@ +{% extends "/root/layout.html" %} + +{% block title %}Home Page page{% endblock %} + +{% block content %} +

Welcome to the Home Page

+

This is a simple Jinja template example.

+

+ View project task overview +

+ +{% endblock %} diff --git a/tad/templates/layout.html b/tad/site/templates/root/layout.html similarity index 100% rename from tad/templates/layout.html rename to tad/site/templates/root/layout.html diff --git a/tad/site/templates/task.jinja b/tad/site/templates/task.jinja new file mode 100644 index 000000000..81b7abda8 --- /dev/null +++ b/tad/site/templates/task.jinja @@ -0,0 +1,9 @@ +
+

{{ task.title }}

+
{{ task.description }}
+ {% if task.user_id %} +
+ Assigned to Avatar +
+ {% endif %} +
diff --git a/tad/templates/root/index.html b/tad/templates/root/index.html deleted file mode 100644 index ce9e75d6b..000000000 --- a/tad/templates/root/index.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends "layout.html" %} - -{% block title %}Home Page{% endblock %} - -{% block content %} -

Welcome to the Home Page

-

This is a simple Jinja template example.

-{% endblock %} diff --git a/tests/api/routes/test_pages.py b/tests/api/routes/test_pages.py new file mode 100644 index 000000000..b65e4ec0c --- /dev/null +++ b/tests/api/routes/test_pages.py @@ -0,0 +1,8 @@ +from fastapi.testclient import TestClient + + +def test_get_main_page(client: TestClient) -> None: + response = client.get("/pages/") + assert response.status_code == 200 + assert response.headers["content-type"] == "text/html; charset=utf-8" + assert b"" in response.content diff --git a/tests/api/routes/test_status.py b/tests/api/routes/test_status.py new file mode 100644 index 000000000..640079758 --- /dev/null +++ b/tests/api/routes/test_status.py @@ -0,0 +1,20 @@ +from fastapi.testclient import TestClient +from tad.models.task import MoveTask + +from tests.database_test_utils import init_db + + +def test_post_move_task(client: TestClient) -> None: + init_db( + [ + {"table": "status", "id": 2}, + {"table": "task", "id": 1, "status_id": 2}, + {"table": "task", "id": 2, "status_id": 2}, + {"table": "task", "id": 3, "status_id": 2}, + ] + ) + move_task: MoveTask = MoveTask(taskId="2", statusId="2", previousSiblingId="1", nextSiblingId="3") + response = client.post("/tasks/move", json=move_task.model_dump(by_alias=True)) + assert response.status_code == 200 + assert response.headers["content-type"] == "text/html; charset=utf-8" + assert b'class="progress_card_container"' in response.content diff --git a/tests/api/routes/test_tasks_move.py b/tests/api/routes/test_tasks_move.py new file mode 100644 index 000000000..9408a5b0e --- /dev/null +++ b/tests/api/routes/test_tasks_move.py @@ -0,0 +1,29 @@ +from fastapi.testclient import TestClient + +from tests.database_test_utils import init_db + + +def test_post_task_move(client: TestClient) -> None: + init_db( + [ + {"table": "status", "id": 1}, + {"table": "task", "id": 1, "status_id": 1}, + {"table": "task", "id": 2, "status_id": 1}, + ] + ) + response = client.post( + "/tasks/move", json={"taskId": "1", "statusId": "1", "previousSiblingId": "2", "nextSiblingId": ""} + ) + assert response.status_code == 200 + assert response.headers["content-type"] == "text/html; charset=utf-8" + assert b'id="card-1"' in response.content + + +def test_post_task_move_error(client: TestClient) -> None: + init_db() + response = client.post( + "/tasks/move", json={"taskId": "1", "statusId": "1", "previousSiblingId": "2", "nextSiblingId": ""} + ) + assert response.status_code == 500 + assert response.headers["content-type"] == "text/html; charset=utf-8" + assert b"This is an error message" in response.content diff --git a/tests/conftest.py b/tests/conftest.py index 77538545b..353ad2b3b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,28 +1,83 @@ +import os from collections.abc import Generator +from multiprocessing import Process +from time import sleep +from typing import Any import pytest +import uvicorn +from _pytest.fixtures import SubRequest from fastapi.testclient import TestClient -from sqlmodel import Session, SQLModel, create_engine -from sqlmodel.pool import StaticPool +from playwright.sync_api import Page, Playwright, sync_playwright +from sqlmodel import Session +from tad.core.config import settings +from tad.core.db import get_engine from tad.main import app -# needed to make sure create_all knows about the models -from tad.models import * # noqa: F403 + +class TestSettings: + HTTP_SERVER_SCHEME: str = "http://" + HTTP_SERVER_HOST: str = "127.0.0.1" + HTTP_SERVER_PORT: int = 8000 + + +def run_server() -> None: + uvicorn.run(app, host=TestSettings.HTTP_SERVER_HOST, port=TestSettings.HTTP_SERVER_PORT) + + +def wait_for_server_ready(url: str, timeout: int = 30) -> None: + # todo we can not use playwright because it gives async errors, so we need another + # wait to check the server for being up + sleep(5) @pytest.fixture(scope="module") -def client(db: Session) -> Generator[TestClient, None, None]: +def server() -> Generator[Any, Any, Any]: + # todo (robbert) use a better way to get the test database in the app configuration + os.environ["APP_DATABASE_FILE"] = "database.sqlite3.test" + process = Process(target=run_server) + process.start() + server_address = ( + TestSettings.HTTP_SERVER_SCHEME + TestSettings.HTTP_SERVER_HOST + ":" + str(TestSettings.HTTP_SERVER_PORT) + ) + wait_for_server_ready(server_address) + yield server_address + process.terminate() + del os.environ["APP_DATABASE_FILE"] + + +@pytest.fixture(scope="session") +def get_session() -> Generator[Session, Any, Any]: + with Session(get_engine()) as session: + yield session + + +def pytest_configure() -> None: + """ + Called after the Session object has been created and + before performing collection and entering the run test loop. + """ + # todo (robbert) creating an in memory database does not work right, tables seem to get lost? + settings.APP_DATABASE_FILE = "database.sqlite3.test" # set to none so we'll use an in memory database + + +@pytest.fixture(scope="module") +def client() -> Generator[TestClient, None, None]: with TestClient(app, raise_server_exceptions=True) as c: c.timeout = 5 yield c -@pytest.fixture(scope="module") -def db() -> Generator[Session, None, None]: - engine = create_engine("sqlite://", poolclass=StaticPool) - SQLModel.metadata.create_all(engine) +@pytest.fixture(scope="session") +def playwright(): + with sync_playwright() as p: + yield p - with Session(engine) as session: - yield session - SQLModel.metadata.drop_all(engine) +@pytest.fixture(params=["chromium", "firefox", "webkit"]) +def browser(playwright: Playwright, request: SubRequest) -> Generator[Page, Any, Any]: + browser = getattr(playwright, request.param).launch(headless=True) + context = browser.new_context() + page = context.new_page() + yield page + browser.close() diff --git a/tests/core/test_config.py b/tests/core/test_config.py index f7c8bbc34..3ca07a165 100644 --- a/tests/core/test_config.py +++ b/tests/core/test_config.py @@ -14,6 +14,7 @@ def test_default_settings(): assert settings.PROJECT_NAME == "TAD" assert settings.PROJECT_DESCRIPTION == "Transparency of Algorithmic Decision making" assert settings.APP_DATABASE_SCHEME == "sqlite" + # todo (robbert) we change the database for the test and use the default config assert settings.SQLALCHEMY_DATABASE_URI == "sqlite:///database.sqlite3" diff --git a/tests/core/test_db.py b/tests/core/test_db.py index 5c8aab814..23470d99c 100644 --- a/tests/core/test_db.py +++ b/tests/core/test_db.py @@ -6,7 +6,7 @@ @pytest.mark.skip(reason="not working yet") -async def test_check_dabase(): +async def test_check_database(): mock_session = Mock(spec=Session) with patch("sqlmodel.Session", return_value=mock_session): diff --git a/tests/database_test_utils.py b/tests/database_test_utils.py new file mode 100644 index 000000000..a5ed82548 --- /dev/null +++ b/tests/database_test_utils.py @@ -0,0 +1,121 @@ +from typing import Any + +from sqlalchemy import text +from sqlmodel import Session, SQLModel +from tad.core.db import get_engine + +# todo (robbert) it seems pytest runs all methods in the tests folder, +# this should be moved or marked as helper functions + + +def enrich_with_default_values(specification: dict[str, str | int]) -> dict[str, str | int]: + """ + If a known table dictionary is given, like a task or status, default values will be added + and an enriched dictionary is returned. + :param specification: the dictionary to be enriched + :return: an enriched dictionary + """ + default_specification: dict[str, str | int] = {} + if specification["table"] == "task": + default_specification["title"] = "Test task " + str(specification["id"]) + default_specification["description"] = "Test task description " + str(specification["id"]) + default_specification["sort_order"] = specification["id"] + default_specification["status_id"] = 1 + elif specification["table"] == "status": + default_specification["name"] = "Status " + str(specification["id"]) + default_specification["sort_order"] = specification["id"] + return default_specification | specification + + +def fix_missing_relations(specification: dict[str, Any]) -> None: + """ + If a dictionary with a known table is given, like a task, the related item, + for example a status, will be created in the database if the id does not + exist yet. We do this to comply with database relationships and make it + easier to set up tests with minimal effort. + :param specification: a dictionary with a table specification + :return: None + """ + if specification["table"] == "task": + status_specification = {"id": specification["status_id"], "table": "status"} + if not item_exists(status_specification): + create_db_entries([status_specification]) + + +def get_items(specification: dict[str, str | int]) -> Any: + """ + Create a query based on the dictionary specification and return the result + :param specification: a dictionary with a table specification + :return: the results of the query + """ + values = ", ".join( + key + "=" + str(val) if str(val).isnumeric() else str('"' + val + '"') # type: ignore + for key, val in specification.items() # type: ignore + if key != "table" # type: ignore + ) + table = specification["table"] + statement = f"SELECT * FROM {table} WHERE {values}" # noqa S608 + with Session(get_engine()) as session: + return session.exec(text(statement)).all() # type: ignore + + +def item_exists(specification: dict[str, Any]) -> bool: + """ + Check if an item exists in the database with the table and id given + in the dictionary + :param specification: a dictionary with a table specification + :return: True if the item exists in the database, False otherwise + """ + result = get_items(specification) + return len(result) != 0 + + +def create_db_entries(specifications: list[dict[str, Any]]) -> None: + """ + Given an array of specifications, create the database entries. + + If you want to start with an empty database, use init_db instead! + + See init_db doc for examples. + + :param specifications: an array of dictionaries with table specifications + :return: None + """ + for specification in specifications: + specification = enrich_with_default_values(specification) + exists_specification = {"table": specification["table"], "id": specification["id"]} + if not item_exists(exists_specification): + fix_missing_relations(specification) + table = specification.pop("table") + keys = ", ".join(key for key in specification) + values = ", ".join( + str(val) if str(val).isnumeric() else str("'" + val + "'") + for val in specification.values() # type: ignore + ) + statement = f"INSERT INTO {table} ({keys}) VALUES ({values})" # noqa S608 + with Session(get_engine()) as session: + session.exec(text(statement)) # type: ignore + session.commit() + + +def init_db(specifications: list[dict[str, str | int]] | None = None) -> None: + """ + Drop all database tables and create them. Then fill the database with the + entries from the array of dictionaries with table specifications. + + Example: [{'table': 'task', 'id': 1 'title': 'Test task 1', 'description': 'Test task description 1'}] + + The example below will be enriched so all required fields for a task will have a value. + + Example: [{'table': 'task', 'id': 1}] + + Example: [{"table": "status", "id": 1},{"table": "task", "id": 1, "status_id": 1}] + + :param specifications: an array of dictionaries with table specifications + :return: None + """ + if specifications is None: + specifications = [] + SQLModel.metadata.drop_all(get_engine()) + SQLModel.metadata.create_all(get_engine()) + create_db_entries(specifications) diff --git a/tests/e2e/__init__.py b/tests/e2e/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/e2e/test_move_task.py b/tests/e2e/test_move_task.py new file mode 100644 index 000000000..184ee139f --- /dev/null +++ b/tests/e2e/test_move_task.py @@ -0,0 +1,71 @@ +from playwright.sync_api import Page, expect + +from tests.database_test_utils import init_db + + +def test_move_task_to_column(server: str, browser: Page) -> None: + """ + Test moving a task in the browser to another column and verify that after a reload + it is in the right column. + :param start_server: the start server fixture + :return: None + """ + init_db( + [ + {"table": "status", "id": 1}, + {"table": "status", "id": 2}, + {"table": "status", "id": 3}, + {"table": "status", "id": 4}, + {"table": "task", "id": 1, "status_id": 1}, + ] + ) + + browser.goto(f"{server}/pages/") + + expect(browser.locator("#column-1 #card-1")).to_be_visible() + expect(browser.locator("#column-3")).to_be_visible() + + # todo (Robbert) action below is performed twice, because once does not work, we need find out why and fix it + browser.locator("#card-1").drag_to(browser.locator("#column-3")) + browser.locator("#card-1").drag_to(browser.locator("#column-3")) + + browser.reload() + + card = browser.locator("#column-3 #card-1") + expect(card).to_have_id("card-1") + expect(card).to_be_visible() + + +def test_move_task_order_in_same_column(server: str, browser: Page) -> None: + """ + Test moving a task in the browser below another task and verify that after a reload + it is in the right position in the column. + :return: None + """ + init_db( + [ + {"table": "task", "id": 1, "status_id": 1}, + {"table": "task", "id": 2, "status_id": 1}, + {"table": "task", "id": 3, "status_id": 1}, + ] + ) + + browser.goto(f"{server}/pages/") + + expect(browser.locator("#column-1 #card-1")).to_be_visible() + expect(browser.locator("#column-1")).to_be_visible() + + # todo (robbert) code below doesn't do what it should do, card is not moved + task = browser.locator("#card-1") + task.hover() + browser.mouse.down() + browser.mouse.move(0, 50) + browser.mouse.up() + # https://playwright.dev/docs/input + browser.reload() + + tasks_in_column = browser.locator("#column-1").locator(".progress_card_container").all() + # todo (robbert) this order should be changed if code above works correctly + expect(tasks_in_column[0]).to_have_id("card-1") + expect(tasks_in_column[1]).to_have_id("card-2") + expect(tasks_in_column[2]).to_have_id("card-3") diff --git a/tests/repositories/test_statuses.py b/tests/repositories/test_statuses.py new file mode 100644 index 000000000..922de976e --- /dev/null +++ b/tests/repositories/test_statuses.py @@ -0,0 +1,63 @@ +import pytest +from sqlmodel import Session +from tad.models import Status +from tad.repositories.exceptions import RepositoryError +from tad.repositories.statuses import StatusesRepository +from tests.database_test_utils import get_items, init_db + + +def test_find_all(get_session: Session): + init_db( + [ + {"table": "status", "id": 1}, + {"table": "status", "id": 2}, + ] + ) + status_repository: StatusesRepository = StatusesRepository(get_session) + results = status_repository.find_all() + assert results[0].id == 1 + assert results[1].id == 2 + assert len(results) == 2 + + +def test_find_all_no_results(get_session: Session): + init_db() + status_repository: StatusesRepository = StatusesRepository(get_session) + results = status_repository.find_all() + assert len(results) == 0 + + +def test_save(get_session: Session): + init_db() + status_repository: StatusesRepository = StatusesRepository(get_session) + status: Status = Status(id=1, name="test", sort_order=10) + status_repository.save(status) + result = get_items({"table": "status", "id": 1}) + assert result[0].id == 1 + assert result[0].name == "test" + assert result[0].sort_order == 10 + + +def test_save_failed(get_session: Session): + init_db() + status_repository: StatusesRepository = StatusesRepository(get_session) + status: Status = Status(id=1, name="test", sort_order=10) + status_repository.save(status) + status: Status = Status(id=1, name="test has duplicate id", sort_order=10) + with pytest.raises(RepositoryError): + status_repository.save(status) + + +def test_find_by_id(get_session: Session): + init_db([{"table": "status", "id": 1, "name": "test for find by id"}]) + status_repository: StatusesRepository = StatusesRepository(get_session) + result: Status = status_repository.find_by_id(1) + assert result.id == 1 + assert result.name == "test for find by id" + + +def test_find_by_id_failed(get_session: Session): + init_db() + status_repository: StatusesRepository = StatusesRepository(get_session) + with pytest.raises(RepositoryError): + status_repository.find_by_id(1) diff --git a/tests/repositories/test_tasks.py b/tests/repositories/test_tasks.py new file mode 100644 index 000000000..9a9bb41f3 --- /dev/null +++ b/tests/repositories/test_tasks.py @@ -0,0 +1,79 @@ +import pytest +from sqlmodel import Session +from tad.models import Task +from tad.repositories.exceptions import RepositoryError +from tad.repositories.tasks import TasksRepository +from tests.database_test_utils import get_items, init_db + + +def test_find_all(get_session: Session): + init_db( + [ + {"table": "task", "id": 1, "status_id": 1}, + {"table": "task", "id": 2, "status_id": 1}, + ] + ) + tasks_repository: TasksRepository = TasksRepository(get_session) + results = tasks_repository.find_all() + assert results[0].id == 1 + assert results[1].id == 2 + assert len(results) == 2 + + +def test_find_all_no_results(get_session: Session): + init_db() + tasks_repository: TasksRepository = TasksRepository(get_session) + results = tasks_repository.find_all() + assert len(results) == 0 + + +def test_save(get_session: Session): + init_db() + tasks_repository: TasksRepository = TasksRepository(get_session) + task: Task = Task(id=1, title="Test title", description="Test description", sort_order=10) + tasks_repository.save(task) + result = get_items({"table": "task", "id": 1}) + assert result[0].id == 1 + assert result[0].title == "Test title" + assert result[0].description == "Test description" + assert result[0].sort_order == 10 + + +def test_save_failed(get_session: Session): + init_db() + tasks_repository: TasksRepository = TasksRepository(get_session) + task: Task = Task(id=1, title="Test title", description="Test description", sort_order=10) + tasks_repository.save(task) + task_duplicate: Task = Task(id=1, title="Test title duplicate", description="Test description", sort_order=10) + with pytest.raises(RepositoryError): + tasks_repository.save(task_duplicate) + + +def test_find_by_id(get_session: Session): + init_db([{"table": "task", "id": 1, "title": "test for find by id"}]) + tasks_repository: TasksRepository = TasksRepository(get_session) + result: Task = tasks_repository.find_by_id(1) + assert result.id == 1 + assert result.title == "test for find by id" + + +def test_find_by_id_failed(get_session: Session): + init_db() + tasks_repository: TasksRepository = TasksRepository(get_session) + with pytest.raises(RepositoryError): + tasks_repository.find_by_id(1) + + +def test_find_by_status_id(get_session: Session): + init_db( + [ + {"table": "status", "id": 1}, + {"table": "task", "id": 1, "status_id": 1}, + {"table": "task", "id": 2, "status_id": 1}, + ] + ) + tasks_repository: TasksRepository = TasksRepository(get_session) + results = tasks_repository.find_by_status_id(1) + assert len(results) == 2 + assert results[0].id == 1 + assert results[1].id == 2 diff --git a/tests/services/test_statuses_service.py b/tests/services/test_statuses_service.py new file mode 100644 index 000000000..ba69fca98 --- /dev/null +++ b/tests/services/test_statuses_service.py @@ -0,0 +1,38 @@ +from collections.abc import Generator, Sequence +from typing import Any +from unittest.mock import patch + +import pytest +from tad.models import Status +from tad.repositories.statuses import StatusesRepository +from tad.services.statuses import StatusesService + + +class MockStatusesRepository: + def __init__(self): + pass + + def find_by_id(self, status_id: int) -> Status: + return Status(id=status_id, name="Test status", sort_order=1) + + def find_all(self) -> Sequence[Status]: + return [self.find_by_id(1)] + + +@pytest.fixture(scope="module") +def mock_statuses_repository() -> Generator[MockStatusesRepository, Any, Any]: + with patch("tad.services.statuses.StatusesRepository"): + mock_statuses_repository = MockStatusesRepository() + yield mock_statuses_repository + + +def test_get_status(mock_statuses_repository: StatusesRepository): + statuses_service = StatusesService(mock_statuses_repository) + status: Status = statuses_service.get_status(1) + assert status.id == 1 + + +def test_get_statuses(mock_statuses_repository: StatusesRepository): + statuses_service = StatusesService(mock_statuses_repository) + statuses = statuses_service.get_statuses() + assert len(statuses) == 1 diff --git a/tests/services/test_tasks_service.py b/tests/services/test_tasks_service.py new file mode 100644 index 000000000..77c8bea18 --- /dev/null +++ b/tests/services/test_tasks_service.py @@ -0,0 +1,115 @@ +from collections.abc import Sequence +from unittest.mock import patch + +import pytest +from tad.models import Status, Task, User +from tad.repositories.statuses import StatusesRepository +from tad.repositories.tasks import TasksRepository +from tad.services.statuses import StatusesService +from tad.services.tasks import TasksService + + +class MockStatusesRepository: + def __init__(self): + self._statuses: list[Status] = [] + self.reset() + + def reset(self): + self._statuses.clear() + self._statuses.append(Status(id=1, name="todo", sort_order=1)) + self._statuses.append(Status(id=2, name="in_progress", sort_order=1)) + self._statuses.append(Status(id=3, name="review", sort_order=1)) + self._statuses.append(Status(id=4, name="done", sort_order=1)) + + def find_by_id(self, status_id: int) -> Status: + return next(filter(lambda x: x.id == status_id, self._statuses)) + + +class MockTasksRepository: + def __init__(self): + self._tasks: list[Task] = [] + self.reset() + + def reset(self): + self._tasks.clear() + self._tasks.append(Task(id=1, title="Test 1", description="Description 1", status_id=1, sort_order=10)) + self._tasks.append(Task(id=2, title="Test 2", description="Description 2", status_id=1, sort_order=20)) + self._tasks.append(Task(id=3, title="Test 3", description="Description 3", status_id=1, sort_order=30)) + self._tasks.append(Task(id=4, title="Test 4", description="Description 4", status_id=2, sort_order=10)) + self._tasks.append(Task(id=5, title="Test 5", description="Description 5", status_id=3, sort_order=20)) + + def find_all(self): + return self._tasks + + def find_by_status_id(self, status_id: int) -> Sequence[Task]: + return list(filter(lambda x: x.status_id == status_id, self._tasks)) + + def find_by_id(self, task_id: int) -> Task: + return next(filter(lambda x: x.id == task_id, self._tasks)) + + def save(self, task: Task) -> Task: + return task + + +@pytest.fixture(scope="module") +def mock_tasks_repository(): + with patch("tad.services.tasks.TasksRepository"): + mock_tasks_repository = MockTasksRepository() + yield mock_tasks_repository + + +@pytest.fixture(scope="module") +def mock_statuses_repository(): + with patch("tad.services.statuses.StatusesRepository"): + mock_statuses_repository = MockStatusesRepository() + yield mock_statuses_repository + + +@pytest.fixture(scope="module") +def tasks_service_with_mock(mock_tasks_repository: TasksRepository, mock_statuses_repository: StatusesRepository): + statuses_service = StatusesService(mock_statuses_repository) + tasks_service = TasksService(statuses_service, mock_tasks_repository) + return tasks_service + + +def test_get_tasks(tasks_service_with_mock: TasksService, mock_tasks_repository: TasksRepository): + assert len(tasks_service_with_mock.get_tasks(1)) == 3 + + +def test_assign_task(tasks_service_with_mock: TasksService, mock_tasks_repository: TasksRepository): + task1: Task = mock_tasks_repository.find_by_id(1) + user1: User = User(id=1, name="User 1", avatar="none.jpg") + tasks_service_with_mock.assign_task(task1, user1) + assert task1.user_id == 1 + + +def test_move_task(tasks_service_with_mock: TasksService, mock_tasks_repository: MockTasksRepository): + # test changing order + mock_tasks_repository.reset() + assert mock_tasks_repository.find_by_id(1).sort_order == 10 + tasks_service_with_mock.move_task(1, 1, 2, 3) + assert mock_tasks_repository.find_by_id(1).sort_order == 25 + + # test changing order + mock_tasks_repository.reset() + tasks_service_with_mock.move_task(1, 1, 3, None) + assert mock_tasks_repository.find_by_id(1).sort_order == 40 + + # test moving to in progress + mock_tasks_repository.reset() + mock_tasks_repository.find_by_id(1).sort_order = 0 + tasks_service_with_mock.move_task(1, 2, 0, 0) + assert mock_tasks_repository.find_by_id(1).sort_order == 10 + assert mock_tasks_repository.find_by_id(1).user_id == 1 + + # test moving to todo + mock_tasks_repository.reset() + mock_tasks_repository.find_by_id(1).sort_order = 0 + tasks_service_with_mock.move_task(1, 4, 0, 0) + assert mock_tasks_repository.find_by_id(1).sort_order == 10 + + # test moving move under other card + mock_tasks_repository.reset() + mock_tasks_repository.find_by_id(2).sort_order = 10 + tasks_service_with_mock.move_task(2, 1, 0, 1) + assert mock_tasks_repository.find_by_id(2).sort_order == 5