Skip to content

Commit

Permalink
Merge pull request #49 from InseeFrLab/feat/sprint21
Browse files Browse the repository at this point in the history
Feat/sprint21
  • Loading branch information
MichaelC67 authored May 21, 2024
2 parents fbd77b3 + ba853f5 commit dc77a17
Show file tree
Hide file tree
Showing 14 changed files with 316 additions and 233 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,40 @@ The variable ENDTIME is updated EDITED part by removing the ancient third elemen

![DURATION ENDTIME VALUE](./src/documentation/images/update_survey_delete_activity_duration_endtime_value.png)

## Offline

The application is completely functional offline in browser or in the application, you can exit the application and when you return you will be able to use it without any problem and all the cached data will be used.

For the reviewer mode, the information recovered is done on two requetes:

- To retrieve the data: REACT_APP_STROMAE_BACK_OFFICE_API_BASE_URL + "api/survey-unit/" + idSurvey + "/data"
- To retrieve the stateData : REACT_APP_STROMAE_BACK_OFFICE_API_BASE_URL + "api/survey-unit/" + idSurvey + "/state-data"

For the interviewer mode, the information retrieved is done on the following request:

- REACT_APP_STROMAE_BACK_OFFICE_API_BASE_URL + "api/survey-unit/" + idSurvey.

Same mechanism used to save information relevant to surveys.

Once in offline mode, authentication is not performed or the token is reviewed until the next online connection. Likewise, there is no requirement for the released API, everything is cached.

### Data synchronization

The information displayed will always be the most recent information found.
The cached last modification date will always be compared (on object data -> lastLocalSaveDate), with the date of last modification in remote (on stateData -> date) and if the value in Remote is the most recent, the data will be updated by that of the remote.

### Offline update data

#### Interviewer mode

As there is no requirement with the API, the local data will not be sent until we go online and made a modification to the survey.

#### Reviewer mode

As there is no requirement with the API, the local data will not be sent until we go online and : either click on the "update the list" button, or modify the corresponding survey.

If we click the "update list" button after having been in offline mode and having made modifications, we will send all the households that have been modified in offline.

## Maintenance and evolution

### Install local development environment
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "edt",
"version": "3.14.13",
"dateVersion": "17/04/2024",
"version": "3.15.0",
"dateVersion": "13/05/2024",
"licence": "MIT",
"dependencies": {
"@emotion/react": "^11.10.4",
"@emotion/styled": "^11.10.4",
"@inseefr/lunatic": "2.0.7-v2",
"@inseefrlab/lunatic-edt": "0.12.5",
"@inseefrlab/lunatic-edt": "0.12.6",
"@mui/material": "^5.10.7",
"@mui/styles": "^5.12.0",
"@react-pdf/font": "2.2.0",
Expand Down
34 changes: 34 additions & 0 deletions src/documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,40 @@ The variable ENDTIME is updated EDITED part by removing the ancient third elemen

![DURATION ENDTIME VALUE](./images/update_survey_delete_activity_duration_endtime_value.png)

## Offline

The application is completely functional offline in browser or in the application, you can exit the application and when you return you will be able to use it without any problem and all the cached data will be used.

For the reviewer mode, the information recovered is done on two requetes:

- To retrieve the data: REACT_APP_STROMAE_BACK_OFFICE_API_BASE_URL + "api/survey-unit/" + idSurvey + "/data"
- To retrieve the stateData : REACT_APP_STROMAE_BACK_OFFICE_API_BASE_URL + "api/survey-unit/" + idSurvey + "/state-data"

For the interviewer mode, the information retrieved is done on the following request:

- REACT_APP_STROMAE_BACK_OFFICE_API_BASE_URL + "api/survey-unit/" + idSurvey.

Same mechanism used to save information relevant to surveys.

Once in offline mode, authentication is not performed or the token is reviewed until the next online connection. Likewise, there is no requirement for the released API, everything is cached.

### Data synchronization

The information displayed will always be the most recent information found.
The cached last modification date will always be compared (on object data -> lastLocalSaveDate), with the date of last modification in remote (on stateData -> date) and if the value in Remote is the most recent, the data will be updated by that of the remote.

### Offline update data

#### Interviewer mode

As there is no requirement with the API, the local data will not be sent until we go online and made a modification to the survey.

#### Reviewer mode

As there is no requirement with the API, the local data will not be sent until we go online and : either click on the "update the list" button, or modify the corresponding survey.

If we click the "update list" button after having been in offline mode and having made modifications, we will send all the households that have been modified in offline.

## Maintenance and evolution

### Install local development environment
Expand Down
7 changes: 2 additions & 5 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,23 @@ const oidcConfigOnline = {
authority: getAuthority(),
clientId: process.env.REACT_APP_KEYCLOAK_CLIENT_ID,
redirectUri: process.env.REACT_APP_KEYCLOAK_REDIRECT_URI,
automaticSilentRenew: !navigator.onLine,
automaticSilentRenew: true,
};

const oidcConfigOffline = {
automaticSilentRenew: !navigator.onLine,
automaticSilentRenew: false,
silent_redirect_uri: currentHost,
};

let oidcPropss = {};

if (navigator.onLine) {
console.log("nav online");
if (isSSO) {
console.log("isSSO");
oidcPropss = Object.assign(oidcConfigOnline, oidcConfigSSO);
} else {
oidcPropss = oidcConfigOnline;
}
} else {
console.log("nav offline");
oidcPropss = oidcConfigOnline;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const getAlertUnlockLabels = (variableEdited: boolean, t: TFunction<"translation
};

const isChildDisplayed = (path: string): boolean => {
return path.split(EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER)[1].length > 0;
return path?.split(EdtRoutesNameEnum.ACTIVITY_OR_ROUTE_PLANNER)[1]?.length > 0;
};

const isActivity = (location: Location) => {
Expand Down Expand Up @@ -165,7 +165,7 @@ const onFinish = (
) => {
if (closed) {
const data = setValue(idSurvey, FieldNameEnum.ISCLOSED, true);
saveData(idSurvey, data ?? callbackHolder.getData()).then(() => {
saveData(idSurvey, data ?? callbackHolder.getData(), false, true).then(() => {
navigate(
getCurrentNavigatePath(
idSurvey,
Expand Down Expand Up @@ -434,6 +434,7 @@ const ActivityOrRoutePlannerPage = () => {
);
contextIteration = loopSize - 1;
const routeData = setValue(idSurvey, FieldNameEnum.ISROUTE, isRouteBool, contextIteration);
console.log(routeData, isRouteBool);
saveData(idSurvey, routeData).then(() => {
navToActivityOrRoute(idSurvey, contextIteration, isRouteBool);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { ReactComponent as ExtensionDisabledIcon } from "assets/illustration/mui
import { ReactComponent as ExtensionIcon } from "assets/illustration/mui-icon/extension.svg";
import { ReactComponent as SearchIcon } from "assets/illustration/mui-icon/search.svg";
import { SEPARATOR_DEFAUT } from "constants/constants";
import { Index } from "elasticlunrjs";
import { LoopEnum } from "enumerations/LoopEnum";
import React, { useCallback, useState } from "react";
import { useTranslation } from "react-i18next";
Expand Down Expand Up @@ -73,6 +74,8 @@ const MainActivityPage = () => {
const [displayStepper, setDisplayStepper] = useState<boolean>(true);
const [displayHeader, setDisplayHeader] = useState<boolean>(true);
const [isAlertDisplayed, setIsAlertDisplayed] = useState<boolean>(false);
const [index, setIndex] = useState<Index<AutoCompleteActiviteOption>>();

const referentiel = getNomenclatureRef();
const specificProps: ActivitySelecterSpecificProps = {
categoriesIcons: {
Expand Down Expand Up @@ -181,7 +184,7 @@ const MainActivityPage = () => {
categoryId: string,
newActivity: string,
) => {
createNewActivityInCategory(newItem, categoryId, newActivity, referentiel);
createNewActivityInCategory(newItem, categoryId, newActivity, referentiel, index, setIndex);
},
widthGlobal: true,
separatorSuggester: process.env.REACT_APP_SEPARATOR_SUGGESTER ?? SEPARATOR_DEFAUT,
Expand Down
40 changes: 32 additions & 8 deletions src/pages/activity/activity-summary/ActivitySummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { callbackHolder } from "orchestrator/Orchestrator";
import ErrorPage from "pages/error/Error";
import React, { useCallback, useEffect, useState } from "react";
import { TFunction, useTranslation } from "react-i18next";
import { useLocation, useNavigate, useOutletContext } from "react-router-dom";
import { Outlet, useLocation, useNavigate, useOutletContext } from "react-router-dom";
import { getFlatLocalStorageValue, getLocalStorageValue } from "service/local-storage-service";
import { getLoopSize, setLoopSize } from "service/loop-service";
import {
Expand All @@ -62,10 +62,12 @@ import {
} from "service/survey-activity-service";
import {
existVariableEdited,
getData,
getFullFrenchDate,
getPrintedFirstName,
getSource,
getSurveyDate,
getSurveyRights,
getValue,
isDemoMode,
lockSurvey,
Expand Down Expand Up @@ -197,6 +199,10 @@ const ActivitySummaryPage = () => {
const [gapEndTime, setGapEndTime] = React.useState<string>();
const [initialized, setInitialized] = React.useState<boolean>(false);
const [error, setError] = useState<ErrorCodeEnum | undefined>(undefined);
const [isRoute, setIsRoute] = React.useState(false);
const [activityOrRoute, setActivityOrRoute] = React.useState<ActivityRouteOrGap | undefined>(
undefined,
);

const { activitiesRoutesOrGaps } = getActivitiesOrRoutes(t, idSurvey, context.source);
const surveyDate = getSurveyDatePlanner(idSurvey);
Expand Down Expand Up @@ -253,12 +259,14 @@ const ActivitySummaryPage = () => {
[idSurvey],
);

const navToActivityOrRoute = (iteration: number): void => {
const navToActivityOrRoute = (iteration: number, isItRoute?: boolean): void => {
const isEditedSummary: { [key: string]: string } = {
[LocalStorageVariableEnum.IS_EDITED_SUMMARY]: "true",
};
localStorage.setItem(idSurvey, JSON.stringify(isEditedSummary));
setIsSummaryEdited(true);
setIsRoute(isItRoute ?? false);

navigate(
getCurrentNavigatePath(
idSurvey,
Expand All @@ -273,12 +281,13 @@ const ActivitySummaryPage = () => {
};

const onEditActivityOrRoute = useCallback(
(iteration: number) => {
(iteration: number, activity: ActivityRouteOrGap) => {
const isEditedSummary: { [key: string]: string } = {
[LocalStorageVariableEnum.IS_EDITED_SUMMARY]: "true",
};
localStorage.setItem(idSurvey, JSON.stringify(isEditedSummary));
setIsSummaryEdited(true);
setActivityOrRoute(activity);
navToEditActivity(idSurvey, iteration);
},
[idSurvey],
Expand All @@ -299,7 +308,8 @@ const ActivitySummaryPage = () => {
);

const onEditActivity = useCallback(
(iteration: number) => () => onEditActivityOrRoute(iteration),
(iteration: number, activity: ActivityRouteOrGap) => () =>
onEditActivityOrRoute(iteration, activity),
[],
);

Expand Down Expand Up @@ -341,8 +351,10 @@ const ActivitySummaryPage = () => {
setValueOrNull(idSurvey, FieldNameEnum.START_TIME, startTime, contextIteration);
setValueOrNull(idSurvey, FieldNameEnum.END_TIME, endTime, contextIteration);
const updatedData = setValue(idSurvey, FieldNameEnum.ISROUTE, isRouteBool, contextIteration);
saveData(idSurvey, updatedData).then(() => {

saveData(idSurvey, updatedData, false, true).then(() => {
onCloseAddActivityOrRoute();
setIsRoute(isRouteBool);
navigate(
getLoopParameterizedNavigatePath(
idSurvey,
Expand All @@ -363,8 +375,9 @@ const ActivitySummaryPage = () => {
);
contextIteration = loopSize - 1;
const routeData = setValue(idSurvey, FieldNameEnum.ISROUTE, isRouteBool, contextIteration);
saveData(idSurvey, routeData).then(() => {
navToActivityOrRoute(contextIteration);
context.isRoute = isRouteBool;
saveData(idSurvey, routeData, false, true).then(() => {
navToActivityOrRoute(contextIteration, isRouteBool);
});
};

Expand Down Expand Up @@ -577,7 +590,7 @@ const ActivitySummaryPage = () => {
onClick={navToCard(getIterationOrZero(activity))}
onClickGap={onOpenAddActivityOrRoute}
activityOrRoute={activity}
onEdit={onEditActivity(getIterationOrZero(activity))}
onEdit={onEditActivity(getIterationOrZero(activity), activity)}
onDelete={onDeleteActivity(
idSurvey,
context.source,
Expand Down Expand Up @@ -722,6 +735,17 @@ const ActivitySummaryPage = () => {
open={isAddActivityOrRouteOpen}
/>
</SurveyPage>
<Outlet
context={{
source: source,
data: getData(idSurvey),
idSurvey: idSurvey,
surveyRootPage: context.surveyRootPage,
isRoute: isRoute,
activityOrRoute: activityOrRoute,
rightsSurvey: getSurveyRights(idSurvey ?? ""),
}}
/>
</>,
);
};
Expand Down
19 changes: 11 additions & 8 deletions src/pages/end-survey/EndSurvey.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ const EndSurveyPage = () => {
border: true,
};

const saveDataAndInit = useCallback((surveyData: SurveyData) => {
saveData(idSurvey, surveyData.data).then(() => {
const saveDataAndInit = useCallback((surveyData: SurveyData, forceUpdate?: boolean) => {
saveData(idSurvey, surveyData.data, false, forceUpdate).then(() => {
initializeSurveysDatasCache().finally(() => {
setIsModalDisplayed(true);
});
Expand All @@ -102,25 +102,25 @@ const EndSurveyPage = () => {
};

if (!isDemoMode && !isReviewer() && navigator.onLine) {
remotePutSurveyData(idSurvey, surveyData)
return remotePutSurveyData(idSurvey, surveyData)
.then(surveyDataAnswer => {
surveyData.data.lastRemoteSaveDate = surveyDataAnswer.stateData?.date;
saveDataAndInit(surveyData);
return saveDataAndInit(surveyData, true);
})
.catch(() => {
setErrorSubmit(true);
});
} else if (!isDemoMode && isReviewer() && navigator.onLine) {
remotePutSurveyDataReviewer(idSurvey, stateData, surveyData.data)
return remotePutSurveyDataReviewer(idSurvey, stateData, surveyData.data)
.then(surveyDataAnswer => {
surveyData.data.lastRemoteSaveDate = surveyDataAnswer.stateData?.date;
saveDataAndInit(surveyData);
return saveDataAndInit(surveyData, true);
})
.catch(() => {
setErrorSubmit(true);
});
} else {
saveDataAndInit(surveyData);
return saveDataAndInit(surveyData, true);
}
}, []);

Expand All @@ -143,7 +143,10 @@ const EndSurveyPage = () => {
setIsModalDisplayed: (value: SetStateAction<boolean>) => void,
): void => {
if (forceQuit) {
navToHome();
const dataWithIsEnvoyed = setValue(idSurvey, FieldNameEnum.ISENVOYED, true);
saveData(idSurvey, dataWithIsEnvoyed, false, true).then(() => {
navToHome();
});
} else {
setIsModalDisplayed(true);
}
Expand Down
Loading

0 comments on commit dc77a17

Please sign in to comment.