|
|
|
@ -1,6 +1,7 @@ |
|
|
|
|
import { css } from '@emotion/css'; |
|
|
|
|
import { isArray, isObject } from 'lodash'; |
|
|
|
|
import React from 'react'; |
|
|
|
|
import { useAsync } from 'react-use'; |
|
|
|
|
|
|
|
|
|
import { |
|
|
|
|
type PluginExtensionLinkConfig, |
|
|
|
@ -12,7 +13,6 @@ import { |
|
|
|
|
isDateTime, |
|
|
|
|
dateTime, |
|
|
|
|
PluginContextProvider, |
|
|
|
|
PluginMeta, |
|
|
|
|
} from '@grafana/data'; |
|
|
|
|
import { Modal } from '@grafana/ui'; |
|
|
|
|
import appEvents from 'app/core/app_events'; |
|
|
|
@ -51,11 +51,10 @@ export function handleErrorsInFn(fn: Function, errorMessagePrefix = '') { |
|
|
|
|
export function getEventHelpers(pluginId: string, context?: Readonly<object>): PluginExtensionEventHelpers { |
|
|
|
|
const openModal: PluginExtensionEventHelpers['openModal'] = async (options) => { |
|
|
|
|
const { title, body, width, height } = options; |
|
|
|
|
const pluginMeta = await getPluginSettings(pluginId); |
|
|
|
|
|
|
|
|
|
appEvents.publish( |
|
|
|
|
new ShowModalReactEvent({ |
|
|
|
|
component: getModalWrapper({ title, body, width, height, pluginMeta }), |
|
|
|
|
component: wrapWithPluginContext<ModalWrapperProps>(pluginId, getModalWrapper({ title, body, width, height })), |
|
|
|
|
}) |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
@ -67,6 +66,38 @@ type ModalWrapperProps = { |
|
|
|
|
onDismiss: () => void; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
export const wrapWithPluginContext = <T,>(pluginId: string, Component: React.ComponentType<T>) => { |
|
|
|
|
const WrappedExtensionComponent = (props: T & React.JSX.IntrinsicAttributes) => { |
|
|
|
|
const { |
|
|
|
|
error, |
|
|
|
|
loading, |
|
|
|
|
value: pluginMeta, |
|
|
|
|
} = useAsync(() => getPluginSettings(pluginId, { showErrorAlert: false })); |
|
|
|
|
|
|
|
|
|
if (loading) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (error) { |
|
|
|
|
logWarning(`Could not fetch plugin meta information for "${pluginId}", aborting. (${error.message})`); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!pluginMeta) { |
|
|
|
|
logWarning(`Fetched plugin meta information is empty for "${pluginId}", aborting.`); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<PluginContextProvider meta={pluginMeta}> |
|
|
|
|
<Component {...props} /> |
|
|
|
|
</PluginContextProvider> |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
return WrappedExtensionComponent; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// Wraps a component with a modal.
|
|
|
|
|
// This way we can make sure that the modal is closable, and we also make the usage simpler.
|
|
|
|
|
const getModalWrapper = ({ |
|
|
|
@ -76,17 +107,14 @@ const getModalWrapper = ({ |
|
|
|
|
body: Body, |
|
|
|
|
width, |
|
|
|
|
height, |
|
|
|
|
pluginMeta, |
|
|
|
|
}: { pluginMeta: PluginMeta } & PluginExtensionOpenModalOptions) => { |
|
|
|
|
}: PluginExtensionOpenModalOptions) => { |
|
|
|
|
const className = css({ width, height }); |
|
|
|
|
|
|
|
|
|
const ModalWrapper = ({ onDismiss }: ModalWrapperProps) => { |
|
|
|
|
return ( |
|
|
|
|
<PluginContextProvider meta={pluginMeta}> |
|
|
|
|
<Modal title={title} className={className} isOpen onDismiss={onDismiss} onClickBackdrop={onDismiss}> |
|
|
|
|
<Body onDismiss={onDismiss} /> |
|
|
|
|
</Modal> |
|
|
|
|
</PluginContextProvider> |
|
|
|
|
<Modal title={title} className={className} isOpen onDismiss={onDismiss} onClickBackdrop={onDismiss}> |
|
|
|
|
<Body onDismiss={onDismiss} /> |
|
|
|
|
</Modal> |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|