Skip to content

Conversation

@sanjeevz3009
Copy link
Contributor

@sanjeevz3009 sanjeevz3009 commented Jan 26, 2026

What is the context of this PR?

  • This PR is to enable digital publishing to lift and shift help (index) and information pages from the old world/legacy to the new Wagtail CMS.
  • This PR enhances, tweaks and updates the IndexPage and InformationPage models to meet the latest requirements from business and to align with the new UI designs for the help (index) and information pages.
  • This supports the proposed soft launch for help pages (phase 1).
  • To enable the moving of 6 help information pages from the legacy system to the new CMS.
  • To allow users to navigate in an accessible way to relevant child information pages on ‘Accessibility', ‘Browsers’, 'Cookies’, 'Privacy', 'Terms and Conditions', and 'Fair Use Policy'.

How to review

  • Carefully look through the ACs on the JIRA card and validate that this PR addresses all the business needs required for help pages, phase 1 launch.
  • Make sure the index and information page designs match. The design files are attached to the JIRA card.
  • Review the tests to ensure we have confidence in the changes.

Important

Review the two new migration files in this PR thoroughly.

Caution

When this PR gets merged -> deployed to Sandbox and Staging -> all Index and Information pages will get deleted.

Follow-up Actions

  • Deployment/ routing needs to be in place to make sure users are directed to the help page in Wagtail/ should be served from Wagtail, not the legacy world.
  • Sanity checks in Sandbox and Staging to validate everything is working as expected.

List any follow-up actions (if applicable), like needed documentation updates or additional testing.

…k created.

- CoreStoryBlock updated
- ONS Hero and Breadcrumbs added to index_page template
- Related links removed from index_page template
- InformationPage model updated to remove last_updated field, nested information pages, related pages.
- IndexPage model updated to remove content, related_links fields and featured_items
@sanjeevz3009 sanjeevz3009 added Enhancement Enhance the functionality of existing features. status: Needs tests status: In-progress labels Jan 26, 2026
@sanjeevz3009 sanjeevz3009 changed the title Feature/enable index info pages prod ready cms 880 Enhance Index & Information Pages For Production Jan 26, 2026
@sanjeevz3009
Copy link
Contributor Author

This PR is still being worked on. I will post an update once all the ACs on the JIRA card are covered, so devs can functionally test this and provide early feedback.

@sanjeevz3009 sanjeevz3009 marked this pull request as ready for review January 28, 2026 17:39
@sanjeevz3009 sanjeevz3009 requested a review from a team as a code owner January 28, 2026 17:39
…yBlock and removal of all information and index pages and tests updated to reflect this

- core/tests/test_blocks.py _make_information_page private method updated to reflect the new CoreStoryBlock changes
- core/private_media/tests/test_signal_handlers.py generate_non_media_referencing_content and generate_media_referencing_content updated to reflect the new CoreStoryBlock changes
- standard_pages/models.py InformationPage model cached_analytics_values property updated to be more defensive for NoneType errors
- standard_pages/tests/factories.py IndexPageFactory updated to reflect the new IndexModel page changes
- standard_pages/tests/factories.py InformationPageFactory updated to reflect the new InformationPage model changes
- taxonomy/tests/test_forms.py dropped due to the integration test complexity and brittle nature. This will be replaced by a UI test
- information.feature file updated to include a new draft scenario to replace the test_forms integration test
- standard_pages/tests/test_models.py setUpTestData IndexPageFactory arguments updated
- Redundant tests removed from InformationPageTestCase and IndexPageTestCase
- standard_pages/tests/test_pages.py DatePlaceholderTestCase removed due to the functionality being validated in the information_page.feature UI test and implicitly by other tests in the codebase
… to test the Index and Information page, creation and restriction logic
@MebinAbraham MebinAbraham changed the title Enhance Index & Information Pages For Production Enhance Index & Information Pages Jan 29, 2026
@sanjeevz3009
Copy link
Contributor Author

This PR is still being worked on. I will post an update once all the ACs on the JIRA card are covered, so devs can functionally test this and provide early feedback.

Update: More unit/ integration tests might be added, and UI tests are being fixed/ updated/ created.

