Skip to content

Commit d3f935a

Browse files
authored
Improve behavior on errors when importing a dataset (#74)
* Improve error display * Italics * Review fixes * Add error to modal * Try explicit return * Try without explicit return * Different order * Show error * Error codes
1 parent f053b86 commit d3f935a

File tree

1 file changed

+46
-7
lines changed

1 file changed

+46
-7
lines changed

src/api/EpiData.ts

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable @typescript-eslint/restrict-template-expressions */
12
import UIkit from 'uikit';
23
import { appendIssueToTitle } from '../components/dialogs/utils';
34
import {
@@ -43,11 +44,23 @@ const ENDPOINT = process.env.EPIDATA_ENDPOINT_URL;
4344

4445
export const fetchOptions: RequestInit = process.env.NODE_ENV === 'development' ? { cache: 'force-cache' } : {};
4546

47+
function processResponse<T>(response: Response): Promise<T> {
48+
if (response.ok) {
49+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
50+
return response.json();
51+
}
52+
return response.text().then((text) => {
53+
throw new Error(`[${response.status}] ${text}`);
54+
});
55+
}
56+
4657
export function fetchImpl<T>(url: URL): Promise<T> {
4758
const urlGetS = url.toString();
4859
if (urlGetS.length < 4096) {
4960
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
50-
return fetch(url.toString(), fetchOptions).then((d) => d.json());
61+
return fetch(url.toString(), fetchOptions).then((d) => {
62+
return processResponse(d);
63+
});
5164
}
5265
const params = new URLSearchParams(url.searchParams);
5366
url.searchParams.forEach((d) => url.searchParams.delete(d));
@@ -56,7 +69,9 @@ export function fetchImpl<T>(url: URL): Promise<T> {
5669
...fetchOptions,
5770
method: 'POST',
5871
body: params,
59-
}).then((d) => d.json());
72+
}).then((d) => {
73+
return processResponse(d);
74+
});
6075
}
6176

6277
// generic epidata loader
@@ -147,26 +162,50 @@ export function loadDataSet(
147162
url.searchParams.set('format', 'json');
148163
return fetchImpl<Record<string, unknown>[]>(url)
149164
.then((res) => {
150-
const data = loadEpidata(title, res, columns, columnRenamings, { _endpoint: endpoint, ...params });
151-
if (data.datasets.length == 0) {
165+
try {
166+
const data = loadEpidata(title, res, columns, columnRenamings, { _endpoint: endpoint, ...params });
167+
if (data.datasets.length == 0) {
168+
return UIkit.modal
169+
.alert(
170+
`
171+
<div class="uk-alert uk-alert-error">
172+
<a href="${url.href}">API Link</a> returned no data, which suggests that the API has no available information for the selected location.
173+
</div>`,
174+
)
175+
.then(() => null);
176+
}
177+
return data;
178+
} catch (error) {
179+
console.warn('failed loading data', error);
180+
// EpiData API error - JSON with "message" property
181+
if ('message' in res) {
182+
return UIkit.modal
183+
.alert(
184+
`
185+
<div class="uk-alert uk-alert-error">
186+
[f01] Failed to fetch API data from <a href="${url.href}">API Link</a>:<br/><i>${res['message']}</i>
187+
</div>`,
188+
)
189+
.then(() => null);
190+
}
191+
// Fallback for generic error
152192
return UIkit.modal
153193
.alert(
154194
`
155195
<div class="uk-alert uk-alert-error">
156-
<a href="${url.href}">API Link</a> returned no data.
196+
[f02] Failed to fetch API data from <a href="${url.href}">API Link</a>:<br/><i>${error}</i>
157197
</div>`,
158198
)
159199
.then(() => null);
160200
}
161-
return data;
162201
})
163202
.catch((error) => {
164203
console.warn('failed fetching data', error);
165204
return UIkit.modal
166205
.alert(
167206
`
168207
<div class="uk-alert uk-alert-error">
169-
Failed to fetch API data from <a href="${url.href}">API Link</a>.
208+
[f03] Failed to fetch API data from <a href="${url.href}">API Link</a>:<br/><i>${error}</i>
170209
</div>`,
171210
)
172211
.then(() => null);

0 commit comments

Comments
 (0)