From 8e2cb66bf9c585eff8a6150ec9c2c444e1becabe Mon Sep 17 00:00:00 2001 From: Nuwan Samarasinghe Date: Tue, 4 Feb 2025 10:48:38 +0000 Subject: [PATCH] FS-5006: improvements for the all questions pages and here try to simplify the process fix all questions previews fix all questions previews --- app/all_questions/metadata_utils.py | 2 +- app/blueprints/application/routes.py | 6 +- app/blueprints/template/routes.py | 4 +- app/export_config/generate_all_questions.py | 150 +++++++++--------- app/export_config/generate_fund_round_html.py | 4 +- tests/test_config_export.py | 2 +- 6 files changed, 80 insertions(+), 88 deletions(-) diff --git a/app/all_questions/metadata_utils.py b/app/all_questions/metadata_utils.py index 3efccf06..2c6bbd75 100644 --- a/app/all_questions/metadata_utils.py +++ b/app/all_questions/metadata_utils.py @@ -376,7 +376,7 @@ def build_components_from_page( if "condition" in next_config and next_config["path"] != "/summary": condition_name = next_config["condition"] condition_config = next(fc for fc in form_conditions if fc["name"] == condition_name) - destination = index_of_printed_headers[next_config["path"]]["heading_number"] + destination = index_of_printed_headers[next_config["path"]]["title"] text_with_coordinators = "" for condition in [ cc for cc in condition_config["value"]["conditions"] if cc["field"]["name"] == c["name"] diff --git a/app/blueprints/application/routes.py b/app/blueprints/application/routes.py index 9d0edea1..0aa5cfa8 100644 --- a/app/blueprints/application/routes.py +++ b/app/blueprints/application/routes.py @@ -32,7 +32,7 @@ from app.db.queries.clone import clone_single_form from app.db.queries.fund import get_all_funds, get_fund_by_id from app.db.queries.round import get_round_by_id -from app.export_config.generate_all_questions import print_html +from app.export_config.generate_all_questions import generate_html from app.export_config.generate_assessment_config import ( generate_assessment_config_for_round, ) @@ -121,7 +121,7 @@ def view_all_questions(round_id): section_data, lang="en", ) - html = print_html(print_data) + html = generate_html(print_data) return render_template( "view_questions.html", round=round, @@ -263,7 +263,7 @@ def view_form_questions(round_id, section_id, form_id): section_data, lang="en", ) - html = print_html(print_data, True) + html = generate_html(print_data, True) return render_template( "view_questions.html", round=round, fund=fund, question_html=html, title=form.name_in_apply_json["en"] ) diff --git a/app/blueprints/template/routes.py b/app/blueprints/template/routes.py index fd382082..d5fabeea 100644 --- a/app/blueprints/template/routes.py +++ b/app/blueprints/template/routes.py @@ -13,7 +13,7 @@ get_form_by_template_name, update_form, ) -from app.export_config.generate_all_questions import print_html +from app.export_config.generate_all_questions import generate_html from app.export_config.generate_form import build_form_json from app.export_config.helpers import human_to_kebab_case from app.shared.helpers import flash_message @@ -96,7 +96,7 @@ def template_questions(form_id): section_data, lang="en", ) - html = print_html(print_data, False, False, False) + html = generate_html(print_data, False, False) return render_template("view_template_questions.html", question_html=html, form=form) diff --git a/app/export_config/generate_all_questions.py b/app/export_config/generate_all_questions.py index 279b397f..f1fadff5 100644 --- a/app/export_config/generate_all_questions.py +++ b/app/export_config/generate_all_questions.py @@ -1,9 +1,8 @@ -from airium import Airium # noqa: E402 +from airium import Airium -# Initialise Airium html printer -air = Airium() - -# Define start and end html +# -------------------------- +# Boilerplate HTML Templates +# -------------------------- BOILERPLATE_START = """ {% extends "apply/base.html" %} {%- from 'govuk_frontend_jinja/components/inset-text/macro.html' import govukInsetText -%} @@ -14,8 +13,7 @@ {% block content %}
- {% trans %}{{fund_title}}{% endtrans %} {% trans %}{{round_title}}{% endtrans %} - + {% trans %}{{fund_title}}{% endtrans %} {% trans %}{{round_title}}{% endtrans %}

