mirror of https://github.com/grafana/grafana.git
				
				
				
			AppPlugins: Expose react-router to apps (#33775)
* Allow Route component usage in app plugins * i tried * fix catalog app * fix catalog app * remove catalog changes from this PR * remove extra files * feat(plugins): expose react-router to plugins rather than export via grafana-ui * Bring back query and pathname to AppRootPage and add deprecation notice Co-authored-by: Ryan McKinley <ryantxu@gmail.com> Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
This commit is contained in:
		
							parent
							
								
									fb9223ab42
								
							
						
					
					
						commit
						4cbffae1b4
					
				| 
						 | 
				
			
			@ -12,14 +12,27 @@ export enum CoreApp {
 | 
			
		|||
 | 
			
		||||
export interface AppRootProps<T = KeyValue> {
 | 
			
		||||
  meta: AppPluginMeta<T>;
 | 
			
		||||
 | 
			
		||||
  path: string; // The URL path to this page
 | 
			
		||||
  query: KeyValue; // The URL query parameters
 | 
			
		||||
  /**
 | 
			
		||||
   * base URL segment for an app, /app/pluginId
 | 
			
		||||
   */
 | 
			
		||||
  basename: string; // The URL path to this page
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Pass the nav model to the container... is there a better way?
 | 
			
		||||
   */
 | 
			
		||||
  onNavChanged: (nav: NavModel) => void;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The URL query parameters
 | 
			
		||||
   * @deprecated Use react-router instead
 | 
			
		||||
   */
 | 
			
		||||
  query: KeyValue;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The URL path to this page
 | 
			
		||||
   * @deprecated Use react-router instead
 | 
			
		||||
   */
 | 
			
		||||
  path: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface AppPluginMeta<T = KeyValue> extends PluginMeta<T> {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -185,6 +185,7 @@ const getBaseWebpackConfig: WebpackConfigurationGetter = async (options) => {
 | 
			
		|||
      'react-redux',
 | 
			
		||||
      'redux',
 | 
			
		||||
      'rxjs',
 | 
			
		||||
      'react-router-dom',
 | 
			
		||||
      'd3',
 | 
			
		||||
      'angular',
 | 
			
		||||
      '@grafana/ui',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ export class AppWrapper extends React.Component<AppWrapperProps, AppWrapperState
 | 
			
		|||
 | 
			
		||||
    return (
 | 
			
		||||
      <Route
 | 
			
		||||
        exact
 | 
			
		||||
        exact={route.exact === undefined ? true : route.exact}
 | 
			
		||||
        path={route.path}
 | 
			
		||||
        key={route.path}
 | 
			
		||||
        render={(props) => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,4 +16,5 @@ export interface RouteDescriptor {
 | 
			
		|||
  pageClass?: string;
 | 
			
		||||
  /** Can be used like an id for the route if the same component is used by many routes */
 | 
			
		||||
  routeName?: string;
 | 
			
		||||
  exact?: boolean;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
// Libraries
 | 
			
		||||
import React, { Component } from 'react';
 | 
			
		||||
import { AppEvents, AppPlugin, AppPluginMeta, NavModel, PluginType } from '@grafana/data';
 | 
			
		||||
import { AppEvents, AppPlugin, AppPluginMeta, KeyValue, NavModel, PluginType } from '@grafana/data';
 | 
			
		||||
import { createHtmlPortalNode, InPortal, OutPortal, HtmlPortalNode } from 'react-reverse-portal';
 | 
			
		||||
 | 
			
		||||
import Page from 'app/core/components/Page/Page';
 | 
			
		||||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ import { getNotFoundNav, getWarningNav, getExceptionNav } from 'app/core/nav_mod
 | 
			
		|||
import { appEvents } from 'app/core/core';
 | 
			
		||||
import PageLoader from 'app/core/components/PageLoader/PageLoader';
 | 
			
		||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
 | 
			
		||||
import { locationSearchToObject } from '@grafana/runtime';
 | 
			
		||||
 | 
			
		||||
interface RouteParams {
 | 
			
		||||
  pluginId: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +92,6 @@ class AppRootPage extends Component<Props, State> {
 | 
			
		|||
  };
 | 
			
		||||
 | 
			
		||||
  render() {
 | 
			
		||||
    const { location, queryParams } = this.props;
 | 
			
		||||
    const { loading, plugin, nav, portalNode } = this.state;
 | 
			
		||||
 | 
			
		||||
    if (plugin && !plugin.root) {
 | 
			
		||||
| 
						 | 
				
			
			@ -105,9 +105,10 @@ class AppRootPage extends Component<Props, State> {
 | 
			
		|||
          {plugin && plugin.root && (
 | 
			
		||||
            <plugin.root
 | 
			
		||||
              meta={plugin.meta}
 | 
			
		||||
              query={queryParams}
 | 
			
		||||
              path={location.pathname}
 | 
			
		||||
              basename={this.props.match.url}
 | 
			
		||||
              onNavChanged={this.onNavChanged}
 | 
			
		||||
              query={locationSearchToObject(this.props.location.search) as KeyValue}
 | 
			
		||||
              path={this.props.location.pathname}
 | 
			
		||||
            />
 | 
			
		||||
          )}
 | 
			
		||||
        </InPortal>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,8 @@ grafanaUI.DataSourceApi = grafanaData.DataSourceApi;
 | 
			
		|||
// rxjs
 | 
			
		||||
import * as rxjs from 'rxjs';
 | 
			
		||||
import * as rxjsOperators from 'rxjs/operators';
 | 
			
		||||
// routing
 | 
			
		||||
import * as reactRouter from 'react-router-dom';
 | 
			
		||||
 | 
			
		||||
// add cache busting
 | 
			
		||||
const bust = `?_cache=${Date.now()}`;
 | 
			
		||||
| 
						 | 
				
			
			@ -92,6 +94,7 @@ exposeToPlugin('angular', angular);
 | 
			
		|||
exposeToPlugin('d3', d3);
 | 
			
		||||
exposeToPlugin('rxjs', rxjs);
 | 
			
		||||
exposeToPlugin('rxjs/operators', rxjsOperators);
 | 
			
		||||
exposeToPlugin('react-router-dom', reactRouter);
 | 
			
		||||
 | 
			
		||||
// Experimental modules
 | 
			
		||||
exposeToPlugin('prismjs', prismjs);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,6 +149,7 @@ export function getAppRoutes(): RouteDescriptor[] {
 | 
			
		|||
    },
 | 
			
		||||
    {
 | 
			
		||||
      path: '/a/:pluginId/',
 | 
			
		||||
      exact: false,
 | 
			
		||||
      // Someday * and will get a ReactRouter under that path!
 | 
			
		||||
      component: SafeDynamicImport(
 | 
			
		||||
        () => import(/* webpackChunkName: "AppRootPage" */ 'app/features/plugins/AppRootPage')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue