Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React router upgrade part 3 #776

Merged
merged 35 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
535beee
:wrench: Remove obsolete addon
sergei-maertens Jan 16, 2025
8f9adff
:recycle: [open-formulieren/open-forms#4929] Refactor test - mock at …
sergei-maertens Jan 16, 2025
88017d6
:recycle: [open-formulieren/open-forms#4929] Take props from context …
sergei-maertens Jan 16, 2025
a4683da
:arrow_up: [open-formulieren/open-forms#4929] Bump testing-library pa…
sergei-maertens Jan 16, 2025
5114bdb
:bug: [open-formulieren/open-forms#4929] Fixed a test-specific bug in…
sergei-maertens Jan 16, 2025
0079fa0
:clown_face: [open-formulieren/open-forms#4929] Add API endpoint mock…
sergei-maertens Jan 16, 2025
37aeaf9
:art: [open-formulieren/open-forms#4929] Minor improvements to the St…
sergei-maertens Jan 16, 2025
55c165c
:art: [open-formulieren/open-forms#4929] Small code improvements
sergei-maertens Jan 16, 2025
5f96507
:white_check_mark: [open-formulieren/open-forms#4929] Add test for su…
sergei-maertens Jan 16, 2025
71f4250
:recycle: [open-formulieren/open-forms#4929] Pass processing error vi…
sergei-maertens Jan 17, 2025
e0484cf
:art: [open-formulieren/open-forms#4929] Simplify SubmissionSummary s…
sergei-maertens Jan 17, 2025
c750dcc
:recycle: [open-formulieren/open-forms#4929] Remove need for processi…
sergei-maertens Jan 17, 2025
3e35c07
:truck: Move post completion views to 'views' folder in storybook.
sergei-maertens Jan 17, 2025
f6e2537
:recycle: [open-formulieren/open-forms#4929] Remove the need for an o…
sergei-maertens Jan 17, 2025
7b96f50
:recycle: [open-formulieren/open-forms#4929] Move SubmissionSummary r…
sergei-maertens Jan 17, 2025
9697156
:recycle: [open-formulieren/open-forms#4929] Ensure summary -> paymen…
sergei-maertens Jan 17, 2025
51d8674
:coffin: [open-formulieren/open-forms#4929] Delete dead code
sergei-maertens Jan 17, 2025
3d27813
:white_check_mark: [open-formulieren/open-forms#4929] Add tests for f…
sergei-maertens Jan 17, 2025
5f43008
:clown_face: [open-formulieren/open-forms#4929] Fix payment plugin st…
sergei-maertens Jan 17, 2025
703519a
:recycle: [open-formulieren/open-forms#4929] Removed the need to trac…
sergei-maertens Jan 17, 2025
8bb788d
:recycle: [open-formulieren/open-forms#4929] Simplify props for payme…
sergei-maertens Jan 17, 2025
537d743
:recycle: [open-formulieren/open-forms#4929] Remove need to track app…
sergei-maertens Jan 17, 2025
f5da831
:coffin: [open-formulieren/open-forms#4929] Remove onFailure prop
sergei-maertens Jan 17, 2025
4644a93
:coffin: [open-formulieren/open-forms#4929] Delete dead code
sergei-maertens Jan 18, 2025
dd1f2e9
:recycle: [open-formulieren/open-forms#4929] Move failure handling en…
sergei-maertens Jan 18, 2025
f530400
:recycle: [open-formulieren/open-forms#4929] Simplify Form state mana…
sergei-maertens Jan 18, 2025
cff4b05
:recycle: [open-formulieren/open-forms#4929] Move analytics tool conf…
sergei-maertens Jan 18, 2025
f4df338
:truck: [open-formulieren/open-forms#4929] Move SubmissionProvider in…
sergei-maertens Jan 18, 2025
f20a1f3
:fire: [open-formulieren/open-forms#4929] Remove deprecated code/cons…
sergei-maertens Jan 18, 2025
963ead2
:recycle: [open-formulieren/open-forms#4929] Extract progress indicat…
sergei-maertens Jan 18, 2025
865b7d0
:wrench: Disable coverage on test helpers
sergei-maertens Jan 18, 2025
8933bf9
:recycle: Replace useQuery hook with useSearchParams from react-router
sergei-maertens Jan 18, 2025
a5d2856
:truck: [open-formulieren/open-forms#4929] Move all route definitions…
sergei-maertens Jan 20, 2025
161f4aa
:truck: [open-formulieren/open-forms#4929] Declare app routes
sergei-maertens Jan 20, 2025
49c9615
:ok_hand: [open-formulieren/open-forms#4929] PR feedback
sergei-maertens Jan 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .storybook/main.mts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const config: StorybookConfig = {
'storybook-react-intl',
'storybook-addon-remix-react-router',
'@storybook/addon-coverage',
'@storybook/addon-webpack5-compiler-babel',
],
framework: {
name: '@storybook/react-vite',
Expand Down
563 changes: 60 additions & 503 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@
"@storybook/react-vite": "^8.4.7",
"@storybook/test-runner": "^0.20.0",
"@storybook/types": "^8.4.7",
"@testing-library/dom": ">=8.20.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.0",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@utrecht/component-library-css": "1.0.0-alpha.604",
"@utrecht/component-library-react": "1.0.0-alpha.353",
Expand Down
17 changes: 12 additions & 5 deletions src/api-mocks/submissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@
return HttpResponse.json(submission, {status: 201});
});

export const mockSubmissionGet = () =>
export const mockSubmissionGet = (submission = buildSubmission()) =>
http.get(`${BASE_URL}submissions/:uuid`, () => {
return HttpResponse.json(SUBMISSION_DETAILS, {status: 200});
return HttpResponse.json(submission, {status: 200});

Check warning on line 78 in src/api-mocks/submissions.js

View check run for this annotation

Codecov / codecov/patch

src/api-mocks/submissions.js#L78

Added line #L78 was not covered by tests
});

export const mockSubmissionStepGet = () =>
Expand Down Expand Up @@ -112,6 +112,13 @@
)
);

export const mockSubmissionCompletePost = () =>
http.post(`${BASE_URL}submissions/:uuid/_complete`, () =>
HttpResponse.json({

Check warning on line 117 in src/api-mocks/submissions.js

View check run for this annotation

Codecov / codecov/patch

src/api-mocks/submissions.js#L116-L117

Added lines #L116 - L117 were not covered by tests
statusUrl: `${BASE_URL}submissions/${SUBMISSION_DETAILS.id}/super-random-token/status`,
})
);

/**
* Simulate a successful backend processing status without payment.
*/
Expand Down Expand Up @@ -160,6 +167,6 @@
})
);

export const mockSubmissionPaymentStartGet = http.post(`${BASE_URL}payment/:uuid/demo/start`, () =>
HttpResponse.json({data: {method: 'get', action: 'https://example.com'}})
);
export const mockSubmissionPaymentStartPost = (
data = {type: 'get', url: 'https://example.com', data: {}}
) => http.post(`${BASE_URL}payment/:uuid/demo/start`, () => HttpResponse.json(data));
sergei-maertens marked this conversation as resolved.
Show resolved Hide resolved
118 changes: 37 additions & 81 deletions src/components/Form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
useLocation,
useMatch,
useNavigate,
useSearchParams,
} from 'react-router-dom';
import {useAsync, usePrevious} from 'react-use';
import {useImmerReducer} from 'use-immer';
Expand All @@ -20,8 +21,6 @@
import {ConfirmationView, StartPaymentView} from 'components/PostCompletionViews';
import ProgressIndicator from 'components/ProgressIndicator';
import RequireSubmission from 'components/RequireSubmission';
import {SessionTrackerModal} from 'components/Sessions';
import {SubmissionSummary} from 'components/Summary';
import {
PI_TITLE,
START_FORM_QUERY_PARAM,
Expand All @@ -32,7 +31,6 @@
import useAutomaticRedirect from 'hooks/useAutomaticRedirect';
import useFormContext from 'hooks/useFormContext';
import usePageViews from 'hooks/usePageViews';
import useQuery from 'hooks/useQuery';
import useRecycleSubmission from 'hooks/useRecycleSubmission';
import Types from 'types';

Expand All @@ -41,11 +39,7 @@

const initialState = {
submission: null,
submittedSubmission: null,
processingStatusUrl: '',
processingError: '',
completed: false,
startingError: '',
};

const reducer = (draft, action) => {
Expand All @@ -56,29 +50,16 @@
draft.submission = action.payload;
break;
}
case 'SUBMITTED': {
return {
...initialState,
submittedSubmission: action.payload.submission,
processingStatusUrl: action.payload.processingStatusUrl,
};
}
case 'PROCESSING_FAILED': {
// set the error message in the state
draft.processingError = action.payload;
// put the submission back in the state as well, so we can re-submit
draft.submission = draft.submittedSubmission;
// put the submission back in the state so we can re-submit
const {submission} = action.payload;
draft.submission = submission;

Check warning on line 56 in src/components/Form.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Form.jsx#L55-L56

Added lines #L55 - L56 were not covered by tests
break;
}
case 'PROCESSING_SUCCEEDED': {
draft.processingError = null;
draft.completed = true;
break;
}
case 'CLEAR_PROCESSING_ERROR': {
draft.processingError = '';
break;
}
case 'DESTROY_SUBMISSION': {
return {
...initialState,
Expand All @@ -88,10 +69,6 @@
const initialState = action.payload;
return initialState;
}
case 'STARTING_ERROR': {
draft.startingError = action.payload;
break;
}
default: {
throw new Error(`Unknown action ${action.type}`);
}
Expand All @@ -110,11 +87,11 @@
const form = useFormContext();
const navigate = useNavigate();
const shouldAutomaticallyRedirect = useAutomaticRedirect(form);
const queryParams = useQuery();
const [params] = useSearchParams();
usePageViews();
const intl = useIntl();
const prevLocale = usePrevious(intl.locale);
const {pathname: currentPathname} = useLocation();
const {pathname: currentPathname, state: routerState} = useLocation();

// TODO replace absolute path check with relative
const introductionMatch = useMatch('/introductie');
Expand Down Expand Up @@ -175,23 +152,6 @@
setSubmissionId(submission.id);
};

const onSubmitForm = processingStatusUrl => {
removeSubmissionId();
dispatch({
type: 'SUBMITTED',
payload: {
submission: state.submission,
processingStatusUrl,
},
});

if (submission?.payment.isRequired && !state.submission.payment.hasPaid) {
navigate('/betalen');
} else {
navigate('/bevestiging');
}
};

const onDestroySession = async () => {
await destroy(`${config.baseUrl}authentication/${state.submission.id}/session`);

Expand All @@ -203,24 +163,23 @@
navigate('/');
};

const onProcessingFailure = errorMessage => {
// TODO: provide generic fallback message in case no explicit
// message is shown
dispatch({type: 'PROCESSING_FAILED', payload: errorMessage});
navigate('/overzicht');
const onProcessingFailure = (submission, errorMessage) => {
dispatch({type: 'PROCESSING_FAILED', payload: {submission}});
navigate('/overzicht', {state: {errorMessage}});

Check warning on line 168 in src/components/Form.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Form.jsx#L167-L168

Added lines #L167 - L168 were not covered by tests
};

// handle redirect from payment provider to render appropriate page and include the
// params as state for the next component.
if (queryParams.get('of_payment_status')) {
if (params.get('of_payment_status')) {
// TODO: store details in sessionStorage instead, to survive hard refreshes
return (
<Navigate
replace
to="/bevestiging"
state={{
status: queryParams.get('of_payment_status'),
userAction: queryParams.get('of_payment_action'),
statusUrl: queryParams.get('of_submission_status'),
status: params.get('of_payment_status'),
userAction: params.get('of_payment_action'),
statusUrl: params.get('of_submission_status'),
}}
/>
);
Expand All @@ -236,7 +195,7 @@
const isStartPage = !isIntroductionPage && !summaryMatch && stepMatch == null && !paymentMatch;
const submissionAllowedSpec = state.submission?.submissionAllowed ?? form.submissionAllowed;
const showOverview = submissionAllowedSpec !== SUBMISSION_ALLOWED.noWithoutOverview;
const submission = state.submission || state.submittedSubmission;
const submission = state.submission || (!!paymentMatch && routerState.submission) || null;
const isCompleted = state.completed;
const formName = form.name;
const needsPayment = submission ? submission.payment.isRequired : form.paymentRequired;
Expand Down Expand Up @@ -306,37 +265,15 @@
/>
) : null;

if (state.startingError) throw state.startingError;

// Route the correct page based on URL
const router = (
<Routes>
<Route
path="overzicht"
element={
<ErrorBoundary useCard>
<SessionTrackerModal>
<RequireSubmission
retrieveSubmissionFromContext
processingError={state.processingError}
onConfirm={onSubmitForm}
component={SubmissionSummary}
onClearProcessingErrors={() => dispatch({type: 'CLEAR_PROCESSING_ERROR'})}
onDestroySession={onDestroySession}
form={form}
/>
</SessionTrackerModal>
</ErrorBoundary>
}
/>

<Route
path="betalen"
element={
<ErrorBoundary useCard>
<RequireSubmission
submission={state.submittedSubmission}
statusUrl={state.processingStatusUrl}
retrieveSubmissionFromContext
onFailure={onProcessingFailure}
onConfirmed={() => dispatch({type: 'PROCESSING_SUCCEEDED'})}
component={StartPaymentView}
Expand All @@ -351,7 +288,6 @@
element={
<ErrorBoundary useCard>
<ConfirmationView
statusUrl={state.processingStatusUrl}
onFailure={onProcessingFailure}
onConfirmed={() => dispatch({type: 'PROCESSING_SUCCEEDED'})}
downloadPDFText={form.submissionReportDownloadLinkTitle}
Expand All @@ -370,6 +306,7 @@
submission={state.submission}
onSubmissionObtained={onSubmissionObtained}
onDestroySession={onDestroySession}
removeSubmissionId={removeSubmissionId}
>
<Outlet />
{router}
Expand All @@ -385,23 +322,42 @@
submission: null,
onSubmissionObtained: () => {},
onDestroySession: () => {},
removeSubmissionId: () => {},

Check warning on line 325 in src/components/Form.jsx

View check run for this annotation

Codecov / codecov/patch

src/components/Form.jsx#L325

Added line #L325 was not covered by tests
});

const SubmissionProvider = ({
submission = null,
onSubmissionObtained,
onDestroySession,
removeSubmissionId,
children,
}) => (
<SubmissionContext.Provider value={{submission, onSubmissionObtained, onDestroySession}}>
<SubmissionContext.Provider
value={{submission, onSubmissionObtained, onDestroySession, removeSubmissionId}}
>
{children}
</SubmissionContext.Provider>
);

SubmissionProvider.propTypes = {
/**
* The submission currently being filled out / submitted / viewed. It must exist in
* the backend session.
*/
submission: Types.Submission,
/**
* Callback for when a submission was (re-)loaded to store it in the state.
*/
onSubmissionObtained: PropTypes.func.isRequired,
/**
* Callback for when an abort/logout/stop button is clicked which terminates the
* form submission / session.
*/
onDestroySession: PropTypes.func.isRequired,
/**
* Callback to remove the submission reference (it's ID) from the local storage.
*/
removeSubmissionId: PropTypes.func.isRequired,
};

const useSubmissionContext = () => useContext(SubmissionContext);
Expand Down
Loading
Loading