mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-21 17:48:13 +08:00
* update to webpack 5 * update babel * update eslint * update cheerio * update npm min to v7 * revert engine change * generate package lock with npm v6 (lockfileVersion 1) * add region to test setup * update blueprint popover2 * tabindex changes due to blueprint popover2 revision * update snapshots * update lodash and pako * fix typo * fix lodash refactoring * more lodash refactoring * update babel and blueprintjs * update jest support packages * update puppeteer * update regl * update react-icons and react-helmet * update react and react-dom
141 lines
3.5 KiB
JavaScript
141 lines
3.5 KiB
JavaScript
import sortBy from "lodash.sortby";
|
|
/* XXX: cough, cough, ... */
|
|
import { postNetworkErrorToast } from "../components/framework/toasters";
|
|
|
|
/*
|
|
dispatch an action error to the user. Currently we use
|
|
async toasts.
|
|
*/
|
|
let networkErrorToastKey = null;
|
|
export const dispatchNetworkErrorMessageToUser = (message) => {
|
|
if (!networkErrorToastKey) {
|
|
networkErrorToastKey = postNetworkErrorToast(message);
|
|
} else {
|
|
postNetworkErrorToast(message, networkErrorToastKey);
|
|
}
|
|
};
|
|
|
|
/*
|
|
Catch unexpected errors and make sure we don't lose them!
|
|
*/
|
|
export function catchErrorsWrap(fn, dispatchToUser = false) {
|
|
return (dispatch, getState) => {
|
|
fn(dispatch, getState).catch((error) => {
|
|
console.error(error);
|
|
if (dispatchToUser) {
|
|
dispatchNetworkErrorMessageToUser(error.message);
|
|
}
|
|
dispatch({ type: "UNEXPECTED ERROR", error });
|
|
});
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Wrapper to perform async fetch with some modest error handling
|
|
* and decoding. Arguments are identical to standard fetch.
|
|
*/
|
|
export const doFetch = async (url, init = {}) => {
|
|
try {
|
|
// add defaults to the fetch init param.
|
|
init = {
|
|
method: "get",
|
|
credentials: "include",
|
|
...init,
|
|
};
|
|
const acceptType = init.headers?.get("Accept");
|
|
const res = await fetch(url, init);
|
|
if (
|
|
res.ok &&
|
|
(!acceptType || res.headers.get("Content-Type").includes(acceptType))
|
|
) {
|
|
return res;
|
|
}
|
|
|
|
// else an error
|
|
const msg = `Unexpected HTTP response ${res.status}, ${res.statusText}`;
|
|
dispatchNetworkErrorMessageToUser(msg);
|
|
throw new Error(msg);
|
|
} catch (e) {
|
|
// network error
|
|
const msg = "Unexpected HTTP error";
|
|
dispatchNetworkErrorMessageToUser(msg);
|
|
throw e;
|
|
}
|
|
};
|
|
|
|
/*
|
|
Wrapper to perform an async fetch and JSON decode response.
|
|
*/
|
|
export const doJsonRequest = async (url, init = {}) => {
|
|
const res = await doFetch(url, {
|
|
...init,
|
|
headers: new Headers({ Accept: "application/json" }),
|
|
});
|
|
return res.json();
|
|
};
|
|
|
|
/*
|
|
Wrapper to perform an async fetch for binary data.
|
|
*/
|
|
export const doBinaryRequest = async (url, init = {}) => {
|
|
const res = await doFetch(url, {
|
|
...init,
|
|
headers: new Headers({ Accept: "application/octet-stream" }),
|
|
});
|
|
return res.arrayBuffer();
|
|
};
|
|
|
|
/*
|
|
This function "packs" filter index lists into the more efficient
|
|
"range" form specified in the REST 0.2 spec.
|
|
|
|
Specifically, it turns an array of indices [0, 1, 2, 10, 11, 14, ...]
|
|
into a form that encodes runs of consecutive numbers as [min, max].
|
|
Array may not be sorted, but will only contain uniq values.
|
|
|
|
Parameters:
|
|
indices - input array of numbers (index)
|
|
minRangeLength - hint, min range length before it is encoded into range format.
|
|
sorted - boolean hint indicating array is presorted, ascending order
|
|
|
|
So [1, 2, 3, 4, 10, 11, 14] -> [ [1, 4], [10, 11], 14]
|
|
*/
|
|
export const rangeEncodeIndices = (
|
|
indices,
|
|
minRangeLength = 3,
|
|
sorted = false
|
|
) => {
|
|
if (indices.length === 0) {
|
|
return indices;
|
|
}
|
|
|
|
if (!sorted) {
|
|
indices = sortBy(indices);
|
|
}
|
|
|
|
const result = new Array(indices.length);
|
|
let resultTail = 0;
|
|
|
|
let i = 0;
|
|
while (i < indices.length) {
|
|
const begin = indices[i];
|
|
let current;
|
|
do {
|
|
current = indices[i];
|
|
i += 1;
|
|
} while (i < indices.length && indices[i] === current + 1);
|
|
|
|
if (current - begin + 1 >= minRangeLength) {
|
|
result[resultTail] = [begin, current];
|
|
resultTail += 1;
|
|
} else {
|
|
for (let j = begin; j <= current; j += 1, resultTail += 1) {
|
|
result[resultTail] = j;
|
|
}
|
|
}
|
|
}
|
|
|
|
result.length = resultTail;
|
|
return result;
|
|
};
|