Functionality is all ready, migration files are in place, existing unit/ integration tests are updated/ fixed to reflect the changes on the PR. Added new viewset tests for Index and Information page restriction logic around nested pages, etc.

…d to reflect the latest changes on the PR.

- Removal of checking for the date placeholder in Wagtail admin UI
- Fixed failing tests by updating the selectors in user_adds_info_page_contents and adding new checks to check for ToC etc
- page_editor.py and information_page.py updated to now include a check to validate the published date which is set automatically
"ariaLabel": toc_aria_label,
"itemsList": table_of_contents,
"button": {
"text": _("Save or print this page")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This string doesn't seem to be in our messages, we probably need to move it out of this structure so it gets picked up

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now digging a bit, I realised this pattern is used in the stats and methods page. So I was like, hmmm, maybe they don't appear in the .po file as well.

Then I realised I forgot to run make makemessages.

b485cf6

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.po file fixed fully. I got it to a weird/ brokenish state before. Done: af2530f

Comment on lines 9 to 22
{% if page.last_published_at %}
{%- set last_updated_label = _("Last updated:") -%}
{%- set last_updated_item = {
"term": last_updated_label,
"descriptions": [
{
"description": page.last_updated|ons_date("DATE_FORMAT")
"description": page.last_published_at|ons_date("DATE_FORMAT")
}
]
}
-%}
{% else %}
{%- set last_updated_item = None -%}
{% endif %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want to display this always on the preview of the very first draft; it would otherwise be omitted and could cause confusion. I suggest that if we don't have a date because it has never been published, we should default to a label like "Populated on publish."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, done: f7cd105

if hasattr(block.block, "to_table_of_contents_items"):
items += block.block.to_table_of_contents_items(block.value)
# TODO: Need to check the GTM stuff
# add_table_of_contents_gtm_attributes(items)
Copy link
Contributor

@MebinAbraham MebinAbraham Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be as-is. We maybe get some new needs, but we can follow up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: f7cd105

Comment on lines 81 to 82
# TODO: Confirm if the below content type is correct
search_index_content_type: ClassVar[str] = "static_landing_page"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not, but will be fixed by CMS-1007, so no changes needed in this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left an updated TODO, done: f7cd105


def test_index_page_cannot_have_index_page_child(self):
"""Home -> Index Page -> Index Page should be forbidden."""
index_page = IndexPageFactory()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move this in setUpTestData, and also define the "add info page under the index page" URL (reverse("wagtailadmin_pages:add", args=("standard_pages", "indexpage", index_page.pk))) there as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First part done: f7cd105

Second part, not sure I understand the value of defining the reverse URL in setUpTestData. I might be missing something obvious.

Scenario: The CMS user can see the date placeholder in the date field of the information page
When the user creates an information page as a child of the home page
Then the date placeholder "YYYY-MM-DD" is displayed in the "Last updated" textbox
# TODO: Write the step definitions and implementation for this scenario
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still to do

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: f7cd105

context.page.get_by_role("link", name="Test Info Page", exact=True).click()


def _get_information_page(context: Context) -> InformationPage | None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't say I agree with the approach here.

  1. page_id is generic, but this targets an info page. imho, you should make it more specific (i.e. information_page_id if going down this rout
  2. when no page id is in the context, you return the last published information page, but don't set the page id in the context. It may come in handy

I'd recommend switching the approach to rely on the specific page added to the context (that is context.information_page, context.statistical_article_page etc) which we use in several places

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update: ah, I see. this is set in functional_tests/steps/page_editor.py. Still feels a tad brittle

return [{"url": "#" + slugify(value["title"]), "text": value["title"]}]


class CoreSectionContentBlock(StreamBlock):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: now that this is here, should it not be defined before SectionContentBlock?

also, it would be nice to have the same order of the matching blocks, so they follow a predictable path.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aside: there is a case to be made for this to really live in the standard_pages app as that is the only one using it 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First question, first part: I have ordered the CoreSectionContentBlock in a way that is now it's consistent with SectionContentBlock. b437db8

First question, second part: I thought it made sense/ easier to read when the order goes SectionContentBlock then SectionBlock and CoreSectionContentBlock then CoreSectionBlock.

  • Happy to re-arrange the order if this is truly pressing.

The second question: Yes, it's only used in the standard_pages app, correct. Not sure if I want to move it, unless we know for sure, we aren't going to use this block anywhere else.

  • Maybe @MebinAbraham can shine some wisdom into what the future holds here.

"0003_topic_slug", # Ignoring NOT NULL constraint
"0007_rename_bundle_api_content_id_bundle_bundle_api_bundle_id", # Ignoring RENAMING constraint
"0010_rename_glossaryterm_to_definition", # Ignoring RENAMING table (GlossaryTerm -> Definition)
"0005_remove_indexpage_content_and_more", # Ignoring dropping fields
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do wonder if at this point the migration linter is more or less pointless. This is now 40 lines long 🙈

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had this exact conversation with @MebinAbraham when I had to add the above migration to the ignore_name.

As every once in a while, I question whether adding the migration linter is worth it with @AdamHawtin and @MebinAbraham. Andy also brought this concern up. The consensus from Adam, Mebin and me, or what puts me at bay from not pushing for removal, is that.

  1. These are just breaking changes. So once we go live, we shouldn’t have any of the migrations above ignored in theory. Mebin's comment.
  2. I think there are plans to remove the multiple migration files we have for each app into one via squashing, or I forgot the vision we had.
  3. The migration linter will be more useful and important once we go live.

We also wanted to write tests for the migrations also moving forward in the future (unrelated to the above issue raised).

I'll let @MebinAbraham share more wisdom here.

template = "templates/pages/information_page.html"

parent_page_types: ClassVar[list[str]] = ["home.HomePage", "InformationPage", "IndexPage"]
parent_page_types: ClassVar[list[str]] = ["home.HomePage", "IndexPage"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not find this in the requirements - any chance you can point me to them? Arguably a "process" page under "about us" could be valid

Copy link
Contributor Author

@sanjeevz3009 sanjeevz3009 Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: Information pages should still be able to be created under index pages and the top level of the site (Home) due to unknown business needs in this area currently.

-Index can contain informationpages only

-Information pages can be created under a home page or an index page only

Decision log: https://officefornationalstatistics.atlassian.net/wiki/x/IwGsD

Changed nesting rules to Home>Index>Information or Home>Information (captured on card CMS-880)

This was decided in refinement + business signed off. This was because there was no need for a nested index or information pages for phase 1. Maybe there is a need post phase 1, but currently not. It was decided that we can turn it back on if and when needed.

For now, this reduces all the possible positive paths we need to test, etc.

@@ -1,91 +0,0 @@
import http
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: why remove this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is following up on a conversation @AdamHawtin and I had about how we don't want to write integration tests like this. It's unreadable and seems brittle.

To my point, I realised now our de-duplication functionality regressed and doesn't work for de-duplicating the taxonomy topics. This test didn't catch that anyway. I wrote this at early days of onboarding the team, so we did intend on removing this.

This is now replaced by more readable + reliable UI test here: #475 (comment)

I will create a bug card or do a follow-up to fix the de-duplication functionality for taxonomy topics (as that was a feature Adam thought of and we added out of an initiative to improve the UX).

- information_page.py check_information_page_content updated to reflect the latest information_page template changes + enhanced to test Welsh content further such as the ToC
- localisation.py check_new_information_is_displayed_with_welsh_content selectors updated
…age has no live version, InformationPage model ToC has the gtm attributes adding enabled, de-duplication UI test added to test the de-duplication functionality (currently not working as expected/ regressed).

- .po file blank line added
- standard_pages/models.py TODOs updated
- standard_pages/tests/test_viewsets.py refactored
- functional_tests/step_helpers/topic_page_utils.py updated to reflect the extraction of the method get_or_create_topic
- functional_tests/step_helpers/utils.py updated to include get_or_create_topic function so it can be used anywhere for UI testing purposes
- information_page.py updated to include the step definitions needed for the de-duplication UI scenario
- page_editor.py updated to include a step to add/ create taxonomy topics
- topic_page.py updated to reflect the extracted get_or_create_topic method into the utils.py file
… scenario and CoreSectionContentBlock blocks re-ordered to align with SectionContentBlock.
…he index page auto population of info pages mechanism.

- factories and step file updated to reflect the changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement Enhance the functionality of existing features.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants