Validate each document tab form separately [WHIT-3214]#11436
Open
eYinka wants to merge 8 commits into
Open
Conversation
8644b69 to
afd0dfb
Compare
In Standard Edition model, we have these association checks: - `organisation_association_enabled` - `worldwide_organisation_association_required?` - `world_location_association_required?` And they are responsible for enabling validations on their associated fields each time an edition is updated. They now return false if the field in question doesn't belong to the current tab context (i.e If you're on a different tab that doesn't include the associated fields). I've added `current_tab_context_includes_field?` to centralise that check.
Introducing a form object that validates a single tab's fields in isolation. It separates block_content fields (which are validated via a scoped BlockContent) from edition attribute fields. Edition attribute fields in this context are fields that are meant to be validated on the edition. Rather than duplicating code to represent them specially for standard edition, we handle their validation by running `edition.valid?` under a temporary tab context, then cherry-picking only that tab's errors for displaying to the user later. This is the core of the per-tab validation feature and should be hopefully sufficient for what we need. **Note:** The inclusion of `ADDITIONAL_DEFAULT_TAB_FIELDS` brings a question for future work. We should be looking at including `title` and `summary` in the document's tab schema of each configurable document type.
We needed a way to validate only a part of an edition, in the case of config-driven form tabs i.e when a user is saving data on a particular tab, they should only see errors related to that tab. Consequently, we will need to skip the full edition validation when patching up that chunk of the edition. Rails allows us to specify options like `validate: false` to do that. This commit prepares the save handler to accept such options.
7fec067 to
e20c4bf
Compare
When a tab context is present (i.e. user is saving a non-document tab), validate only that tab's fields via TabForm form object instead of running full edition validation. On success, we call save with `validate: false`. On failure, we simply copy tab errors onto `@edition.errors` so that the existing error summary component displays them correctly. For the non-tab pages, fall back to the parent controller's handler and run full validation.
This will be useful in future commit to iterate over a configurable document's form tabs
Now, we compute which tabs are invalid and surface them through to the sidebar component. The sidebar will list every invalid tab as links rather than a flat list of errors for StandardEditions. I've also added a hint text to the preview edition component to let publishers know that the preview of an edition "may be out of date" if any tab is invalid; as we will not send an edition in bad state to publishing API.
The Document tab nav item was only highlighted when current_tab was nil. Passing `?current_tab=documents` (e.g. from an error link) left it non-highlighted. I've added `on_default_tab` which is true when `current_tab` is either nil (implicitly defaults to documents tab at the moment) or equals `edition.default_tab`, so both forms of "on the default tab" are handled.
We have agreed to only send a globally valid edition to Publishing API. In that sense, the Edition Publisher and Edition Scheduler services now collect each tab's failure reasons (e.g. "Social media accounts tab is invalid") so publishers see useful messages rather than a generic one. Consequently, the Draft Edition Updater service skips pushing to Publishing API if any tab is invalid.
e20c4bf to
eb62998
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Move the edition validation off of the edition model on to the configurable form object, and validate each form independently. Make sure that all forms are validated before the edition can be published.
In the scope of this implementation:
Why
Visual Changes
Testing
Experiencing the full benefit of this work is tricky, because you will almost never have a saved multi-tab edition in bad state unless you manually manipulate the data.
Currently, the only way to access dynamic tabs is by saving the document tab first, which means the draft is fully valid before any subsequent updates can be made. Therefore, it's not inherently clear that we are scoping validations per tab.
For anyone that wants to give it a go locally, an easy way is to configure a document type (like topical event) with
"send_change_history": true, then:Future Improvements:
validate_block_contentandscoped_block_contentfrom has_block_content.rb.TabForm will then be the single point for handling all
block_contentvalidation. For now, it's fine to keep the validation in both places because not all tabs are currently fully config-driven, andedition.valid?is called in several places that don't go through TabForm.titleandsummaryto the documents schema of all config driven document typeslabelto each form in document type configurations./standard-editions/:id/editand/standard-editions/:id/edit?current_tab=documents. The latter is necessary for validating only the documents tab while the former will assume full edition validation.JIRA
This application is owned by the Whitehall Experience team. Please let us know in #govuk-whitehall-experience-tech when you raise any PRs.
Follow these steps if you are doing a Rails upgrade.