Skip to content
This repository has been archived by the owner on Jan 4, 2023. It is now read-only.

Show errors 500 and 400 on preview #639

Merged
merged 28 commits into from
Oct 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
503a121
feat(river): use HAPI FHIR $validate in preview
simonvadee Sep 14, 2021
bfd46e7
clean(settings): remove PYROG_API_URL
simonvadee Sep 15, 2021
a24267f
clean(docker): use env variables in docker-compose
simonvadee Sep 15, 2021
1fc63ba
fix(preview): update preview serializer
simonvadee Sep 16, 2021
ef15842
feat(app): use OperationOutcomeIssue in preview errors
simonvadee Sep 16, 2021
e18286c
deps: bump "requests" package to 2.26.0
simonvadee Sep 20, 2021
6a312e5
deps: add test dependency to "responses"
simonvadee Sep 20, 2021
480026d
fix(fhir_api): validate() does not raise on non-2XX
simonvadee Sep 20, 2021
81db5ef
tests(adapters): add tests for fhir_api adapter
simonvadee Sep 21, 2021
084980e
test(preview): test preview with validation errors
simonvadee Sep 21, 2021
ca4a42a
refactor(tests): clean fhir_api adapter tests
simonvadee Sep 22, 2021
50d0092
fix(tests): scope of api_client is function
simonvadee Sep 22, 2021
8e4c5b7
fix(fhir_api): differentiate _get and _post
simonvadee Sep 22, 2021
703bd38
fix(tests): scope api_client for "module"
simonvadee Sep 22, 2021
0d0ba75
chore(tests): add fhir_api marker
simonvadee Sep 22, 2021
29cd41b
fix(tests): remove unsued snapshots
simonvadee Sep 22, 2021
5635678
fix[app]: handle api errors in preview with notistack and not only al…
Sep 22, 2021
102de13
refactor(app): creation of an handling error function
Sep 22, 2021
06b813e
fix(app): add handling of server errors
Sep 23, 2021
7a29917
Merge branch 'v4' into mc/app/showErrorsOnPreview
Klochette Oct 11, 2021
43dd5d6
fix(app): merging v4 in branch
Oct 11, 2021
84c6f14
fix(app): corrections from reviews and add functions for different er…
Oct 11, 2021
b88472e
fix(app): fix error display on validation
Oct 11, 2021
1051621
fix(app): river schema reset
Oct 11, 2021
77ee7b0
fix(app): resolve reviews, change api generated to what's in v4
Oct 11, 2021
a6ae5ae
fix(app): delete cast for color
Oct 11, 2021
15bb1b7
fix(app): reset to v4
Oct 12, 2021
3483a36
fix(app): reset ambr
Oct 12, 2021
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
157 changes: 110 additions & 47 deletions app/src/features/Preview/Preview.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useCallback } from "react";

