Skip to content
This repository has been archived by the owner on Jul 25, 2024. It is now read-only.

Commit

Permalink
Merge pull request #128 from communitiesuk/FPASF-394-find-home-page
Browse files Browse the repository at this point in the history
updated find home page content
  • Loading branch information
israr-ulhaq authored Jul 18, 2024
2 parents 8bbd60a + 4011bd5 commit 49444be
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 138 deletions.
13 changes: 6 additions & 7 deletions app/main/forms.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from flask_wtf import FlaskForm
from govuk_frontend_wtf.wtforms_widgets import GovRadioInput, GovSelect, GovSubmitInput
from govuk_frontend_wtf.wtforms_widgets import GovRadioInput, GovSubmitInput
from wtforms.fields import RadioField, SelectField, SubmitField
from wtforms.validators import AnyOf, InputRequired
from wtforms.validators import InputRequired


class CookiesForm(FlaskForm):
Expand All @@ -24,16 +24,15 @@ class CookiesForm(FlaskForm):

class DownloadForm(FlaskForm):
file_format = SelectField(
"File type",
widget=GovSelect(),
validators=[AnyOf(["json", "xlsx"])],
"Which format do you need?",
widget=GovRadioInput(),
choices=[
("xlsx", "XSLX (Excel)"),
("xlsx", "XLSX (Microsoft Excel)"),
("json", "JSON"),
],
default=None,
)
download = SubmitField("Download", widget=GovSubmitInput())
download = SubmitField("Confirm and request data", widget=GovSubmitInput())


class RetrieveForm(FlaskForm):
Expand Down
119 changes: 65 additions & 54 deletions app/main/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,65 +69,76 @@ def download():
)

