diff --git a/queen-v2/src/components/orchestrator/breadcrumb/component.js b/queen-v2/src/components/orchestrator/breadcrumb/component.js
deleted file mode 100644
index 8bad6362..00000000
--- a/queen-v2/src/components/orchestrator/breadcrumb/component.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import React, { useContext } from 'react';
-import PropTypes from 'prop-types';
-import D from 'i18n';
-import { useStyles } from './component.style';
-import { getIterations } from 'utils/questionnaire';
-import { OrchestratorContext } from '../queen';
-
-const getNewPage = page => iterations => {
- if (page.includes('.')) {
- const [root, ...rest] = page.split('.');
- return `${root}.${rest.map((p, i) => `${p}#${iterations[i]}`).join('.')}`;
- }
- return page;
-};
-
-const hasToBlock = (prevProps, nextProps) => {
- const prevSubseqId = prevProps?.subsequence?.id;
- const prevSeqId = prevProps?.sequence?.id;
- const nextSubseqId = nextProps?.subsequence?.id;
- const nextSeqId = nextProps?.sequence?.id;
- const prevPage = prevProps?.currentPage;
- const nextPage = nextProps?.currentPage;
- return prevSeqId === nextSeqId && prevSubseqId === nextSubseqId && prevPage === nextPage;
-};
-
-const BreadcrumbQueen = ({ sequence, subsequence, currentPage }) => {
- const { setPage } = useContext(OrchestratorContext);
- const classes = useStyles({ sequence, subsequence });
- const changePage = page => {
- const iterations = getIterations(currentPage);
- const newPage = getNewPage(page)(iterations);
- setPage(newPage);
- };
-
- return (
-
-
-
- {subsequence && subsequence.label && (
-
- )}
-
-
- );
-};
-
-BreadcrumbQueen.propTypes = {
- sequence: PropTypes.shape({
- label: PropTypes.string,
- page: PropTypes.string,
- }).isRequired,
- subsequence: PropTypes.shape({
- label: PropTypes.string,
- page: PropTypes.string,
- }),
- currentPage: PropTypes.string.isRequired,
-};
-
-BreadcrumbQueen.defaultProps = {
- subsequence: null,
-};
-
-export default React.memo(BreadcrumbQueen, hasToBlock);
diff --git a/queen-v2/src/components/orchestrator/breadcrumb/component.style.js b/queen-v2/src/components/orchestrator/breadcrumb/component.style.js
deleted file mode 100644
index e4aaf04d..00000000
--- a/queen-v2/src/components/orchestrator/breadcrumb/component.style.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import { makeStyles } from '@material-ui/core';
-
-export const useStyles = makeStyles(theme => ({
- root: props => ({
- paddingBottom: `${!props.subsequence ? '3px' : '0px'}`,
- borderBottom: `${!props.subsequence ? `${theme.palette.declarations.main} 2px solid` : ''}`,
- width: 'max-content',
- color: 'black',
- marginTop: '0.3em',
- }),
-
- breadcrumbButton: {
- cursor: 'pointer',
- backgroundColor: 'transparent',
- border: 'none',
- textTransform: 'uppercase',
- fontSize: '95%',
- '&:hover': {
- fontWeight: 'bold',
- },
-
- '&::before': {
- content: "'\u3009'",
- marginRight: '0.8em',
- fontWeight: 'bold',
- },
- },
-
- subsequenceButton: {
- '&::before': {
- content: "'\u3009'",
- marginRight: '0.8em',
- fontWeight: 'bold',
- },
-
- marginLeft: '0.8em',
- display: 'inline',
- paddingBottom: '3px',
- borderBottom: `${theme.palette.declarations.main} 2px solid`,
- },
-}));
diff --git a/queen-v2/src/components/orchestrator/breadcrumb/index.js b/queen-v2/src/components/orchestrator/breadcrumb/index.js
deleted file mode 100644
index b404d7fd..00000000
--- a/queen-v2/src/components/orchestrator/breadcrumb/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './component';
diff --git a/queen-v2/src/components/orchestrator/buttons/component.js b/queen-v2/src/components/orchestrator/buttons/component.js
deleted file mode 100644
index e09b9c68..00000000
--- a/queen-v2/src/components/orchestrator/buttons/component.js
+++ /dev/null
@@ -1,138 +0,0 @@
-import React, { useContext, useEffect, useRef, useState } from 'react';
-import KeyboardEventHandler from 'react-keyboard-event-handler';
-import PropTypes from 'prop-types';
-import D from 'i18n';
-import { useStyles } from './component.style';
-import { Button, IconButton } from 'components/designSystem';
-import { PlayArrow, SkipNext } from '@material-ui/icons';
-import { OrchestratorContext } from '../queen';
-
-const skipNextIcon =
;
-
-const Buttons = ({ rereading, setPendingChangePage }) => {
- const { readonly, page, isFirstPage, isLastPage } = useContext(OrchestratorContext);
-
- const classes = useStyles();
-
- const previousButtonRef = useRef();
- const nextButtonRef = useRef();
- const fastNextButtonRef = useRef();
- const returnLabel = isFirstPage ? '' : D.goBackReturn;
-
- const keysToHandle = ['alt+enter', 'alt+backspace', 'alt+end'];
-
- const [focusPrevious, setFocusPrevious] = useState(false);
- const [focusNext, setFocusNext] = useState(false);
- const [focusFastForward, setFocusFastForward] = useState(false);
-
- const onfocusPrevious = value => () => setFocusPrevious(value);
- const onfocusNext = value => () => setFocusNext(value);
- const onfocusFastForward = value => () => setFocusFastForward(value);
-
- const [pageChanging, setPageChanging] = useState(false);
-
- const localPagePrevious = () => setPageChanging('previous');
- const localPageNext = () => setPageChanging('next');
- const localPageFastForward = () => setPageChanging('fastForward');
-
- useEffect(() => {
- setPageChanging(false);
- }, [page]);
-
- const keyboardShortcut = (key, e) => {
- e.preventDefault();
- if (key === 'alt+enter' && ((!isLastPage && rereading) || readonly)) {
- if (nextButtonRef && nextButtonRef.current) {
- nextButtonRef.current.focus();
- localPageNext();
- }
- }
- if (key === 'alt+backspace' && !isFirstPage) {
- if (previousButtonRef && previousButtonRef.current) {
- previousButtonRef.current.focus();
- localPagePrevious();
- }
- }
- if (key === 'alt+end' && !readonly && rereading && !isLastPage) {
- if (fastNextButtonRef && fastNextButtonRef.current) {
- fastNextButtonRef.current.focus();
- localPageFastForward();
- }
- }
- };
-
- useEffect(() => {
- if ((focusNext || focusFastForward || focusPrevious) && pageChanging) {
- setPendingChangePage(pageChanging);
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [pageChanging, setPendingChangePage]);
-
- return (
- <>
-
-
- >
- );
-};
-
-Buttons.propTypes = {
- rereading: PropTypes.bool.isRequired,
- setPendingChangePage: PropTypes.func.isRequired,
-};
-
-export default React.memo(Buttons);
diff --git a/queen-v2/src/components/orchestrator/buttons/component.style.js b/queen-v2/src/components/orchestrator/buttons/component.style.js
deleted file mode 100644
index d471d902..00000000
--- a/queen-v2/src/components/orchestrator/buttons/component.style.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import { makeStyles } from '@material-ui/core';
-
-export const useStyles = makeStyles(theme => ({
- root: {
- position: 'absolute',
- paddingRight: '15%',
- bottom: 0,
- right: 0,
- display: 'grid',
- margin: 'auto',
- whiteSpace: 'nowrap',
- gridTemplateRows: '60px 60px 60px',
- },
-
- shortButtonSpan: {
- color: '#777777',
- fontSize: '13px',
- display: 'block',
- width: 'min-content',
- marginLeft: 'auto',
- },
-
- nextButton: { gridRowStart: 2, gridRowEnd: 2 },
- fastButtonWrapper: { gridRowStart: 3, gridRowEnd: 3 },
- fastButton: { borderRadius: '15px', fontSize: '95%' },
-
- fastButtonSpan: { display: 'block', fontSize: '68%' },
-
- navigation: { textAlign: 'right' },
-
- previousIcon: { transform: 'rotate(180deg)' },
-}));
diff --git a/queen-v2/src/components/orchestrator/buttons/continue/continue.style.js b/queen-v2/src/components/orchestrator/buttons/continue/continue.style.js
deleted file mode 100644
index d5bf20cb..00000000
--- a/queen-v2/src/components/orchestrator/buttons/continue/continue.style.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { makeStyles } from '@material-ui/core';
-
-export const useStyles = makeStyles({
- root: { width: 'auto' },
- wrapperButton: { textAlign: 'right', marginRight: '8em' },
- labelHelp: { fontSize: '84%' },
- help: { fontSize: '72%', color: '#777777' },
-});
diff --git a/queen-v2/src/components/orchestrator/buttons/continue/index.js b/queen-v2/src/components/orchestrator/buttons/continue/index.js
deleted file mode 100644
index 6f82f30a..00000000
--- a/queen-v2/src/components/orchestrator/buttons/continue/index.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import React, { useContext, useEffect, useRef, useState } from 'react';
-import KeyboardEventHandler from 'react-keyboard-event-handler';
-import { ArrowRightAlt } from '@material-ui/icons';
-import { Button } from 'components/designSystem';
-import PropTypes from 'prop-types';
-import D from 'i18n';
-import { useStyles } from './continue.style';
-import { OrchestratorContext } from 'components/orchestrator/queen';
-import { paradataHandler, SIMPLE_CLICK_EVENT } from 'utils/events';
-
-const ButtonContinue = ({ setPendingChangePage }) => {
- const { readonly, isLastPage, page } = useContext(OrchestratorContext);
- const classes = useStyles();
-
- const lastLabel = readonly ? D.simpleQuit : D.saveAndQuit;
- const getNextLabel = isLastPage ? lastLabel : D.continueButton;
-
- const continueButtonRef = useRef();
-
- const utilInfo = type => {
- return {
- ...SIMPLE_CLICK_EVENT,
- idParadataObject: `${type}-button`,
- page: page,
- };
- };
-
- const [pageChanging, setPageChanging] = useState(null);
-
- const localPageNext = () => setPageChanging('next');
-
- const localFinalQuit = () => setPageChanging('quit');
-
- const pageNextFunction = isLastPage
- ? paradataHandler(localFinalQuit)(utilInfo('end-survey'))
- : paradataHandler(localPageNext)(utilInfo('next-button'));
-
- const [focus, setFocus] = useState(false);
- const onfocus = value => () => setFocus(value);
-
- useEffect(() => {
- setPageChanging(false);
- }, [page]);
-
- const keysToHandle = ['alt+enter'];
-
- const keyboardShortcut = (key, e) => {
- e.preventDefault();
- if (key === 'alt+enter') {
- if (continueButtonRef && continueButtonRef.current) {
- continueButtonRef.current.focus();
- pageNextFunction();
- }
- }
- };
-
- useEffect(() => {
- if (focus && pageChanging) {
- setPendingChangePage(pageChanging);
- }
- }, [focus, pageChanging, setPendingChangePage]);
-
- const componentToDisplay = (
-
- }
- >
- {getNextLabel}
-
- {` ${D.helpShortCut} `}
- {D.ctrlEnter}
-
-
- );
-
- return (
- <>
- {readonly && isLastPage && componentToDisplay}
- {!readonly && componentToDisplay}
- >
- );
-};
-
-ButtonContinue.propTypes = {
- setPendingChangePage: PropTypes.func.isRequired,
-};
-
-export default React.memo(ButtonContinue);
diff --git a/queen-v2/src/components/orchestrator/buttons/index.js b/queen-v2/src/components/orchestrator/buttons/index.js
deleted file mode 100644
index b404d7fd..00000000
--- a/queen-v2/src/components/orchestrator/buttons/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './component';
diff --git a/queen-v2/src/components/orchestrator/header/header.js b/queen-v2/src/components/orchestrator/header/header.js
deleted file mode 100644
index 7b2dd1d1..00000000
--- a/queen-v2/src/components/orchestrator/header/header.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import React, { useCallback, useContext, useRef } from 'react';
-import KeyboardEventHandler from 'react-keyboard-event-handler';
-import PropTypes from 'prop-types';
-import * as lunatic from '@inseefr/lunatic';
-import D from 'i18n';
-import insee from 'img/insee.png';
-import Navigation from '../navigation';
-import BreadcrumbQueen from '../breadcrumb';
-import { useStyles } from './header.style';
-import { ButtonBase, IconButton } from '@material-ui/core';
-import { ExitToApp } from '@material-ui/icons';
-import { OrchestratorContext } from '../queen';
-import { paradataHandler, SIMPLE_CLICK_EVENT } from 'utils/events';
-
-const Header = ({ title, hierarchy }) => {
- const { page, standalone, queenBindings, quit, setPage, currentPage } =
- useContext(OrchestratorContext);
- const classes = useStyles({ standalone });
- const setToFirstPage = useCallback(() => setPage('1'), [setPage]);
- const quitButtonRef = useRef();
-
- const utilInfo = type => {
- return {
- ...SIMPLE_CLICK_EVENT,
- idParadataObject: `${type}-button`,
- page: currentPage,
- };
- };
- const { sequence, subSequence } = hierarchy || {};
-
- const sequenceBinded = {
- ...sequence,
- label: lunatic.interpret(['VTL'])(queenBindings)(sequence?.label),
- };
-
- const subSequenceBinded = subSequence
- ? {
- ...subSequence,
- label: lunatic.interpret(['VTL'])(queenBindings)(subSequence?.label),
- }
- : null;
-
- const quitShortCut = () => {
- if (quitButtonRef && quitButtonRef.current) quitButtonRef.current.focus();
- quit();
- };
-
- return (
-
-
-
-
-
-
-
-
- {title}
- {sequence && (
-
- )}
-
- {!standalone && (
- <>
-
-
-
-
-
-
- >
- )}
-
- );
-};
-
-Header.propTypes = {
- title: PropTypes.string.isRequired,
-};
-
-export default Header;
diff --git a/queen-v2/src/components/orchestrator/header/header.style.js b/queen-v2/src/components/orchestrator/header/header.style.js
deleted file mode 100644
index 7c9499e8..00000000
--- a/queen-v2/src/components/orchestrator/header/header.style.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import { makeStyles } from '@material-ui/core';
-
-const backgroundHeaderColor = 'white';
-const borderStyleHeader = '1px solid #777777';
-const widthBorder = '59px'; // 60(width grid template) - 1(border-width)
-
-export const useStyles = makeStyles(theme => ({
- root: props => ({
- width: '100%',
- flex: '0 1 65px',
- display: 'grid',
- gridTemplateColumns: `${props.standalone ? '60px 60px auto' : '60px 60px auto 60px'}`,
- backgroundColor: 'white',
- borderRight: 0,
- borderLeft: 0,
- borderBottom: `${borderStyleHeader}`,
- }),
- headerItemNavigation: {
- height: '100%',
- width: `${widthBorder}`,
- borderRight: `${borderStyleHeader}`,
- },
- headerClose: {
- width: `${widthBorder}`,
- borderLeft: `${borderStyleHeader}`,
- },
- headerLogo: {
- padding: '6px',
- marginLeft: '2px',
- justifySelf: 'center',
- alignSelf: 'center',
- height: '50px',
- width: 'auto',
- backgroundColor: `${backgroundHeaderColor}`,
- },
- inseeIcon: {
- padding: 0,
- border: 'none',
- cursor: 'pointer',
- backgroundColor: 'transparent',
- },
- closeIcon: {
- padding: '5px',
- paddingTop: '7px',
- '& svg': { fontSize: '2em' },
- },
-
- headerTitle: {
- padding: '0.4em',
- paddingLeft: '1em',
- },
- questionnaireTitle: {
- textTransform: 'uppercase',
- fontSize: '80%',
- },
-}));
diff --git a/queen-v2/src/components/orchestrator/header/index.js b/queen-v2/src/components/orchestrator/header/index.js
deleted file mode 100644
index 77992c5a..00000000
--- a/queen-v2/src/components/orchestrator/header/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './header';
diff --git a/queen-v2/src/components/orchestrator/index.js b/queen-v2/src/components/orchestrator/index.js
deleted file mode 100644
index 0b9e8aa1..00000000
--- a/queen-v2/src/components/orchestrator/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export { default } from './orchestrator';
-export { OrchestratorContext } from './queen';
diff --git a/queen-v2/src/components/orchestrator/navigation/component.js b/queen-v2/src/components/orchestrator/navigation/component.js
deleted file mode 100644
index d9b419c7..00000000
--- a/queen-v2/src/components/orchestrator/navigation/component.js
+++ /dev/null
@@ -1,255 +0,0 @@
-import {
- NEXT_FOCUS,
- PREVIOUS_FOCUS,
- createArrayOfRef,
- createReachableElement,
- getNewFocusElementIndex,
-} from 'utils/navigation';
-/* eslint-disable jsx-a11y/click-events-have-key-events */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
-import { dependencies, version } from '../../../../package.json';
-
-import { Apps } from '@material-ui/icons';
-import { ButtonItemMenu } from 'components/designSystem';
-import D from 'i18n';
-import { IconButton } from '@material-ui/core';
-import KeyboardEventHandler from 'react-keyboard-event-handler';
-import { OrchestratorContext } from '../queen';
-import PropTypes from 'prop-types';
-import SequenceNavigation from './sequenceNavigation';
-import StopNavigation from './stopNavigation';
-import SubsequenceNavigation from './subSequenceNavigation';
-import { useStyles } from './component.style';
-
-const Navigation = ({ className, title }) => {
- const { setMenuOpen, readonly, setPage } = useContext(OrchestratorContext);
- const [open, setOpen] = useState(false);
- const [surveyOpen, setSurveyOpen] = useState(false);
- const [stopOpen, setStopOpen] = useState(false);
- const [selectedSequence, setSelectedSequence] = useState(undefined);
-
- const lunaticVersion = dependencies['@inseefr/lunatic'].replace('^', '');
-
- const offset = 1;
-
- const menuItemsSurvey = [D.surveyNavigation];
- const menuItemsQuality = !readonly ? ['Arrêt'] : [];
-
- const [currentFocusElementIndex, setCurrentFocusElementIndex] = useState(0);
- const [listRefs] = useState(
- [...menuItemsSurvey, ...menuItemsQuality].reduce(
- _ => [..._, React.createRef()],
- createArrayOfRef(offset)
- )
- );
-
- const setFocus = useCallback(
- index => () => setCurrentFocusElementIndex(index),
- [setCurrentFocusElementIndex]
- );
- const reachableRefs = [...menuItemsSurvey, ...menuItemsQuality].reduce(
- _ => [..._, true],
- createReachableElement(offset)
- );
-
- const openCloseSubMenu = useCallback(
- type => {
- if (type === 'sequence') {
- setStopOpen(false);
- if (surveyOpen) {
- setSelectedSequence(undefined);
- setSurveyOpen(false);
- listRefs[1].current.focus();
- } else {
- setSurveyOpen(true);
- }
- } else if (type === 'stop') {
- setSurveyOpen(false);
- if (stopOpen) {
- setStopOpen(false);
- listRefs[2].current.focus();
- } else {
- setStopOpen(true);
- }
- }
- },
- [listRefs, stopOpen, surveyOpen]
- );
-
- const openCloseMenu = useCallback(() => {
- if (surveyOpen) openCloseSubMenu('sequence');
- if (stopOpen) openCloseSubMenu('stop');
- setOpen(!open);
- setMenuOpen(!open);
- listRefs[0].current.focus();
- }, [surveyOpen, openCloseSubMenu, stopOpen, open, setMenuOpen, listRefs]);
-
- const setNavigationPage = useCallback(
- page => {
- openCloseMenu();
- setPage(page);
- },
- [openCloseMenu, setPage]
- );
-
- const getKeysToHandle = () => {
- if (open && (surveyOpen || stopOpen)) return ['alt+b'];
- if (open) return ['alt+b', 'esc', 'right', 'up', 'down'];
- return ['alt+b'];
- };
- const keysToHandle = getKeysToHandle();
-
- const keyboardShortcut = (key, e) => {
- e.preventDefault();
- if (key === 'alt+b') {
- openCloseMenu();
- }
- if (key === 'esc' && !surveyOpen) openCloseMenu();
- if (key === 'right') {
- if (currentFocusElementIndex === 1) openCloseSubMenu('sequence');
- if (currentFocusElementIndex === 2) openCloseSubMenu('stop');
- }
- if (key === 'down' || key === 'up') {
- const directionFocus = key === 'down' ? NEXT_FOCUS : PREVIOUS_FOCUS;
- const newRefIndex =
- getNewFocusElementIndex(directionFocus)(currentFocusElementIndex)(reachableRefs);
- listRefs[newRefIndex]?.current?.focus();
- }
- };
- const classes = useStyles();
-
- const [trapFocus, setTrapFocus] = useState(false);
-
- useEffect(() => {
- setTimeout(() => setTrapFocus(open), 250);
- }, [open]);
-
- const rootRef = useRef();
-
- const menu = (
- <>
-
-
-
-
- {open && (
- <>
-
-
{`${D.goToNavigation} ...`}
-
-
-
{`Queen : ${version} | Lunatic : ${lunaticVersion}`}
- >
- )}
-
- >
- );
- return (
-
- {trapFocus &&
{menu}}
- {!trapFocus && menu}
- {open && (
- <>
-
- {surveyOpen && (
-
- )}
- {stopOpen && }
-
- {surveyOpen && (
-
- {selectedSequence && selectedSequence.components.length > 0 && (
- setSelectedSequence(undefined)}
- setPage={setNavigationPage}
- />
- )}
-
- )}
- >
- )}
-
- {open &&
}
-
-
-
- );
-};
-
-const comparison = (_, nextProps) => {
- return !nextProps.menuOpen;
-};
-
-Navigation.propTypes = {
- title: PropTypes.string.isRequired,
-};
-
-export default React.memo(Navigation, comparison);
diff --git a/queen-v2/src/components/orchestrator/navigation/component.style.js b/queen-v2/src/components/orchestrator/navigation/component.style.js
deleted file mode 100644
index 986bf2be..00000000
--- a/queen-v2/src/components/orchestrator/navigation/component.style.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import { makeStyles } from '@material-ui/core';
-
-const menuWidthDesktop = 250;
-const sequenceMenuWidthDesktop = 375;
-const subsequenceMenuWidthDesktop = 250;
-
-const menuWidthMobile = 250;
-const sequenceMenuWidthMobile = 250;
-const subsequenceMenuWidthMobile = 250;
-
-export const useStyles = makeStyles(theme => ({
- navigation: { alignSelf: 'center' },
- menuIcon: {
- position: 'relative',
- zIndex: 35,
- padding: '7px',
- '& svg': { fontSize: '2em' },
- },
- itemTitle: {
- width: '100%',
- border: 'none',
- backgroundColor: 'transparent',
- marginTop: '3em',
- color: '#085394',
- paddingLeft: '1.2em',
- paddingTop: '0.5em',
- paddingBottom: '0.5em',
- },
-
- menu: {
- height: '100%',
- width: `${menuWidthDesktop}px`,
- left: `-${menuWidthDesktop}px`,
- position: 'fixed',
- zIndex: 30,
- top: 0,
- overflowX: 'hidden' /* Disable horizontal scroll */,
- transition: 'transform 250ms ease',
- backgroundColor: 'white',
- borderRight: '1px solid #777777',
- '&.slideIn': { transform: `translateX(${menuWidthDesktop}px)` },
- '& ul': { paddingLeft: 0 },
- '& li': { display: 'block' },
-
- [theme.breakpoints.down('md')]: {
- width: `${menuWidthMobile}px`,
- left: `-${menuWidthMobile}px`,
- },
- },
-
- version: {
- backgroundColor: 'whitesmoke',
- borderTop: '1px solid #777777',
- position: 'fixed',
- width: '100%',
- left: 0,
- bottom: 0,
- textAlign: 'center',
- paddingTop: '2px',
- paddingBottom: '2px',
- },
-
- navigationContainer: { marginTop: '80px' },
- goToNavigationSpan: {
- fontSize: '80%',
- color: '#777777',
- textTransform: 'uppercase',
- paddingLeft: '1.2em',
- },
- backgroundMenu: {
- outline: 'none',
- position: 'fixed',
- top: 0,
- left: 0,
- zIndex: 20,
- width: '100%',
- height: '100%',
- backgroundColor: 'grey',
- opacity: 0.5,
- },
-
- title: { padding: '0.3em', paddingLeft: '1.2em', textTransform: 'uppercase', fontSize: '80%' },
-
- subMenuNavigationContainer: {
- height: '100%',
- position: 'absolute',
- top: 0,
- overflowX: 'hidden' /* Disable horizontal scroll */,
- transition: 'transform 450ms ease',
- '& ul': { paddingLeft: 0 },
- borderRight: '1px solid #777777',
- [theme.breakpoints.down('md')]: { '& .content': { marginTop: '70px' } },
- },
-
- sequenceNavigationContainer: {
- width: `${sequenceMenuWidthDesktop}px`,
- left: `-${sequenceMenuWidthDesktop}px`,
- zIndex: 29,
- backgroundColor: '#eeeeee',
- '& .content > div': { marginTop: '45px' },
- '&.slideIn': { transform: `translateX(${menuWidthDesktop + sequenceMenuWidthDesktop}px)` },
- [theme.breakpoints.down('md')]: {
- width: `${sequenceMenuWidthMobile}px`,
- left: `-${sequenceMenuWidthMobile}px`,
- zIndex: 31,
- '&.slideIn': { transform: `translateX(${sequenceMenuWidthMobile}px)` },
- },
- },
-
- subsequenceNavigationContainer: {
- width: `${subsequenceMenuWidthDesktop}px`,
- left: `${menuWidthDesktop - subsequenceMenuWidthDesktop}px`,
- zIndex: 28,
- backgroundColor: 'white',
- '& ul': { paddingLeft: 0 },
- '&.slideIn': {
- transform: `translateX(${sequenceMenuWidthDesktop + subsequenceMenuWidthDesktop}px)`,
- },
- [theme.breakpoints.down('md')]: {
- width: `${subsequenceMenuWidthMobile}px`,
- left: `-${subsequenceMenuWidthMobile}px`,
- zIndex: 32,
- '&.slideIn': { transform: `translateX(${subsequenceMenuWidthMobile}px)` },
- },
- },
-}));
diff --git a/queen-v2/src/components/orchestrator/navigation/index.js b/queen-v2/src/components/orchestrator/navigation/index.js
deleted file mode 100644
index b404d7fd..00000000
--- a/queen-v2/src/components/orchestrator/navigation/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './component';
diff --git a/queen-v2/src/components/orchestrator/navigation/sequenceNavigation/component.js b/queen-v2/src/components/orchestrator/navigation/sequenceNavigation/component.js
deleted file mode 100644
index 557bf95e..00000000
--- a/queen-v2/src/components/orchestrator/navigation/sequenceNavigation/component.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/* eslint-disable jsx-a11y/no-autofocus */
-import React, { useState, useCallback, useEffect } from 'react';
-import KeyboardEventHandler from 'react-keyboard-event-handler';
-import PropTypes from 'prop-types';
-import D from 'i18n';
-import { useStyles } from '../component.style';
-import { ButtonItemMenu } from 'components/designSystem';
-import {
- createArrayOfRef,
- createReachableElement,
- getNewFocusElementIndex,
- NEXT_FOCUS,
- PREVIOUS_FOCUS,
-} from 'utils/navigation';
-
-const SequenceNavigation = ({
- title,
- components,
- setPage,
- setSelectedSequence,
- subSequenceOpen,
- close,
-}) => {
- const offset = 1;
- const [currentFocusElement, setCurrentFocusElement] = useState(undefined);
- const [currentFocusElementIndex, setCurrentFocusElementIndex] = useState(0);
-
- const [listRefs] = useState(
- components
- ? components.reduce(_ => [..._, React.createRef()], createArrayOfRef(offset))
- : createArrayOfRef(offset)
- );
- const reachableRefs = components.reduce((_, { reachable }) => {
- return [..._, reachable];
- }, createReachableElement(offset));
-
- useEffect(() => {
- if (!subSequenceOpen && currentFocusElementIndex >= 0) {
- listRefs[currentFocusElementIndex].current.focus();
- setCurrentFocusElement(undefined);
- }
- }, [subSequenceOpen, currentFocusElementIndex, listRefs]);
-
- const setFocus = useCallback(
- index => () => setCurrentFocusElementIndex(index),
- [setCurrentFocusElementIndex]
- );
-
- const openSubComponents = sequence => {
- if (sequence.components && sequence.components.length > 0) {
- if (!currentFocusElement || currentFocusElement !== sequence.id) {
- setSelectedSequence(sequence);
- setCurrentFocusElement(sequence.id);
- }
- if (currentFocusElement === sequence.id) {
- listRefs[0].current.focus();
- setSelectedSequence(undefined);
- setCurrentFocusElement(undefined);
- }
- } else if (sequence.reachable) {
- setPage(sequence.page);
- }
- };
-
- const open = sequence => () => openSubComponents(sequence);
- const closeMenu = () => close('sequence');
-
- const keysToHandle = subSequenceOpen ? ['left', 'esc'] : ['left', 'right', 'esc', 'up', 'down'];
- const keyboardShortcut = (key, e) => {
- e.preventDefault();
- const indexOfSequence = currentFocusElementIndex - offset;
- if (key === 'right' && indexOfSequence >= 0) openSubComponents(components[indexOfSequence]);
- if (key === 'esc' || key === 'left') {
- if (!subSequenceOpen) closeMenu();
- else openSubComponents(components[indexOfSequence]);
- }
- if (key === 'down' || key === 'up') {
- const directionFocus = key === 'down' ? NEXT_FOCUS : PREVIOUS_FOCUS;
- const newRefIndex =
- getNewFocusElementIndex(directionFocus)(currentFocusElementIndex)(reachableRefs);
- listRefs[newRefIndex].current.focus();
- }
- };
-
- const classes = useStyles();
-
- return (
-
-
- {'\u3008'}
- {D.goBackNavigation}
-
-
-
{title}
-
-
-
-
- );
-};
-
-SequenceNavigation.propTypes = {
- title: PropTypes.string.isRequired,
- components: PropTypes.arrayOf(PropTypes.any).isRequired,
- setPage: PropTypes.func.isRequired,
- setSelectedSequence: PropTypes.func.isRequired,
- subSequenceOpen: PropTypes.bool.isRequired,
- close: PropTypes.func.isRequired,
-};
-
-export default SequenceNavigation;
diff --git a/queen-v2/src/components/orchestrator/navigation/sequenceNavigation/index.js b/queen-v2/src/components/orchestrator/navigation/sequenceNavigation/index.js
deleted file mode 100644
index b404d7fd..00000000
--- a/queen-v2/src/components/orchestrator/navigation/sequenceNavigation/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './component';
diff --git a/queen-v2/src/components/orchestrator/navigation/stopNavigation/component.js b/queen-v2/src/components/orchestrator/navigation/stopNavigation/component.js
deleted file mode 100644
index 270ea4d4..00000000
--- a/queen-v2/src/components/orchestrator/navigation/stopNavigation/component.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import React, { useState, useCallback } from 'react';
-import KeyboardEventHandler from 'react-keyboard-event-handler';
-import D from 'i18n';
-import { ButtonItemMenu } from 'components/designSystem';
-import {
- createArrayOfRef,
- createReachableElement,
- getNewFocusElementIndex,
- NEXT_FOCUS,
- PREVIOUS_FOCUS,
-} from 'utils/navigation';
-import { useStyles } from '../component.style';
-import { StopModal } from 'components/shared/modals/stopModal';
-
-const StopNavigation = React.forwardRef(({ close }, ref) => {
- const offset = 1;
- const labels = [
- {
- label: "Arrêt définitif de l'interview (refus, impossibilité de continuer, ...)",
- definitive: true,
- },
- {
- label: "Arrêt provisoire de l'interview",
- definitive: false,
- },
- ];
-
- const [currentFocusElementIndex, setCurrentFocusElementIndex] = useState(0);
- const [listRefs] = useState(
- labels.reduce(_ => [..._, React.createRef()], createArrayOfRef(offset))
- );
- const openModal = type => () => {
- setDefinitive(type);
- setOpen(true);
- };
- const closeMenu = () => close('stop');
-
- const setFocus = useCallback(
- index => () => setCurrentFocusElementIndex(index),
- [setCurrentFocusElementIndex]
- );
- const reachableRefs = labels.reduce(_ => [..._, true], createReachableElement(offset));
-
- const keysToHandle = ['left', 'right', 'esc', 'up', 'down'];
- const keyboardShortcut = (key, e) => {
- e.preventDefault();
- if (key === 'right') openModal(labels[currentFocusElementIndex]);
- if (key === 'esc' || key === 'left') {
- if (!open) closeMenu();
- }
- if (key === 'down' || key === 'up') {
- const directionFocus = key === 'down' ? NEXT_FOCUS : PREVIOUS_FOCUS;
- const newRefIndex =
- getNewFocusElementIndex(directionFocus)(currentFocusElementIndex)(reachableRefs);
- listRefs[newRefIndex].current.focus();
- }
- };
- const classes = useStyles();
-
- const [open, setOpen] = useState(false);
- const [definitive, setDefinitive] = useState(false);
-
- return (
- <>
-
-
- {'\u3008'}
- {D.goBackNavigation}
-
-
-
{"Quelle est la nature de l'arrêt ?"}
-
-
-
-
-
- >
- );
-});
-
-export default StopNavigation;
diff --git a/queen-v2/src/components/orchestrator/navigation/stopNavigation/index.js b/queen-v2/src/components/orchestrator/navigation/stopNavigation/index.js
deleted file mode 100644
index b404d7fd..00000000
--- a/queen-v2/src/components/orchestrator/navigation/stopNavigation/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './component';
diff --git a/queen-v2/src/components/orchestrator/navigation/subSequenceNavigation/component.js b/queen-v2/src/components/orchestrator/navigation/subSequenceNavigation/component.js
deleted file mode 100644
index 581507ae..00000000
--- a/queen-v2/src/components/orchestrator/navigation/subSequenceNavigation/component.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import React, { useState, useCallback } from 'react';
-import KeyboardEventHandler from 'react-keyboard-event-handler';
-import PropTypes from 'prop-types';
-import D from 'i18n';
-import { ButtonItemMenu } from 'components/designSystem';
-import {
- createArrayOfRef,
- createReachableElement,
- getNewFocusElementIndex,
- NEXT_FOCUS,
- PREVIOUS_FOCUS,
-} from 'utils/navigation';
-
-const SubsequenceNavigation = ({ sequence, close, setPage }) => {
- const offset = 2;
- const [currentFocusElementIndex, setCurrentFocusElementIndex] = useState(0);
- const [listRefs] = useState(
- sequence.components
- ? sequence.components.reduce(_ => [..._, React.createRef()], createArrayOfRef(offset))
- : createArrayOfRef(offset)
- );
-
- const setFocus = useCallback(
- index => () => setCurrentFocusElementIndex(index),
- [setCurrentFocusElementIndex]
- );
- const reachableRefs = sequence.components.reduce((_, { reachable }) => {
- return [..._, reachable];
- }, createReachableElement(offset));
-
- const keysToHandle = ['up', 'down'];
- const keyboardShortcut = (key, e) => {
- e.preventDefault();
- if (key === 'down' || key === 'up') {
- const directionFocus = key === 'down' ? NEXT_FOCUS : PREVIOUS_FOCUS;
- const newRefIndex =
- getNewFocusElementIndex(directionFocus)(currentFocusElementIndex)(reachableRefs);
- listRefs[newRefIndex].current.focus();
- }
- };
-
- const changePage = useCallback(
- ({ page, goToPage, reachable }) =>
- () => {
- if (reachable && goToPage) setPage(goToPage);
- else if (reachable && page) setPage(page);
- },
- [setPage]
- );
-
- return (
-
-
- {'\u3008'}
- {D.goBackNavigation}
-
-
- {sequence.labelNav}
-
-
-
-
- );
-};
-
-SubsequenceNavigation.propTypes = {
- sequence: PropTypes.objectOf(PropTypes.any).isRequired,
- close: PropTypes.func.isRequired,
- setPage: PropTypes.func.isRequired,
-};
-
-export default SubsequenceNavigation;
diff --git a/queen-v2/src/components/orchestrator/navigation/subSequenceNavigation/index.js b/queen-v2/src/components/orchestrator/navigation/subSequenceNavigation/index.js
deleted file mode 100644
index b404d7fd..00000000
--- a/queen-v2/src/components/orchestrator/navigation/subSequenceNavigation/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './component';
diff --git a/queen-v2/src/components/orchestrator/orchestrator.js b/queen-v2/src/components/orchestrator/orchestrator.js
deleted file mode 100644
index b584af50..00000000
--- a/queen-v2/src/components/orchestrator/orchestrator.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import * as lunatic from '@inseefr/lunatic';
-
-import PropTypes from 'prop-types';
-import QueenOrchestrator from 'components/orchestrator/queen';
-import React from 'react';
-import { getCalculatedVariablesFromSource } from 'utils/questionnaire';
-import { useLunaticFetcher } from 'utils/hook';
-
-const Orchestrator = ({
- surveyUnit,
- standalone,
- readonly,
- savingType,
- preferences,
- pagination,
- missing,
- features,
- source,
- suggesters,
- autoSuggesterLoading,
- filterDescription,
- save,
- close,
-}) => {
- const { data } = surveyUnit;
- const { lunaticFetcher: suggesterFetcher } = useLunaticFetcher();
- const calculatedVariables = getCalculatedVariablesFromSource(source);
- const lunaticResult = lunatic.useLunaticSplit(source, data, {
- savingType,
- preferences,
- features,
- pagination,
- suggesters,
- autoSuggesterLoading,
- suggesterFetcher,
- });
-
- return (
-
- );
-};
-
-Orchestrator.propTypes = {
- surveyUnit: PropTypes.objectOf(PropTypes.any).isRequired,
- standalone: PropTypes.bool.isRequired,
- readonly: PropTypes.bool.isRequired,
- savingType: PropTypes.oneOf(['COLLECTED', 'FORCED', 'EDITED']).isRequired,
- preferences: PropTypes.arrayOf(PropTypes.string).isRequired,
- features: PropTypes.arrayOf(PropTypes.string).isRequired,
- filterDescription: PropTypes.bool.isRequired,
- source: PropTypes.objectOf(PropTypes.any).isRequired,
- save: PropTypes.func.isRequired,
- close: PropTypes.func.isRequired,
-};
-
-export default React.memo(Orchestrator);
diff --git a/queen-v2/src/components/orchestrator/orchestrator.style.js b/queen-v2/src/components/orchestrator/orchestrator.style.js
deleted file mode 100644
index 4849e359..00000000
--- a/queen-v2/src/components/orchestrator/orchestrator.style.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { makeStyles } from '@material-ui/core';
-
-export const useStyles = makeStyles(theme => ({
- root: {
- display: 'flex',
- flexFlow: 'column',
- height: '100%',
- },
- bodyContainer: {
- flex: '1 1 auto',
- backgroundColor: theme.palette.background.default,
- display: 'grid',
- gridTemplateColumns: 'auto 60px',
- gridTemplateRows: '100%',
- },
- components: {
- display: 'grid',
- gridTemplateRows: 'auto 60px',
- },
- loopInfo: {
- position: 'absolute',
- // 65(width of top bar) + 4
- top: '69px',
- // 60(width of right bar) + 4
- right: '64px',
- },
-}));
diff --git a/queen-v2/src/components/orchestrator/progress/index.js b/queen-v2/src/components/orchestrator/progress/index.js
deleted file mode 100644
index ac4fa34b..00000000
--- a/queen-v2/src/components/orchestrator/progress/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './progress';
diff --git a/queen-v2/src/components/orchestrator/progress/progress.js b/queen-v2/src/components/orchestrator/progress/progress.js
deleted file mode 100644
index 0fbb1372..00000000
--- a/queen-v2/src/components/orchestrator/progress/progress.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { ProgressBar } from '@inseefr/lunatic';
-
-const Progress = ({ nbModules, page }) => (
-
-);
-
-Progress.propTypes = {
- nbModules: PropTypes.number.isRequired,
- page: PropTypes.number.isRequired,
-};
-
-export default Progress;
diff --git a/queen-v2/src/components/orchestrator/queen.js b/queen-v2/src/components/orchestrator/queen.js
deleted file mode 100644
index 0361167c..00000000
--- a/queen-v2/src/components/orchestrator/queen.js
+++ /dev/null
@@ -1,352 +0,0 @@
-import * as UQ from 'utils/questionnaire';
-import * as lunatic from '@inseefr/lunatic';
-
-import {
- COMPLETED,
- VALIDATED,
- useQuestionnaireState,
- useValidatedPages,
-} from 'utils/hook/questionnaire';
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
-
-import ContinueButton from './buttons/continue';
-import D from 'i18n';
-import { DIRECT_CONTINUE_COMPONENTS } from 'utils/constants';
-import Header from './header';
-import { MissingButton } from 'components/lightOrchestrator/buttons/missing/missing-button';
-import NavBar from '../lightOrchestrator/navBar';
-// import { Panel } from 'components/designSystem';
-import PropTypes from 'prop-types';
-import SimpleLoader from 'components/shared/preloader/simple';
-import { useCustomLunaticStyles } from './lunaticStyle/style';
-import { useStyles } from './orchestrator.style';
-
-export const OrchestratorContext = React.createContext();
-
-const dontKnowButton =
;
-const refusedButton =
;
-
-const QueenOrchestrator = ({
- lunatic: {
- questionnaire,
- components,
- handleChange,
- bindings,
- allBindings,
- state: { getState },
- pagination: { goNext, goPrevious, page, setPage, isFirstPage, isLastPage, flow, maxPage },
- },
- surveyUnit,
- source,
- save,
- close,
- readonly,
- standalone,
- filterDescription,
- preferences,
- features,
- missing,
- pagination,
- savingType,
- calculatedVariables,
-}) => {
- const classes = useStyles();
- const topRef = useRef();
- const lunaticClasses = useCustomLunaticStyles();
- const { stateData } = surveyUnit;
-
- const [changingPage, setChangingPage] = useState(false);
- const [menuOpen, setMenuOpen] = useState(false);
-
- const [pendingChangePage, setPendingChangePage] = useState(null);
- const [questionnaireUpdated, setQuestionnaireUpdated] = useState(true);
- const [haveToGoNext, setHaveToGoNext] = useState(false);
-
- const [queenFlow, setQueenFlow] = useState('next');
- const [rereading, setRereading] = useState(false);
-
- const [state, changeState] = useQuestionnaireState(
- questionnaire,
- stateData?.state,
- surveyUnit?.id
- );
- const [validatedPages, addValidatedPages] = useValidatedPages(
- stateData?.currentPage,
- questionnaire,
- bindings
- );
-
- const [pageFastfoward, setPageFastFoward] = useState(null);
-
- const [comment /* , setComment */] = useState(surveyUnit.comment);
-
- const saveQueen = useCallback(
- async lastState => {
- save({
- ...surveyUnit,
- stateData: {
- state: lastState ? lastState : state,
- date: new Date().getTime(),
- currentPage: page,
- },
- data: getState(questionnaire),
- comment: comment,
- });
- },
- [comment, getState, page, save, questionnaire, state, surveyUnit]
- );
-
- const changePage = useCallback(
- (type, freshBindings) => {
- setChangingPage(true);
- setQueenFlow(type);
- setPendingChangePage(null);
- setHaveToGoNext(false);
- saveQueen();
- if (type === 'next') {
- addValidatedPages(page);
- goNext(null, freshBindings);
- } else if (type === 'previous') goPrevious();
- setRereading(false);
- },
- [addValidatedPages, page, goPrevious, goNext, saveQueen]
- );
-
- const quit = useCallback(async () => {
- setPendingChangePage(null);
- if (isLastPage) {
- // TODO : make algo to calculate COMPLETED event
- changeState(COMPLETED);
- changeState(VALIDATED);
- await saveQueen(VALIDATED);
- } else await saveQueen();
- close();
- }, [changeState, close, isLastPage, saveQueen]);
-
- const definitiveQuit = useCallback(async () => {
- setPendingChangePage(null);
- changeState(VALIDATED);
- await saveQueen(VALIDATED);
- close();
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [changeState, close]);
-
- const { maxLocalPages, occurences, currentComponent, queenBindings } = UQ.getInfoFromCurrentPage(
- components,
- calculatedVariables
- )(allBindings)(page)(maxPage);
- const { componentType: currentComponentType, hierarchy } = currentComponent || {};
-
- const canGoNext = UQ.canGoNext(currentComponent)(queenBindings);
-
- useEffect(() => {
- if (
- currentComponentType &&
- !rereading &&
- !['Sequence', 'Subsequence'].includes(currentComponentType) &&
- queenFlow !== 'fastForward'
- ) {
- setRereading(canGoNext);
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [page, rereading]);
-
- // fastFoward effect
- useEffect(() => {
- if (
- changingPage && // only if page is changing
- queenFlow === 'fastForward' && // only during the fastFoward flow
- page !== pageFastfoward // only if page has changed after goNext effect
- ) {
- if (canGoNext && page !== maxPage) {
- setPageFastFoward(page);
- goNext();
- } else {
- setPageFastFoward(null);
- setQueenFlow(null);
- setChangingPage(false);
- }
- }
- }, [canGoNext, changingPage, goNext, maxPage, page, pageFastfoward, queenFlow]);
-
- useEffect(() => {
- if (queenFlow !== 'fastForward' && changingPage) setChangingPage(false);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [page]);
-
- /**
- * This function updates the values of the questionnaire responses
- * from the data entered by the user.
- * This function is disabled when app is in readonly mode.
- * @param {*} component the current component
- */
- const onChange = updatedValue => {
- if (!readonly) {
- setQuestionnaireUpdated(false);
- handleChange(updatedValue);
- setQuestionnaireUpdated(true);
- setHaveToGoNext(h => h || UQ.haveToGoNext(currentComponentType, updatedValue));
- }
- };
-
- useEffect(() => {
- if (!isLastPage && haveToGoNext) {
- setPendingChangePage('next');
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [haveToGoNext, isLastPage, currentComponentType]);
-
- useEffect(() => {
- if (questionnaireUpdated && pendingChangePage) {
- if (pendingChangePage === 'previous') changePage('previous');
- if (pendingChangePage === 'next') changePage('next');
- if (pendingChangePage === 'fastForward') changePage('fastForward');
- if (pendingChangePage === 'quit') quit();
- }
- }, [questionnaireUpdated, pendingChangePage, changePage, quit]);
-
- const missingStrategy = useCallback(
- b => {
- if (!isLastPage) {
- setChangingPage(true);
- setTimeout(() => {
- changePage('next', b);
- }, 200);
- }
- },
- [changePage, isLastPage]
- );
-
- const context = useMemo(
- () => ({
- menuOpen,
- setMenuOpen,
- quit,
- definitiveQuit,
- setPage,
- standalone,
- readonly,
- page,
- maxPages: maxLocalPages,
- occurences,
- isFirstPage,
- isLastPage,
- validatedPages,
- questionnaire: source,
- bindings: allBindings,
- queenBindings,
- }),
- [
- menuOpen,
- quit,
- definitiveQuit,
- setPage,
- standalone,
- readonly,
- page,
- maxLocalPages,
- occurences,
- isFirstPage,
- isLastPage,
- validatedPages,
- source,
- allBindings,
- queenBindings,
- ]
- );
-
- return (
-
-
-
-
- {changingPage &&
}
-
- {components.map(component => {
- const { componentType, id } = component;
- const Component = lunatic[componentType];
- if (componentType !== 'FilterDescription')
- return (
-
= 8
- ? 'split-fieldset'
- : ''
- }`}
- key={`component-${id}`}
- >
- {queenFlow !== 'fastForward' && (
-
- )}
-
- );
- return null;
- })}
- {/* {loopBindings && (
-
- {Object.values(loopBindings).length > 0 &&
- Object.values(loopBindings)[0].map((_, ind) => {
- return (
-
{
- if (value && value[ind]) return {`${value[ind]} `};
- return null;
- })}
- variables={Object.entries(responseBindings).reduce((acc, [key, value]) => {
- return { ...acc, [key]: value[ind] };
- }, {})}
- setPage={setPage}
- goToSeePage={allFirstLoopPages[ind]}
- />
- );
- })}
-
- )} */}
- {!DIRECT_CONTINUE_COMPONENTS.includes(currentComponentType) &&
- ((canGoNext && !rereading) || isLastPage) && (
-
- )}
-
-
-
-
-
- );
-};
-
-QueenOrchestrator.propTypes = {
- surveyUnit: PropTypes.objectOf(PropTypes.any).isRequired,
- lunatic: PropTypes.objectOf(PropTypes.any).isRequired,
-};
-
-export default React.memo(QueenOrchestrator);
diff --git a/queen-v2/src/components/orchestrator/rightNavbar/component.js b/queen-v2/src/components/orchestrator/rightNavbar/component.js
deleted file mode 100644
index a93337e3..00000000
--- a/queen-v2/src/components/orchestrator/rightNavbar/component.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import React, { useContext } from 'react';
-import * as UQ from 'utils/questionnaire';
-import { OrchestratorContext } from '../queen';
-import { useStyles } from './component.style';
-
-const RightNavBar = ({ children }) => {
- const { page, maxPages, occurences } = useContext(OrchestratorContext);
- const classes = useStyles();
-
- const currentLocalPages = page.includes('.')
- ? UQ.getPageWithoutAnyIteration(page).split('.')
- : [page];
-
- const displayPages = currentLocalPages
- .map((p, i) => {
- return { localScopePage: p, localScopeMaxPage: maxPages[i] };
- })
- .reverse();
-
- const occurencesOrdered = occurences.slice().reverse();
- return (
-
-
- {displayPages.map((pages, i) => {
- const { localScopePage, localScopeMaxPage } = pages;
- return (
-
- {occurencesOrdered && occurencesOrdered[i] && (
-
-
Occurence
- {occurencesOrdered[i].map((v, o) => {
- return (
-
- {v}
-
- );
- })}
-
- )}
-
-
n° page
-
- {`${localScopePage}/${localScopeMaxPage}`}
-
-
-
- );
- })}
-
- {children}
-
- );
-};
-
-export default React.memo(RightNavBar);
diff --git a/queen-v2/src/components/orchestrator/rightNavbar/component.style.js b/queen-v2/src/components/orchestrator/rightNavbar/component.style.js
deleted file mode 100644
index d9433ee3..00000000
--- a/queen-v2/src/components/orchestrator/rightNavbar/component.style.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import { makeStyles } from '@material-ui/core';
-
-export const useStyles = makeStyles({
- root: {
- gridColumnStart: 2,
- gridColumnEnd: 2,
- gridRowStart: 1,
- gridRowEnd: 3,
- position: 'relative',
- borderLeft: '1px solid #777777',
- },
- detail: { display: 'block' },
- page: {
- marginTop: '0.3em',
- paddingTop: '0.3em',
- paddingBottom: '0.3em',
- fontSize: '80%',
- textAlign: 'center',
- borderRadius: '5px',
- width: '57px',
- margin: 'auto',
- backgroundColor: 'white',
- },
- pages: {
- position: 'absolute',
- bottom: '200px',
- },
- labelPage: { fontSize: '90%', marginBottom: '4px' },
-});
diff --git a/queen-v2/src/components/orchestrator/rightNavbar/index.js b/queen-v2/src/components/orchestrator/rightNavbar/index.js
deleted file mode 100644
index b404d7fd..00000000
--- a/queen-v2/src/components/orchestrator/rightNavbar/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './component';
diff --git a/queen-v2/src/components/orchestratorManager/orchestratorManager.js b/queen-v2/src/components/orchestratorManager/orchestratorManager.js
index 541218c5..695ee599 100644
--- a/queen-v2/src/components/orchestratorManager/orchestratorManager.js
+++ b/queen-v2/src/components/orchestratorManager/orchestratorManager.js
@@ -1,6 +1,11 @@
-import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
+import { useContext, useEffect, useMemo, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom';
-import { ORCHESTRATOR_COLLECT, ORCHESTRATOR_READONLY, READ_ONLY } from 'utils/constants';
+import {
+ GLOBAL_QUEEN_VARIABLES,
+ ORCHESTRATOR_COLLECT,
+ ORCHESTRATOR_READONLY,
+ READ_ONLY,
+} from 'utils/constants';
import { EventsManager, INIT_ORCHESTRATOR_EVENT, INIT_SESSION_EVENT } from 'utils/events';
import { useAPI, useAPIRemoteData, useAuth, useGetReferentiel } from 'utils/hook';
import { COMPLETED, VALIDATED, useQuestionnaireState } from 'utils/hook/questionnaire';
@@ -11,12 +16,21 @@ import Error from 'components/shared/Error';
import NotFound from 'components/shared/not-found';
import Preloader from 'components/shared/preloader';
import { sendCloseEvent } from 'utils/communication';
+import { useConstCallback } from 'utils/hook/useConstCallback';
import surveyUnitIdbService from 'utils/indexedbb/services/surveyUnit-idb-service';
-import { checkQuestionnaire } from 'utils/questionnaire';
+import {
+ addGlobalVariablesToData,
+ addGlobalVariablesToQuestionnaire,
+ checkQuestionnaire,
+ getFullData,
+ removeNullCollectedData,
+} from 'utils/questionnaire';
export const OrchestratorManager = () => {
const { standalone, apiUrl } = useContext(AppContext);
const { readonly: readonlyParam, idQ, idSU } = useParams();
+ const [surveyUnitData, setSurveyUnitData] = useState(null);
+ const [initalStateForLunatic, setInitalStateForLunatic] = useState(null);
const history = useHistory();
const readonly = readonlyParam === READ_ONLY;
@@ -34,7 +48,6 @@ export const OrchestratorManager = () => {
const { surveyUnit, questionnaire, loadingMessage, errorMessage } = useAPIRemoteData(idSU, idQ);
const stateData = surveyUnit?.stateData;
- const initialData = surveyUnit?.data;
const { oidcUser } = useAuth();
const isAuthenticated = !!oidcUser?.profile;
@@ -46,7 +59,6 @@ export const OrchestratorManager = () => {
const { putUeData /* postParadata */ } = useAPI();
const [getState, changeState, onDataChange] = useQuestionnaireState(
surveyUnit?.id,
- initialData,
stateData?.state
);
@@ -65,7 +77,20 @@ export const OrchestratorManager = () => {
if (!init && questionnaire && surveyUnit) {
const { valid, error: questionnaireError } = checkQuestionnaire(questionnaire);
if (valid) {
- setSource(questionnaire);
+ const globalQueenData = {
+ [GLOBAL_QUEEN_VARIABLES.GLOBAL_SURVEY_UNIT_ID]: surveyUnit.id,
+ [GLOBAL_QUEEN_VARIABLES.GLOBAL_QUESTIONNAIRE_ID]:
+ surveyUnit.questionnaireId ?? questionnaire.id,
+ };
+ const newQuestionnaire = addGlobalVariablesToQuestionnaire(questionnaire, globalQueenData);
+ setSource(newQuestionnaire);
+
+ const newData = addGlobalVariablesToData(surveyUnit?.data || {}, globalQueenData);
+ setSurveyUnitData(newData);
+ setInitalStateForLunatic({
+ initialData: newData,
+ lastReachedPage: surveyUnit?.stateData?.currentPage,
+ });
setInit(true);
LOGGER.log(INIT_ORCHESTRATOR_EVENT);
} else {
@@ -81,94 +106,88 @@ export const OrchestratorManager = () => {
/** take a survey-unit as parameter, then save it in IDB, then save paradatas in IDB
* If in standalone mode : make API calls to persist data in DB
*/
- const saveData = useCallback(
- async unit => {
- if (!readonly) {
- const putSurveyUnit = async unit => {
- const { id, ...other } = unit;
- await putUeData(id, other);
- };
-
- await surveyUnitIdbService.addOrUpdateSU(unit);
-
- /**
- * Disable temporaly paradata
- *
- * const paradatas = LOGGER.getEventsToSend();
- */
- // TODO : make a true update of paradatas : currently adding additional completed arrays => SHOULD save one and only one array
- // await paradataIdbService.update(paradatas);
- if (standalone) {
- // TODO managing errors
- await putSurveyUnit(unit);
- // await postParadata(paradatas);
- }
+ const saveData = useConstCallback(async unit => {
+ if (!readonly) {
+ const putSurveyUnit = async unit => {
+ const { id, ...other } = unit;
+ await putUeData(id, other);
+ };
+
+ await surveyUnitIdbService.addOrUpdateSU(unit);
+
+ /**
+ * Disable temporaly paradata
+ *
+ * const paradatas = LOGGER.getEventsToSend();
+ */
+ // TODO : make a true update of paradatas : currently adding additional completed arrays => SHOULD save one and only one array
+ // await paradataIdbService.update(paradatas);
+ if (standalone) {
+ // TODO managing errors
+ await putSurveyUnit(unit);
+ // await postParadata(paradatas);
}
- },
- [putUeData, readonly, standalone]
- );
-
- const saveQueen = useCallback(
- async (newState, newData, lastReachedPage) => {
- const currentState = getState();
- saveData({
- comment: {},
- ...surveyUnit,
- stateData: {
- state: newState ?? currentState,
- date: new Date().getTime(),
- currentPage: lastReachedPage,
- },
- data: newData ?? surveyUnit.data,
- });
- },
- [getState, saveData, surveyUnit]
- );
-
- const closeOrchestrator = useCallback(() => {
+ }
+ });
+
+ const savePartialQueen = useConstCallback(async (newState, newPartialData, lastReachedPage) => {
+ const currentState = getState();
+
+ const newData = getFullData(surveyUnitData, removeNullCollectedData(newPartialData));
+ setSurveyUnitData(newData);
+ saveData({
+ comment: {},
+ ...surveyUnit,
+ stateData: {
+ state: newState ?? currentState,
+ date: new Date().getTime(),
+ currentPage: lastReachedPage,
+ },
+ data: newData ?? surveyUnitData,
+ });
+ });
+
+ const closeOrchestrator = useConstCallback(() => {
if (standalone) {
history.push('/');
} else {
sendCloseEvent(surveyUnit.id);
}
- }, [history, standalone, surveyUnit?.id]);
-
- const quit = useCallback(
- async (pager, getData) => {
- const { page, maxPage, lastReachedPage } = pager;
- const isLastPage = page === maxPage;
- const newData = getData();
- if (isLastPage) {
- // TODO : make algo to calculate COMPLETED event
- changeState(COMPLETED);
- changeState(VALIDATED);
- await saveQueen(VALIDATED, newData, lastReachedPage);
- } else await saveQueen(undefined, newData, lastReachedPage);
- closeOrchestrator();
- },
- [changeState, closeOrchestrator, saveQueen]
- );
-
- const definitiveQuit = useCallback(
- async (pager, getData) => {
- const { lastReachedPage } = pager;
- const newData = getData();
+ });
+
+ const quit = useConstCallback(async (pager, getChangedData) => {
+ const { page, maxPage, lastReachedPage } = pager;
+ const isLastPage = page === maxPage;
+ const newData = getChangedData(true);
+ if (isLastPage) {
+ // TODO : make algo to calculate COMPLETED event
+ changeState(COMPLETED);
changeState(VALIDATED);
- await saveQueen(VALIDATED, newData, lastReachedPage);
- closeOrchestrator();
- },
- [changeState, closeOrchestrator, saveQueen]
- );
+ await savePartialQueen(VALIDATED, newData, lastReachedPage);
+ } else await savePartialQueen(undefined, newData, lastReachedPage);
+ closeOrchestrator();
+ });
+
+ const definitiveQuit = useConstCallback(async (pager, getChangedData) => {
+ const { lastReachedPage } = pager;
+ const newData = getChangedData(true);
+ changeState(VALIDATED);
+ await savePartialQueen(VALIDATED, newData, lastReachedPage);
+ closeOrchestrator();
+ });
+
return (
<>
{![READ_ONLY, undefined].includes(readonlyParam) &&
}
{loadingMessage &&
}
{error &&
}
- {!loadingMessage && !error && source && surveyUnit && (
+ {!loadingMessage && !error && source && initalStateForLunatic && (
{
missing={true}
shortcut={true}
filterDescription={false}
- save={saveQueen}
+ save={savePartialQueen}
onDataChange={onDataChange}
close={closeOrchestrator}
quit={quit}
diff --git a/queen-v2/src/components/visualizer/visualizer.js b/queen-v2/src/components/visualizer/visualizer.js
index cb31f1b9..980c678f 100644
--- a/queen-v2/src/components/visualizer/visualizer.js
+++ b/queen-v2/src/components/visualizer/visualizer.js
@@ -1,129 +1,136 @@
-import { useCallback, useContext, useEffect, useState } from 'react';
+import { useContext, useEffect, useState } from 'react';
import { useGetReferentiel, useRemoteData, useVisuQuery } from 'utils/hook';
-import { checkQuestionnaire, downloadDataAsJson } from 'utils/questionnaire';
+import {
+ addGlobalVariablesToData,
+ addGlobalVariablesToQuestionnaire,
+ checkQuestionnaire,
+ downloadDataAsJson,
+ getFullData,
+ removeNullCollectedData,
+} from 'utils/questionnaire';
import { AppContext } from 'components/app';
import LightOrchestrator from 'components/lightOrchestrator';
import Error from 'components/shared/Error';
import Preloader from 'components/shared/preloader';
import { useHistory } from 'react-router';
+import { GLOBAL_QUEEN_VARIABLES } from 'utils/constants';
import { useQuestionnaireState } from 'utils/hook/questionnaire';
+import { useConstCallback } from 'utils/hook/useConstCallback';
import surveyUnitIdbService from 'utils/indexedbb/services/surveyUnit-idb-service';
import QuestionnaireForm from './questionnaireForm';
const Visualizer = () => {
const { apiUrl, standalone } = useContext(AppContext);
+ const [surveyUnitData, setSurveyUnitData] = useState(null);
- const [surveyUnit, setSurveyUnit] = useState(undefined);
+ const [initalStateForLunatic, setInitalStateForLunatic] = useState(null);
const [error, setError] = useState(null);
const [source, setSource] = useState(null);
const { questionnaireUrl, dataUrl, nomenclatures, readonly } = useVisuQuery();
- const {
- surveyUnit: suData,
- questionnaire,
- loadingMessage,
- errorMessage,
- } = useRemoteData(questionnaireUrl, dataUrl);
+ const { surveyUnit, questionnaire, loadingMessage, errorMessage } = useRemoteData(
+ questionnaireUrl,
+ dataUrl
+ );
const { getReferentielForVizu } = useGetReferentiel(nomenclatures);
const [getState, , onDataChange] = useQuestionnaireState(
surveyUnit?.id,
- suData?.data,
- suData?.stateData?.state
+ surveyUnit?.stateData?.state
);
const history = useHistory();
useEffect(() => {
- if (suData === null) return;
- const unit = {
- ...suData,
- id: '1234',
- };
+ if (surveyUnit === null) return;
const insertSuInIndexedDB = async su => {
- console.log('Initiating sudata in IDB', su);
+ console.log('Initiating fake surveyUnit in IDB', su);
await surveyUnitIdbService.addOrUpdateSU(su);
};
- insertSuInIndexedDB(unit);
- setSurveyUnit(unit);
- }, [suData]);
+ insertSuInIndexedDB(surveyUnit);
+ }, [surveyUnit]);
useEffect(() => {
- if (questionnaireUrl && questionnaire && suData) {
+ if (questionnaireUrl && questionnaire && surveyUnit) {
const { valid, error: questionnaireError } = checkQuestionnaire(questionnaire);
if (valid) {
- setSource(questionnaire);
+ const globalQueenData = {
+ [GLOBAL_QUEEN_VARIABLES.GLOBAL_SURVEY_UNIT_ID]: surveyUnit.id,
+ [GLOBAL_QUEEN_VARIABLES.GLOBAL_QUESTIONNAIRE_ID]:
+ surveyUnit.questionnaireId ?? questionnaire.id,
+ };
+ const newQuestionnaire = addGlobalVariablesToQuestionnaire(questionnaire, globalQueenData);
+ setSource(newQuestionnaire);
+
+ const newData = addGlobalVariablesToData(surveyUnit?.data || {}, globalQueenData);
+ setSurveyUnitData(newData);
+ setInitalStateForLunatic({
+ initialData: newData,
+ lastReachedPage: surveyUnit?.stateData?.currentPage,
+ });
} else {
setError(questionnaireError);
}
}
- }, [questionnaireUrl, questionnaire, suData, apiUrl]);
+ }, [questionnaireUrl, questionnaire, surveyUnit, apiUrl]);
useEffect(() => {
if (errorMessage) setError(errorMessage);
}, [errorMessage]);
- // const save = useCallback(async (unit, newData) => {
- // console.log(unit, newData);
- // await surveyUnitIdbService.addOrUpdateSU({
- // ...unit,
- // data: newData,
- // });
- // }, []);
-
- const save = useCallback(
- async (newState, newData, lastReachedPage) => {
- const currentState = getState();
- const unit = {
- ...surveyUnit,
- stateData: {
- state: newState ?? currentState,
- date: new Date().getTime(),
- currentPage: lastReachedPage,
- },
- data: newData ?? surveyUnit?.data,
- };
- await surveyUnitIdbService.addOrUpdateSU(unit);
- },
- [getState, surveyUnit]
- );
- const closeAndDownloadData = useCallback(
- async (pager, getData) => {
- const { lastReachedPage } = pager;
- const newData = getData();
- const unit = {
- ...surveyUnit,
- stateData: {
- state: getState(),
- date: new Date().getTime(),
- currentPage: lastReachedPage,
- },
- data: newData ?? surveyUnit?.data,
- };
-
- downloadDataAsJson(unit, 'data');
- history.push('/');
- },
- [getState, history, surveyUnit]
- );
+ const savePartial = useConstCallback(async (newState, newPartialData, lastReachedPage) => {
+ const currentState = getState();
+
+ const newData = getFullData(surveyUnitData, removeNullCollectedData(newPartialData));
+ setSurveyUnitData(newData);
+ const unit = {
+ ...surveyUnit,
+ stateData: {
+ state: newState ?? currentState,
+ date: new Date().getTime(),
+ currentPage: lastReachedPage,
+ },
+ data: newData ?? surveyUnit.data,
+ };
+ await surveyUnitIdbService.addOrUpdateSU(unit);
+ });
+
+ const closeAndDownloadData = useConstCallback(async (pager, getChangedData) => {
+ const { lastReachedPage } = pager;
+ const newData = getFullData(surveyUnitData, removeNullCollectedData(getChangedData(true)));
+ const unit = {
+ ...surveyUnit,
+ stateData: {
+ state: getState(),
+ date: new Date().getTime(),
+ currentPage: lastReachedPage,
+ },
+ data: newData ?? surveyUnit?.data,
+ };
+
+ downloadDataAsJson(unit, 'data');
+ history.push('/');
+ });
return (
<>
{loadingMessage && }
{error && }
- {questionnaireUrl && source && surveyUnit && (
+ {questionnaireUrl && source && initalStateForLunatic && (
{
const responseFromQueen = await fetch('/manifest.json');
const { icons } = await responseFromQueen.json();
- const urlsToPrecache = [
- `/manifest.json`,
- `/configuration.json`,
- process.env.REACT_APP_LUNATIC_LOADER_WORKER_PATH,
- process.env.REACT_APP_LUNATIC_SEARCH_WORKER_PATH,
- process.env.REACT_APP_LUNATIC_LABEL_WORKER_PATH,
- ].concat(icons.map(({ src }) => src));
+ const urlsToPrecache = [`/manifest.json`, `/configuration.json`].concat(
+ icons.map(({ src }) => src)
+ );
const cache = await self.caches.open(configurationCacheName);
await cache.addAll(urlsToPrecache);
cache
diff --git a/queen-v2/src/utils/constants/index.js b/queen-v2/src/utils/constants/index.js
index 4d1bdc69..83213005 100644
--- a/queen-v2/src/utils/constants/index.js
+++ b/queen-v2/src/utils/constants/index.js
@@ -66,4 +66,9 @@ export const SHORTCUT_NEXT = 'alt+enter';
export const SHORTCUT_PREVIOUS = 'alt+backspace';
export const SHORTCUT_FAST_FORWARD = 'alt+end';
+export const GLOBAL_QUEEN_VARIABLES = {
+ GLOBAL_SURVEY_UNIT_ID: 'GLOBAL_SURVEY_UNIT_ID',
+ GLOBAL_QUESTIONNAIRE_ID: 'GLOBAL_QUESTIONNAIRE_ID',
+};
+
export * from './paradata';
diff --git a/queen-v2/src/utils/hook/api.js b/queen-v2/src/utils/hook/api.js
index 1f915870..4d6f1891 100644
--- a/queen-v2/src/utils/hook/api.js
+++ b/queen-v2/src/utils/hook/api.js
@@ -1,4 +1,4 @@
-import { useCallback, useContext, useEffect, useState } from 'react';
+import { useContext, useEffect, useState } from 'react';
import { DEFAULT_DATA_URL, OIDC } from 'utils/constants';
import { AppContext } from 'components/app';
@@ -9,6 +9,7 @@ import clearAllData from 'utils/indexedbb/services/allTables-idb-service';
import surveyUnitIdbService from 'utils/indexedbb/services/surveyUnit-idb-service';
import { useAsyncValue } from '.';
import { useAuth } from './auth';
+import { useConstCallback } from './useConstCallback';
const clean = async (standalone = false) => {
try {
@@ -36,25 +37,19 @@ export const useGetReferentiel = nomenclatures => {
const { oidcUser } = useAuth();
const { apiUrl } = useContext(AppContext);
- const getReferentiel = useCallback(
- refName => {
- const finalUrl = `${apiUrl}/api/nomenclature/${refName}`;
+ const getReferentiel = useConstCallback(refName => {
+ const finalUrl = `${apiUrl}/api/nomenclature/${refName}`;
+ return getFetcherForLunatic(oidcUser?.access_token)(finalUrl);
+ });
+
+ const getReferentielForVizu = useConstCallback(refName => {
+ if (nomenclatures && Object.keys(nomenclatures).includes(refName)) {
+ const finalUrl = nomenclatures[refName];
return getFetcherForLunatic(oidcUser?.access_token)(finalUrl);
- },
- [apiUrl, oidcUser]
- );
-
- const getReferentielForVizu = useCallback(
- refName => {
- if (nomenclatures && Object.keys(nomenclatures).includes(refName)) {
- const finalUrl = nomenclatures[refName];
- return getFetcherForLunatic(oidcUser?.access_token)(finalUrl);
- }
- // No nomenclature, return empty array to lunatic
- return Promise.resolve([]);
- },
- [nomenclatures, oidcUser]
- );
+ }
+ // No nomenclature, return empty array to lunatic
+ return Promise.resolve([]);
+ });
return { getReferentiel, getReferentielForVizu };
};
@@ -63,74 +58,50 @@ export const useAPI = () => {
const { authenticationType, oidcUser } = useAuth();
const { apiUrl } = useContext(AppContext);
- const getCampaigns = useCallback(() => {
+ const getCampaigns = useConstCallback(() => {
const token = authenticationType === OIDC ? oidcUser?.access_token : null;
return API.getCampaigns(apiUrl)(token);
- }, [apiUrl, authenticationType, oidcUser]);
-
- const getQuestionnaire = useCallback(
- questionnaireID => {
- const token = authenticationType === OIDC ? oidcUser?.access_token : null;
- return API.getQuestionnaire(apiUrl)(questionnaireID)(token);
- },
- [apiUrl, authenticationType, oidcUser]
- );
-
- const getRequiredNomenclatures = useCallback(
- id => {
- const token = authenticationType === OIDC ? oidcUser?.access_token : null;
- return API.getRequiredNomenclatures(apiUrl)(id)(token);
- },
- [apiUrl, authenticationType, oidcUser]
- );
-
- const getSurveyUnits = useCallback(
- id => {
- const token = authenticationType === OIDC ? oidcUser?.access_token : null;
- return API.getSurveyUnits(apiUrl)(id)(token);
- },
- [apiUrl, authenticationType, oidcUser]
- );
-
- const getNomenclature = useCallback(
- id => {
- const token = authenticationType === OIDC ? oidcUser?.access_token : null;
- return API.getNomenclature(apiUrl)(id)(token);
- },
- [apiUrl, authenticationType, oidcUser]
- );
-
- const getUeData = useCallback(
- surveyUnitID => {
- const token = authenticationType === OIDC ? oidcUser?.access_token : null;
- return API.getUeData(apiUrl)(surveyUnitID)(token);
- },
- [apiUrl, authenticationType, oidcUser]
- );
-
- const putUeData = useCallback(
- (surveyUnitID, body) => {
- const token = authenticationType === OIDC ? oidcUser?.access_token : null;
- return API.putUeData(apiUrl)(surveyUnitID)(token)(body);
- },
- [apiUrl, authenticationType, oidcUser]
- );
-
- const putUeDataToTempZone = useCallback(
- (surveyUnitID, body) => {
- const token = authenticationType === OIDC ? oidcUser?.access_token : null;
- return API.putUeDataToTempZone(apiUrl)(surveyUnitID)(token)(body);
- },
- [apiUrl, authenticationType, oidcUser]
- );
-
- const postParadata = useCallback(
- body => {
- const token = authenticationType === OIDC ? oidcUser?.access_token : null;
- return API.postParadata(apiUrl)(token)(body);
- },
- [apiUrl, authenticationType, oidcUser]
- );
+ });
+
+ const getQuestionnaire = useConstCallback(questionnaireID => {
+ const token = authenticationType === OIDC ? oidcUser?.access_token : null;
+ return API.getQuestionnaire(apiUrl)(questionnaireID)(token);
+ });
+
+ const getRequiredNomenclatures = useConstCallback(id => {
+ const token = authenticationType === OIDC ? oidcUser?.access_token : null;
+ return API.getRequiredNomenclatures(apiUrl)(id)(token);
+ });
+
+ const getSurveyUnits = useConstCallback(id => {
+ const token = authenticationType === OIDC ? oidcUser?.access_token : null;
+ return API.getSurveyUnits(apiUrl)(id)(token);
+ });
+
+ const getNomenclature = useConstCallback(id => {
+ const token = authenticationType === OIDC ? oidcUser?.access_token : null;
+ return API.getNomenclature(apiUrl)(id)(token);
+ });
+
+ const getUeData = useConstCallback(surveyUnitID => {
+ const token = authenticationType === OIDC ? oidcUser?.access_token : null;
+ return API.getUeData(apiUrl)(surveyUnitID)(token);
+ });
+
+ const putUeData = useConstCallback((surveyUnitID, body) => {
+ const token = authenticationType === OIDC ? oidcUser?.access_token : null;
+ return API.putUeData(apiUrl)(surveyUnitID)(token)(body);
+ });
+
+ const putUeDataToTempZone = useConstCallback((surveyUnitID, body) => {
+ const token = authenticationType === OIDC ? oidcUser?.access_token : null;
+ return API.putUeDataToTempZone(apiUrl)(surveyUnitID)(token)(body);
+ });
+
+ const postParadata = useConstCallback(body => {
+ const token = authenticationType === OIDC ? oidcUser?.access_token : null;
+ return API.postParadata(apiUrl)(token)(body);
+ });
return {
getCampaigns,
@@ -236,7 +207,7 @@ export const useRemoteData = (questionnaireUrl, dataUrl) => {
setLoadingMessage(Dictionary.waintingData);
const dR = await API.getRequest(dataUrl || DEFAULT_DATA_URL)(fakeToken);
if (!dR.error) {
- setSurveyUnit(dR.data);
+ setSurveyUnit({ ...(dR.data || {}), id: '1234' });
setLoadingMessage(null);
} else setErrorMessage(getErrorMessage(dR, 'd'));
setLoadingMessage(null);
diff --git a/queen-v2/src/utils/hook/questionnaire.js b/queen-v2/src/utils/hook/questionnaire.js
index 980b20b9..266eeb24 100644
--- a/queen-v2/src/utils/hook/questionnaire.js
+++ b/queen-v2/src/utils/hook/questionnaire.js
@@ -1,52 +1,37 @@
-import { sendCompletedEvent, sendStartedEvent, sendValidatedEvent } from 'utils/communication';
import { useCallback, useRef } from 'react';
+import { sendCompletedEvent, sendStartedEvent, sendValidatedEvent } from 'utils/communication';
+import { useConstCallback } from './useConstCallback';
export const NOT_STARTED = null;
export const INIT = 'INIT';
export const COMPLETED = 'COMPLETED';
export const VALIDATED = 'VALIDATED';
-export const useQuestionnaireState = (idSurveyUnit, initialData, initialState = NOT_STARTED) => {
- console.log('useQuestionnaireState', { idSurveyUnit, initialData, initialState });
+export const useQuestionnaireState = (idSurveyUnit, initialState = NOT_STARTED) => {
const stateRef = useRef(initialState);
const getState = useCallback(() => stateRef.current, []);
- const initialDataRef = useRef(initialData);
-
// Send an event when questionnaire's state has changed (started, completed, validated)
- const changeState = useCallback(
- newState => {
- console.log('change state to ', newState);
- if (newState === INIT) sendStartedEvent(idSurveyUnit);
- if (newState === COMPLETED) sendCompletedEvent(idSurveyUnit);
- if (newState === VALIDATED) sendValidatedEvent(idSurveyUnit);
- stateRef.current = newState;
- },
- [idSurveyUnit]
- );
- const onDataChange = useCallback(
- newData => {
- // initialisation des data de référence
- if (initialDataRef.current === undefined) {
- console.log('persisting initial data');
- initialDataRef.current = JSON.stringify(newData);
- }
+ const changeState = useConstCallback(newState => {
+ if (newState === INIT) sendStartedEvent(idSurveyUnit);
+ if (newState === COMPLETED) sendCompletedEvent(idSurveyUnit);
+ if (newState === VALIDATED) sendValidatedEvent(idSurveyUnit);
+ stateRef.current = newState;
+ });
+ const onDataChange = useConstCallback((newData = {}) => {
+ const { COLLECTED = {} } = newData;
+ const hasDataChanged = Object.keys(COLLECTED).length > 0;
- if (stateRef.current === NOT_STARTED) {
- changeState(INIT);
- } else if (
- stateRef.current === VALIDATED &&
- initialDataRef.current !== JSON.stringify(newData)
- ) {
- // state VALIDATED et données entrantes !== données initiales
- changeState(INIT);
- } else {
- // here we do nothing
- console.log({ newData, state: stateRef.current });
- }
- },
- [changeState]
- );
+ if (stateRef.current === NOT_STARTED) {
+ changeState(INIT);
+ } else if (stateRef.current === VALIDATED && hasDataChanged) {
+ // state VALIDATED et données entrantes !== données initiales
+ changeState(INIT);
+ } else {
+ // here we do nothing
+ console.log({ newData, state: stateRef.current });
+ }
+ });
// Analyse collected variables to update state (only to STARTED state)
diff --git a/queen-v2/src/utils/hook/useConstCallback.js b/queen-v2/src/utils/hook/useConstCallback.js
new file mode 100644
index 00000000..0d60b5b1
--- /dev/null
+++ b/queen-v2/src/utils/hook/useConstCallback.js
@@ -0,0 +1,13 @@
+import { useRef, useState } from 'react';
+/**
+ * See https://github.com/garronej/powerhooks#useconstcallback for details
+ */
+export function useConstCallback(callback) {
+ const callbackRef = useRef();
+ callbackRef.current = callback;
+ return useState(
+ () =>
+ (...args) =>
+ callbackRef.current(...args)
+ )[0];
+}
diff --git a/queen-v2/src/utils/index.js b/queen-v2/src/utils/index.js
index 6c4b684e..2cef6543 100644
--- a/queen-v2/src/utils/index.js
+++ b/queen-v2/src/utils/index.js
@@ -1,12 +1,2 @@
export { default as addOnlineStatusObserver } from './online-status-observer';
export const getPercent = (n, length) => Math.round((100 * n) / length);
-
-export const goToTopPage = topRef => {
- if (topRef && topRef.current) {
- topRef.current.tabIndex = -1;
- topRef.current.focus();
- topRef.current.blur();
- window.scrollTo({ top: 0 });
- topRef.current.removeAttribute('tabindex');
- }
-};
diff --git a/queen-v2/src/utils/questionnaire/questionnaire.js b/queen-v2/src/utils/questionnaire/questionnaire.js
index 95de5b10..0360407e 100644
--- a/queen-v2/src/utils/questionnaire/questionnaire.js
+++ b/queen-v2/src/utils/questionnaire/questionnaire.js
@@ -1,4 +1,4 @@
-import { MIN_LUNATIC_MODEL_VERSION, MIN_ENO_CORE_VERSION } from 'utils/constants';
+import { MIN_ENO_CORE_VERSION, MIN_LUNATIC_MODEL_VERSION } from 'utils/constants';
const checkVersion = (actualVersion, expectedVersion) => {
try {
@@ -54,3 +54,25 @@ export const checkQuestionnaire = ({
}
return { valid: true };
};
+
+/**
+ *
+ * @param {*} source questionnaire source
+ * @param {*} variables object of key, value
+ */
+export const addGlobalVariablesToQuestionnaire = (source = {}, globalVariables = {}) => {
+ const { variables } = source;
+ const newVariables = Object.entries(globalVariables).reduce((result, [name, value]) => {
+ return [...result, { variableType: 'EXTERNAL', name: name, value: null }];
+ }, variables);
+ return { ...source, variables: newVariables };
+};
+
+export const addGlobalVariablesToData = (lunaticData = {}, globalVariables = {}) => {
+ const { EXTERNAL } = lunaticData;
+ const newEXTERNAL = Object.entries(globalVariables).reduce((result, [name, value]) => {
+ return { ...result, [name]: value };
+ }, EXTERNAL || {});
+
+ return { ...lunaticData, EXTERNAL: newEXTERNAL };
+};
diff --git a/queen-v2/src/utils/questionnaire/specialQueenData.js b/queen-v2/src/utils/questionnaire/specialQueenData.js
index c4154528..cc7a9af7 100644
--- a/queen-v2/src/utils/questionnaire/specialQueenData.js
+++ b/queen-v2/src/utils/questionnaire/specialQueenData.js
@@ -3,3 +3,41 @@ import * as lunatic from '@inseefr/lunatic';
export const getStateToSave = questionnaire => lunatic.getState(questionnaire);
export const getNotNullCollectedState = questionnaire =>
lunatic.getCollectedStateByValueType(questionnaire)('COLLECTED', false);
+
+export const getFullData = (oldData = {}, partialData = {}) => {
+ const {
+ CALCULATED: oldCALCULATED = {},
+ EXTERNAL: oldEXTERNAL = {},
+ COLLECTED: oldCOLLECTED = {},
+ } = oldData;
+ const {
+ CALCULATED: partialCALCULATED = {},
+ EXTERNAL: partialEXTERNAL = {},
+ COLLECTED: partialCOLLECTED = {},
+ } = partialData;
+
+ return {
+ CALCULATED: { ...oldCALCULATED, ...partialCALCULATED },
+ EXTERNAL: { ...oldEXTERNAL, ...partialEXTERNAL },
+ COLLECTED: { ...oldCOLLECTED, ...partialCOLLECTED },
+ };
+};
+
+export const removeNullCollectedData = (data = {}) => {
+ const { COLLECTED } = data;
+ let newCollected = Object.keys(COLLECTED).reduce((returnedValue, variableName) => {
+ const newContent = Object.keys(COLLECTED[variableName]).reduce((returnedContent, type) => {
+ if (COLLECTED[variableName][type] !== null) {
+ return { ...returnedContent, [type]: COLLECTED[variableName][type] };
+ }
+ return returnedContent;
+ }, {});
+
+ return { ...returnedValue, [variableName]: newContent };
+ }, {});
+
+ return {
+ ...data,
+ COLLECTED: newCollected,
+ };
+};
diff --git a/queen/package.json b/queen/package.json
index bd14eeea..aacf79ea 100644
--- a/queen/package.json
+++ b/queen/package.json
@@ -1,6 +1,6 @@
{
"name": "queen",
- "version": "0.10.19",
+ "version": "0.10.20",
"description": "Web application for the management of questionnaires powered by Lunatic",
"repository": {
"type": "git",
@@ -26,6 +26,7 @@
"prop-types": "^15.7.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
+ "react-error-boundary": "^4.0.11",
"react-keyboard-event-handler": "^1.5.4",
"react-markdown": "^5.0.3",
"react-router-dom": "^5.2.0",
diff --git a/queen/src/components/app/app.js b/queen/src/components/app/app.js
index 88a3fe03..c80bc426 100644
--- a/queen/src/components/app/app.js
+++ b/queen/src/components/app/app.js
@@ -1,10 +1,12 @@
import { AuthProvider } from 'components/auth';
import Rooter from 'components/router';
+import { ErrorFallback } from 'components/shared/Error/ErrorFallback';
import Preloader from 'components/shared/preloader';
import ServiceWorkerNotification from 'components/shared/serviceWorkerNotification';
import { StyleProvider } from 'components/style';
import D from 'i18n';
import React, { useEffect, useState } from 'react';
+import { ErrorBoundary } from 'react-error-boundary';
import { BrowserRouter } from 'react-router-dom';
import root from 'react-shadow/material-ui';
import { addOnlineStatusObserver } from 'utils';
@@ -28,18 +30,20 @@ const App = () => {
return (
- {configuration && (
-
-
-
-
-
-
-
-
-
-
- )}
+
+ {configuration && (
+
+
+
+
+
+
+
+
+
+
+ )}
+
{!configuration && }
);
diff --git a/queen/src/components/shared/Error/ErrorFallback.js b/queen/src/components/shared/Error/ErrorFallback.js
new file mode 100644
index 00000000..b3751f0c
--- /dev/null
+++ b/queen/src/components/shared/Error/ErrorFallback.js
@@ -0,0 +1,87 @@
+import {
+ Accordion,
+ AccordionDetails,
+ AccordionSummary,
+ Box,
+ Container,
+ Typography,
+ makeStyles,
+} from '@material-ui/core';
+import { ExpandMore } from '@material-ui/icons';
+import { dependencies, version } from '../../../../package.json';
+
+const lunaticVersion = dependencies['@inseefr/lunatic'].replace('^', '');
+
+const useStyles = makeStyles(theme => ({
+ root: {
+ position: 'relative',
+ top: '3em',
+ padding: '1em',
+ textAlign: 'center',
+ },
+ error: {
+ backgroundColor: 'white',
+ textAlign: 'left',
+ },
+ resetButton: {
+ marginTop: '1em',
+ color: 'white',
+ },
+ title: {
+ color: 'white',
+ margin: '0.5em',
+ },
+ alignBlock: {
+ textAlign: 'left',
+ display: 'block',
+ },
+}));
+
+export const ErrorFallback = ({ error }) => {
+ const classes = useStyles();
+ return (
+
+
+
+ {`QUEEN V1 :`}
+ {`Une erreur inconnue est survenue`}
+
+
+ }
+ aria-controls="panel1a-content"
+ id="panel1a-header"
+ >
+ {`Détail de l'erreur`}
+
+
+
+ {`Avant tout chose, veuillez vérifier que le questionnaire est compatible "lunatic-v1" 😉`}
+
+ {error.message}
+ {error.stack}
+
+
+
+ }
+ aria-controls="panel2a-content"
+ id="panel2a-header"
+ >
+ {`Information sur l'application`}
+
+
+
+ {`Version de Queen : `}
+ {version}
+
+
+ {`Version de Lunatic : `}
+ {lunaticVersion}
+
+
+
+
+
+ );
+};
diff --git a/queen/src/components/shared/ErrorBoundary/index.js b/queen/src/components/shared/ErrorBoundary/index.js
deleted file mode 100644
index e9db89a4..00000000
--- a/queen/src/components/shared/ErrorBoundary/index.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from 'react';
-import Error from '../Error';
-
-class ErrorBoundary extends React.Component {
- constructor(props) {
- super(props);
- this.state = { hasError: false };
- }
-
- static getDerivedStateFromError(error) {
- return { hasError: true };
- }
-
- // componentDidCatch(error, errorInfo) {}
-
- render() {
- if (this.state.hasError) {
- return ;
- }
-
- return this.props.children;
- }
-}
-
-export default ErrorBoundary;
diff --git a/yarn.lock b/yarn.lock
index 2818ca6c..06e723f1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1644,10 +1644,10 @@
remove-accents "^0.4.2"
sass "^1.32.2"
-"@inseefr/lunatic@^2.6.1":
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/@inseefr/lunatic/-/lunatic-2.6.1.tgz#00f71d1356fdc9e5807c6734dd8e02ceb61dc583"
- integrity sha512-VT9nvz4tdcdg/CgD40srtBQfPmJtrvsh5v96xBDLrNR6pK4UGGFGBkp1mPbq8Y6ulNGcwiGSUCitXz0WvTBSlQ==
+"@inseefr/lunatic@^2.7.4":
+ version "2.7.4"
+ resolved "https://registry.yarnpkg.com/@inseefr/lunatic/-/lunatic-2.7.4.tgz#1effadafd95d9333f73a84a3a0da0ac6b2c192c2"
+ integrity sha512-82+PRRChVK3DeyrhAVBCTYxVi9jTmqUbelWnfjHu4ktDqeRPk6Wm6LubcF3nn29Kzw46Vf7RsVmwi1RDj0+I6A==
dependencies:
"@inseefr/trevas" "^0.1.20"
"@inseefr/vtl-2.0-antlr-tools" "^0.1.0-bundle"
@@ -14063,6 +14063,13 @@ react-dom@^18.2.0:
loose-envify "^1.1.0"
scheduler "^0.23.0"
+react-error-boundary@^4.0.11:
+ version "4.0.11"
+ resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.11.tgz#36bf44de7746714725a814630282fee83a7c9a1c"
+ integrity sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+
react-error-overlay@^6.0.9:
version "6.0.11"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"