diff --git a/.env.development b/.env.development index 78bbd017..f14235d5 100644 --- a/.env.development +++ b/.env.development @@ -1,7 +1,6 @@ REACT_APP_STROMAE_BACK_OFFICE_API_BASE_URL=https://stromae-edt-kc.demo.insee.io/ REACT_APP_EDT_ORGANISATION_API_BASE_URL=https://edt-api-kc.demo.insee.io/ REACT_APP_KEYCLOAK_AUTHORITY=https://auth.demo.insee.io/auth/realms/questionnaires-edt/ -REACT_APP_KEYCLOAK_AUTHORITY_REVIEWER=https://auth.insee.io/auth/realms/questionnaires-particuliers/?kc_idp_hint=insee-ssp REACT_APP_KEYCLOAK_CLIENT_ID=client-edt REACT_APP_KEYCLOAK_REDIRECT_URI=http://localhost:3000/ REACT_APP_HOUSE_REFERENCE_REGULAR_EXPRESSION=.\$ @@ -9,4 +8,6 @@ REACT_APP_SEPARATOR_SUGGESTER=; REACT_APP_NODE_ENV="development" REACT_APP_CHROMIUM_PATH=node_modules/chromium/lib/chromium/chrome-win/chrome.exe REACT_APP_NUM_ACTIVITY_SURVEYS=6 -REACT_APP_NUM_WORKTIME_SURVEYS=3 \ No newline at end of file +REACT_APP_NUM_WORKTIME_SURVEYS=3 +REACT_APP_REVIEWER_ROLE=edt-reviewer +REACT_APP_SURVEYED_ROLE=repondant_coleman \ No newline at end of file diff --git a/.env.production b/.env.production index b0fb172b..70693bca 100644 --- a/.env.production +++ b/.env.production @@ -1,7 +1,6 @@ REACT_APP_STROMAE_BACK_OFFICE_API_BASE_URL=https://stromae-edt-kc.demo.insee.io/ REACT_APP_EDT_ORGANISATION_API_BASE_URL=https://edt-api-kc.demo.insee.io/ REACT_APP_KEYCLOAK_AUTHORITY=https://auth.demo.insee.io/auth/realms/questionnaires-edt/ -REACT_APP_KEYCLOAK_AUTHORITY_REVIEWER=https://auth.insee.io/auth/realms/questionnaires-particuliers/?kc_idp_hint=insee-ssp REACT_APP_KEYCLOAK_CLIENT_ID=client-edt REACT_APP_KEYCLOAK_REDIRECT_URI=https://insee-recette-edt.k8s.keyconsulting.fr/ REACT_APP_HOUSE_REFERENCE_REGULAR_EXPRESSION=.\$ @@ -9,4 +8,6 @@ REACT_APP_SEPARATOR_SUGGESTER=; REACT_APP_NODE_ENV="production" REACT_APP_CHROMIUM_PATH=/builds/insee/edt/deploy/pwa-edt/node_modules/chromium/lib/chromium/chrome-linux/chrome REACT_APP_NUM_ACTIVITY_SURVEYS=6 -REACT_APP_NUM_WORKTIME_SURVEYS=3 \ No newline at end of file +REACT_APP_NUM_WORKTIME_SURVEYS=3 +REACT_APP_REVIEWER_ROLE=edt-reviewer +REACT_APP_SURVEYED_ROLE=repondant_coleman \ No newline at end of file diff --git a/.env.staging b/.env.staging index 05323084..c623a30a 100644 --- a/.env.staging +++ b/.env.staging @@ -1,7 +1,6 @@ REACT_APP_STROMAE_BACK_OFFICE_API_BASE_URL=https://stromae-edt-kc.demo.insee.io/ REACT_APP_EDT_ORGANISATION_API_BASE_URL=https://edt-api-kc.demo.insee.io/ REACT_APP_KEYCLOAK_AUTHORITY=https://auth.demo.insee.io/auth/realms/questionnaires-edt/ -REACT_APP_KEYCLOAK_AUTHORITY_REVIEWER=https://auth.insee.io/auth/realms/questionnaires-particuliers/?kc_idp_hint=insee-ssp REACT_APP_KEYCLOAK_CLIENT_ID=client-edt REACT_APP_KEYCLOAK_REDIRECT_URI=https://insee-edt.k8s.keyconsulting.fr/ REACT_APP_HOUSE_REFERENCE_REGULAR_EXPRESSION=.\$ @@ -10,4 +9,6 @@ REACT_APP_NODE_ENV="staging" REACT_APP_CHROMIUM_PATH=/builds/insee/edt/deploy/pwa-edt/node_modules/chromium/lib/chromium/chrome-linux/chrome REACT_APP_NUM_ACTIVITY_SURVEYS=6 REACT_APP_NUM_WORKTIME_SURVEYS=3 -DISPLAY=:10.0 \ No newline at end of file +DISPLAY=:10.0 +REACT_APP_REVIEWER_ROLE=edt-reviewer +REACT_APP_SURVEYED_ROLE=repondant_coleman \ No newline at end of file diff --git a/README.md b/README.md index d65dd3d5..80b4594c 100644 --- a/README.md +++ b/README.md @@ -340,11 +340,11 @@ Those states have been defined to ease the visibility of the ongoing current sur ## Lifecycle state -![](https://imgur.com/Y3bjnVs.png) +![](./src/documentation/images/lifecycle_state.png) ### Project structure -![](https://i.imgur.com/Jt1FrnR.png) +![](./src/documentation/images/projet_structure.png) `src` : Contains all the source code of the application. It also has the 2 surveys sources required by Lunatic and used by EDT. @@ -392,7 +392,7 @@ SSO is available using INSEE LDAP only with users with reviewer role. The review #### Architecture schema -![](https://i.imgur.com/Q3sKoCe.png) +![](./src/documentation/images/schema_architecture.png) #### API Edt-pilotage @@ -976,7 +976,7 @@ The `.env.production` file is used when the builded app is hosted. REACT_APP_STROMAE_BACK_OFFICE_API_BASE_URL=https://stromae-edt-kc.demo.insee.io/ REACT_APP_EDT_ORGANISATION_API_BASE_URL=https://edt-api-kc.demo.insee.io/ REACT_APP_KEYCLOAK_AUTHORITY=https://auth.demo.insee.io/auth/realms/questionnaires-edt/ -REACT_APP_KEYCLOAK_AUTHORITY_REVIEWER=https://auth.insee.io/auth/realms/questionnaires-particuliers/?kc_idp_hint=insee-ssp +REACT_APP_KEYCLOAK_AUTHORITY_REVIEWER=https://auth.insee.io/auth/realms/questionnaires-particuliers/ REACT_APP_KEYCLOAK_CLIENT_ID=client-edt REACT_APP_KEYCLOAK_REDIRECT_URI=https://insee-recette-edt.k8s.keyconsulting.fr/ REACT_APP_HOUSE_REFERENCE_REGULAR_EXPRESSION=.\$ @@ -1019,7 +1019,7 @@ Even if you create a path, it never passes through this component, so we cannot The callbackHolder function recovers the data and the errors which give us lunatic. -![](https://imgur.com/SNpbvje.png) +![](./src/documentation/images/orchestrator_code.png) The getData() function provided by lunatic, instead of returning it within callbackHolder, we proceed to process the data recovered by lunatic, to be able to transform that data, along with that of the database and obtain our data model filled with the COLLECTED and EDITED. @@ -1038,9 +1038,7 @@ For each existing property : - **value of COLLECTED:** data of lunatic *(callbackholder.getData()[prop].COLLECTED)*; - -![](https://imgur.com/JCtEcUC.png) - +![](./src/documentation/images/orchestrator_code_interviewer.png) If the user is a reviewer, the data is treated as follows: @@ -1076,11 +1074,11 @@ value of lunatic for value[iteration], other -> value of bdd (EDITED) - **value of EDITED:** data of bbdd *(data[prop].EDITED)*; - **value of COLLECTED:** data of bbdd *(data[prop].COLLECTED)*; -![](https://imgur.com/PNZL2hu.png) +![](./src/documentation/images/orchestrator_code_reviewer.png) Here a diagram of the flow of orchestrator data -![Orchestrator data flow](https://imgur.com/yYYqvSJ.png) +![Orchestrator data flow](./src/documentation/images/orchestrator_flow.png) ## Maintenance and evolution diff --git a/e2e/mocks/activitySurveySource.json b/e2e/mocks/activitySurveySource.json index f7f8063f..a73e7c61 100644 --- a/e2e/mocks/activitySurveySource.json +++ b/e2e/mocks/activitySurveySource.json @@ -850,7 +850,7 @@ "name": "OTHERPRIVATE" }, "id": "5", - "label": "\"Autre moyen privé (monorue,kk trottinette ou skate, bateau, électrique ou non...)\"" + "label": "\"Autre moyen privé (monoroue, trottinette ou skate, bateau, électrique ou non...)\"" }, { "response": { diff --git a/package.json b/package.json index c2800e0a..ee058617 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "edt", - "version": "3.10.3", - "dateVersion": "09/01/2024", + "version": "3.12.4", + "dateVersion": "20/02/2024", "licence": "MIT", "dependencies": { "@emotion/react": "^11.10.4", "@emotion/styled": "^11.10.4", "@inseefr/lunatic": "2.0.7-v2", - "@inseefrlab/lunatic-edt": "^0.11.7", + "@inseefrlab/lunatic-edt": "^0.12.1", "@mui/material": "^5.10.7", "@mui/styles": "^5.12.0", "@react-pdf/font": "2.2.0", @@ -62,6 +62,7 @@ "@typescript-eslint/eslint-plugin": "^5.38.0", "@typescript-eslint/parser": "^5.38.0", "concurrently": "^7.4.0", + "dayjs": "^1.11.5", "eslint": "^7.11.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-storybook": "^0.6.4", @@ -75,8 +76,7 @@ "prettier": "^2.7.1", "react-app-rewired": "^2.2.1", "tsc-watch": "^5.0.3", - "typescript": "^4.8.3", - "dayjs": "^1.11.5" + "typescript": "^4.8.3" }, "scripts": { "start": "react-scripts start", diff --git a/src/App.scss b/src/App.scss index 232e9230..00836261 100644 --- a/src/App.scss +++ b/src/App.scss @@ -12,6 +12,13 @@ html, body { min-height: 100vh; overflow: hidden !important; padding: 0 !important; + position: fixed; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + border: none; + z-index: 2147483647; } #root { diff --git a/src/App.tsx b/src/App.tsx index 33d4b547..456ed2d8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,7 +10,7 @@ import { useTranslation } from "react-i18next"; import { EdtRoutes } from "routes/EdtRoutes"; import { getDatas, initializeDatas, initializeListSurveys } from "service/survey-service"; import { getUserRights, setAuth, setUser, setUserToken } from "service/user-service"; - +import { getCookie } from "utils/utils"; const App = () => { const { t } = useTranslation(); const [initialized, setInitialized] = useState(false); @@ -30,53 +30,46 @@ const App = () => { }; useEffect(() => { + if ( + window.location.search && + getCookie("KC_RESTART") == null && + localStorage.getItem("setauth") == null + ) { + localStorage.setItem("setauth", "yes"); + window.location.search = ""; + } + if (auth?.userData?.access_token && getDatas().size === 0 && error === undefined) { setUserToken(auth.userData?.access_token); setUser(auth.userData); - } - - setAuth(auth); - //keeps user token up to date after session renewal - auth.userManager?.events.addUserLoaded(() => { - auth.userManager.getUser().then(user => { - setUserToken(user?.access_token || ""); + setAuth(auth); + //keeps user token up to date after session renewal + auth.userManager.events.addUserLoaded(() => { + auth.userManager.getUser().then(user => { + setUserToken(user?.access_token || ""); + }); }); - }); - - auth.userManager?.events.addSilentRenewError(() => { - if (navigator.onLine) { - auth.userManager - .signoutRedirect({ - id_token_hint: getTokenHint(), - }) - .then(() => auth.userManager.clearStaleState()) - .then(() => auth.userManager.signoutRedirectCallback()) - .then(() => { - sessionStorage.clear(); - localStorage.clear(); - }) - .then(() => auth.userManager.clearStaleState()) - .then(() => window.location.replace(process.env.REACT_APP_PUBLIC_URL || "")) - .catch(err => { - setErrorType(err); - }); - } - }); - auth.userManager?.settings.userStore.getAllKeys().then(keys => { - auth.userManager.settings.stateStore.getAllKeys().then(keysState => { - if ( - window.location.search.includes("state") && - auth.userData == null && - keys.length == 0 && - keysState.length == 0 - ) { - window.location.search = ""; + auth.userManager.events.addSilentRenewError(() => { + if (navigator.onLine) { + auth.userManager + .signoutRedirect({ + id_token_hint: getTokenHint(), + }) + .then(() => auth.userManager.clearStaleState()) + .then(() => auth.userManager.signoutRedirectCallback()) + .then(() => { + sessionStorage.clear(); + localStorage.clear(); + }) + .then(() => auth.userManager.clearStaleState()) + .then(() => window.location.replace(process.env.REACT_APP_PUBLIC_URL || "")) + .catch(err => { + setErrorType(err); + }); } }); - }); - if (auth.userData) { initializeDatas(setError).then(() => { setInitialized(true); }); @@ -89,7 +82,7 @@ const App = () => { } }, [auth]); - const renderErrorOrLoadingPage = () => { + const errorOrLoadingPage = () => { return !error ? ( { ); }; - return <>{initialized && !error ? : renderErrorOrLoadingPage()}; + return <>{initialized && !error ? : errorOrLoadingPage()}; }; export default App; diff --git a/src/activity-survey.json b/src/activity-survey.json index 3637547f..9f289788 100644 --- a/src/activity-survey.json +++ b/src/activity-survey.json @@ -513,6 +513,30 @@ "name": "ISLOCKED", "componentRef": "" }, + { + "variableType": "COLLECTED", + "values": { + "COLLECTED": null, + "EDITED": null, + "INPUTED": null, + "FORCED": null, + "PREVIOUS": null + }, + "name": "QUALITY_SCORE", + "componentRef": "" + }, + { + "variableType": "COLLECTED", + "values": { + "COLLECTED": null, + "EDITED": null, + "INPUTED": null, + "FORCED": null, + "PREVIOUS": null + }, + "name": "QUALITY_SCORE_SUBSTRACT_POINTS", + "componentRef": "" + }, { "variableType": "CALCULATED", "expression": "true", @@ -907,7 +931,7 @@ "name": "OTHERPRIVATE" }, "id": "5", - "label": "\"Autre moyen privé (monorue,kk trottinette ou skate, bateau, électrique ou non...)\"" + "label": "\"Autre moyen privé (monoroue, trottinette ou skate, bateau, électrique ou non...)\"" }, { "response": { diff --git a/src/assets/illustration/install/ios/edge2.svg b/src/assets/illustration/install/ios/edge2.svg index 7807978a..6022677c 100644 --- a/src/assets/illustration/install/ios/edge2.svg +++ b/src/assets/illustration/install/ios/edge2.svg @@ -1,27 +1,33 @@ - - - - Laura - Laura - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + diff --git a/src/components/commons/InstallPageStep/InstallPageStep.tsx b/src/components/commons/InstallPageStep/InstallPageStep.tsx index 41f34860..49cc7cb3 100644 --- a/src/components/commons/InstallPageStep/InstallPageStep.tsx +++ b/src/components/commons/InstallPageStep/InstallPageStep.tsx @@ -3,7 +3,7 @@ import { Box } from "@mui/material"; import InfoIcon from "assets/illustration/info.svg"; import { EdtRoutesNameEnum } from "enumerations/EdtRoutesNameEnum"; import { useCallback } from "react"; -import { isMobile as isMobileDevice, isIOS } from "react-device-detect"; +import { isIOS, isMobile as isMobileDevice } from "react-device-detect"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { getNavigatePath } from "service/navigation-service"; diff --git a/src/components/commons/Responsive/Responsive.tsx b/src/components/commons/Responsive/Responsive.tsx index 6968f850..2487274a 100644 --- a/src/components/commons/Responsive/Responsive.tsx +++ b/src/components/commons/Responsive/Responsive.tsx @@ -22,4 +22,4 @@ const Default = ({ children }: ResponsiveProps) => { return isNotMobile ? <>{children} : <>; }; -export { Desktop, Tablet, Mobile, Default }; +export { Default, Desktop, Mobile, Tablet }; diff --git a/src/components/commons/SurveyPage/SurveyPageStep/SurveyPageStep.tsx b/src/components/commons/SurveyPage/SurveyPageStep/SurveyPageStep.tsx index eb9db393..db2d36d3 100644 --- a/src/components/commons/SurveyPage/SurveyPageStep/SurveyPageStep.tsx +++ b/src/components/commons/SurveyPage/SurveyPageStep/SurveyPageStep.tsx @@ -69,8 +69,9 @@ const SurveyPageStep = (props: SurveyPageStepProps) => { const { classes, cx } = useStyles({ "isMobile": !isPwa(), "isIOS": isIOS, - "isOpen": context.isOpenHeader ?? false, + "iosHeight": context.isOpenHeader ? "80vh" : "87vh", "withStepper": isStep, + "innerHeight": window.innerHeight, }); const stepData = getStepData(currentPage); @@ -131,19 +132,17 @@ const SurveyPageStep = (props: SurveyPageStepProps) => { modifiable: modifiable, }; - const nextRouteNav = useCallback(() => { - if (validateButton) { - return validateButton; - } else { - nextRoute - ? saveAndNavFullPath(idSurvey, nextRoute) - : saveAndNextStep(idSurvey, context.source, context.surveyRootPage, currentPage); - } - }, []); - const surveyPageNotStepProps = { idSurvey: idSurvey, - validate: nextRouteNav, + validate: + validateButton ?? + useCallback( + () => + nextRoute + ? saveAndNavFullPath(idSurvey, nextRoute) + : saveAndNextStep(idSurvey, context.source, context.surveyRootPage, currentPage), + [], + ), srcIcon: errorIcon, altIcon: errorAltIcon ? t(errorAltIcon) : undefined, onNavigateBack: useCallback(() => saveAndNav(idSurvey), []), @@ -203,18 +202,15 @@ const SurveyPageStep = (props: SurveyPageStepProps) => { ); }; -const stylePageMobileTabletWhenIOS = (isOpen: boolean) => { - return isOpen ? "80vh" : "87vh"; -}; - const useStyles = makeStylesEdt<{ isMobile: boolean; isIOS: boolean; - isOpen: boolean; + iosHeight: string; withStepper: boolean; + innerHeight: number; }>({ "name": { SurveyPageStep }, -})((theme, { isIOS, isOpen, withStepper }) => ({ +})((theme, { isIOS, iosHeight, withStepper, innerHeight }) => ({ bottomPadding: { paddingBottom: "4rem", }, @@ -222,8 +218,8 @@ const useStyles = makeStylesEdt<{ height: withStepper ? "90%" : "100%", }, pageMobileTablet: { - height: "100%", - maxHeight: isIOS ? stylePageMobileTabletWhenIOS(isOpen) : "94vh", + maxHeight: isIOS ? iosHeight : innerHeight + "px", + height: isIOS ? "100%" : innerHeight + "px", }, })); diff --git a/src/components/edt/DayCard/DayCard.tsx b/src/components/edt/DayCard/DayCard.tsx index 4c86fc6c..e5713e68 100644 --- a/src/components/edt/DayCard/DayCard.tsx +++ b/src/components/edt/DayCard/DayCard.tsx @@ -45,7 +45,7 @@ const DayCard = (props: DayCardProps) => { const progressActivity = getScore(idSurvey, t); const modeReviewer = getIsModeReviewer(); const { activitiesRoutesOrGaps, overlaps } = getActivitiesOrRoutes(t, idSurvey); - const qualityScore = getQualityScore(activitiesRoutesOrGaps, overlaps, t); + const qualityScore = getQualityScore(idSurvey, activitiesRoutesOrGaps, overlaps, t).group; const stateSurvey = getStatutSurvey(idSurvey); const isItMobile = isMobile(); @@ -229,6 +229,8 @@ const useStyles = makeStylesEdt({ "name": { DayCard } })(theme => ({ display: "flex", flexDirection: "column", alignItems: "center", + textAlign: "center", + minWidth: "67px", }, qualityScoreText: { color: theme.palette.secondary.main, diff --git a/src/components/edt/HelpMenu/HelpMenuInner.tsx b/src/components/edt/HelpMenu/HelpMenuInner.tsx index 40f474b0..bb0b80de 100644 --- a/src/components/edt/HelpMenu/HelpMenuInner.tsx +++ b/src/components/edt/HelpMenu/HelpMenuInner.tsx @@ -50,42 +50,39 @@ const HelpMenuInner = (props: HelpMenuInnerProps) => { {t("accessibility.asset.help-menu.contact-alt")} - - {getDeviceNavigatorIsAvaiableForInstall() && ( - <> - - - {t("accessibility.asset.help-menu.install-alt")} - - -

