mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Fix undo/redo and SO.resolve redirect issues (#116773)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
f6f7c2d1de
commit
25426708a8
2 changed files with 61 additions and 16 deletions
|
@ -6,11 +6,13 @@
|
|||
*/
|
||||
|
||||
import React, { FC, useRef, useEffect } from 'react';
|
||||
import { Observable } from 'rxjs';
|
||||
import PropTypes from 'prop-types';
|
||||
import { History } from 'history';
|
||||
// @ts-expect-error
|
||||
import createHashStateHistory from 'history-extra/dist/createHashStateHistory';
|
||||
import { ScopedHistory } from 'kibana/public';
|
||||
import { skipWhile, timeout, take } from 'rxjs/operators';
|
||||
import { useNavLinkService } from '../../services';
|
||||
// @ts-expect-error
|
||||
import { shortcutManager } from '../../lib/shortcut_manager';
|
||||
|
@ -40,14 +42,50 @@ export const App: FC<{ history: ScopedHistory }> = ({ history }) => {
|
|||
});
|
||||
});
|
||||
|
||||
// We are using our own history due to needing pushState functionality not yet available on standard history
|
||||
// This effect will listen for changes on the scoped history and push that to our history
|
||||
// This is needed for SavedObject.resolve redirects
|
||||
useEffect(() => {
|
||||
return history.listen((location) => {
|
||||
historyRef.current.replace(location.hash.substr(1));
|
||||
return history.listen(({ pathname, hash }) => {
|
||||
// The scoped history could have something that triggers a url change, and that change is not seen by
|
||||
// our hash router. For example, a scopedHistory.replace() as done as part of the saved object resolve
|
||||
// alias match flow will do the replace on the scopedHistory, and our app doesn't react appropriately
|
||||
|
||||
// So, to work around this, whenever we see a url on the scoped history, we're going to wait a beat and see
|
||||
// if it shows up in our hash router. If it doesn't, then we're going to force it onto our hash router
|
||||
|
||||
// I don't like this at all, and to overcome this we should switch away from hash router sooner rather than later
|
||||
// and just use scopedHistory as our history object
|
||||
const expectedPath = hash.substr(1);
|
||||
const action = history.action;
|
||||
|
||||
// Observable of all the path
|
||||
const hashPaths$ = new Observable<string>((subscriber) => {
|
||||
subscriber.next(historyRef.current.location.pathname);
|
||||
|
||||
const unsubscribeHashListener = historyRef.current.listen(({ pathname: newPath }) => {
|
||||
subscriber.next(newPath);
|
||||
});
|
||||
|
||||
return unsubscribeHashListener;
|
||||
});
|
||||
|
||||
const subscription = hashPaths$
|
||||
.pipe(
|
||||
skipWhile((value) => value !== expectedPath),
|
||||
timeout(100),
|
||||
take(1)
|
||||
)
|
||||
.subscribe({
|
||||
error: (e) => {
|
||||
if (action === 'REPLACE') {
|
||||
historyRef.current.replace(expectedPath);
|
||||
} else {
|
||||
historyRef.current.push(expectedPath);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
window.setTimeout(() => subscription.unsubscribe(), 150);
|
||||
});
|
||||
}, [history]);
|
||||
}, [history, historyRef]);
|
||||
|
||||
return (
|
||||
<ShortcutManagerContextWrapper>
|
||||
|
|
|
@ -35,7 +35,7 @@ export const useWorkpad = (
|
|||
const [error, setError] = useState<string | Error | undefined>(undefined);
|
||||
|
||||
const [resolveInfo, setResolveInfo] = useState<
|
||||
{ aliasId: string | undefined; outcome: string } | undefined
|
||||
{ id: string; aliasId: string | undefined; outcome: string } | undefined
|
||||
>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -47,15 +47,16 @@ export const useWorkpad = (
|
|||
workpad: { assets, ...workpad },
|
||||
} = await workpadResolve(workpadId);
|
||||
|
||||
setResolveInfo({ aliasId, outcome });
|
||||
setResolveInfo({ aliasId, outcome, id: workpadId });
|
||||
|
||||
if (outcome === 'conflict') {
|
||||
// If it's an alias match, we know we are going to redirect so don't even dispatch that we got the workpad
|
||||
if (outcome !== 'aliasMatch') {
|
||||
workpad.aliasId = aliasId;
|
||||
}
|
||||
|
||||
dispatch(setAssets(assets));
|
||||
dispatch(setWorkpad(workpad, { loadPages }));
|
||||
dispatch(setZoomScale(1));
|
||||
dispatch(setAssets(assets));
|
||||
dispatch(setWorkpad(workpad, { loadPages }));
|
||||
dispatch(setZoomScale(1));
|
||||
}
|
||||
} catch (e) {
|
||||
setError(e as Error | string);
|
||||
}
|
||||
|
@ -63,15 +64,21 @@ export const useWorkpad = (
|
|||
}, [workpadId, dispatch, setError, loadPages, workpadResolve]);
|
||||
|
||||
useEffect(() => {
|
||||
(() => {
|
||||
// If the resolved info is not for the current workpad id, bail out
|
||||
if (resolveInfo && resolveInfo.id !== workpadId) {
|
||||
return;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
if (!resolveInfo) return;
|
||||
|
||||
const { aliasId, outcome } = resolveInfo;
|
||||
if (outcome === 'aliasMatch' && platformService.redirectLegacyUrl && aliasId) {
|
||||
platformService.redirectLegacyUrl(`#${getRedirectPath(aliasId)}`, getWorkpadLabel());
|
||||
const redirectPath = getRedirectPath(aliasId);
|
||||
await platformService.redirectLegacyUrl(`#${redirectPath}`, getWorkpadLabel());
|
||||
}
|
||||
})();
|
||||
}, [resolveInfo, getRedirectPath, platformService]);
|
||||
}, [workpadId, resolveInfo, getRedirectPath, platformService]);
|
||||
|
||||
return [storedWorkpad.id === workpadId ? storedWorkpad : undefined, error];
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue