diff --git a/package.json b/package.json index d6512fb1..3a557df5 100644 --- a/package.json +++ b/package.json @@ -91,5 +91,8 @@ "husky": "^8.0.1", "lint-staged": "^13.0.3", "prettier": "^2.7.1" + }, + "volta": { + "node": "16.20.1" } } diff --git a/public/static/questionnaire/famille/data.json b/public/static/questionnaire/famille/data.json index ea67dc4f..b081e9ae 100644 --- a/public/static/questionnaire/famille/data.json +++ b/public/static/questionnaire/famille/data.json @@ -3661,6 +3661,6 @@ "stateData": { "state": "INIT", "date": 1668677099410, - "currentPage": "2" + "currentPage": "2.1#1" } } diff --git a/src/components/genericPages/end.js b/src/components/genericPages/end.js index 7e399649..8246797c 100644 --- a/src/components/genericPages/end.js +++ b/src/components/genericPages/end.js @@ -1,3 +1,4 @@ +import { interpret } from '@inseefr/trevas'; import Button from '@material-ui/core/Button'; import Card from '@material-ui/core/Card'; import CardActions from '@material-ui/core/CardActions'; @@ -6,15 +7,14 @@ import CardHeader from '@material-ui/core/CardHeader'; import Divider from '@material-ui/core/Divider'; import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; -import React from 'react'; - -import { interpret } from '@inseefr/trevas'; import { GetApp } from '@material-ui/icons'; import { format, formatDistance } from 'date-fns'; +import React from 'react'; import { useLocation, useParams } from 'react-router-dom'; import { buttonDictionary, endPageDictionary } from '../../i18n'; import { SIMPLE_CLICK_EVENT, paradataHandler } from '../../utils/events'; import { useAPI } from '../../utils/hooks'; +import { END_PAGE } from '../../utils/pagination'; import { buildBuidings, dateFnsLocal, @@ -44,7 +44,6 @@ const EndPage = ({ metadata: { inseeContext, variables, genericPages }, personalization, stateData: { date }, - currentPage, }) => { const classes = useStyles(); @@ -52,7 +51,7 @@ const EndPage = ({ return { ...SIMPLE_CLICK_EVENT, idParadataObject: `${type}-button`, - page: currentPage, + page: END_PAGE, }; }; const finalDate = date || 0; diff --git a/src/components/genericPages/validation.js b/src/components/genericPages/validation.js index b6c6c75d..d3334486 100644 --- a/src/components/genericPages/validation.js +++ b/src/components/genericPages/validation.js @@ -8,6 +8,7 @@ import Send from '@material-ui/icons/Send'; import React from 'react'; import { buttonDictionary, validationPageDictionary } from '../../i18n'; import { SIMPLE_CLICK_EVENT, paradataHandler } from '../../utils/events'; +import { VALIDATION_PAGE } from '../../utils/pagination'; import { MarkdownTypo } from '../designSystem'; const useStyles = makeStyles((theme) => ({ @@ -25,7 +26,6 @@ const useStyles = makeStyles((theme) => ({ const ValidationPage = ({ metadata: { inseeContext, genericPages }, setValidationConfirmation, - currentPage, }) => { const classes = useStyles(); const { title, body } = @@ -33,7 +33,7 @@ const ValidationPage = ({ const utilInfo = { ...SIMPLE_CLICK_EVENT, idParadataObject: 'validate-button', - page: currentPage, + page: VALIDATION_PAGE, }; return ( diff --git a/src/components/modals/welcomeBack/welcomeBack.js b/src/components/modals/welcomeBack/welcomeBack.js index d9e391d2..869d6208 100644 --- a/src/components/modals/welcomeBack/welcomeBack.js +++ b/src/components/modals/welcomeBack/welcomeBack.js @@ -13,13 +13,14 @@ const utilInfo = (type) => { }; }; -const WelcomeBack = ({ open, setOpen, goToFirstPage }) => { +const WelcomeBack = ({ open, setOpen, goToFirstPage, goBackToSavedPage }) => { const goToCurrentPage = () => { + goBackToSavedPage?.(); setOpen(false); }; const goToFirst = () => { - goToFirstPage(); + goToFirstPage?.(); setOpen(false); }; diff --git a/src/components/orchestrator/collector/index.js b/src/components/orchestrator/collector/index.js index 618f7770..cf45e536 100644 --- a/src/components/orchestrator/collector/index.js +++ b/src/components/orchestrator/collector/index.js @@ -2,10 +2,11 @@ import * as lunatic from '@inseefr/lunatic'; import Card from '@material-ui/core/Card'; import Container from '@material-ui/core/Container'; import { makeStyles } from '@material-ui/core/styles'; -import { memo, useCallback, useEffect, useRef, useState } from 'react'; +import { memo, useCallback, useMemo, useRef, useState } from 'react'; import { simpleLog } from '../../../utils/events'; import { END_PAGE, + FORM_PAGE, VALIDATION_PAGE, WELCOME_PAGE, isLunaticPage, @@ -43,7 +44,6 @@ const OrchestratorComponent = ({ const [validationConfirmation, setValidationConfirmation] = useState(false); const { stateData, data, personalization } = stromaeData; - const [currentStateData, setCurrentStateData] = useState(stateData); const [validated, setValidated] = useState( stateData && @@ -51,13 +51,11 @@ const OrchestratorComponent = ({ stateData.state === 'EXTRACTED' || stateData.state === 'TOEXTRACT') ); - - const logFunction = (e) => simpleLog({ ...e, page: currentPage }); const { getComponents, waiting, pageTag, - pager: { page }, + goToPage, goNextPage, goPreviousPage, isFirstPage, @@ -65,8 +63,6 @@ const OrchestratorComponent = ({ compileControls, getData, } = lunatic.useLunatic(source, data, { - // ToDo : initial page - //initialPage, features, preferences, autoSuggesterLoading, @@ -74,28 +70,38 @@ const OrchestratorComponent = ({ activeControls, }); - const components = getComponents(); + const logFunction = (e) => simpleLog({ ...e, page: currentPage }); + + // Control whether to display the modal to go back to the previous state + const showBackModal = !init && !validated && !!stateData?.currentPage; - const [currentPage, setCurrentPage] = useState(() => { - if (validated) return END_PAGE; + // Indicate in which state the orchestrator is, with stromae we need a welcome page before the form and an end page after + const [orchestratorState, setOrchestratorState] = useState(() => { + if (validated) { + return END_PAGE; + } + if (showBackModal) { + return WELCOME_PAGE; + } if (stateData?.currentPage) { - return page; + return FORM_PAGE; } return WELCOME_PAGE; }); - const updateStateData = useCallback( - (newState) => { - const newStateData = { - state: newState ?? INIT, - date: new Date().getTime(), - currentPage: currentPage, - }; - setCurrentStateData(newStateData); - return newStateData; - }, - [currentPage] + const currentStateData = useMemo( + () => ({ + state: orchestratorState === END_PAGE ? VALIDATED : INIT, + date: new Date().getTime(), + currentPage: + orchestratorState === FORM_PAGE ? pageTag : orchestratorState, + }), + [pageTag, orchestratorState] ); + const currentPage = + orchestratorState === FORM_PAGE ? pageTag : orchestratorState; + + const components = getComponents(); const logoutAndClose = async () => { let dataToSave = { stateData: currentStateData, data: getData() }; @@ -105,8 +111,9 @@ const OrchestratorComponent = ({ quit(dataToSave); }; + // Scroll at the top of the form const goToTop = () => { - if (topRef && topRef.current) { + if (topRef.current) { topRef.current.tabIndex = -1; topRef.current.focus(); topRef.current.blur(); @@ -116,13 +123,7 @@ const OrchestratorComponent = ({ }; const validateQuestionnaire = () => { setValidated(true); - const validateUpdateState = updateStateData(VALIDATED); - const dataToSave = { - stateData: validateUpdateState, - data: getData(), - }; - save(dataToSave); - setCurrentPage(END_PAGE); + setOrchestratorState(END_PAGE); }; const [errorActive, setErrorActive] = useState({}); @@ -146,53 +147,53 @@ const OrchestratorComponent = ({ const onNext = useCallback( (event, skipValidation = false) => { closeErrorsModal(); - if (currentPage === WELCOME_PAGE) setCurrentPage(page); - else { - const onNextUpdateState = updateStateData(); - const dataToSave = { - stateData: onNextUpdateState, - data: getData(), - }; + if (orchestratorState === WELCOME_PAGE) { + setOrchestratorState(FORM_PAGE); + } else { if (!isLastPage) { if (isNewSequence(components)) { + let dataToSave = { stateData: currentStateData, data: getData() }; save(dataToSave); } handleGoNext(skipValidation, goNextPage); } else { - save(dataToSave); - handleGoNext(skipValidation, () => setCurrentPage(VALIDATION_PAGE)); + handleGoNext(skipValidation, () => + setOrchestratorState(VALIDATION_PAGE) + ); } } goToTop(); }, [ closeErrorsModal, + orchestratorState, + isLastPage, components, - currentPage, - getData, - goNextPage, handleGoNext, - isLastPage, - page, + goNextPage, + currentStateData, + getData, save, - updateStateData, ] ); const onPrevious = () => { - if (currentPage === VALIDATION_PAGE) setCurrentPage(page); + if (orchestratorState === VALIDATION_PAGE) setOrchestratorState(FORM_PAGE); else { if (!isFirstPage) goPreviousPage(); - else setCurrentPage(WELCOME_PAGE); + else setOrchestratorState(WELCOME_PAGE); } }; - useEffect(() => { - if (isLunaticPage(currentPage)) { - setCurrentPage(page); + const restoreSavedPage = () => { + // stateData currentPage can be "welcomePage" instead of a normal page number + if (isLunaticPage(stateData?.currentPage)) { + goToPage({ page: stateData?.currentPage }); + setOrchestratorState(FORM_PAGE); + } else { + setOrchestratorState(stateData?.currentPage); } - }, [currentPage, page]); - + }; const lunaticDisplay = () => ( - {currentPage === WELCOME_PAGE && ( + {orchestratorState === WELCOME_PAGE && ( )} - {isLunaticPage(currentPage) && lunaticDisplay()} - {currentPage === VALIDATION_PAGE && ( + {orchestratorState === FORM_PAGE && lunaticDisplay()} + {orchestratorState === VALIDATION_PAGE && ( )} - {currentPage === END_PAGE && ( + {orchestratorState === END_PAGE && ( )} @@ -281,11 +280,9 @@ const OrchestratorComponent = ({ /> )} setInit(!o)} - goToFirstPage={() => { - setCurrentPage(WELCOME_PAGE); - }} + goBackToSavedPage={restoreSavedPage} /> - ![WELCOME_PAGE, VALIDATION_PAGE, END_PAGE].includes(page); + page && ![WELCOME_PAGE, VALIDATION_PAGE, END_PAGE].includes(page); diff --git a/yarn.lock b/yarn.lock index fa2ef515..65a278f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2390,10 +2390,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== -"@inseefr/lunatic@2.4.9": - version "2.4.9" - resolved "https://registry.yarnpkg.com/@inseefr/lunatic/-/lunatic-2.4.9.tgz#788892acc94e3a52dd4f1b4a02ea702b2ab4405f" - integrity sha512-qQDnARkPVHjMD/xlIRVPdizTjqZKNFT9Ws4P9Yy6hfEELnOrUemMBgKqmydiHazNhYX4BN5Kdn1dn0AbfBCYjQ== +"@inseefr/lunatic@2.4.7-gotopage": + version "2.4.7-gotopage" + resolved "https://registry.yarnpkg.com/@inseefr/lunatic/-/lunatic-2.4.7-gotopage.tgz#ec5dab8ba21a2bc59997854f53c5b56829a2f2a4" + integrity sha512-MmhQHVkHu50ZYoxBz+iNXvw/wfYnvpcjmOw7Su7BJZVpMS1j5p+b5t7MKuO7zIhmq4+dYE9yXfyxy5ds/FFDgA== dependencies: "@inseefr/trevas" "^0.1.17" "@inseefr/vtl-2.0-antlr-tools" "^0.1.0-bundle"