{t("component.help-menu.install-label")}

-
- - {t("accessibility.asset.mui-icon.arrow-forward-ios")} - + +

{t("component.help-menu.contact-label")}

+
+ + {t("accessibility.asset.mui-icon.arrow-forward-ios")} + +
+ + {getDeviceNavigatorIsAvaiableForInstall() && ( + <> + + + {t("accessibility.asset.help-menu.install-alt")} + + +

{t("component.help-menu.install-label")}

+
+ + {t("accessibility.asset.mui-icon.arrow-forward-ios")} - - - )} - - - {t("accessibility.asset.help-menu.help-alt")} - - -

{t("component.help-menu.help-label")}

-
- - {t("accessibility.asset.mui-icon.arrow-forward-ios")} + + + )} + + + {t("accessibility.asset.help-menu.help-alt")}

{t("component.help-menu.help-label")}

diff --git a/src/documentation/README.md b/src/documentation/README.md index 1881c717..ec03803e 100644 --- a/src/documentation/README.md +++ b/src/documentation/README.md @@ -296,8 +296,7 @@ It contains all the survey "fields" components and an associated storybook docum ### Initial survey state -A surveyed, when loggin in the first time, will be able to see REACT_APP_NUM_ACTIVITY_SURVEYS (total amount of activity surveys, accessible in env file) activity surveys and -REACT_APP_NUM_WORKTIME_SURVEYS work time surveys. +A surveyed, when loggin in the first time, will be able to see all of activity surveys and work time surveys recovered by the API. When a survey has never been started, no data are visible in the indexedDB. @@ -340,11 +339,11 @@ Those states have been defined to ease the visibility of the ongoing current sur ## Lifecycle state -![](https://imgur.com/Y3bjnVs.png) +![](./images/lifecycle_state.png) ### Project structure -![](https://i.imgur.com/Jt1FrnR.png) +![](./images/projet_structure.png) `src` : Contains all the source code of the application. It also has the 2 surveys sources required by Lunatic and used by EDT. @@ -374,12 +373,12 @@ Those states have been defined to ease the visibility of the ongoing current sur EDT is using a Keycloak for authentification. It uses `oidc-react` (https://github.com/bjerkio/oidc-react) to manage the connection between the Keycloak and the app. You can find the oidc config inside the `src/index.tsx` file. -These two environment variables are used to setup the connection : +These three environment variables are used to setup the connection : ``` REACT_APP_KEYCLOAK_AUTHORITY=https://auth.demo.insee.io/auth/realms/questionnaires-edt/ -REACT_APP_KEYCLOAK_AUTHORITY_REVIEWER=https://auth.insee.io/auth/realms/questionnaires-particuliers/?kc_idp_hint=insee-ssp REACT_APP_KEYCLOAK_CLIENT_ID=client-edt +REACT_APP_KEYCLOAK_REDIRECT_URI=https://insee-recette-edt.k8s.keyconsulting.fr/ ``` The user bearer token is used to call the secured APIs. @@ -392,7 +391,7 @@ SSO is available using INSEE LDAP only with users with reviewer role. The review #### Architecture schema -![](https://i.imgur.com/Q3sKoCe.png) +![](./images/schema_architecture.png) #### API Edt-pilotage @@ -565,6 +564,8 @@ https://github.com/InseeFr/Queen-Back-Office ## Services `alert-service.ts` : Used to get alert content. +`auth-service.ts` : Contains config for SSO authentification. + `api-service.ts` : Contains all API calls. `loop-service.ts` : Used to handle loop size and loop data to recover the current state of the navigation. @@ -652,48 +653,79 @@ Usage : this enumeration is used to define the nomenclature ids that are used by ``` export enum FieldNameEnum { -LASTNAME = "LASTNAME", FIRSTNAME = "FIRSTNAME", SURVEYDATE = "SURVEYDATE", -START_TIME = "START_TIME", -END_TIME = "END_TIME", -MAINACTIVITY_ID = "MAINACTIVITY_ID", -MAINACTIVITY_SUGGESTERID = "MAINACTIVITY_SUGGESTERID", -MAINACTIVITY_ISFULLYCOMPLETED = "MAINACTIVITY_ISFULLYCOMPLETED", -MAINACTIVITY_LABEL = "MAINACTIVITY_LABEL", -INPUT_SUGGESTER = "INPUT_SUGGESTER", -ACTIVITY_SELECTER_HISTORY = "ACTIVITY_SELECTER_HISTORY", -ROUTE = "ROUTE", -GOAL = "GOAL", -WITHSECONDARYACTIVITY = "WITHSECONDARYACTIVITY", -SECONDARYACTIVITY = "SECONDARYACTIVITY", -SECONDARYACTIVITY_LABEL = "SECONDARYACTIVITY_LABEL", -MEANOFTRANSPORT = "MEANOFTRANSPORT", -PLACE = "PLACE", -WITHSOMEONE = "WITHSOMEONE", -COUPLE = "COUPLE", -PARENTS = "PARENTS", -CHILD = "CHILD", -OTHERKNOWN = "OTHERKNOWN", -OTHER = "OTHER", -WITHSCREEN = "WITHSCREEN", -WEEKLYPLANNER = "WEEKLYPLANNER", -WEEKTYPE = "WEEKTYPE", -WORKINGWEEK = "WORKINGWEEK", -HOLIDAYWEEK = "HOLIDAYWEEK", -OTHERWEEK = "OTHERWEEK", -GREATESTACTIVITYDAY = "GREATESTACTIVITYDAY", -WORSTACTIVITYDAY = "WORSTACTIVITYDAY", -KINDOFDAY = "KINDOFDAY", -EXCEPTIONALDAY = "EXCEPTIONALDAY", -TRAVELTIME = "TRAVELTIME", -PHONETIME = "PHONETIME", -ISCLOSED = "ISCLOSED", -ISENVOYED = "ISENVOYED", -ISROUTE = "ISROUTE", -ISCOMPLETED = "ISCOMPLETED", -ISVALIDATED = "ISVALIDATED", -ISLOCKED = "ISLOCKED", + + //TIME + START_TIME = "START_TIME", + END_TIME = "END_TIME", + + //SUGGESTER + INPUT_SUGGESTER = "INPUT_SUGGESTER", + + //PLACE + PLACE = "PLACE", + + //WITH SOMEONE + WITHSOMEONE = "WITHSOMEONE", + COUPLE = "COUPLE", + PARENTS = "PARENTS", + CHILD = "CHILD", + OTHERKNOWN = "OTHERKNOWN", + OTHER = "OTHER", + WITHSCREEN = "WITHSCREEN", + + // VARIABLES CLOTURE + + GREATESTACTIVITYDAY = "GREATESTACTIVITYDAY", + WORSTACTIVITYDAY = "WORSTACTIVITYDAY", + KINDOFDAY = "KINDOFDAY", + EXCEPTIONALDAY = "EXCEPTIONALDAY", + TRAVELTIME = "TRAVELTIME", + PHONETIME = "PHONETIME", + + ISCLOSED = "ISCLOSED", //SURVEY CLOSED + ISENVOYED = "ISENVOYED", //SURVEY ENVOYED + ISROUTE = "ISROUTE", // IS ROUTE + ISCOMPLETED = "ISCOMPLETED", // ALL VARIABLES SET FOR SURVEY + ISVALIDATED = "ISVALIDATED", //SURVEY VALIDATED + ISLOCKED = "ISLOCKED", //SURVEY LOCKED + + //ACTIVITY + + //MAIN ACTIVITY + ACTIVITY_SELECTER_HISTORY = "ACTIVITY_SELECTER_HISTORY", + MAINACTIVITY_ID = "MAINACTIVITY_ID", + MAINACTIVITY_SUGGESTERID = "MAINACTIVITY_SUGGESTERID", + MAINACTIVITY_ISFULLYCOMPLETED = "MAINACTIVITY_ISFULLYCOMPLETED", + MAINACTIVITY_LABEL = "MAINACTIVITY_LABEL", + GOAL = "GOAL", + + //SECONDARY ACTIVITY + WITHSECONDARYACTIVITY = "WITHSECONDARYACTIVITY", + SECONDARYACTIVITY = "SECONDARYACTIVITY", + SECONDARYACTIVITY_LABEL = "SECONDARYACTIVITY_LABEL", + SECONDARYACTIVITY_SUGGESTERID = "SECONDARYACTIVITY_SUGGESTERID", + + //SCORE + QUALITY_SCORE = "QUALITY_SCORE", //QUALITY SCORE + QUALITY_SCORE_SUBSTRACT_POINTS = "QUALITY_SCORE_SUBSTRACT_POINTS", //POINT TO SUBSTRACT FOR CALCULATE SCORE + + //ROUTE + ROUTE = "ROUTE", + FOOT = "FOOT", + BICYCLE = "BICYCLE", + TWOWHEELSMOTORIZED = "TWOWHEELSMOTORIZED", + PRIVATECAR = "PRIVATECAR", + OTHERPRIVATE = "OTHERPRIVATE", + PUBLIC = "PUBLIC", + + //WEEKLY PLANNER + WEEKLYPLANNER = "WEEKLYPLANNER", + DATES = "DATES", + DATES_STARTED = "DATES_STARTED", + WEEKTYPE = "WEEKTYPE", + } ``` @@ -777,25 +809,25 @@ let mappingPageOrchestrator: OrchestratorEdtNavigation[] = [ { parentPage: EdtRoutesNameEnum.ACTIVITY, page: EdtRoutesNameEnum.WHO_ARE_YOU, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: "1", }, { parentPage: EdtRoutesNameEnum.ACTIVITY, page: EdtRoutesNameEnum.DAY_OF_SURVEY, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: "2", }, { parentPage: EdtRoutesNameEnum.ACTIVITY, page: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: "3", }, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.ACTIVITY_DURATION, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "2", surveyStep: 1, @@ -803,7 +835,7 @@ surveyStep: 1, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.MAIN_ACTIVITY, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "3", surveyStep: 2, @@ -811,7 +843,7 @@ surveyStep: 2, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.ROUTE, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "4", surveyStep: 2, @@ -819,7 +851,7 @@ surveyStep: 2, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.MEAN_OF_TRANSPORT, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "5", surveyStep: 3, @@ -827,7 +859,7 @@ surveyStep: 3, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.SECONDARY_ACTIVITY, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "6", surveyStep: 3, @@ -835,7 +867,7 @@ surveyStep: 3, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.ACTIVITY_LOCATION, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "7", surveyStep: 4, @@ -843,7 +875,7 @@ surveyStep: 4, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.WITH_SOMEONE, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "8", surveyStep: 5, @@ -851,7 +883,7 @@ surveyStep: 5, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.WITH_SCREEN, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "9", surveyStep: 6, @@ -859,7 +891,7 @@ surveyStep: 6, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.MAIN_ACTIVITY_GOAL, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "10", surveyStep: 2, @@ -867,7 +899,7 @@ surveyStep: 2, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.SECONDARY_ACTIVITY_SELECTION, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "11", surveyStep: 3, @@ -875,7 +907,7 @@ surveyStep: 3, { parentPage: EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER, page: EdtRoutesNameEnum.WITH_SOMEONE_SELECTION, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: getLoopInitialPage(LoopEnum.ACTIVITY_OR_ROUTE), surveySubPage: "12", surveyStep: 5, @@ -883,73 +915,73 @@ surveyStep: 5, { parentPage: EdtRoutesNameEnum.ACTIVITY, page: EdtRoutesNameEnum.GREATEST_ACTIVITY_DAY, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: "5", }, { parentPage: EdtRoutesNameEnum.ACTIVITY, page: EdtRoutesNameEnum.WORST_ACTIVITY_DAY, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: "6", }, { parentPage: EdtRoutesNameEnum.ACTIVITY, page: EdtRoutesNameEnum.KIND_OF_DAY, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: "7", }, { parentPage: EdtRoutesNameEnum.ACTIVITY, page: EdtRoutesNameEnum.EXCEPTIONAL_DAY, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: "8", }, { parentPage: EdtRoutesNameEnum.ACTIVITY, page: EdtRoutesNameEnum.TRAVEL_TIME, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: "9", }, { parentPage: EdtRoutesNameEnum.ACTIVITY, page: EdtRoutesNameEnum.PHONE_TIME, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: "10", }, { parentPage: EdtRoutesNameEnum.ACTIVITY, page: EdtRoutesNameEnum.EDIT_GLOBAL_INFORMATION, -surveySource: "activity-survey.json", +surveySource: SourcesEnum.ACTIVITY_SURVEY, surveyPage: "3", }, { parentPage: EdtRoutesNameEnum.WORK_TIME, page: EdtRoutesNameEnum.WHO_ARE_YOU, -surveySource: "work-time-survey.json", +surveySource: SourcesEnum.WORK_TIME_SURVEY, surveyPage: "1", }, { parentPage: EdtRoutesNameEnum.WORK_TIME, page: EdtRoutesNameEnum.DAY_OF_SURVEY, -surveySource: "work-time-survey.json", +surveySource: SourcesEnum.WORK_TIME_SURVEY, surveyPage: "2", }, { parentPage: EdtRoutesNameEnum.WORK_TIME, page: EdtRoutesNameEnum.WEEKLY_PLANNER, -surveySource: "work-time-survey.json", +surveySource: SourcesEnum.WORK_TIME_SURVEY, surveyPage: "3", }, { parentPage: EdtRoutesNameEnum.WORK_TIME, page: EdtRoutesNameEnum.KIND_OF_WEEK, -surveySource: "work-time-survey.json", +surveySource: SourcesEnum.WORK_TIME_SURVEY, surveyPage: "4", }, { parentPage: EdtRoutesNameEnum.WORK_TIME, page: EdtRoutesNameEnum.EDIT_GLOBAL_INFORMATION, -surveySource: "work-time-survey.json", +surveySource: SourcesEnum.WORK_TIME_SURVEY, surveyPage: "5", }, ]; @@ -1019,7 +1051,7 @@ Even if you create a path, it never passes through this component, so we cannot The callbackHolder function recovers the data and the errors which give us lunatic. -![](https://imgur.com/SNpbvje.png) +![](./images/orchestrator_code.png) The getData() function provided by lunatic, instead of returning it within callbackHolder, we proceed to process the data recovered by lunatic, to be able to transform that data, along with that of the database and obtain our data model filled with the COLLECTED and EDITED. @@ -1038,9 +1070,7 @@ For each existing property : - **value of COLLECTED:** data of lunatic *(callbackholder.getData()[prop].COLLECTED)*; - -![](https://imgur.com/JCtEcUC.png) - +![](./images/orchestrator_code_interviewer.png) If the user is a reviewer, the data is treated as follows: @@ -1076,11 +1106,14 @@ value of lunatic for value[iteration], other -> value of bdd (EDITED) - **value of EDITED:** data of bbdd *(data[prop].EDITED)*; - **value of COLLECTED:** data of bbdd *(data[prop].COLLECTED)*; -![](https://imgur.com/PNZL2hu.png) +![](./images/orchestrator_code_reviewer.png) Here a diagram of the flow of orchestrator data -![Orchestrator data flow](https://imgur.com/yYYqvSJ.png) +![Orchestrator data flow](./images/orchestrator_flow.png) + +#### Examples + ## Maintenance and evolution diff --git a/src/documentation/images/lifecycle_state.png b/src/documentation/images/lifecycle_state.png new file mode 100644 index 00000000..7a1cb2eb Binary files /dev/null and b/src/documentation/images/lifecycle_state.png differ diff --git a/src/documentation/images/orchestrator_code.png b/src/documentation/images/orchestrator_code.png new file mode 100644 index 00000000..5705e7c9 Binary files /dev/null and b/src/documentation/images/orchestrator_code.png differ diff --git a/src/documentation/images/orchestrator_code_interviewer.png b/src/documentation/images/orchestrator_code_interviewer.png new file mode 100644 index 00000000..4499b3cd Binary files /dev/null and b/src/documentation/images/orchestrator_code_interviewer.png differ diff --git a/src/documentation/images/orchestrator_code_reviewer.png b/src/documentation/images/orchestrator_code_reviewer.png new file mode 100644 index 00000000..d7ec90da Binary files /dev/null and b/src/documentation/images/orchestrator_code_reviewer.png differ diff --git a/src/documentation/images/orchestrator_flow.png b/src/documentation/images/orchestrator_flow.png new file mode 100644 index 00000000..92f92275 Binary files /dev/null and b/src/documentation/images/orchestrator_flow.png differ diff --git a/src/documentation/images/projet_structure.png b/src/documentation/images/projet_structure.png new file mode 100644 index 00000000..385d64a0 Binary files /dev/null and b/src/documentation/images/projet_structure.png differ diff --git a/src/documentation/images/schema_architecture.png b/src/documentation/images/schema_architecture.png new file mode 100644 index 00000000..6e76a9cd Binary files /dev/null and b/src/documentation/images/schema_architecture.png differ diff --git a/src/enumerations/FieldNameEnum.ts b/src/enumerations/FieldNameEnum.ts index dd37394b..121a6995 100644 --- a/src/enumerations/FieldNameEnum.ts +++ b/src/enumerations/FieldNameEnum.ts @@ -1,28 +1,95 @@ export enum FieldNameEnum { - LASTNAME = "LASTNAME", + //VAR COMMMONS FIRSTNAME = "FIRSTNAME", SURVEYDATE = "SURVEYDATE", + + //TIME START_TIME = "START_TIME", END_TIME = "END_TIME", + + //SUGGESTER + INPUT_SUGGESTER = "INPUT_SUGGESTER", + + //PLACE + PLACE = "PLACE", + + //WITH SOMEONE + WITHSOMEONE = "WITHSOMEONE", + COUPLE = "COUPLE", + PARENTS = "PARENTS", + CHILD = "CHILD", + OTHERKNOWN = "OTHERKNOWN", + OTHER = "OTHER", + WITHSCREEN = "WITHSCREEN", + + // VARIABLES CLOTURE + + GREATESTACTIVITYDAY = "GREATESTACTIVITYDAY", + WORSTACTIVITYDAY = "WORSTACTIVITYDAY", + KINDOFDAY = "KINDOFDAY", + EXCEPTIONALDAY = "EXCEPTIONALDAY", + TRAVELTIME = "TRAVELTIME", + PHONETIME = "PHONETIME", + + ISCLOSED = "ISCLOSED", //SURVEY CLOSED + ISENVOYED = "ISENVOYED", //SURVEY ENVOYED + ISROUTE = "ISROUTE", // IS ROUTE + ISCOMPLETED = "ISCOMPLETED", // ALL VARIABLES SET FOR SURVEY + ISVALIDATED = "ISVALIDATED", //SURVEY VALIDATED + ISLOCKED = "ISLOCKED", //SURVEY LOCKED + + //ACTIVITY + + //MAIN ACTIVITY + ACTIVITY_SELECTER_HISTORY = "ACTIVITY_SELECTER_HISTORY", MAINACTIVITY_ID = "MAINACTIVITY_ID", MAINACTIVITY_SUGGESTERID = "MAINACTIVITY_SUGGESTERID", MAINACTIVITY_ISFULLYCOMPLETED = "MAINACTIVITY_ISFULLYCOMPLETED", MAINACTIVITY_LABEL = "MAINACTIVITY_LABEL", - INPUT_SUGGESTER = "INPUT_SUGGESTER", - ACTIVITY_SELECTER_HISTORY = "ACTIVITY_SELECTER_HISTORY", - ROUTE = "ROUTE", GOAL = "GOAL", + + //SECONDARY ACTIVITY WITHSECONDARYACTIVITY = "WITHSECONDARYACTIVITY", SECONDARYACTIVITY = "SECONDARYACTIVITY", SECONDARYACTIVITY_LABEL = "SECONDARYACTIVITY_LABEL", SECONDARYACTIVITY_SUGGESTERID = "SECONDARYACTIVITY_SUGGESTERID", + + //SCORE + QUALITY_SCORE = "QUALITY_SCORE", //QUALITY SCORE + QUALITY_SCORE_SUBSTRACT_POINTS = "QUALITY_SCORE_SUBSTRACT_POINTS", //POINT TO SUBSTRACT FOR CALCULATE SCORE + + //ROUTE + ROUTE = "ROUTE", FOOT = "FOOT", BICYCLE = "BICYCLE", TWOWHEELSMOTORIZED = "TWOWHEELSMOTORIZED", PRIVATECAR = "PRIVATECAR", OTHERPRIVATE = "OTHERPRIVATE", PUBLIC = "PUBLIC", + + //WEEKLY PLANNER + WEEKLYPLANNER = "WEEKLYPLANNER", + DATES = "DATES", + DATES_STARTED = "DATES_STARTED", + WEEKTYPE = "WEEKTYPE", +} + +export enum FieldNameEnumActivity { + //VAR COMMMONS + FIRSTNAME = "FIRSTNAME", + SURVEYDATE = "SURVEYDATE", + + //TIME + START_TIME = "START_TIME", + END_TIME = "END_TIME", + + //SUGGESTER + INPUT_SUGGESTER = "INPUT_SUGGESTER", + + //PLACE PLACE = "PLACE", + + //WITH SOMEONE WITHSOMEONE = "WITHSOMEONE", COUPLE = "COUPLE", PARENTS = "PARENTS", @@ -30,23 +97,60 @@ export enum FieldNameEnum { OTHERKNOWN = "OTHERKNOWN", OTHER = "OTHER", WITHSCREEN = "WITHSCREEN", - WEEKLYPLANNER = "WEEKLYPLANNER", - WEEKTYPE = "WEEKTYPE", - WORKINGWEEK = "WORKINGWEEK", - HOLIDAYWEEK = "HOLIDAYWEEK", - OTHERWEEK = "OTHERWEEK", + + // VARIABLES CLOTURE + GREATESTACTIVITYDAY = "GREATESTACTIVITYDAY", WORSTACTIVITYDAY = "WORSTACTIVITYDAY", KINDOFDAY = "KINDOFDAY", EXCEPTIONALDAY = "EXCEPTIONALDAY", TRAVELTIME = "TRAVELTIME", PHONETIME = "PHONETIME", + + ISCLOSED = "ISCLOSED", //SURVEY CLOSED + ISENVOYED = "ISENVOYED", //SURVEY ENVOYED + ISROUTE = "ISROUTE", // IS ROUTE + ISCOMPLETED = "ISCOMPLETED", // ALL VARIABLES SET FOR SURVEY + ISVALIDATED = "ISVALIDATED", //SURVEY VALIDATED + ISLOCKED = "ISLOCKED", //SURVEY LOCKED + + //ACTIVITY + + //MAIN ACTIVITY + ACTIVITY_SELECTER_HISTORY = "ACTIVITY_SELECTER_HISTORY", + MAINACTIVITY_ID = "MAINACTIVITY_ID", + MAINACTIVITY_SUGGESTERID = "MAINACTIVITY_SUGGESTERID", + MAINACTIVITY_ISFULLYCOMPLETED = "MAINACTIVITY_ISFULLYCOMPLETED", + MAINACTIVITY_LABEL = "MAINACTIVITY_LABEL", + GOAL = "GOAL", + + //SECONDARY ACTIVITY + WITHSECONDARYACTIVITY = "WITHSECONDARYACTIVITY", + SECONDARYACTIVITY = "SECONDARYACTIVITY", + SECONDARYACTIVITY_LABEL = "SECONDARYACTIVITY_LABEL", + SECONDARYACTIVITY_SUGGESTERID = "SECONDARYACTIVITY_SUGGESTERID", + + //SCORE + QUALITY_SCORE = "QUALITY_SCORE", //QUALITY SCORE + QUALITY_SCORE_SUBSTRACT_POINTS = "QUALITY_SCORE_SUBSTRACT_POINTS", //POINT TO SUBSTRACT FOR CALCULATE SCORE + + //ROUTE + ROUTE = "ROUTE", + FOOT = "FOOT", + BICYCLE = "BICYCLE", + TWOWHEELSMOTORIZED = "TWOWHEELSMOTORIZED", + PRIVATECAR = "PRIVATECAR", + OTHERPRIVATE = "OTHERPRIVATE", + PUBLIC = "PUBLIC", +} + +//enums not array +export enum FieldNameEnumWorkTIme { + FIRSTNAME = "FIRSTNAME", + SURVEYDATE = "SURVEYDATE", + WEEKTYPE = "WEEKTYPE", ISCLOSED = "ISCLOSED", ISENVOYED = "ISENVOYED", - ISROUTE = "ISROUTE", - ISCOMPLETED = "ISCOMPLETED", ISVALIDATED = "ISVALIDATED", ISLOCKED = "ISLOCKED", - DATES = "DATES", - DATES_STARTED = "DATES_STARTED", } diff --git a/src/i18n/locales/fr/fr.json b/src/i18n/locales/fr/fr.json index cdf9f71d..8f24ba6d 100644 --- a/src/i18n/locales/fr/fr.json +++ b/src/i18n/locales/fr/fr.json @@ -221,7 +221,8 @@ "closeds-survey-label": "Carnets clôturés", "validated-survey-label": "Carnet validé", "validateds-survey-label": "Carnets validés", - "refresh-button": "Actualiser la liste" + "refresh-button": "Actualiser la liste", + "all-campaigns": "Toutes les vagues" }, "reviewer-home": { "welcome": "Bienvenue dans votre espace", @@ -339,7 +340,9 @@ "what-to-edit": "Que souhaitez-vous modifier ?" }, "activity-duration": { - "hour-alert": "Attention! L'heure de fin est antérieure à l'heure de début" + "hour-alert": "Attention! L'heure de fin est antérieure à l'heure de début", + "cancel": "Annuler", + "validate": "OK" }, "weekly-planner": { "info-light": "Pour remplir votre calendrier de travail de la semaine, indiquez chaque jour les moments de la journée où vous travaillez.", @@ -452,7 +455,7 @@ "button": "Revenir à l’accueil", "alt-icon": "Illustration enquête envoyée", "survey-content": "Vous avez complété votre semainier.", - "activity-content": "Vous avez complété votre 1ère journée." + "activity-content": "Vous avez complété votre journée." } }, "day-characteristic": { @@ -544,7 +547,7 @@ }, "edge": { "step-2": "Cliquez sur le menu en bas à droite", - "step-3": "Sélectionnez << Ajouter au appareil >>" + "step-3": "Sélectionnez << Ajouter au téléphone >>" } }, "step-final": "Votre application Carnet EDT est installée" diff --git a/src/index.tsx b/src/index.tsx index e5812fa6..db8b2966 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,6 +3,7 @@ import { CssBaseline, StyledEngineProvider, ThemeProvider } from "@mui/material" import { AuthProvider } from "oidc-react"; import React from "react"; import ReactDOM from "react-dom/client"; +import { createUserManager, isSSO } from "service/auth-service"; import App from "./App"; import "./index.css"; import reportWebVitals from "./reportWebVitals"; @@ -11,13 +12,15 @@ import * as serviceWorkerRegistration from "./serviceWorkerRegistration"; const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement); const getAuthority = () => { - const authority = window.location.search.includes("kc_idp_hint=insee-ssp") - ? process.env.REACT_APP_KEYCLOAK_AUTHORITY_REVIEWER - : process.env.REACT_APP_KEYCLOAK_AUTHORITY; + const authority = process.env.REACT_APP_KEYCLOAK_AUTHORITY; console.log("oidc authority: ", authority); return authority; }; +const oidcConfigSSO = { + userManager: createUserManager(), +}; + const oidcConfig = { onSignIn: () => { //to remove keycloak params in url @@ -28,8 +31,10 @@ const oidcConfig = { redirectUri: process.env.REACT_APP_KEYCLOAK_REDIRECT_URI, }; +const oidcProps = isSSO ? Object.assign(oidcConfig, oidcConfigSSO) : oidcConfig; + root.render( - + diff --git a/src/interface/entity/Api.ts b/src/interface/entity/Api.ts index 9edc9446..fcb7e565 100644 --- a/src/interface/entity/Api.ts +++ b/src/interface/entity/Api.ts @@ -4,6 +4,7 @@ import { LunaticData } from "interface/lunatic/Lunatic"; export interface UserSurveys { id?: number; campaignId: string; + subCampaignId?: string; interviewerId: string; questionnaireModelId: string; reviewerId?: string; diff --git a/src/interface/entity/Household.ts b/src/interface/entity/Household.ts index e9619bf6..51132543 100644 --- a/src/interface/entity/Household.ts +++ b/src/interface/entity/Household.ts @@ -8,4 +8,5 @@ export interface Household { surveyDate?: string; stats: StatsHousehold; campaingId: string; + subCampaignId?: string; } diff --git a/src/orchestrator/Orchestrator.tsx b/src/orchestrator/Orchestrator.tsx index 91117c4a..8abe1543 100644 --- a/src/orchestrator/Orchestrator.tsx +++ b/src/orchestrator/Orchestrator.tsx @@ -3,9 +3,10 @@ import * as lunaticEDT from "@inseefrlab/lunatic-edt"; import { important, makeStylesEdt } from "@inseefrlab/lunatic-edt"; import { Box, CircularProgress } from "@mui/material"; import FlexCenter from "components/commons/FlexCenter/FlexCenter"; -import { FieldNameEnum } from "enumerations/FieldNameEnum"; +import { FieldNameEnum, FieldNameEnumActivity } from "enumerations/FieldNameEnum"; import { LunaticData, LunaticModel } from "interface/lunatic/Lunatic"; import React from "react"; +import { getCurrentPageSource } from "service/orchestrator-service"; import { isReviewer } from "service/user-service"; const { ...edtComponents } = lunaticEDT; @@ -63,6 +64,7 @@ const getDataOfCurrentBinding = ( ) => { // partie collected dejà set (mode enquete) -> set values of collected (value current lunawtic) to edited // and collected remains with the collected value on bdd + if (collected) { if (editedSaved && Array.isArray(collected)) { collected = getDataOfLoop(collected, editedSaved, iteration); @@ -78,17 +80,8 @@ const getDataOfCurrentBinding = ( }; //prop is for activity and prop being modified -const isPropOfActivityCurrent = (prop: string, bindings: string[]) => { - return prop != FieldNameEnum.WEEKLYPLANNER && bindings != null && bindings.includes(prop); -}; - -//prop is a activity -const isPropActivity = (prop: string, dataOfField: any) => { - return prop != FieldNameEnum.WEEKLYPLANNER && dataOfField; -}; -//prop is a work time -const isPropWorktime = (prop: string, dataOfField: any) => { - return prop == FieldNameEnum.WEEKLYPLANNER && dataOfField; +const isPropCurrent = (prop: string, bindings: string[]) => { + return bindings != null && bindings.includes(prop); }; //return a copy of a object @@ -97,50 +90,108 @@ const copyObject = (object: any) => { return Array.isArray(object) ? [...object] : JSON.parse(JSON.stringify(object)); }; +const isWorkTime = (source: LunaticModel | undefined) => { + return source ? source.label == "WorkTime" : getCurrentPageSource().label == "WorkTime"; +}; + +const propsWorkTime = (source: LunaticModel): string[] => { + const bindingDependenciesOfComponent = source.components.map( + component => component.bindingDependencies ?? [], + ); + // array of arrays to array + const bindingDependencies = ([] as string[]).concat(...bindingDependenciesOfComponent); + //unique values + const uniqueBindingDependencies = bindingDependencies?.filter( + (value, index, array) => array.indexOf(value) === index, + ); + return uniqueBindingDependencies; +}; + +//if weekly planner, doesn't distinction edited/collected, so edited/collected get value of collected +const setDataOfWorkTimeReviewer = ( + source: LunaticModel | undefined, + data: LunaticData | undefined, + dataCollected: any, +) => { + if (!source) { + source = getCurrentPageSource(); + } + + const weeklyPlannerProps = propsWorkTime(source); + weeklyPlannerProps.forEach(prop => { + let dataOfField = dataCollected[prop]; + const collectedSaved = data?.COLLECTED?.[prop]?.COLLECTED; + const editedSaved = data?.COLLECTED?.[prop]?.EDITED; + if (dataOfField) { + dataOfField.EDITED = editedSaved; + dataOfField.COLLECTED = collectedSaved; + } + }); + + return dataCollected; +}; + +const setDataOfActivityReviewer = ( + dataCollected: any, + data: LunaticData | undefined, + components: any, + iteration: number | undefined, +) => { + const bindings: string[] = components?.filter( + (component: any) => component.componentType != "Sequence", + )[0]?.bindingDependencies; + + for (let prop in FieldNameEnumActivity as any) { + let dataOfField = dataCollected[prop]; + const collected = dataOfField?.COLLECTED; + const edited = dataOfField?.EDITED; + const editedSaved = data?.COLLECTED?.[prop]?.EDITED; + const collectedSaved = data?.COLLECTED?.[prop]?.COLLECTED; + //prop activity + prop currently being edited + if (isPropCurrent(prop, bindings)) { + //get data of current prop -> + //COLLECTED : value of bdd (COLLECTED) + //EDITED: if exist EDITED -> value of lunatic for value[iteration], other -> value of bdd (EDITED) + + dataOfField = getDataOfCurrentBinding( + copyObject(collected), + copyObject(edited), + copyObject(collectedSaved), + copyObject(editedSaved), + dataOfField, + iteration, + ); + } else if (dataOfField) { + //prop activity + prop not currently being edited, + //so edited get value of edited in bdd, and collected get value of partie collected in bdd + dataOfField.EDITED = copyObject(editedSaved); + dataOfField.COLLECTED = copyObject(collectedSaved); + } + dataCollected[prop] = dataOfField; + } + return dataCollected; +}; + //data of a reviewer const getDataReviewer = ( getData: any, data: LunaticData | undefined, components: any, iteration: number | undefined, + source?: LunaticModel, ) => { const callbackholder = getData(); - const dataCollected = callbackholder.COLLECTED; - const bindings: string[] = components?.filter( - (component: any) => component.componentType != "Sequence", - )[0]?.bindingDependencies; + let dataCollected = callbackholder.COLLECTED; + + if (!source) { + source = getCurrentPageSource(); + } // data -> get data of bdd, callbackholder -> lunatic / current data if (callbackholder && dataCollected) { - for (let prop in FieldNameEnum as any) { - let dataOfField = dataCollected[prop]; - const collected = dataOfField?.COLLECTED; - const edited = dataOfField?.EDITED; - const editedSaved = data?.COLLECTED?.[prop]?.EDITED; - const collectedSaved = data?.COLLECTED?.[prop]?.COLLECTED; - //prop activity + prop currently being edited - if (isPropOfActivityCurrent(prop, bindings)) { - //get data of current prop -> - //COLLECTED : value of bdd (COLLECTED) - //EDITED: if exist EDITED -> value of lunatic for value[iteration], other -> value of bdd (EDITED) - dataOfField = getDataOfCurrentBinding( - copyObject(collected), - copyObject(edited), - copyObject(collectedSaved), - copyObject(editedSaved), - dataOfField, - iteration, - ); - } else if (isPropActivity(prop, dataOfField)) { - //prop activity + prop not currently being edited, - //so edited get value of edited in bdd, and collected get value of partie collected in bdd - dataOfField.EDITED = copyObject(editedSaved); - dataOfField.COLLECTED = copyObject(collectedSaved); - } - //if weekly planner, doesn't distinction edited/collected, so edited/collected get value of collected - if (isPropWorktime(prop, dataOfField)) { - dataOfField.EDITED = collected; - dataOfField.COLLECTED = collected; - } + if (isWorkTime(source)) { + dataCollected = setDataOfWorkTimeReviewer(source, data, dataCollected); + } else { + dataCollected = setDataOfActivityReviewer(dataCollected, data, components, iteration); } } callbackholder.COLLECTED = dataCollected; @@ -148,18 +199,25 @@ const getDataReviewer = ( }; //data of interviewer -const getDataInterviewer = (getData: any, data: LunaticData | undefined) => { +const getDataInterviewer = (getData: any, data: LunaticData | undefined, source?: LunaticModel) => { const callbackholder = getData(); const dataCollected = callbackholder.COLLECTED; //dataCollected values get of lunatic - if (callbackholder && dataCollected) { - for (let prop in FieldNameEnum as any) { + if (callbackholder && dataCollected && source) { + for (let prop in FieldNameEnumActivity as any) { const dataOfField = dataCollected[prop]; //set values edited with values in bdd, because we don't recover the edited part with lunatic if (dataOfField) { dataOfField.EDITED = data?.COLLECTED?.[prop]?.EDITED; } } + propsWorkTime(source).forEach(prop => { + const dataOfField = dataCollected[prop]; + //set values edited with values in bdd, because we don't recover the edited part with lunatic + if (dataOfField) { + dataOfField.EDITED = data?.COLLECTED?.[prop]?.EDITED; + } + }); } callbackholder.COLLECTED = dataCollected; return callbackholder; @@ -190,12 +248,24 @@ const getVariablesActivity = ( variableCollected = variableCollected ?? value?.[bindingDependency]; let variable = isReviewerMode || isLocked ? variableEdited ?? variableCollected : variableCollected; - variables.set(bindingDependency, variable); }); return variables; }; +const getVariableOfWeeklyPlannerInterviewer = ( + varCollected: any, + varEdited: any, + value: any, + bindingDependency: string, +) => { + if (Array.isArray(varEdited) && varEdited.length > 0 && varEdited[0] != null) { + return varEdited; + } else { + return varCollected ?? value?.[bindingDependency]; + } +}; + const getVariablesWeeklyPlanner = ( data: LunaticData | undefined, dataBdd: LunaticData | undefined, @@ -203,11 +273,18 @@ const getVariablesWeeklyPlanner = ( value: any, ) => { let variables = new Map(); + const isReviewerMode = isReviewer(); bindingDependencies?.forEach((bindingDependency: string) => { const varC = dataBdd?.COLLECTED?.[bindingDependency]?.COLLECTED; - const variableCollected = varC ?? value?.[bindingDependency]; - variables.set(bindingDependency, variableCollected); + const varE = dataBdd?.COLLECTED?.[bindingDependency]?.EDITED; + let variable = null; + if (isReviewerMode) { + variable = varE ?? varC; + } else { + variable = getVariableOfWeeklyPlannerInterviewer(varC, varE, value, bindingDependency); + } + variables.set(bindingDependency, variable); }); return variables; }; @@ -218,8 +295,9 @@ const getVariables = ( iteration: number | undefined | null, bindingDependencies: string[], value: any, + source: LunaticModel | undefined, ) => { - if (bindingDependencies.find((bindingDependency: string) => bindingDependency == "WEEKLYPLANNER")) { + if (isWorkTime(source)) { const variables = getVariablesWeeklyPlanner(data, dataBdd, bindingDependencies, value); return variables; } else { @@ -228,7 +306,7 @@ const getVariables = ( }; export const OrchestratorForStories = (props: OrchestratorProps) => { - const { source, data, cbHolder, page, subPage, iteration, componentSpecificProps, overrideOptions } = + let { source, data, cbHolder, page, subPage, iteration, componentSpecificProps, overrideOptions } = props; const { classes, cx } = useStyles(); const { getComponents, getCurrentErrors, getData } = lunatic.useLunatic(source, data, { @@ -243,14 +321,19 @@ export const OrchestratorForStories = (props: OrchestratorProps) => { const currentErrors = getCurrentErrors(); const getDataLocal = () => { - return isReviewer() + const dataLocal = isReviewer() ? getDataReviewer(getData, data, components, iteration) - : getDataInterviewer(getData, data); + : getDataInterviewer(getData, data, source); + return dataLocal; }; cbHolder.getData = getDataLocal; cbHolder.getErrors = getCurrentErrors; + if (!source) { + source = getCurrentPageSource(); + } + const renderComponent = () => { return ( @@ -282,6 +365,7 @@ export const OrchestratorForStories = (props: OrchestratorProps) => { iteration, getBindingDependencies(components), value, + source, )} bindingDependencies={getBindingDependencies(components)} value={value} diff --git a/src/pages/activity/Activity.tsx b/src/pages/activity/Activity.tsx index 767ad4bd..103a97cd 100644 --- a/src/pages/activity/Activity.tsx +++ b/src/pages/activity/Activity.tsx @@ -1,4 +1,3 @@ -import { Default } from "components/commons/Responsive/Responsive"; import SurveySelecter from "components/edt/SurveySelecter/SurveySelecter"; import { EdtRoutesNameEnum } from "enumerations/EdtRoutesNameEnum"; import { ErrorCodeEnum } from "enumerations/ErrorCodeEnum"; @@ -8,6 +7,7 @@ import { OrchestratorContext } from "interface/lunatic/Lunatic"; import { callbackHolder } from "orchestrator/Orchestrator"; import { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; +import { useMediaQuery } from "react-responsive"; import { Outlet, useNavigate, useOutletContext, useParams } from "react-router-dom"; import { getParameterizedNavigatePath, @@ -16,6 +16,7 @@ import { setEnviro, } from "service/navigation-service"; import { getCurrentSurveyRootPage } from "service/orchestrator-service"; +import { tabletMinWidth } from "service/responsive"; import { getData, getSource, getSurveyRights, getTabsData } from "service/survey-service"; const ActivityPage = () => { @@ -71,20 +72,23 @@ const ActivityPage = () => { } }, []); + const isNotMobile = useMediaQuery({ minWidth: tabletMinWidth }); return ( <> - - = maxTabsPerRow} - maxTabsPerRow={maxTabsPerRow} - maxTabIndex={200} - /> - + <> + {isNotMobile && ( + = maxTabsPerRow} + maxTabsPerRow={maxTabsPerRow} + maxTabIndex={200} + /> + )} + { return { "isIOS": isIOS, "modifiable": modifiable, - "isOpen": context.isOpenHeader ?? false, + "iosHeight": context.isOpenHeader ? "80vh" : "87vh", + "innerHeight": window.innerHeight, }; }; @@ -900,13 +901,14 @@ const ActivityOrRoutePlannerPage = () => { ); }; -const styleSurveyPageBoxTabletWhenIOS = (isOpen: boolean) => { - return isOpen ? "80vh" : "87vh"; -}; - -const useStyles = makeStylesEdt<{ isIOS: boolean; modifiable: boolean; isOpen: boolean }>({ +const useStyles = makeStylesEdt<{ + isIOS: boolean; + modifiable: boolean; + iosHeight: string; + innerHeight: number; +}>({ "name": { ActivityOrRoutePlannerPage }, -})((theme, { isIOS, modifiable, isOpen }) => ({ +})((theme, { isIOS, modifiable, iosHeight }) => ({ snackbar: { bottom: "90px !important", "& .MuiSnackbarContent-root": { @@ -943,8 +945,8 @@ const useStyles = makeStylesEdt<{ isIOS: boolean; modifiable: boolean; isOpen: b maxHeight: "100vh", }, surveyPageBoxTablet: { - height: "100vh", - maxHeight: isIOS ? styleSurveyPageBoxTabletWhenIOS(isOpen) : "94vh", + height: innerHeight + "px", + maxHeight: isIOS ? iosHeight : innerHeight + "px", }, outletBoxDesktop: { flexGrow: "12", @@ -953,7 +955,7 @@ const useStyles = makeStylesEdt<{ isIOS: boolean; modifiable: boolean; isOpen: b width: "100%", }, outletBoxMobileTablet: { - flexGrow: "1", + flexGrow: "12", display: "flex", height: "100%", }, diff --git a/src/pages/activity/activity-or-route-planner/activity-duration/ActivityDuration.tsx b/src/pages/activity/activity-or-route-planner/activity-duration/ActivityDuration.tsx index 7124b9c6..dda3c263 100644 --- a/src/pages/activity/activity-or-route-planner/activity-duration/ActivityDuration.tsx +++ b/src/pages/activity/activity-or-route-planner/activity-duration/ActivityDuration.tsx @@ -64,7 +64,11 @@ const ActivityDurationPage = () => { arrowDownIconAlt: t("accessibility.asset.mui-icon.expand-more"), modifiable: !surveyReadOnly(context.rightsSurvey), defaultLanguage: "fr", - ariaLabelTimepicker: t("accessibility.asset.timepicker-alt"), + labels: { + ariaLabelTimepicker: t("accessibility.asset.timepicker-alt"), + cancelLabel: t("page.activity-duration.cancel"), + validateLabel: t("page.activity-duration.validate"), + }, }; let startTimeDay: Dayjs; diff --git a/src/pages/activity/activity-summary/ActivitySummary.tsx b/src/pages/activity/activity-summary/ActivitySummary.tsx index bbeeccec..ccd86d62 100644 --- a/src/pages/activity/activity-summary/ActivitySummary.tsx +++ b/src/pages/activity/activity-summary/ActivitySummary.tsx @@ -148,10 +148,6 @@ const addActivityOrRoute = ( : onAddActivity(idSurvey, isRoute); }; -const isDemo = getFlatLocalStorageValue(LocalStorageVariableEnum.IS_DEMO_MODE) === "true"; -const isReviewer = getUserRights() === EdtUserRightsEnum.REVIEWER; -const isReviewerMode = isReviewer && !isDemo; - const renderPageOrLoadingOrError = ( initialized: boolean, error: ErrorCodeEnum | undefined, @@ -220,6 +216,10 @@ const ActivitySummaryPage = () => { const modifiable = !surveyReadOnly(context.rightsSurvey); const { classes } = useStyles({ "modifiable": modifiable }); + const isDemo = getFlatLocalStorageValue(LocalStorageVariableEnum.IS_DEMO_MODE) === "true"; + const isReviewer = getUserRights() == EdtUserRightsEnum.REVIEWER; + const isReviewerMode = isReviewer && !isDemo; + useEffect(() => { setScore(getScore(idSurvey, t)); }, [activitiesRoutesOrGaps]); diff --git a/src/pages/activity/help/HelpActivity/HelpActivity.tsx b/src/pages/activity/help/HelpActivity/HelpActivity.tsx index 42fecada..2c16657f 100644 --- a/src/pages/activity/help/HelpActivity/HelpActivity.tsx +++ b/src/pages/activity/help/HelpActivity/HelpActivity.tsx @@ -48,7 +48,7 @@ const HelpActivity = () => { const isItTablet = isTablet(); const isItMobile = isMobile(); - const { classes, cx } = useStyles(); + const { classes, cx } = useStyles({ "innerHeight": window.innerHeight }); const activitiesRoutesOrGaps = mockActivitiesRoutesOrGaps(); const surveyDate = "2023-03-29"; @@ -212,15 +212,22 @@ const HelpActivity = () => { const heightClass = isPwa() ? classes.fullHeight : classes.fullHeightNav; + const isMobileApp = () => { + return !isPwa() && isMobileNav && (isIOS || isAndroid); + }; + + function getClassCondition(condition: boolean, classNameYes: any, classNameNo: any) { + return condition ? classNameYes : classNameNo; + } + return ( {renderHelp()} {(isItDesktop || !isSubchildDisplayed) && ( @@ -313,7 +320,7 @@ const HelpActivity = () => { ); }; -const useStyles = makeStylesEdt({ "name": { HelpActivity } })(theme => ({ +const useStyles = makeStylesEdt<{ innerHeight: number }>({ "name": { HelpActivity } })(theme => ({ root: { height: important("100vh"), maxHeight: important("100vh"), @@ -344,8 +351,8 @@ const useStyles = makeStylesEdt({ "name": { HelpActivity } })(theme => ({ display: "flex", alignItems: "flex-start", overflow: "hidden", - height: "100vh", - maxHeight: "94vh", + height: "100%", + maxHeight: isIOS ? "87vh" : innerHeight + "px", }, innerContentBox: { border: "1px solid transparent", diff --git a/src/pages/activity/help/HelpDuration/HelpDuration.tsx b/src/pages/activity/help/HelpDuration/HelpDuration.tsx index ff59a07a..4e950aaf 100644 --- a/src/pages/activity/help/HelpDuration/HelpDuration.tsx +++ b/src/pages/activity/help/HelpDuration/HelpDuration.tsx @@ -51,7 +51,11 @@ const HelpDuration = () => { helpImage: imageHelp, arrowDownIcon: arrowDown, arrowDownIconAlt: t("accessibility.asset.mui-icon.expand-more"), - ariaLabelTimepicker: t("accessibility.asset.timepicker-alt"), + labels: { + ariaLabelTimepicker: t("accessibility.asset.timepicker-alt"), + cancelLabel: t("page.activity-duration.cancel"), + validateLabel: t("page.activity-duration.validate"), + }, defaultLanguage: "fr", }; diff --git a/src/pages/day-of-survey/DayOfSurvey.tsx b/src/pages/day-of-survey/DayOfSurvey.tsx index 0347ed10..6b4880a7 100644 --- a/src/pages/day-of-survey/DayOfSurvey.tsx +++ b/src/pages/day-of-survey/DayOfSurvey.tsx @@ -4,19 +4,30 @@ import dayjs from "dayjs"; import customParseFormat from "dayjs/plugin/customParseFormat"; import { EdtRoutesNameEnum } from "enumerations/EdtRoutesNameEnum"; import { FieldNameEnum } from "enumerations/FieldNameEnum"; +import { ModePersistenceEnum } from "enumerations/ModePersistenceEnum"; +import { SourcesEnum } from "enumerations/SourcesEnum"; import { OrchestratorContext } from "interface/lunatic/Lunatic"; import { callbackHolder } from "orchestrator/Orchestrator"; -import React from "react"; -import { useLocation, useOutletContext } from "react-router-dom"; +import React, { useCallback } from "react"; +import { useLocation, useNavigate, useOutletContext } from "react-router-dom"; import { navToErrorPage } from "service/navigation-service"; import { surveyReadOnly } from "service/survey-activity-service"; -import { getComponentId, setValue } from "service/survey-service"; +import { + getComponentId, + getData, + getModePersistence, + getPerson, + navToPlanner, + saveData, + setValue, +} from "service/survey-service"; import { getSurveyIdFromUrl } from "utils/utils"; const DayOfSurveyPage = () => { const context: OrchestratorContext = useOutletContext(); const location = useLocation(); const idSurvey = getSurveyIdFromUrl(context, location); + const navigate = useNavigate(); let [disabledButton, setDisabledButton] = React.useState(false); const modifiable = @@ -61,6 +72,39 @@ const DayOfSurveyPage = () => { return () => document.removeEventListener("keypress", keypressChange, true); }, [callbackHolder]); + const setSurveyDate = (input: string) => { + const dataBdd = getData(idSurvey); + dayjs.extend(customParseFormat); + const inputFormatted = dayjs(input, "DD/MM/YYYY").format("YYYY-MM-DD"); + let dataSurveyDate = { + COLLECTED: + getModePersistence(dataBdd) == ModePersistenceEnum.COLLECTED ? inputFormatted : null, + EDITED: getModePersistence(dataBdd) == ModePersistenceEnum.EDITED ? inputFormatted : null, + FORCED: null, + INPUTED: null, + PREVIOUS: null, + }; + + if (dataBdd.COLLECTED && dataSurveyDate) { + dataBdd.COLLECTED[FieldNameEnum.SURVEYDATE] = dataSurveyDate; + } + return dataBdd; + }; + + const validate = useCallback(() => { + const input = (document.getElementsByClassName("MuiInputBase-input")?.[0] as HTMLInputElement) + ?.value; + const personAct = getPerson(idSurvey); + const surveyRootPage = + personAct?.data?.questionnaireModelId == SourcesEnum.WORK_TIME_SURVEY + ? EdtRoutesNameEnum.WORK_TIME + : EdtRoutesNameEnum.ACTIVITY; + const dataUpdated = setSurveyDate(input); + saveData(idSurvey, dataUpdated, false, true).then(() => { + navigate(navToPlanner(idSurvey, surveyRootPage)); + }); + }, []); + return ( { errorAltIcon={"accessibility.asset.day-of-survey-alt"} isStep={false} disableButton={modifiable ? disabledButton : true} + validateButton={validate} /> ); }; diff --git a/src/pages/edit-global-information/EditGlobalInformation.tsx b/src/pages/edit-global-information/EditGlobalInformation.tsx index 0aea81a7..76f5c106 100644 --- a/src/pages/edit-global-information/EditGlobalInformation.tsx +++ b/src/pages/edit-global-information/EditGlobalInformation.tsx @@ -9,7 +9,7 @@ import { callbackHolder } from "orchestrator/Orchestrator"; import React, { useCallback } from "react"; import { useLocation, useNavigate, useOutletContext } from "react-router-dom"; import { getComponentsOfVariable, setValue, validateAllGroup } from "service/survey-service"; -import { getSurveyIdFromUrl } from "utils/utils"; +import { formatDate, getSurveyIdFromUrl } from "utils/utils"; const EditGlobalInformationPage = () => { const context: OrchestratorContext = useOutletContext(); @@ -49,9 +49,13 @@ const EditGlobalInformationPage = () => { }, [callbackHolder]); const validate = useCallback(() => { - const input = (document.getElementsByClassName("MuiInputBase-input")?.[0] as HTMLInputElement) - ?.value; - validateAllGroup(idSurvey, input, navigate); + const inputName = ( + document.getElementsByClassName("MuiInputBase-input")?.[0] as HTMLInputElement + )?.value; + const inputDate = ( + document.getElementsByClassName("MuiInputBase-input")?.[1] as HTMLInputElement + )?.value; + validateAllGroup(navigate, idSurvey, inputName, formatDate(inputDate)); }, []); return ( diff --git a/src/pages/home-reviewer/HomeReviewer.tsx b/src/pages/home-reviewer/HomeReviewer.tsx index 35938ae9..536db836 100644 --- a/src/pages/home-reviewer/HomeReviewer.tsx +++ b/src/pages/home-reviewer/HomeReviewer.tsx @@ -58,6 +58,7 @@ const HomeReviewerPage = () => { localStorage.clear(); }) .then(() => auth.userManager.clearStaleState()) + .then(() => localStorage.removeItem("auth")) .then(() => window.location.replace(process.env.REACT_APP_PUBLIC_URL || "")); }, []); @@ -90,6 +91,7 @@ const HomeReviewerPage = () => { {process.env.REACT_APP_NODE_ENV !== "production" && ( - +