{{pageHeading}}

""" @@ -26,14 +24,21 @@ """ -def print_html_toc(air: Airium, sections: dict): - """Prints a table of contents for the supplied sections to the supplied `Airium` instance - - Args: - air (Airium): Instance to write html to - sections (dict): Sections for this TOC +# -------------------------- +# Table of Contents Section +# -------------------------- +def generate_table_of_contents(air, sections): """ - with air.h2(klass="govuk-heading-m "): + Generates a table of contents from the given sections. + + Example Output: +

Table of contents

+
    +
  1. Section 1
  2. +
  3. Section 2
  4. +
+ """ + with air.h2(klass="govuk-heading-m"): air("Table of contents") with air.ol(klass="govuk-list govuk-list--number"): for anchor, details in sections.items(): @@ -42,92 +47,79 @@ def print_html_toc(air: Airium, sections: dict): air(details["title_text"]) -def print_components(air: Airium, components: list, show_field_types: bool = False): - """Prints the components within a page - - Args: - air (Airium): Instance to print html - components (list): List of components to print +# -------------------------- +# Component Rendering Section +# -------------------------- +def render_components(air, components, show_field_types=False): """ - for c in components: - # Print the title + Renders components within a page. + + Example Output: +
+

Component Title [Type]

+
    +
  • Bullet 1
  • +
  • Bullet 2
  • +
+

Some additional text.

