Plugins: Catalog force enable via config and remove enterprise plugin options (#34358)

* force enable catalog based on backend config

* update comments

* chore(plugin-catalog): remove config page in favour of backend flag

* docs(plugin-catalog): update readme

Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
This commit is contained in:
Will Browne 2021-05-19 10:22:31 +02:00 committed by GitHub
parent 354aa54a33
commit 4e31169a43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 20 additions and 118 deletions

View File

@ -84,6 +84,11 @@ func (app *AppPlugin) InitApp(panels map[string]*PanelPlugin, dataSources map[st
cfg *setting.Cfg) []*PluginStaticRoute {
staticRoutes := app.InitFrontendPlugin(cfg)
// force enable bundled catalog app
if app.Id == "grafana-plugin-catalog-app" && cfg.CatalogAppEnabled {
app.AutoEnabled = true
}
// check if we have child panels
for _, panel := range panels {
if strings.HasPrefix(panel.PluginDir, app.PluginDir) {

View File

@ -1,21 +1,5 @@
# Grafana plugin catalog
Browse and manage plugins from within Grafana.
Allow Admin users to browse and manage plugins from within Grafana.
- Admin users can browse plugins, list installed plugins, and install / uninstall plugins
![Screenshot](/src/img/discover.png)
## Installation
1. Navigate to **Configuration** -> **Plugins** and click on the Catalog plugin in the list
1. Click the **Enable app** to enable the plugin
1. Click the **Pin app** to add it to the side menu
## Configuration
| Option | Description |
| ------------------------- | ------------------------------------------------ |
| _Enable app_ | Must be done before being able to use the plugin |
| _Pin app_ | Add the app to the side menu |
| _Show Enterprise plugins_ | Show Enterprise plugins in the catalog |
This plugin is **included** with Grafana however it is only accessible if [enabled in Grafana settings](https://grafana.com/docs/grafana/next/administration/configuration/#catalog_app_enabled).

View File

@ -1,71 +0,0 @@
import React, { useState } from 'react';
import { PluginConfigPageProps, AppPluginMeta, PluginMeta } from '@grafana/data';
import { CatalogAppSettings } from 'types';
import { Button, Field, Legend, Switch } from '@grafana/ui';
import { api } from '../api';
import { PLUGIN_ID } from '../constants';
interface Props extends PluginConfigPageProps<AppPluginMeta<CatalogAppSettings>> {}
export const Settings = ({ plugin }: Props) => {
const [meta, setMeta] = useState(plugin.meta);
const [state, setState] = useState<CatalogAppSettings>(meta.jsonData ?? {});
const { pinned, enabled } = meta;
const { includeEnterprise } = state;
const onSave = () => {
updateAndReload(PLUGIN_ID, {
pinned,
enabled,
jsonData: state,
});
};
return (
<>
<Legend>General</Legend>
<Field label="Enable app">
<Switch
value={enabled}
onChange={(e) => {
setMeta({ ...meta, enabled: e.currentTarget.checked });
}}
/>
</Field>
<Field label="Pin app" description="Add the app to the side menu.">
<Switch
value={pinned}
onChange={(e) => {
setMeta({ ...meta, pinned: e.currentTarget.checked });
}}
/>
</Field>
<Legend>Plugins</Legend>
<Field
label="Show Enterprise plugins"
description="Enterprise plugins require a Grafana Enterprise subscription."
>
<Switch
value={includeEnterprise}
onChange={(e) => {
setState({ ...state, includeEnterprise: e.currentTarget.checked });
}}
/>
</Field>
<Button onClick={onSave}>Save</Button>
</>
);
};
const updateAndReload = async (pluginId: string, data: Partial<PluginMeta>) => {
try {
await api.updatePlugin(pluginId, data);
// Reloading the page as the changes made here wouldn't be propagated to the actual plugin otherwise.
// This is not ideal, however unfortunately currently there is no supported way for updating the plugin state.
window.location.reload();
} catch (e) {
console.error('Error while updating the plugin', e);
}
};

View File

@ -9,7 +9,7 @@ type PluginsState = {
installedPlugins: any[];
};
export const usePlugins = (includeEnterprise = false) => {
export const usePlugins = () => {
const [state, setState] = useState<PluginsState>({ isLoading: true, items: [], installedPlugins: [] });
useEffect(() => {
@ -17,7 +17,7 @@ export const usePlugins = (includeEnterprise = false) => {
const items = await api.getRemotePlugins();
const filteredItems = items
.filter((plugin) => Boolean(plugin.versionSignatureType))
.filter((plugin) => includeEnterprise || plugin.status !== 'enterprise')
.filter((plugin) => plugin.status !== 'enterprise')
.filter((plugin) => !status || plugin.status === status);
const installedPlugins = await api.getInstalledPlugins();
@ -25,7 +25,7 @@ export const usePlugins = (includeEnterprise = false) => {
};
fetchPluginData();
}, [includeEnterprise]);
}, []);
return state;
};

View File

@ -1,15 +1,6 @@
import { ComponentClass } from 'react';
import { AppPlugin, AppPluginMeta, AppRootProps, PluginConfigPageProps } from '@grafana/data';
import { Settings } from './config/Settings';
import { AppPlugin, AppRootProps } from '@grafana/data';
import { MarketplaceRootPage } from './RootPage';
import { CatalogAppSettings } from './types';
export const plugin = new AppPlugin<CatalogAppSettings>()
.setRootPage((MarketplaceRootPage as unknown) as ComponentClass<AppRootProps>)
.addConfigPage({
title: 'Settings',
icon: 'info-circle',
body: (Settings as unknown) as ComponentClass<PluginConfigPageProps<AppPluginMeta<CatalogAppSettings>>>,
id: 'settings',
});
export const plugin = new AppPlugin().setRootPage((MarketplaceRootPage as unknown) as ComponentClass<AppRootProps>);

View File

@ -8,14 +8,13 @@ import { SearchField } from '../components/SearchField';
import { HorizontalGroup } from '../components/HorizontalGroup';
import { usePlugins } from '../hooks/usePlugins';
import { useHistory } from '../hooks/useHistory';
import { CatalogAppSettings, Plugin } from '../types';
import { Plugin } from '../types';
import { Page } from 'components/Page';
export const Browse = ({ query, meta }: AppRootProps) => {
export const Browse = ({ query }: AppRootProps) => {
const { q, filterBy, sortBy } = query;
const { includeEnterprise } = meta.jsonData as CatalogAppSettings;
const plugins = usePlugins(includeEnterprise);
const plugins = usePlugins();
const history = useHistory();
const onSortByChange = (value: SelectableValue<string>) => {

View File

@ -1,7 +1,7 @@
import React from 'react';
import { cx, css } from '@emotion/css';
import { dateTimeParse, AppRootProps, GrafanaTheme2 } from '@grafana/data';
import { dateTimeParse, GrafanaTheme2 } from '@grafana/data';
import { useStyles2, Legend, LinkButton } from '@grafana/ui';
import { PLUGIN_ROOT } from '../constants';
@ -12,14 +12,12 @@ import { SearchField } from '../components/SearchField';
import { PluginTypeIcon } from '../components/PluginTypeIcon';
import { usePlugins } from '../hooks/usePlugins';
import { useHistory } from '../hooks/useHistory';
import { CatalogAppSettings, Plugin } from '../types';
import { Plugin } from '../types';
import { Page } from 'components/Page';
import { Loader } from 'components/Loader';
export const Discover = ({ meta }: AppRootProps) => {
const { includeEnterprise } = meta.jsonData as CatalogAppSettings;
const { items, isLoading } = usePlugins(includeEnterprise);
export const Discover = () => {
const { items, isLoading } = usePlugins();
const history = useHistory();
const styles = useStyles2(getStyles);

View File

@ -9,7 +9,7 @@ import { Page } from 'components/Page';
import { Loader } from 'components/Loader';
export const Library = () => {
const { isLoading, items, installedPlugins } = usePlugins(true);
const { isLoading, items, installedPlugins } = usePlugins();
const styles = useStyles2(getStyles);
const filteredPlugins = items.filter((plugin) => !!installedPlugins.find((_) => _.id === plugin.slug));

View File

@ -1,7 +1,3 @@
export interface CatalogAppSettings {
includeEnterprise?: boolean;
}
export type PluginTypeCode = 'app' | 'panel' | 'datasource';
export interface Plugin {