import { IResource } from "@ahryman40k/ts-fhir-types/lib/R4";
import { Icon } from "@blueprintjs/core";
Expand All @@ -17,7 +17,9 @@ import {
useMediaQuery,
} from "@material-ui/core";
import Alert, { Color } from "@material-ui/lab/Alert";
import { FetchBaseQueryError } from "@reduxjs/toolkit/dist/query";
import clsx from "clsx";
import { useSnackbar } from "notistack";
import { useTranslation } from "react-i18next";
import ReactJson from "react-json-view";
import { useParams } from "react-router-dom";
Expand All @@ -29,6 +31,10 @@ import {
useApiOwnersRetrieveQuery,
useApiPreviewCreateMutation,
} from "services/api/endpoints";
import {
apiValidationErrorFromResponse,
ApiValidationError,
} from "services/api/errors";
import {
ExplorationResponse,
OperationOutcomeIssue,
Expand Down Expand Up @@ -136,6 +142,7 @@ const getAlertSeverityFromOperationOutcomeIssue = (
const Preview = (): JSX.Element => {
const classes = useStyles();
const { t } = useTranslation();
const { enqueueSnackbar } = useSnackbar();
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
const { mappingId } = useParams<{
mappingId?: string;
Expand All @@ -144,20 +151,19 @@ const Preview = (): JSX.Element => {
const [exploration, setExploration] = useState<
ExplorationResponse | null | undefined
>(undefined);

const [alerts, setAlerts] = useState<
AlertOperationOutcomeIssue[] | undefined
>(undefined);

const [preview, setPreview] = useState<IResource | undefined>(undefined);

const handleAlertClose = (index: number) => {
if (alerts) {
const newAlerts = [...alerts];
newAlerts.splice(index, 1);
setAlerts(newAlerts);
}
};

const [preview, setPreview] = useState<IResource | undefined>(undefined);

const { data: mapping } = useApiResourcesRetrieveQuery(
{ id: mappingId ?? "" },
{ skip: !mappingId }
Expand All @@ -172,39 +178,71 @@ const Preview = (): JSX.Element => {

const [apiExploreCreate] = useApiExploreCreateMutation();

useEffect(() => {
if (mappingId && owner && exploration === undefined) {
setExploration(null);
const handleValidationError = useCallback(
({
errors,
errorStatus,
errorField,
}: {
errors?: ApiValidationError<unknown>;
errorStatus: number | "FETCH_ERROR" | "PARSING_ERROR" | "CUSTOM_ERROR";
errorField: string;
}) => {
if (errors) {
const errorEntries = Object.entries(errors);
errorEntries.forEach(([key, text]) => {
for (const error in text) {
enqueueSnackbar(
t<string>("catchValidationErrorPrompt", {
query: errorField,
errorStatus: errorStatus,
errorKey: key,
errorText: text[error],
}),
{
variant: "error",
}
);
}
});
}
},
[enqueueSnackbar, t]
);

const explore = async () => {
try {
const exploration = await apiExploreCreate({
explorationRequestRequest: {
owner: owner?.name ?? "",
table: mapping?.primary_key_table ?? "",
resource_id: mappingId,
},
}).unwrap();
setExploration(exploration);
} catch (e) {
setAlerts([
{
severity: "error",
diagnostics: e.error,
code: "internal",
},
]);
}
};
explore();
}
}, [
apiExploreCreate,
exploration,
mapping?.primary_key_table,
mappingId,
owner,
]);
const handleError = useCallback(
(error: FetchBaseQueryError) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Casting the error variable here doesn't raise any eslint error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it doesn't

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm I thought we were in a catch statement

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm I thought we were in a catch statement

const validationError = apiValidationErrorFromResponse(error);
switch (error.status) {
case "PARSING_ERROR":
enqueueSnackbar(
t<string>("catchValidationErrorPrompt", {
query: error.status,
errorStatus: error.originalStatus.toString(),
errorText: error.error,
}),
{ variant: "error" }
);
break;
case "FETCH_ERROR":
case "CUSTOM_ERROR":
error.data &&
enqueueSnackbar(`${error.status} : ${error.data as string}`, {
variant: "error",
});
break;
default:
validationError &&
handleValidationError({
errors: validationError,
errorStatus: error.status,
errorField: "Preview",
});
break;
}
},
[enqueueSnackbar, handleValidationError, t]
);

const [apiPreviewCreate] = useApiPreviewCreateMutation();

Expand All @@ -230,21 +268,46 @@ const Preview = (): JSX.Element => {
severity: getAlertSeverityFromOperationOutcomeIssue(error),
}))
);
} catch (e) {
setAlerts([
{
severity: "error",
diagnostics: e.error,
code: "internal",
},
]);
} catch (error) {
handleError(error as FetchBaseQueryError);
}
};
previewCreate();
}
}
};

// load the data for the table preview list
useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a small comment explaining what this useEffect does?

if (mappingId && owner && exploration === undefined) {
setExploration(null);

const explore = async () => {
try {
const _exploration = await apiExploreCreate({
explorationRequestRequest: {
owner: owner?.name ?? "",
table: mapping?.primary_key_table ?? "",
resource_id: mappingId,
},
}).unwrap();
setExploration(_exploration);
} catch (error) {
handleError(error as FetchBaseQueryError);
}
};
explore();
}
}, [
apiExploreCreate,
exploration,
mapping?.primary_key_table,
mappingId,
owner,
handleError,
enqueueSnackbar,
]);

return (
<Container className={classes.container} maxWidth="xl">
<BackButton className={classes.button} />
Expand Down Expand Up @@ -318,8 +381,8 @@ const Preview = (): JSX.Element => {
) : (
<div className={classes.texts}>
<Typography>
{t("clickOnAFireIcon")}{" "}
<Icon icon={IconNames.FLAME} className={classes.iconFlame} />{" "}
{t("clickOnAFireIcon")}
<Icon icon={IconNames.FLAME} className={classes.iconFlame} />
{t("inOrderToPreview")}
</Typography>
</div>
Expand Down
7 changes: 4 additions & 3 deletions app/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@
"exportMapping": "Export mapping",
"ETLDashboard": "ETL Dashboard",
"newMapping": "New mapping",
"clickOnAFireIcon": "Click on a",
"inOrderToPreview": "icon in order to preview a line as a FHIR instance",
"clickOnAFireIcon": "Click on a ",
"inOrderToPreview": " icon in order to preview a line as a FHIR instance",
"back": "Back",
"useThisGroupIf": "Use this group if...",
"resources": "Resources",
Expand Down Expand Up @@ -148,5 +148,6 @@
"batchErrors": "⚠️ {{errors}} errors",
"batchSuccess": "✅ Success",
"batchCanceled": "🚫 Canceled",
"noAvailableResource": "No available resource"
"noAvailableResource": "No available resource",
"catchValidationErrorPrompt": "{{ query }} | Error Type : {{ errorStatus }} | {{errorKey}} : {{errorText}}"
}