feat(ui): change fetch indicator color to red when requests are failing

This commit is contained in:
Łukasz Mierzwa
2019-12-25 15:41:26 +00:00
parent 8325dc1ab2
commit 0804aa475b
5 changed files with 45 additions and 4 deletions

View File

@@ -13,7 +13,7 @@ const FetchRetryConfig = {
maxTimeout: 5000
};
const FetchGet = async (uri, options, retryOptions) =>
const FetchGet = async (uri, options, beforeRetry) =>
await promiseRetry(
(retry, number) =>
fetch(
@@ -30,7 +30,10 @@ const FetchGet = async (uri, options, retryOptions) =>
CommonOptions,
options
)
).catch(retry),
).catch(err => {
beforeRetry && beforeRetry(number);
return retry(err);
}),
FetchRetryConfig
);

View File

@@ -79,4 +79,19 @@ describe("Fetch", () => {
});
}
});
it("FetchGet calls beforeRetry before each retry", async () => {
fetch.mockReject(new Error("Fetch error"));
const beforeRetrySpy = jest.fn();
const request = FetchGet("http://example.com", {}, beforeRetrySpy);
await expect(request).rejects.toThrow("Fetch error");
expect(beforeRetrySpy).toHaveBeenCalledTimes(11);
for (let i = 0; i < 10; i++) {
expect(beforeRetrySpy.mock.calls[i][0]).toBe(i + 1);
}
});
});

View File

@@ -44,7 +44,13 @@ const FetchIndicator = observer(
const status = alertStore.status.value.toString();
if (status === AlertStoreStatuses.Fetching.toString())
return <FetchIcon icon={faCircleNotch} spin />;
return (
<FetchIcon
icon={faCircleNotch}
color={alertStore.info.isRetrying ? "danger" : "muted"}
spin
/>
);
if (status === AlertStoreStatuses.Processing.toString())
return <FetchIcon icon={faCircleNotch} color="success" spin />;

View File

@@ -42,6 +42,13 @@ describe("<FetchIndicator />", () => {
expect(tree.find("FontAwesomeIcon").hasClass("text-muted")).toBe(true);
});
it("uses text-danger when we need to retry fetch", () => {
alertStore.info.setIsRetrying();
alertStore.status.setFetching();
const tree = MountedFetchIndicator();
expect(tree.find("FontAwesomeIcon").hasClass("text-danger")).toBe(true);
});
it("opacity is 1 when response is processed", () => {
alertStore.status.setProcessing();
const tree = MountedFetchIndicator();

View File

@@ -182,12 +182,21 @@ class AlertStore {
totalAlerts: 0,
version: "unknown",
upgradeNeeded: false,
isRetrying: false,
reloadNeeded: false,
setIsRetrying() {
this.isRetrying = true;
},
clearIsRetrying() {
this.isRetrying = false;
},
setReloadNeeded() {
this.reloadNeeded = true;
}
},
{
setIsRetrying: action.bound,
clearIsRetrying: action.bound,
setReloadNeeded: action
},
{ name: "API response info" }
@@ -281,7 +290,7 @@ class AlertStore {
`alerts.json?sortOrder=${sortOrder}&sortLabel=${sortLabel}&sortReverse=${sortReverse}&`
) + FormatAPIFilterQuery(this.filters.values.map(f => f.raw));
return FetchGet(alertsURI, {})
return FetchGet(alertsURI, {}, this.info.setIsRetrying)
.then(result => {
// we're sending requests with mode=cors so the response should also be type=cors
// after a few failures in the retry loop we will switch to no-cors
@@ -290,6 +299,7 @@ class AlertStore {
if (result.type === "opaque") {
this.info.setReloadNeeded();
}
this.info.clearIsRetrying();
this.status.setProcessing();
return result.json();
})