-
Notifications
You must be signed in to change notification settings - Fork 7
Spike adding field validation UI feedback
There is a requirement to prevent surveys launching when there are still validation errors.
https://trello.com/c/7DKHeOHG/1067-spike-validator-question-title-1-day
This spike will investigate a possible approach and provide a PoC. This builds on a previous investigative spike: https://github.com/ONSdigital/eq-author-app/wiki/Validation-for-Authors-Spike and is based on prototype https://author.netlify.com/#/eq-author/
The PoC is on this branch: https://github.com/ONSdigital/eq-author-app/compare/1067-spike-validator-question-title-1-day
Specifically, we need to address:
- How error validations should be represented in the schema
- How a page/answer decides if something is invalid
- How a question page calculates & displays the total number of errors
- How a new question page is identified - a newly created page doesn't immediately show validation errors
- How a new answer is identified - a newly created answer doesn't immediately show validation errors
- How the Launch Survey button is only enabled when there are no validation errors
A previous spike https://github.com/ONSdigital/eq-author-app/wiki/Validation-for-Authors-Spike and is based on prototype https://author.netlify.com/#/eq-author/ looked at different approaches to storing the validation. Two options considered are:
- Raise an Error when invalid data submitted - this prevents invalid data from being stored. Not technically what we want as we need the user to be able to save invalid data, just not to be able to launch a survey
- Create a validationError property on the question/answer objects - this allows invalid data to be saved and relies on UI to report on validation errors
A new GraphQL fragment has been created to represent validation errors:
fragment ValidationErrorInfo on QuestionPage {
validationErrorInfo {
errors {
field
message
},
totalCount
}
}
where totalCount = number of errors on page + child answers.
This is calculated in the question page resolver on api. Logic is currently done within component but possible rule engine or separate component would be more beneficial?
const questionPageValidation = page => {
const errors = [];
/* Page validation done here - maybe a better way of doing it? Rule engine, separate component? */
if (!page.title) {
errors.push({
field: "title",
message: "Question title is required",
});
}
// Add total answer validation errors
const answerErrorCount = page.answers.reduce((acc, answer) => {
return answer.validationErrorInfo && answer.validationErrorInfo.totalCount
? acc + answer.validationErrorInfo.totalCount
: acc;
}, 0);
return {
errors,
totalCount: errors.length + answerErrorCount,
};
};
Resolvers.QuestionPage = {
...
validationErrorInfo: page => questionPageValidation(page),
}
The totalCount property calculated in 2. above contains the total number of validation errors on the question page. Adding the validationErrorInfo property to graphql query pageNavItem will return total error count in page
UnwrappedPageNavItem.fragments = {
...
validationErrorInfo {
totalCount
}
eq-author/src/App/QuestionnaireDesignPage/NavigationSidebar/PageNavItem.js
- How a new question page is identified - a newly created page doesn't immediately show validation errors A newly created question page does not show the validation errors immediately so we need to identify it's new. Author uses a mutation to create a page and then redirects to get then queries for newly created page. This means author has no way of identifying the page requested is new.
By adding a parameter (or route param) to the redirect we can identify a new page In the buildPath method we add a new constant QUESTIONNAIRE_NEW and redirect to that if a newPage parameter has been passed to it:
QUESTIONNAIRE: `/q/:questionnaireId/:entityName?/:entityId?/:tab?`,
QUESTIONNAIRE_NEW: `/q/:questionnaireId/:entityName?/:entityId?/:tab??new=1`,
const route = newPage ? Routes.QUESTIONNAIRE_NEW : Routes.QUESTIONNAIRE;
return generatePath(route)({
...
}