InstallControls.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import { css } from '@emotion/css';
  2. import React from 'react';
  3. import { GrafanaTheme2, PluginType } from '@grafana/data';
  4. import { config, featureEnabled } from '@grafana/runtime';
  5. import { HorizontalGroup, Icon, LinkButton, useStyles2 } from '@grafana/ui';
  6. import { getExternalManageLink, isInstallControlsEnabled } from '../../helpers';
  7. import { isGrafanaAdmin } from '../../permissions';
  8. import { useIsRemotePluginsAvailable } from '../../state/hooks';
  9. import { CatalogPlugin, PluginStatus, Version } from '../../types';
  10. import { ExternallyManagedButton } from './ExternallyManagedButton';
  11. import { InstallControlsButton } from './InstallControlsButton';
  12. interface Props {
  13. plugin: CatalogPlugin;
  14. latestCompatibleVersion?: Version;
  15. }
  16. export const InstallControls = ({ plugin, latestCompatibleVersion }: Props) => {
  17. const styles = useStyles2(getStyles);
  18. const isExternallyManaged = config.pluginAdminExternalManageEnabled;
  19. const hasPermission = isGrafanaAdmin();
  20. const isRemotePluginsAvailable = useIsRemotePluginsAvailable();
  21. const isCompatible = Boolean(latestCompatibleVersion);
  22. const isInstallControlsDisabled = plugin.isCore || plugin.isDisabled || !isInstallControlsEnabled();
  23. const pluginStatus = plugin.isInstalled
  24. ? plugin.hasUpdate
  25. ? PluginStatus.UPDATE
  26. : PluginStatus.UNINSTALL
  27. : PluginStatus.INSTALL;
  28. if (isInstallControlsDisabled) {
  29. return null;
  30. }
  31. if (plugin.type === PluginType.renderer) {
  32. return <div className={styles.message}>Renderer plugins cannot be managed by the Plugin Catalog.</div>;
  33. }
  34. if (plugin.isEnterprise && !featureEnabled('enterprise.plugins')) {
  35. return (
  36. <HorizontalGroup height="auto" align="center">
  37. <span className={styles.message}>No valid Grafana Enterprise license detected.</span>
  38. <LinkButton
  39. href={`${getExternalManageLink(plugin.id)}?utm_source=grafana_catalog_learn_more`}
  40. target="_blank"
  41. rel="noopener noreferrer"
  42. size="sm"
  43. fill="text"
  44. icon="external-link-alt"
  45. >
  46. Learn more
  47. </LinkButton>
  48. </HorizontalGroup>
  49. );
  50. }
  51. if (plugin.isDev) {
  52. return (
  53. <div className={styles.message}>This is a development build of the plugin and can&#39;t be uninstalled.</div>
  54. );
  55. }
  56. if (!hasPermission && !isExternallyManaged) {
  57. const message = `You do not have permission to ${pluginStatus} this plugin.`;
  58. return <div className={styles.message}>{message}</div>;
  59. }
  60. if (!plugin.isPublished) {
  61. return (
  62. <div className={styles.message}>
  63. <Icon name="exclamation-triangle" /> This plugin is not published to{' '}
  64. <a href="https://www.grafana.com/plugins" target="__blank" rel="noreferrer">
  65. grafana.com/plugins
  66. </a>{' '}
  67. and can&#39;t be managed via the catalog.
  68. </div>
  69. );
  70. }
  71. if (!isCompatible) {
  72. return (
  73. <div className={styles.message}>
  74. <Icon name="exclamation-triangle" />
  75. &nbsp;This plugin doesn&#39;t support your version of Grafana.
  76. </div>
  77. );
  78. }
  79. if (isExternallyManaged) {
  80. return <ExternallyManagedButton pluginId={plugin.id} pluginStatus={pluginStatus} />;
  81. }
  82. if (!isRemotePluginsAvailable) {
  83. return (
  84. <div className={styles.message}>
  85. The install controls have been disabled because the Grafana server cannot access grafana.com.
  86. </div>
  87. );
  88. }
  89. return (
  90. <InstallControlsButton
  91. plugin={plugin}
  92. pluginStatus={pluginStatus}
  93. latestCompatibleVersion={latestCompatibleVersion}
  94. />
  95. );
  96. };
  97. export const getStyles = (theme: GrafanaTheme2) => {
  98. return {
  99. message: css`
  100. color: ${theme.colors.text.secondary};
  101. `,
  102. };
  103. };