+
+ """ + for component in components: with air.div(klass="govuk-body all-questions-component"): - if not c["hide_title"] and c["title"] is not None: + title = component.get("title") + if not component.get("hide_title") and title: with air.p(klass="govuk-body"): - air(f"{c['title']}") + air(title) if show_field_types: - air(f" [{c['type']}]") + air(f" [{component['type']}]") - for t in c["text"]: - # Print lists as
    bullet lists - if isinstance(t, list): + for text in component.get("text", []): + if isinstance(text, list): with air.ul(klass="govuk-list govuk-list--bullet"): - for bullet in t: - with air.li(klass=""): + for bullet in text: + with air.li(): air(bullet) else: - # Just print the text with air.p(klass="govuk-body"): - air(t) - - -def print_html(sections: dict, show_field_types=False, allow_table_of_content=True, allow_heading_number=True) -> str: - """Prints the HTML for the supplied sections - Args: - sections (dict): All sections to print, as generated by `metadata_utils.generate_print_data_for_sections` - Returns: - str: HTML string - :param sections : form sections - :param allow_heading_number: ignore the heading number - :param allow_table_of_content: ignore table of content - :param show_field_types: ignore field types + air(text) + + +# -------------------------- +# Main HTML Generation Section +# -------------------------- +def generate_html(sections, show_field_types=False, allow_table_of_content=True): + """ + Generates an HTML document for the given sections. + + Example Output: +

    1. Section 1 Title

    +

    1.1 Subheading

    +
    +

    Question Text

    +
    """ air = Airium() with air.div(klass="govuk-!-margin-bottom-8"): if allow_table_of_content: - # Print Table of Contents - print_html_toc(air, sections) - idx_section = 1 + generate_table_of_contents(air, sections) - for anchor, details in sections.items(): + for idx, (anchor, details) in enumerate(sections.items(), start=1): if anchor == "assessment_display_info": continue + air.hr(klass="govuk-section-break govuk-section-break--l govuk-section-break--visible") - # Print each section header, with anchor with air.h2(klass="govuk-heading-l", id=anchor): - air(f"{idx_section}. {details['title_text']}") - - form_print_data = details["form_print_data"] - # Sort in order of numbered headings - for heading in sorted( - form_print_data, - key=lambda item: str((form_print_data[item])["heading_number"]), - ): - header_info = form_print_data[heading] - # Print header for this form - if header_info["is_form_heading"]: - with air.h3(klass="govuk-heading-m"): - if allow_heading_number: - air(f"{header_info['heading_number']}. {header_info['title']}") - else: - air(header_info["title"]) + air(f"{idx}. {details['title_text']}") - else: - # Print header for this form page - with air.h4(klass="govuk-heading-s"): - if allow_heading_number: - air(f"{header_info['heading_number']}. {header_info['title']}") - else: - air(header_info["title"]) + for heading, header_info in sorted(details["form_print_data"].items(), + key=lambda item: str(item[1]["heading_number"])): + tag = "h3" if header_info["is_form_heading"] else "h4" + heading_text = header_info["title"] - # Print components within this form - print_components(air, header_info["components"], show_field_types) + with getattr(air, tag)(klass=f"govuk-heading-{'m' if tag == 'h3' else 's'}"): + air(heading_text) - idx_section += 1 + render_components(air, header_info["components"], show_field_types) - # Concatenate start html, generated html and end html to one string and return - # html = f"{BOILERPLATE_START}{str(air)}{BOILERPLATE_END}" return str(air) - # print(html) - # return html diff --git a/app/export_config/generate_fund_round_html.py b/app/export_config/generate_fund_round_html.py index 80a1961b..238e9811 100644 --- a/app/export_config/generate_fund_round_html.py +++ b/app/export_config/generate_fund_round_html.py @@ -3,7 +3,7 @@ from app.all_questions.metadata_utils import generate_print_data_for_sections from app.db.queries.fund import get_fund_by_id from app.db.queries.round import get_round_by_id -from app.export_config.generate_all_questions import print_html +from app.export_config.generate_all_questions import generate_html from app.export_config.generate_form import build_form_json from app.export_config.helpers import write_config @@ -68,7 +68,7 @@ def generate_all_round_html(round_id, base_output_dir=None): lang="en", ) html_content = frontend_html_prefix - html_content += print_html(print_data) + html_content += generate_html(print_data) html_content += frontend_html_suffix write_config( html_content, diff --git a/tests/test_config_export.py b/tests/test_config_export.py index 8c922316..dbdad69b 100644 --- a/tests/test_config_export.py +++ b/tests/test_config_export.py @@ -274,7 +274,7 @@ def test_generate_fund_round_html(seed_dynamic_data, temp_output_dir): / "html" / f"{fund_short_name.casefold()}_{round_short_name.casefold()}_all_questions_en.html", "expected_output": frontend_html_prefix - + '
    \n

    \n Table of contents\n

    \n
      \n
    1. \n \n Organisation Information\n \n
    2. \n
    \n
    \n

    \n 1. Organisation Information\n

    \n

    \n 1.1. About your organisation\n

    \n

    \n 1.1.1. Organisation Name\n

    \n
    \n

    \n What is your organisation\'s name?\n

    \n

    \n This must match the registered legal organisation name\n

    \n
    \n
    \n

    \n How is your organisation classified?\n

    \n
      \n
    • \n Charity\n
    • \n
    • \n Public Limited Company\n
    • \n
    \n
    \n
    ' # noqa: E501 + + '
    \n

    \n Table of contents\n

    \n
      \n
    1. \n \n Organisation Information\n \n
    2. \n
    \n
    \n

    \n 1. Organisation Information\n

    \n

    \n About your organisation\n

    \n

    \n Organisation Name\n

    \n
    \n

    \n What is your organisation\'s name?\n

    \n

    \n This must match the registered legal organisation name\n

    \n
    \n
    \n

    \n How is your organisation classified?\n

    \n
      \n
    • \n Charity\n
    • \n
    • \n Public Limited Company\n
    • \n
    \n
    \n
    ' # noqa: E501 + frontend_html_suffix, } ]