import React from 'react'; import { useAsync } from 'react-use'; import { css, cx } from '@emotion/css'; import { GrafanaTheme, PanelProps, PluginMeta, PluginType } from '@grafana/data'; import { CustomScrollbar, ModalsController, stylesFactory, Tooltip, useStyles } from '@grafana/ui'; import { config, locationService } from '@grafana/runtime'; import { contextSrv } from 'app/core/services/context_srv'; import { getBackendSrv } from 'app/core/services/backend_srv'; import { UpdatePluginModal } from './components/UpdatePluginModal'; export function PluginList(props: PanelProps) { const pluginState = useAsync(async () => { const plugins: PluginMeta[] = await getBackendSrv().get('api/plugins', { embedded: 0, core: 0 }); return [ { header: 'Installed Apps', list: plugins.filter((p) => p.type === PluginType.app), type: PluginType.app }, { header: 'Installed Panels', list: plugins.filter((p) => p.type === PluginType.panel), type: PluginType.panel }, { header: 'Installed Datasources', list: plugins.filter((p) => p.type === PluginType.datasource), type: PluginType.datasource, }, ]; }, []); const styles = useStyles(getStyles); const isAdmin = contextSrv.user.isGrafanaAdmin; if (pluginState.loading || pluginState.value === undefined) { return null; } return (
{pluginState.value.map((category) => (
{category.header}
{category.list.map((plugin) => ( {plugin.name} v{plugin.info.version} {isAdmin && (plugin.hasUpdate ? ( {({ showModal, hideModal }) => ( { e.preventDefault(); if (config.pluginAdminEnabled) { locationService.push(`/a/grafana-plugin-admin-app/plugin/${plugin.id}`); } else { showModal(UpdatePluginModal, { pluginID: plugin.id, pluginName: plugin.name, onDismiss: hideModal, isOpen: true, }); } }} > Update available! )} ) : plugin.enabled ? ( Up to date ) : ( Enable now ))} ))} {category.list.length === 0 && ( None installed. Browse Grafana.com )}
))}
); } const getStyles = stylesFactory((theme: GrafanaTheme) => ({ pluginList: css` display: flex; flex-direction: column; `, section: css` display: flex; flex-direction: column; &:not(:last-of-type) { margin-bottom: 16px; } `, sectionHeader: css` color: ${theme.colors.textWeak}; margin-bottom: ${theme.spacing.d}; `, image: css` width: 17px; margin-right: ${theme.spacing.xxs}; `, title: css` margin-right: calc(${theme.spacing.d} / 3); `, version: css` font-size: ${theme.typography.size.sm}; color: ${theme.colors.textWeak}; `, item: css` display: flex; justify-content: flex-start; align-items: center; cursor: pointer; margin: ${theme.spacing.xxs}; padding: ${theme.spacing.sm}; background: ${theme.colors.dashboardBg}; border-radius: ${theme.border.radius.md}; `, message: css` margin-left: auto; font-size: ${theme.typography.size.sm}; `, messageEnable: css` color: ${theme.colors.linkExternal}; &:hover { border-bottom: ${theme.border.width.sm} solid ${theme.colors.linkExternal}; } `, messageUpdate: css` &:hover { border-bottom: ${theme.border.width.sm} solid ${theme.colors.text}; } `, messageNoUpdate: css` color: ${theme.colors.textWeak}; `, noneInstalled: css` color: ${theme.colors.textWeak}; font-size: ${theme.typography.size.sm}; `, emphasis: css` font-weight: ${theme.typography.weight.semibold}; font-style: normal; color: ${theme.colors.textWeak}; `, }));