if request.method == "POST":
file_format = form.file_format.data
if file_format not in ["json", "xlsx"]:
current_app.logger.error(
"Unexpected file format requested from /download: {file_format}",
extra=dict(file_format=file_format),
if form.validate_on_submit():
file_format = form.file_format.data
orgs = request.form.getlist(FormNames.ORGS)
regions = request.form.getlist(FormNames.REGIONS)
funds = request.form.getlist(FormNames.FUNDS)
outcome_categories = request.form.getlist(FormNames.OUTCOMES)
from_quarter = request.form.get("from-quarter")
from_year = request.form.get("from-year")
to_quarter = request.form.get("to-quarter")
to_year = request.form.get("to-year")

reporting_period_start = (
financial_quarter_from_mapping(quarter=from_quarter, year=from_year) if to_quarter and to_year else None
)
return abort(500), f"Unknown file format: {file_format}"

orgs = request.form.getlist(FormNames.ORGS)
regions = request.form.getlist(FormNames.REGIONS)
funds = request.form.getlist(FormNames.FUNDS)
outcome_categories = request.form.getlist(FormNames.OUTCOMES)
from_quarter = request.form.get("from-quarter")
from_year = request.form.get("from-year")
to_quarter = request.form.get("to-quarter")
to_year = request.form.get("to-year")

reporting_period_start = (
financial_quarter_from_mapping(quarter=from_quarter, year=from_year) if to_quarter and to_year else None
)

reporting_period_end = (
financial_quarter_to_mapping(quarter=to_quarter, year=to_year) if to_quarter and to_year else None
)
reporting_period_end = (
financial_quarter_to_mapping(quarter=to_quarter, year=to_year) if to_quarter and to_year else None
)

query_params = {"email_address": g.user.email, "file_format": file_format}
if orgs:
query_params["organisations"] = orgs
if regions:
query_params["regions"] = regions
if funds:
query_params["funds"] = funds
if outcome_categories:
query_params["outcome_categories"] = outcome_categories
if reporting_period_start:
query_params["rp_start"] = reporting_period_start
if reporting_period_end:
query_params["rp_end"] = reporting_period_end

status_code = process_async_download(query_params)

current_app.logger.info(
"Request for download by {user_id} with {query_params}",
extra={
"user_id": g.account_id,
"email": g.user.email,
"query_params": query_params,
"request_type": "download",
},
)

query_params = {"email_address": g.user.email, "file_format": file_format}
if orgs:
query_params["organisations"] = orgs
if regions:
query_params["regions"] = regions
if funds:
query_params["funds"] = funds
if outcome_categories:
query_params["outcome_categories"] = outcome_categories
if reporting_period_start:
query_params["rp_start"] = reporting_period_start
if reporting_period_end:
query_params["rp_end"] = reporting_period_end

status_code = process_async_download(query_params)

current_app.logger.info(
"Request for download by {user_id} with {query_params}",
extra={
"user_id": g.account_id,
"email": g.user.email,
"query_params": query_params,
"request_type": "download",
},
if status_code == 204:
return redirect(url_for("main.request_received"))
else:
current_app.logger.error(
"Response status code from data-store/trigger_async_download: {content_type}",
extra=dict(content_type=status_code),
)
return render_template("500.html")

current_app.logger.error(
"Unexpected file format requested from /download: {file_format}",
extra=dict(file_format=form.file_format),
)
if form.file_format.errors:
form.file_format.errors = ["Select a file format"]

if status_code == 204:
return redirect(url_for("main.request_received"))
else:
current_app.logger.error(
"Response status code from data-store/trigger_async_download: {content_type}",
extra=dict(content_type=status_code),
)
return render_template("500.html")
return render_template(
"download.html",
form=form,
funds=get_fund_checkboxes(),
regions=get_region_checkboxes(),
orgs=get_org_checkboxes(),
outcomes=get_outcome_checkboxes(),
returnsParams=get_returns(),
)


@bp.route("/request-received", methods=["GET"])
Expand Down
159 changes: 94 additions & 65 deletions app/templates/main/download.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
{%- from 'govuk_frontend_jinja/components/select/macro.html' import govukSelect -%}
{%- from 'govuk_frontend_jinja/components/button/macro.html' import govukButton -%}
{%- from 'govuk_frontend_jinja/components/label/macro.html' import govukLabel -%}
{%- from 'govuk_frontend_jinja/components/error-summary/macro.html' import govukErrorSummary -%}
{%- from "outcomeCheckboxes.html" import outcomeCheckboxItems -%}
{%- from "checkboxes.html" import checkboxItems -%}
{%- from "select.html" import selectItems -%}
Expand All @@ -14,74 +15,102 @@
{% endblock beforeContent %}

{% block content %}
<h1 class="govuk-heading-xl">Download monitoring and evaluation data</h1>
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
{% if form.errors %}
{{ govukErrorSummary ({
"titleText": "There is a problem",
"errorList": [
{
"text": "Select a file format",
"href": "#"+form.file_format.id
},

<p class="govuk-body">Use the following filters to select the projects you need.</p>
]
})
}}

<p class="govuk-body">The filters you select will be applied at project level. You will be able to download this as a file to your desktop.</p>
{% endif %}
<h1 class="govuk-heading-xl">Get monitoring and evaluation data</h1>
<p class="govuk-body">Use the filters to select the data you need.</p>
<p class="govuk-body">You will get all of the data from all projects and programmes if you do not select any filters.</p>
<form method="post" action="{{ url_for('main.download') }}">

<p class="govuk-inset-text">
If you don't select any filters you will get all the data from all of the projects that are in the system.
</p>
{{ form.csrf_token }}

<form method="post" action="{{ url_for('main.download') }}">
{{ form.csrf_token }}
{{ govukAccordion({
"id": "accordion-download",
"headingLevel": 2,
"showAllSectionsText": "",
"items": [
{
"heading": {
"text": "Filter by fund"
},
"content": {
"html": checkboxItems(funds["name"], funds["items"])
},
},
{
"heading": {
"text": "Filter by region"
},
"content": {
"html": checkboxItems(regions["name"], regions["items"])
}
},
{
"heading": {
"text": "Filter by funded organisation"
},
"content": {
"html": checkboxItems(orgs["name"], orgs["items"])
}
},
{
"heading": {
"text": "Filter by outcomes"
},
"content": {
"html": checkboxItems(outcomes["name"], outcomes["items"])
}
},
{
"heading": {
"text": "Filter by returns period"
},
"content": {
"html": selectItems(returnsParams)
}
}
]
})
}}
<div class="govuk-inset-text">
<p class="govuk-body">We will:</p>
<ul class="govuk-list govuk-list--bullet">
<li>send you an email to the address you’ve signed in with</li>
<li>include a link in the email for you to download your data</li>
</ul>
</div>
{{
form.file_format(
params={
"fieldset": {
"legend": {
"text": form.file_format.label.text,
"classes": "govuk-!-font-weight-bold"
},
}
}
)
}}
{{ form.download }}
</form>
<p class="govuk-body">
<a class="govuk-link govuk-link--no-visited-state" href="{{ url_for('main.data_glossary') }}">Access the funding glossary</a>
</p>
</div>
</div>

{{ govukAccordion({
"id": "accordion-download",
"headingLevel": 2,
"showAllSectionsText": "",
"items": [
{
"heading": {
"text": "Filter by fund"
},
"content": {
"html": checkboxItems(funds["name"], funds["items"])
},
},
{
"heading": {
"text": "Filter by region"
},
"content": {
"html": checkboxItems(regions["name"], regions["items"])
}
},
{
"heading": {
"text": "Filter by funded organisation"
},
"content": {
"html": checkboxItems(orgs["name"], orgs["items"])
}
},
{
"heading": {
"text": "Filter by outcomes"
},
"content": {
"html": checkboxItems(outcomes["name"], outcomes["items"])
}
},
{
"heading": {
"text": "Filter by returns period"
},
"content": {
"html": selectItems(returnsParams)
}
}
]
})
}}

{{ form.file_format }}
{{ form.download }}

</form>

<p class="govuk-body">
<a class="govuk-link govuk-link--no-visited-state" href="{{ url_for('main.data_glossary') }}">Access the funding glossary</a>
</p>
{% endblock content %}
42 changes: 30 additions & 12 deletions tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,41 @@ def test_async_download_redirect_error(flask_test_client, mocked_failing_downloa
assert b"Try again later." in response.data


def test_download_post_unknown_format(flask_test_client):
def test_download_post_unknown_format(flask_test_client, requests_mock):
requests_mock.get("http://data-store/organisations", json=[])
requests_mock.get("http://data-store/regions", json=[])
requests_mock.get("http://data-store/funds", json=[])
requests_mock.get("http://data-store/outcome-categories", json=[])
requests_mock.get(
"http://data-store/reporting-period-range",
json={"end_date": "2023-02-01T00:00:00Z", "start_date": "2023-02-12T00:00:00Z"},
)
response = flask_test_client.post("/download", data={"file_format": "foobar"})
assert response.status_code == 500

assert response.status_code == 200

def test_download_post_no_format(flask_test_client):
response = flask_test_client.post("/download")
assert response.status_code == 500
soup = BeautifulSoup(response.text, "html.parser")
error_summary = soup.find("p", {"class": "govuk-error-message"})
assert error_summary is not None
assert "Select a file format" in error_summary.text


@patch("app.main.download_data.get_response")
def test_download_post_unknown_format_from_api(mock_get_response, flask_test_client):
mock_response = mock_get_response.return_value
mock_response.headers = {"content-type": "InvalidType"}
def test_download_post_no_format(flask_test_client, requests_mock):
requests_mock.get("http://data-store/organisations", json=[])
requests_mock.get("http://data-store/regions", json=[])
requests_mock.get("http://data-store/funds", json=[])
requests_mock.get("http://data-store/outcome-categories", json=[])
requests_mock.get(
"http://data-store/reporting-period-range",
json={"end_date": "2023-02-01T00:00:00Z", "start_date": "2023-02-12T00:00:00Z"},
)
response = flask_test_client.post("/download", data={"file_format": " "})
assert response.headers["Content-Type"] == "text/html; charset=utf-8"
assert response.status_code == 200

response = flask_test_client.post("/download?file_format=anything")
assert response.status_code == 500
soup = BeautifulSoup(response.text, "html.parser")
error_summary = soup.find("p", {"class": "govuk-error-message"})
assert error_summary is not None
assert "Select a file format" in error_summary.text


def test_known_http_error_redirect(flask_test_client):
Expand Down

0 comments on commit 49444be

Please sign in to comment.