mirror of
https://github.com/getredash/redash.git
synced 2026-03-21 07:00:07 -04:00
* Fix too many history.replaceState() error on Safari * fix restyled error by running prettier for client/app/services/location.js
106 lines
2.6 KiB
JavaScript
106 lines
2.6 KiB
JavaScript
import { isNil, isUndefined, isFunction, isObject, trimStart, mapValues, omitBy, extend } from "lodash";
|
|
import qs from "query-string";
|
|
import { createBrowserHistory } from "history";
|
|
|
|
const history = createBrowserHistory();
|
|
|
|
function normalizeLocation(rawLocation) {
|
|
const { pathname, search, hash } = rawLocation;
|
|
const result = {};
|
|
|
|
result.path = pathname;
|
|
result.search = mapValues(qs.parse(search), (value) => (isNil(value) ? true : value));
|
|
result.hash = trimStart(hash, "#");
|
|
result.url = `${pathname}${search}${hash}`;
|
|
|
|
return result;
|
|
}
|
|
|
|
const location = {
|
|
listen(handler) {
|
|
if (isFunction(handler)) {
|
|
return history.listen((unused, action) => handler(location, action));
|
|
} else {
|
|
return () => {};
|
|
}
|
|
},
|
|
|
|
confirmChange(handler) {
|
|
if (isFunction(handler)) {
|
|
return history.block((nextLocation) => {
|
|
return handler(normalizeLocation(nextLocation), location);
|
|
});
|
|
} else {
|
|
return () => {};
|
|
}
|
|
},
|
|
|
|
update(newLocation, replace = false) {
|
|
if (isObject(newLocation)) {
|
|
// remap fields and remove undefined ones
|
|
newLocation = omitBy(
|
|
{
|
|
pathname: newLocation.path,
|
|
search: newLocation.search,
|
|
hash: newLocation.hash,
|
|
},
|
|
isUndefined
|
|
);
|
|
|
|
// keep existing fields (!)
|
|
newLocation = extend(
|
|
{
|
|
pathname: location.path,
|
|
search: location.search,
|
|
hash: location.hash,
|
|
},
|
|
newLocation
|
|
);
|
|
|
|
// serialize search and keep existing search parameters (!)
|
|
if (isObject(newLocation.search)) {
|
|
newLocation.search = omitBy(extend({}, location.search, newLocation.search), isNil);
|
|
newLocation.search = mapValues(newLocation.search, (value) => (value === true ? null : value));
|
|
newLocation.search = qs.stringify(newLocation.search);
|
|
}
|
|
}
|
|
if (replace) {
|
|
if (
|
|
newLocation.pathname !== location.path ||
|
|
newLocation.search !== qs.stringify(location.search) ||
|
|
newLocation.hash !== location.hash
|
|
) {
|
|
history.replace(newLocation);
|
|
}
|
|
} else {
|
|
history.push(newLocation);
|
|
}
|
|
},
|
|
|
|
url: undefined,
|
|
|
|
path: undefined,
|
|
setPath(path, replace = false) {
|
|
location.update({ path }, replace);
|
|
},
|
|
|
|
search: undefined,
|
|
setSearch(search, replace = false) {
|
|
location.update({ search }, replace);
|
|
},
|
|
|
|
hash: undefined,
|
|
setHash(hash, replace = false) {
|
|
location.update({ hash }, replace);
|
|
},
|
|
};
|
|
|
|
function locationChanged() {
|
|
extend(location, normalizeLocation(history.location));
|
|
}
|
|
|
|
history.listen(locationChanged);
|
|
locationChanged(); // init service
|
|
|
|
export default location;
|