AppRootPage: Fixes issue navigating between two app plugin pages (#54519)

* AppRootPage: Fixes issue where it was not possible to navigate to another plugin

* Externalize react-router

* fixing test
This commit is contained in:
Torkel Ödegaard 2022-08-31 15:36:08 +02:00 committed by GitHub
parent 713075c494
commit e5fba788d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 26 deletions

View File

@ -180,6 +180,7 @@ const getBaseWebpackConfig: WebpackConfigurationGetter = async (options) => {
'react-redux',
'redux',
'rxjs',
'react-router',
'react-router-dom',
'd3',
'angular',

View File

@ -81,17 +81,18 @@ describe('AppRootPage', () => {
setEchoSrv(new Echo());
});
const pluginMeta = getMockPlugin({
id: 'my-awesome-plugin',
type: PluginType.app,
enabled: true,
});
it('should not mount plugin twice if nav is changed', async () => {
// reproduces https://github.com/grafana/grafana/pull/28105
getPluginSettingsMock.mockResolvedValue(
getMockPlugin({
type: PluginType.app,
enabled: true,
})
);
getPluginSettingsMock.mockResolvedValue(pluginMeta);
const plugin = new AppPlugin();
plugin.meta = pluginMeta;
plugin.root = RootComponent;
importAppPluginMock.mockResolvedValue(plugin);
@ -106,12 +107,7 @@ describe('AppRootPage', () => {
});
it('should not render component if not at plugin path', async () => {
getPluginSettingsMock.mockResolvedValue(
getMockPlugin({
type: PluginType.app,
enabled: true,
})
);
getPluginSettingsMock.mockResolvedValue(pluginMeta);
class RootComponent extends Component<AppRootProps> {
static timesRendered = 0;
@ -122,6 +118,7 @@ describe('AppRootPage', () => {
}
const plugin = new AppPlugin();
plugin.meta = pluginMeta;
plugin.root = RootComponent;
importAppPluginMock.mockResolvedValue(plugin);
@ -131,18 +128,18 @@ describe('AppRootPage', () => {
expect(await screen.findByText('my great component')).toBeVisible();
// renders the first time
expect(RootComponent.timesRendered).toEqual(1);
expect(RootComponent.timesRendered).toEqual(2);
await act(async () => {
locationService.push('/foo');
});
expect(RootComponent.timesRendered).toEqual(1);
expect(RootComponent.timesRendered).toEqual(2);
await act(async () => {
locationService.push('/a/my-awesome-plugin');
});
expect(RootComponent.timesRendered).toEqual(2);
expect(RootComponent.timesRendered).toEqual(4);
});
});

View File

@ -92,7 +92,15 @@ class AppRootPage extends Component<Props, State> {
render() {
const { loading, plugin, nav, portalNode } = this.state;
if (plugin && !plugin.root) {
if (!plugin || this.props.match.params.pluginId !== plugin.meta.id) {
return (
<Page>
<PageLoader />
</Page>
);
}
if (!plugin.root) {
// TODO? redirect to plugin page?
return <div>No Root App</div>;
}
@ -100,15 +108,13 @@ class AppRootPage extends Component<Props, State> {
return (
<>
<InPortal node={portalNode}>
{plugin && plugin.root && (
<plugin.root
meta={plugin.meta}
basename={this.props.match.url}
onNavChanged={this.onNavChanged}
query={this.props.queryParams as KeyValue}
path={this.props.location.pathname}
/>
)}
<plugin.root
meta={plugin.meta}
basename={this.props.match.url}
onNavChanged={this.onNavChanged}
query={this.props.queryParams as KeyValue}
path={this.props.location.pathname}
/>
</InPortal>
{nav ? (
<Page navModel={nav}>