mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-22 00:49:23 -04:00
Merge branch 'main' into formatting
This commit is contained in:
4
.github/actions/setup-project/action.yml
vendored
4
.github/actions/setup-project/action.yml
vendored
@@ -9,10 +9,10 @@ runs:
|
||||
sudo apt-get update \
|
||||
&& sudo apt-get install -y --no-install-recommends \
|
||||
libcurl4-openssl-dev
|
||||
- name: Set up Python 3.13.2
|
||||
- name: Set up Python 3.12.9
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.13.2"
|
||||
python-version: "3.12.9"
|
||||
- name: Install poetry
|
||||
shell: bash
|
||||
run: pip install poetry==2.1.3
|
||||
|
||||
16
README.md
16
README.md
@@ -189,12 +189,12 @@ session to make the changes take effect.
|
||||
Now we're ready to install the Python version we need with `pyenv`, like so:
|
||||
|
||||
```sh
|
||||
pyenv install 3.13
|
||||
pyenv install 3.12
|
||||
```
|
||||
|
||||
This will install the latest version of Python 3.13.
|
||||
This will install the latest version of Python 3.12.
|
||||
|
||||
_NOTE: This project currently runs on Python 3.13.x._
|
||||
_NOTE: This project currently runs on Python 3.12.x._
|
||||
|
||||
#### [API Step] Python Dependency Installation
|
||||
|
||||
@@ -246,12 +246,12 @@ git clone git@github.com:GSA/notifications-admin.git
|
||||
|
||||
Now go into the project directory (`notifications-admin` by default), create a
|
||||
virtual environment, and set the local Python version to point to the virtual
|
||||
environment (assumes version Python `3.13.2` is what is installed on your
|
||||
environment (assumes version Python `3.12.9` is what is installed on your
|
||||
machine):
|
||||
|
||||
```sh
|
||||
cd notifications-admin
|
||||
pyenv virtualenv 3.13.2 notify-admin
|
||||
pyenv virtualenv 3.12.9 notify-admin
|
||||
pyenv local notify-admin
|
||||
```
|
||||
|
||||
@@ -284,10 +284,10 @@ If you're upgrading an existing project to a newer version of Python, you can
|
||||
follow these steps to get yourself up-to-date.
|
||||
|
||||
First, use `pyenv` to install the newer version of Python you'd like to use;
|
||||
we'll use `3.13` in our example here since we recently upgraded to this version:
|
||||
we'll use `3.12` in our example here since we recently upgraded to this version:
|
||||
|
||||
```sh
|
||||
pyenv install 3.13
|
||||
pyenv install 3.12
|
||||
```
|
||||
|
||||
Next, delete the virtual environment you previously had set up. If you followed
|
||||
@@ -302,7 +302,7 @@ environment with the newer version of Python you just installed:
|
||||
|
||||
```sh
|
||||
cd notifications-admin
|
||||
pyenv virtualenv 3.13.2 notify-admin
|
||||
pyenv virtualenv 3.12.9 notify-admin
|
||||
pyenv local notify-admin
|
||||
```
|
||||
|
||||
|
||||
@@ -13,6 +13,32 @@ from app.utils.pagination import (
|
||||
from app.utils.user import user_has_permissions
|
||||
|
||||
|
||||
def get_download_availability(service_id):
|
||||
"""
|
||||
Check if there are jobs available for each download time period.
|
||||
"""
|
||||
jobs_1_day = job_api_client.get_page_of_jobs(service_id, page=1, limit_days=1)
|
||||
jobs_3_days = job_api_client.get_page_of_jobs(service_id, page=1, limit_days=3)
|
||||
jobs_5_days = job_api_client.get_page_of_jobs(service_id, page=1, limit_days=5)
|
||||
jobs_7_days = job_api_client.get_immediate_jobs(service_id)
|
||||
|
||||
has_1_day_data = len(generate_job_dict(jobs_1_day)) > 0
|
||||
has_3_day_data = len(generate_job_dict(jobs_3_days)) > 0
|
||||
has_5_day_data = len(generate_job_dict(jobs_5_days)) > 0
|
||||
has_7_day_data = len(jobs_7_days) > 0
|
||||
|
||||
return {
|
||||
"has_1_day_data": has_1_day_data,
|
||||
"has_3_day_data": has_3_day_data,
|
||||
"has_5_day_data": has_5_day_data,
|
||||
"has_7_day_data": has_7_day_data,
|
||||
"has_any_download_data": has_1_day_data
|
||||
or has_3_day_data
|
||||
or has_5_day_data
|
||||
or has_7_day_data,
|
||||
}
|
||||
|
||||
|
||||
@main.route("/activity/services/<uuid:service_id>")
|
||||
@user_has_permissions(ServicePermission.VIEW_ACTIVITY)
|
||||
def all_jobs_activity(service_id):
|
||||
@@ -22,6 +48,7 @@ def all_jobs_activity(service_id):
|
||||
all_jobs_dict = generate_job_dict(jobs)
|
||||
prev_page, next_page, pagination = handle_pagination(jobs, service_id, page)
|
||||
message_type = ("sms",)
|
||||
download_availability = get_download_availability(service_id)
|
||||
return render_template(
|
||||
"views/activity/all-activity.html",
|
||||
all_jobs_dict=all_jobs_dict,
|
||||
@@ -29,6 +56,7 @@ def all_jobs_activity(service_id):
|
||||
next_page=next_page,
|
||||
prev_page=prev_page,
|
||||
pagination=pagination,
|
||||
**download_availability,
|
||||
download_link_one_day=url_for(
|
||||
".download_notifications_csv",
|
||||
service_id=current_service.id,
|
||||
@@ -68,9 +96,13 @@ def handle_pagination(jobs, service_id, page):
|
||||
if page > 1
|
||||
else None
|
||||
)
|
||||
total_items = jobs.get("total", 0)
|
||||
page_size = jobs.get("page_size", 50)
|
||||
total_pages = (total_items + page_size - 1) // page_size
|
||||
has_next_link = jobs.get("links", {}).get("next") is not None
|
||||
next_page = (
|
||||
generate_next_dict("main.all_jobs_activity", service_id, page)
|
||||
if jobs.get("links", {}).get("next")
|
||||
if has_next_link and total_items > 50 and page < total_pages
|
||||
else None
|
||||
)
|
||||
pagination = generate_pagination_pages(
|
||||
|
||||
@@ -253,7 +253,15 @@ def get_notifications(service_id, message_type, status_override=None): # noqa
|
||||
)
|
||||
next_page = None
|
||||
|
||||
if "links" in notifications and notifications["links"].get("next", None):
|
||||
total_items = notifications.get("total", 0)
|
||||
page_size = notifications.get("page_size", 50)
|
||||
total_pages = (total_items + page_size - 1) // page_size
|
||||
if (
|
||||
"links" in notifications
|
||||
and notifications["links"].get("next", None)
|
||||
and total_items > 50
|
||||
and page < total_pages
|
||||
):
|
||||
next_page = generate_next_dict(
|
||||
"main.view_notifications", service_id, page, url_args
|
||||
)
|
||||
|
||||
@@ -126,20 +126,33 @@
|
||||
</div>
|
||||
{{show_pagination}}
|
||||
{% if current_user.has_permissions(ServicePermission.VIEW_ACTIVITY) %}
|
||||
<h2 class="line-height-sans-2 margin-bottom-0 margin-top-4">Download recent reports</h2>
|
||||
<p class="font-body-sm">
|
||||
<a href="{{ download_link_one_day }}" download="download" class="usa-link">Download all data last 24 hours (<abbr title="Comma separated values">CSV</abbr>)</a>
|
||||
</p>
|
||||
<p class="font-body-sm">
|
||||
<a href="{{ download_link_three_day }}" download="download" class="usa-link">Download all data last 3 days (<abbr title="Comma separated values">CSV</abbr>)</a>
|
||||
 
|
||||
</p>
|
||||
<p class="font-body-sm">
|
||||
<a href="{{ download_link_five_day }}" download="download" class="usa-link">Download all data last 5 days (<abbr title="Comma separated values">CSV</abbr>)</a>
|
||||
</p>
|
||||
<p class="font-body-sm">
|
||||
<a href="{{ download_link_seven_day }}" download="download" class="usa-link">Download all data last 7 days (<abbr title="Comma separated values">CSV</abbr>)</a>
|
||||
</p>
|
||||
{% if has_any_download_data %}
|
||||
<h2 class="line-height-sans-2 margin-bottom-0 margin-top-4">Download recent reports</h2>
|
||||
{% if has_1_day_data %}
|
||||
<p class="font-body-sm">
|
||||
<a href="{{ download_link_one_day }}" download="download" class="usa-link">Download all data last 24 hours (<abbr title="Comma separated values">CSV</abbr>)</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if has_3_day_data %}
|
||||
<p class="font-body-sm">
|
||||
<a href="{{ download_link_three_day }}" download="download" class="usa-link">Download all data last 3 days (<abbr title="Comma separated values">CSV</abbr>)</a>
|
||||
 
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if has_5_day_data %}
|
||||
<p class="font-body-sm">
|
||||
<a href="{{ download_link_five_day }}" download="download" class="usa-link">Download all data last 5 days (<abbr title="Comma separated values">CSV</abbr>)</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if has_7_day_data %}
|
||||
<p class="font-body-sm">
|
||||
<a href="{{ download_link_seven_day }}" download="download" class="usa-link">Download all data last 7 days (<abbr title="Comma separated values">CSV</abbr>)</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<h2 class="line-height-sans-2 margin-bottom-0 margin-top-4">Download recent reports</h2>
|
||||
<p class="font-body-sm">No recent activity to download. Download links will appear when jobs are available.</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -2,7 +2,8 @@ import multiprocessing
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import logging
|
||||
from app.utils import hilite
|
||||
import gunicorn
|
||||
|
||||
# Let gunicorn figure out the right number of workers
|
||||
@@ -11,6 +12,10 @@ import gunicorn
|
||||
# so adjust it.
|
||||
workers = multiprocessing.cpu_count()
|
||||
worker_class = "gevent"
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logging.info(hilite("Gunicorn timeout set to 240 seconds"))
|
||||
timeout = 240
|
||||
bind = "0.0.0.0:{}".format(os.getenv("PORT"))
|
||||
disable_redirect_access_to_syslog = True
|
||||
gunicorn.SERVER_SOFTWARE = "None"
|
||||
|
||||
27
poetry.lock
generated
27
poetry.lock
generated
@@ -27,6 +27,7 @@ files = [
|
||||
[package.dependencies]
|
||||
idna = ">=2.8"
|
||||
sniffio = ">=1.1"
|
||||
typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
|
||||
|
||||
[package.extras]
|
||||
doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"]
|
||||
@@ -929,6 +930,9 @@ files = [
|
||||
{file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""}
|
||||
|
||||
[package.extras]
|
||||
test = ["pytest (>=6)"]
|
||||
|
||||
@@ -1713,6 +1717,8 @@ files = [
|
||||
{file = "lxml-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:35bc626eec405f745199200ccb5c6b36f202675d204aa29bb52e27ba2b71dea8"},
|
||||
{file = "lxml-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:246b40f8a4aec341cbbf52617cad8ab7c888d944bfe12a6abd2b1f6cfb6f6082"},
|
||||
{file = "lxml-6.0.0-cp310-cp310-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:2793a627e95d119e9f1e19720730472f5543a6d84c50ea33313ce328d870f2dd"},
|
||||
{file = "lxml-6.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:46b9ed911f36bfeb6338e0b482e7fe7c27d362c52fde29f221fddbc9ee2227e7"},
|
||||
{file = "lxml-6.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2b4790b558bee331a933e08883c423f65bbcd07e278f91b2272489e31ab1e2b4"},
|
||||
{file = "lxml-6.0.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2030956cf4886b10be9a0285c6802e078ec2391e1dd7ff3eb509c2c95a69b76"},
|
||||
{file = "lxml-6.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d23854ecf381ab1facc8f353dcd9adeddef3652268ee75297c1164c987c11dc"},
|
||||
{file = "lxml-6.0.0-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:43fe5af2d590bf4691531b1d9a2495d7aab2090547eaacd224a3afec95706d76"},
|
||||
@@ -1725,6 +1731,8 @@ files = [
|
||||
{file = "lxml-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ee56288d0df919e4aac43b539dd0e34bb55d6a12a6562038e8d6f3ed07f9e36"},
|
||||
{file = "lxml-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8dd6dd0e9c1992613ccda2bcb74fc9d49159dbe0f0ca4753f37527749885c25"},
|
||||
{file = "lxml-6.0.0-cp311-cp311-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:d7ae472f74afcc47320238b5dbfd363aba111a525943c8a34a1b657c6be934c3"},
|
||||
{file = "lxml-6.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5592401cdf3dc682194727c1ddaa8aa0f3ddc57ca64fd03226a430b955eab6f6"},
|
||||
{file = "lxml-6.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58ffd35bd5425c3c3b9692d078bf7ab851441434531a7e517c4984d5634cd65b"},
|
||||
{file = "lxml-6.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f720a14aa102a38907c6d5030e3d66b3b680c3e6f6bc95473931ea3c00c59967"},
|
||||
{file = "lxml-6.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2a5e8d207311a0170aca0eb6b160af91adc29ec121832e4ac151a57743a1e1e"},
|
||||
{file = "lxml-6.0.0-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:2dd1cc3ea7e60bfb31ff32cafe07e24839df573a5e7c2d33304082a5019bcd58"},
|
||||
@@ -1737,11 +1745,15 @@ files = [
|
||||
{file = "lxml-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78718d8454a6e928470d511bf8ac93f469283a45c354995f7d19e77292f26108"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:84ef591495ffd3f9dcabffd6391db7bb70d7230b5c35ef5148354a134f56f2be"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:2930aa001a3776c3e2601cb8e0a15d21b8270528d89cc308be4843ade546b9ab"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:219e0431ea8006e15005767f0351e3f7f9143e793e58519dc97fe9e07fae5563"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bd5913b4972681ffc9718bc2d4c53cde39ef81415e1671ff93e9aa30b46595e7"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:390240baeb9f415a82eefc2e13285016f9c8b5ad71ec80574ae8fa9605093cd7"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-manylinux_2_27_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d6e200909a119626744dd81bae409fc44134389e03fbf1d68ed2a55a2fb10991"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ca50bd612438258a91b5b3788c6621c1f05c8c478e7951899f492be42defc0da"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:c24b8efd9c0f62bad0439283c2c795ef916c5a6b75f03c17799775c7ae3c0c9e"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:afd27d8629ae94c5d863e32ab0e1d5590371d296b87dae0a751fb22bf3685741"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:54c4855eabd9fc29707d30141be99e5cd1102e7d2258d2892314cf4c110726c3"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c907516d49f77f6cd8ead1322198bdfd902003c3c330c77a1c5f3cc32a0e4d16"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36531f81c8214e293097cd2b7873f178997dae33d3667caaae8bdfb9666b76c0"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-win32.whl", hash = "sha256:690b20e3388a7ec98e899fd54c924e50ba6693874aa65ef9cb53de7f7de9d64a"},
|
||||
{file = "lxml-6.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:310b719b695b3dd442cdfbbe64936b2f2e231bb91d998e99e6f0daf991a3eba3"},
|
||||
@@ -1749,17 +1761,22 @@ files = [
|
||||
{file = "lxml-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6da7cd4f405fd7db56e51e96bff0865b9853ae70df0e6720624049da76bde2da"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b34339898bb556a2351a1830f88f751679f343eabf9cf05841c95b165152c9e7"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:51a5e4c61a4541bd1cd3ba74766d0c9b6c12d6a1a4964ef60026832aac8e79b3"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d18a25b19ca7307045581b18b3ec9ead2b1db5ccd8719c291f0cd0a5cec6cb81"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d4f0c66df4386b75d2ab1e20a489f30dc7fd9a06a896d64980541506086be1f1"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f4b481b6cc3a897adb4279216695150bbe7a44c03daba3c894f49d2037e0a24"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-manylinux_2_27_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a78d6c9168f5bcb20971bf3329c2b83078611fbe1f807baadc64afc70523b3a"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae06fbab4f1bb7db4f7c8ca9897dc8db4447d1a2b9bee78474ad403437bcc29"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:1fa377b827ca2023244a06554c6e7dc6828a10aaf74ca41965c5d8a4925aebb4"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1676b56d48048a62ef77a250428d1f31f610763636e0784ba67a9740823988ca"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:0e32698462aacc5c1cf6bdfebc9c781821b7e74c79f13e5ffc8bfe27c42b1abf"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4d6036c3a296707357efb375cfc24bb64cd955b9ec731abf11ebb1e40063949f"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7488a43033c958637b1a08cddc9188eb06d3ad36582cebc7d4815980b47e27ef"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-win32.whl", hash = "sha256:5fcd7d3b1d8ecb91445bd71b9c88bdbeae528fefee4f379895becfc72298d181"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:2f34687222b78fff795feeb799a7d44eca2477c3d9d3a46ce17d51a4f383e32e"},
|
||||
{file = "lxml-6.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:21db1ec5525780fd07251636eb5f7acb84003e9382c72c18c542a87c416ade03"},
|
||||
{file = "lxml-6.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4eb114a0754fd00075c12648d991ec7a4357f9cb873042cc9a77bf3a7e30c9db"},
|
||||
{file = "lxml-6.0.0-cp38-cp38-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:7da298e1659e45d151b4028ad5c7974917e108afb48731f4ed785d02b6818994"},
|
||||
{file = "lxml-6.0.0-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7bf61bc4345c1895221357af8f3e89f8c103d93156ef326532d35c707e2fb19d"},
|
||||
{file = "lxml-6.0.0-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63b634facdfbad421d4b61c90735688465d4ab3a8853ac22c76ccac2baf98d97"},
|
||||
{file = "lxml-6.0.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e380e85b93f148ad28ac15f8117e2fd8e5437aa7732d65e260134f83ce67911b"},
|
||||
{file = "lxml-6.0.0-cp38-cp38-win32.whl", hash = "sha256:185efc2fed89cdd97552585c624d3c908f0464090f4b91f7d92f8ed2f3b18f54"},
|
||||
@@ -1767,6 +1784,8 @@ files = [
|
||||
{file = "lxml-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:85b14a4689d5cff426c12eefe750738648706ea2753b20c2f973b2a000d3d261"},
|
||||
{file = "lxml-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f64ccf593916e93b8d36ed55401bb7fe9c7d5de3180ce2e10b08f82a8f397316"},
|
||||
{file = "lxml-6.0.0-cp39-cp39-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:b372d10d17a701b0945f67be58fae4664fd056b85e0ff0fbc1e6c951cdbc0512"},
|
||||
{file = "lxml-6.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a674c0948789e9136d69065cc28009c1b1874c6ea340253db58be7622ce6398f"},
|
||||
{file = "lxml-6.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:edf6e4c8fe14dfe316939711e3ece3f9a20760aabf686051b537a7562f4da91a"},
|
||||
{file = "lxml-6.0.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:048a930eb4572829604982e39a0c7289ab5dc8abc7fc9f5aabd6fbc08c154e93"},
|
||||
{file = "lxml-6.0.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c0b5fa5eda84057a4f1bbb4bb77a8c28ff20ae7ce211588d698ae453e13c6281"},
|
||||
{file = "lxml-6.0.0-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:c352fc8f36f7e9727db17adbf93f82499457b3d7e5511368569b4c5bd155a922"},
|
||||
@@ -1777,10 +1796,14 @@ files = [
|
||||
{file = "lxml-6.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:e0b1520ef900e9ef62e392dd3d7ae4f5fa224d1dd62897a792cf353eb20b6cae"},
|
||||
{file = "lxml-6.0.0-cp39-cp39-win_arm64.whl", hash = "sha256:e35e8aaaf3981489f42884b59726693de32dabfc438ac10ef4eb3409961fd402"},
|
||||
{file = "lxml-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:dbdd7679a6f4f08152818043dbb39491d1af3332128b3752c3ec5cebc0011a72"},
|
||||
{file = "lxml-6.0.0-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:40442e2a4456e9910875ac12951476d36c0870dcb38a68719f8c4686609897c4"},
|
||||
{file = "lxml-6.0.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db0efd6bae1c4730b9c863fc4f5f3c0fa3e8f05cae2c44ae141cb9dfc7d091dc"},
|
||||
{file = "lxml-6.0.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9ab542c91f5a47aaa58abdd8ea84b498e8e49fe4b883d67800017757a3eb78e8"},
|
||||
{file = "lxml-6.0.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:013090383863b72c62a702d07678b658fa2567aa58d373d963cca245b017e065"},
|
||||
{file = "lxml-6.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c86df1c9af35d903d2b52d22ea3e66db8058d21dc0f59842ca5deb0595921141"},
|
||||
{file = "lxml-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4337e4aec93b7c011f7ee2e357b0d30562edd1955620fdd4aeab6aacd90d43c5"},
|
||||
{file = "lxml-6.0.0-pp39-pypy39_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ae74f7c762270196d2dda56f8dd7309411f08a4084ff2dfcc0b095a218df2e06"},
|
||||
{file = "lxml-6.0.0-pp39-pypy39_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:059c4cbf3973a621b62ea3132934ae737da2c132a788e6cfb9b08d63a0ef73f9"},
|
||||
{file = "lxml-6.0.0-pp39-pypy39_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:17f090a9bc0ce8da51a5632092f98a7e7f84bca26f33d161a98b57f7fb0004ca"},
|
||||
{file = "lxml-6.0.0-pp39-pypy39_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9da022c14baeec36edfcc8daf0e281e2f55b950249a455776f0d1adeeada4734"},
|
||||
{file = "lxml-6.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a55da151d0b0c6ab176b4e761670ac0e2667817a1e0dadd04a01d0561a219349"},
|
||||
@@ -4206,5 +4229,5 @@ cffi = ["cffi (>=1.11)"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = "^3.13.2"
|
||||
content-hash = "6f5a26be48841af3784f06d9c79c27a4bc7c2c8183da5d27eae2d371a2884258"
|
||||
python-versions = "^3.12.9"
|
||||
content-hash = "073234a8e1c1abf220f2591459e31fe3c45e87eda57f1dc4fc64804d79051ef7"
|
||||
|
||||
@@ -8,7 +8,7 @@ package-mode = false
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
axe-core-python = "^0.1.0"
|
||||
python = "^3.13.2"
|
||||
python = "^3.12.9"
|
||||
ago = "~=0.1.0"
|
||||
beautifulsoup4 = "^4.13.3"
|
||||
blinker = "~=1.8"
|
||||
|
||||
@@ -1 +1 @@
|
||||
python-3.13.x
|
||||
python-3.12.x
|
||||
|
||||
@@ -9,6 +9,7 @@ from freezegun import freeze_time
|
||||
|
||||
from app.main.views.jobs import get_status_filters, get_time_left
|
||||
from app.models.service import Service
|
||||
from tests import notification_json
|
||||
from tests.conftest import (
|
||||
SERVICE_ONE_ID,
|
||||
create_active_caseworking_user,
|
||||
@@ -284,6 +285,93 @@ def test_link_to_download_notifications(
|
||||
)
|
||||
|
||||
|
||||
def test_download_links_show_when_data_available(
|
||||
client_request,
|
||||
service_one,
|
||||
active_user_with_permissions,
|
||||
mocker,
|
||||
):
|
||||
|
||||
mock_jobs_with_data = {
|
||||
"data": [{"id": "job1", "created_at": "2020-01-01T00:00:00.000000+00:00"}],
|
||||
"total": 1,
|
||||
"page_size": 50
|
||||
}
|
||||
|
||||
mocker.patch("app.job_api_client.get_page_of_jobs", return_value=mock_jobs_with_data)
|
||||
mocker.patch("app.job_api_client.get_immediate_jobs", return_value=[{"id": "job1"}])
|
||||
|
||||
page = client_request.get(
|
||||
"main.all_jobs_activity",
|
||||
service_id=service_one["id"],
|
||||
)
|
||||
|
||||
assert "Download recent reports" in page.text
|
||||
assert "Download all data last 24 hours" in page.text
|
||||
assert "Download all data last 3 days" in page.text
|
||||
assert "Download all data last 5 days" in page.text
|
||||
assert "Download all data last 7 days" in page.text
|
||||
assert "No recent activity to download" not in page.text
|
||||
|
||||
|
||||
def test_download_links_partial_data_available(
|
||||
client_request,
|
||||
service_one,
|
||||
active_user_with_permissions,
|
||||
mocker,
|
||||
):
|
||||
mock_jobs_with_data = {
|
||||
"data": [{"id": "job1", "created_at": "2020-01-01T00:00:00.000000+00:00"}],
|
||||
"total": 1,
|
||||
"page_size": 50
|
||||
}
|
||||
mock_jobs_empty = {"data": [], "total": 0, "page_size": 50}
|
||||
|
||||
def mock_get_page_of_jobs(service_id, page=1, limit_days=None):
|
||||
if limit_days in [1, 5]:
|
||||
return mock_jobs_with_data
|
||||
return mock_jobs_empty
|
||||
|
||||
mocker.patch("app.job_api_client.get_page_of_jobs", side_effect=mock_get_page_of_jobs)
|
||||
mocker.patch("app.job_api_client.get_immediate_jobs", return_value=[])
|
||||
|
||||
page = client_request.get(
|
||||
"main.all_jobs_activity",
|
||||
service_id=service_one["id"],
|
||||
)
|
||||
|
||||
assert "Download recent reports" in page.text
|
||||
assert "Download all data last 24 hours" in page.text
|
||||
assert "Download all data last 3 days" not in page.text
|
||||
assert "Download all data last 5 days" in page.text
|
||||
assert "Download all data last 7 days" not in page.text
|
||||
assert "No recent activity to download" not in page.text
|
||||
|
||||
|
||||
def test_download_links_no_data_available(
|
||||
client_request,
|
||||
service_one,
|
||||
active_user_with_permissions,
|
||||
mocker,
|
||||
):
|
||||
mock_jobs_empty = {"data": [], "total": 0, "page_size": 50}
|
||||
|
||||
mocker.patch("app.job_api_client.get_page_of_jobs", return_value=mock_jobs_empty)
|
||||
mocker.patch("app.job_api_client.get_immediate_jobs", return_value=[])
|
||||
|
||||
page = client_request.get(
|
||||
"main.all_jobs_activity",
|
||||
service_id=service_one["id"],
|
||||
)
|
||||
|
||||
assert "Download recent reports" in page.text
|
||||
assert "Download all data last 24 hours" not in page.text
|
||||
assert "Download all data last 3 days" not in page.text
|
||||
assert "Download all data last 5 days" not in page.text
|
||||
assert "Download all data last 7 days" not in page.text
|
||||
assert "No recent activity to download. Download links will appear when jobs are available." in page.text
|
||||
|
||||
|
||||
def test_download_not_available_to_users_without_dashboard(
|
||||
client_request,
|
||||
active_caseworking_user,
|
||||
@@ -465,12 +553,17 @@ def test_should_show_notifications_for_a_service_with_next_previous(
|
||||
client_request,
|
||||
service_one,
|
||||
active_user_with_permissions,
|
||||
mock_get_notifications_with_previous_next,
|
||||
mock_get_service_statistics,
|
||||
mock_get_service_data_retention,
|
||||
mock_get_no_api_keys,
|
||||
mocker,
|
||||
):
|
||||
mocker.patch(
|
||||
"app.notification_api_client.get_notifications_for_service",
|
||||
return_value=notification_json(
|
||||
service_one["id"], rows=50, with_links=True
|
||||
) | {"total": 150},
|
||||
)
|
||||
page = client_request.get(
|
||||
"main.view_notifications",
|
||||
service_id=service_one["id"],
|
||||
@@ -504,16 +597,76 @@ def test_should_show_notifications_for_a_service_with_next_previous(
|
||||
assert "page 1" in prev_page_link.text.strip()
|
||||
|
||||
|
||||
def test_doesnt_show_pagination_with_search_term(
|
||||
def test_doesnt_show_next_button_on_last_page(
|
||||
client_request,
|
||||
service_one,
|
||||
active_user_with_permissions,
|
||||
mock_get_notifications_with_previous_next,
|
||||
mock_get_service_statistics,
|
||||
mock_get_service_data_retention,
|
||||
mock_get_no_api_keys,
|
||||
mocker,
|
||||
):
|
||||
mocker.patch(
|
||||
"app.notification_api_client.get_notifications_for_service",
|
||||
return_value=notification_json(
|
||||
service_one["id"], rows=50, with_links=True
|
||||
) | {"total": 100},
|
||||
)
|
||||
page = client_request.get(
|
||||
"main.view_notifications",
|
||||
service_id=service_one["id"],
|
||||
message_type="sms",
|
||||
page=2,
|
||||
)
|
||||
|
||||
next_page_link = page.find("a", {"rel": "next"})
|
||||
prev_page_link = page.find("a", {"rel": "previous"})
|
||||
|
||||
assert next_page_link is None
|
||||
assert prev_page_link is not None
|
||||
|
||||
|
||||
def test_doesnt_show_pagination_when_50_or_fewer_items(
|
||||
client_request,
|
||||
service_one,
|
||||
active_user_with_permissions,
|
||||
mock_get_service_statistics,
|
||||
mock_get_service_data_retention,
|
||||
mock_get_no_api_keys,
|
||||
mocker,
|
||||
):
|
||||
mocker.patch(
|
||||
"app.notification_api_client.get_notifications_for_service",
|
||||
return_value=notification_json(
|
||||
service_one["id"], rows=50, with_links=False
|
||||
),
|
||||
)
|
||||
page = client_request.get(
|
||||
"main.view_notifications",
|
||||
service_id=service_one["id"],
|
||||
message_type="sms",
|
||||
)
|
||||
|
||||
assert not page.find("a", {"rel": "next"})
|
||||
assert not page.find("a", {"rel": "previous"})
|
||||
assert not page.select_one(".table-show-more-link")
|
||||
|
||||
|
||||
def test_doesnt_show_pagination_with_search_term(
|
||||
client_request,
|
||||
service_one,
|
||||
active_user_with_permissions,
|
||||
mock_get_service_statistics,
|
||||
mock_get_service_data_retention,
|
||||
mock_get_no_api_keys,
|
||||
mocker,
|
||||
):
|
||||
mocker.patch(
|
||||
"app.notification_api_client.get_notifications_for_service",
|
||||
return_value=notification_json(
|
||||
service_one["id"], rows=50, with_links=True
|
||||
) | {"total": 100},
|
||||
)
|
||||
page = client_request.post(
|
||||
"main.view_notifications",
|
||||
service_id=service_one["id"],
|
||||
|
||||
@@ -50,6 +50,9 @@ def test_all_activity(
|
||||
mock_get_page_of_jobs = mocker.patch(
|
||||
"app.job_api_client.get_page_of_jobs", return_value=MOCK_JOBS
|
||||
)
|
||||
mocker.patch(
|
||||
"app.job_api_client.get_immediate_jobs", return_value=[]
|
||||
)
|
||||
|
||||
response = client_request.get_response(
|
||||
"main.all_jobs_activity",
|
||||
@@ -60,7 +63,11 @@ def test_all_activity(
|
||||
assert response.data is not None, "Response data is None"
|
||||
|
||||
assert "All activity" in response.text
|
||||
mock_get_page_of_jobs.assert_called_with(SERVICE_ONE_ID, page=current_page)
|
||||
|
||||
assert any(
|
||||
call[0][0] == SERVICE_ONE_ID and call[1].get('page') == current_page
|
||||
for call in mock_get_page_of_jobs.call_args_list
|
||||
)
|
||||
page = BeautifulSoup(response.data, "html.parser")
|
||||
table = page.find("table")
|
||||
assert table is not None, "Table not found in the response"
|
||||
@@ -115,7 +122,6 @@ def test_all_activity(
|
||||
|
||||
failed_cell = cells[6].get_text(strip=True)
|
||||
assert failed_cell == "5", f"Expected failed count '5', but got '{failed_cell}'"
|
||||
mock_get_page_of_jobs.assert_called_with(SERVICE_ONE_ID, page=current_page)
|
||||
|
||||
|
||||
def test_all_activity_no_jobs(client_request, mocker):
|
||||
@@ -133,6 +139,9 @@ def test_all_activity_no_jobs(client_request, mocker):
|
||||
"total": 0,
|
||||
},
|
||||
)
|
||||
mocker.patch(
|
||||
"app.job_api_client.get_immediate_jobs", return_value=[]
|
||||
)
|
||||
response = client_request.get_response(
|
||||
"main.all_jobs_activity",
|
||||
service_id=SERVICE_ONE_ID,
|
||||
@@ -152,7 +161,10 @@ def test_all_activity_no_jobs(client_request, mocker):
|
||||
assert (
|
||||
expected_message == actual_message
|
||||
), f"Expected message '{expected_message}', but got '{actual_message}'"
|
||||
mock_get_page_of_jobs.assert_called_with(SERVICE_ONE_ID, page=current_page)
|
||||
assert any(
|
||||
call[0][0] == SERVICE_ONE_ID and call[1].get('page') == current_page
|
||||
for call in mock_get_page_of_jobs.call_args_list
|
||||
)
|
||||
|
||||
|
||||
def test_all_activity_pagination(client_request, mocker):
|
||||
@@ -182,13 +194,19 @@ def test_all_activity_pagination(client_request, mocker):
|
||||
"total": 100,
|
||||
},
|
||||
)
|
||||
mocker.patch(
|
||||
"app.job_api_client.get_immediate_jobs", return_value=[]
|
||||
)
|
||||
|
||||
response = client_request.get_response(
|
||||
"main.all_jobs_activity",
|
||||
service_id=SERVICE_ONE_ID,
|
||||
page=current_page,
|
||||
)
|
||||
mock_get_page_of_jobs.assert_called_with(SERVICE_ONE_ID, page=current_page)
|
||||
assert any(
|
||||
call[0][0] == SERVICE_ONE_ID and call[1].get('page') == current_page
|
||||
for call in mock_get_page_of_jobs.call_args_list
|
||||
)
|
||||
|
||||
page = BeautifulSoup(response.data, "html.parser")
|
||||
pagination_controls = page.find_all("li", class_="usa-pagination__item")
|
||||
|
||||
Reference in New Issue
Block a user