mirror of
https://github.com/grafana/grafana.git
synced 2025-09-19 22:07:33 +08:00
Alerting: Add plugins extension point to alerting home page (#85725)
* Add basic extension point to alerting home page * Remove home page scenes app. Improve plugins styles * Remove unused code * Fix home page rendering when no plugins registered * Add row-based integrations component * Add missing margins * Rollback the Box component changes * Remove unused import
This commit is contained in:
@ -116,6 +116,7 @@ export type PluginExtensionEventHelpers<Context extends object = object> = {
|
||||
// Extension Points available in core Grafana
|
||||
export enum PluginExtensionPoints {
|
||||
AlertInstanceAction = 'grafana/alerting/instance/action',
|
||||
AlertingHomePage = 'grafana/alerting/home',
|
||||
CommandPalette = 'grafana/commandpalette/action',
|
||||
DashboardPanelMenu = 'grafana/dashboard/panel/menu',
|
||||
DataSourceConfig = 'grafana/datasources/config',
|
||||
|
@ -3,23 +3,8 @@ import React from 'react';
|
||||
import SVG from 'react-inlinesvg';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { EmbeddedScene, SceneFlexLayout, SceneFlexItem, SceneReactObject } from '@grafana/scenes';
|
||||
import { useStyles2, useTheme2, Stack, Text, TextLink } from '@grafana/ui';
|
||||
|
||||
export const getOverviewScene = () => {
|
||||
return new EmbeddedScene({
|
||||
body: new SceneFlexLayout({
|
||||
children: [
|
||||
new SceneFlexItem({
|
||||
body: new SceneReactObject({
|
||||
component: GettingStarted,
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
export default function GettingStarted() {
|
||||
const theme = useTheme2();
|
||||
const styles = useStyles2(getWelcomePageStyles);
|
||||
@ -110,9 +95,7 @@ export function WelcomeHeader({ className }: { className?: string }) {
|
||||
const styles = useStyles2(getWelcomeHeaderStyles);
|
||||
|
||||
return (
|
||||
<div className={styles.welcomeHeaderWrapper}>
|
||||
<div className={styles.subtitle}>Learn about problems in your systems moments after they occur</div>
|
||||
|
||||
<Stack gap={2} direction="column">
|
||||
<ContentBox className={cx(styles.ctaContainer, className)}>
|
||||
<WelcomeCTABox
|
||||
title="Alert rules"
|
||||
@ -135,18 +118,11 @@ export function WelcomeHeader({ className }: { className?: string }) {
|
||||
hrefText="Manage notification policies"
|
||||
/>
|
||||
</ContentBox>
|
||||
</div>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
const getWelcomeHeaderStyles = (theme: GrafanaTheme2) => ({
|
||||
welcomeHeaderWrapper: css({
|
||||
color: theme.colors.text.primary,
|
||||
}),
|
||||
subtitle: css({
|
||||
color: theme.colors.text.secondary,
|
||||
paddingBottom: theme.spacing(2),
|
||||
}),
|
||||
ctaContainer: css({
|
||||
padding: theme.spacing(2),
|
||||
display: 'flex',
|
||||
@ -195,6 +171,7 @@ function WelcomeCTABox({ title, description, href, hrefText }: WelcomeCTABoxProp
|
||||
|
||||
const getWelcomeCTAButtonStyles = (theme: GrafanaTheme2) => ({
|
||||
container: css({
|
||||
color: theme.colors.text.primary,
|
||||
flex: 1,
|
||||
minWidth: '240px',
|
||||
display: 'grid',
|
||||
|
@ -1,74 +1,54 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { config } from '@grafana/runtime';
|
||||
import { SceneApp, SceneAppPage } from '@grafana/scenes';
|
||||
import { usePageNav } from 'app/core/components/Page/usePageNav';
|
||||
import { PluginPageContext, PluginPageContextType } from 'app/features/plugins/components/PluginPageContext';
|
||||
import { Box, Stack, Tab, TabContent, TabsBar } from '@grafana/ui';
|
||||
|
||||
import { AlertingPageWrapper } from '../components/AlertingPageWrapper';
|
||||
import { isLocalDevEnv, isOpenSourceEdition } from '../utils/misc';
|
||||
|
||||
import { getOverviewScene, WelcomeHeader } from './GettingStarted';
|
||||
import GettingStarted, { WelcomeHeader } from './GettingStarted';
|
||||
import { getInsightsScenes } from './Insights';
|
||||
|
||||
let homeApp: SceneApp | undefined;
|
||||
|
||||
export function getHomeApp(insightsEnabled: boolean) {
|
||||
if (homeApp) {
|
||||
return homeApp;
|
||||
}
|
||||
|
||||
if (insightsEnabled) {
|
||||
homeApp = new SceneApp({
|
||||
pages: [
|
||||
new SceneAppPage({
|
||||
title: 'Alerting',
|
||||
subTitle: <WelcomeHeader />,
|
||||
url: '/alerting',
|
||||
hideFromBreadcrumbs: true,
|
||||
tabs: [
|
||||
new SceneAppPage({
|
||||
title: 'Insights',
|
||||
url: '/alerting/home/insights',
|
||||
getScene: getInsightsScenes,
|
||||
}),
|
||||
new SceneAppPage({
|
||||
title: 'Get started',
|
||||
url: '/alerting/home/overview',
|
||||
getScene: getOverviewScene,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
} else {
|
||||
homeApp = new SceneApp({
|
||||
pages: [
|
||||
new SceneAppPage({
|
||||
title: 'Alerting',
|
||||
subTitle: <WelcomeHeader />,
|
||||
url: '/alerting',
|
||||
hideFromBreadcrumbs: true,
|
||||
getScene: getOverviewScene,
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return homeApp;
|
||||
}
|
||||
import { PluginIntegrations } from './PluginIntegrations';
|
||||
|
||||
export default function Home() {
|
||||
const insightsEnabled =
|
||||
(!isOpenSourceEdition() || isLocalDevEnv()) && Boolean(config.featureToggles.alertingInsights);
|
||||
|
||||
const appScene = getHomeApp(insightsEnabled);
|
||||
|
||||
const sectionNav = usePageNav('alerting')!;
|
||||
const [pluginContext] = useState<PluginPageContextType>({ sectionNav });
|
||||
const [activeTab, setActiveTab] = useState<'insights' | 'overview'>(insightsEnabled ? 'insights' : 'overview');
|
||||
const insightsScene = getInsightsScenes();
|
||||
|
||||
return (
|
||||
<PluginPageContext.Provider value={pluginContext}>
|
||||
<appScene.Component model={appScene} />
|
||||
</PluginPageContext.Provider>
|
||||
<AlertingPageWrapper
|
||||
title="Alerting"
|
||||
subTitle="Learn about problems in your systems moments after they occur"
|
||||
navId="alerting"
|
||||
>
|
||||
<Stack gap={2} direction="column">
|
||||
<WelcomeHeader />
|
||||
<PluginIntegrations />
|
||||
</Stack>
|
||||
<Box marginTop={{ lg: 2, md: 0, xs: 0 }}>
|
||||
<TabsBar>
|
||||
{insightsEnabled && (
|
||||
<Tab
|
||||
key="insights"
|
||||
label="Insights"
|
||||
active={activeTab === 'insights'}
|
||||
onChangeTab={() => setActiveTab('insights')}
|
||||
/>
|
||||
)}
|
||||
<Tab
|
||||
key="overview"
|
||||
label="Get started"
|
||||
active={activeTab === 'overview'}
|
||||
onChangeTab={() => setActiveTab('overview')}
|
||||
/>
|
||||
</TabsBar>
|
||||
<TabContent>
|
||||
{activeTab === 'insights' && <insightsScene.Component model={insightsScene} />}
|
||||
{activeTab === 'overview' && <GettingStarted />}
|
||||
</TabContent>
|
||||
</Box>
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
import { css } from '@emotion/css';
|
||||
import React from 'react';
|
||||
|
||||
import { PluginExtensionPoints } from '@grafana/data';
|
||||
import { GrafanaTheme2 } from '@grafana/data/';
|
||||
import { getPluginComponentExtensions } from '@grafana/runtime';
|
||||
import { Stack, Text } from '@grafana/ui';
|
||||
import { useStyles2 } from '@grafana/ui/';
|
||||
|
||||
export function PluginIntegrations() {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const { extensions } = getPluginComponentExtensions({
|
||||
extensionPointId: PluginExtensionPoints.AlertingHomePage,
|
||||
limitPerPlugin: 1,
|
||||
});
|
||||
|
||||
if (extensions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack direction="column" gap={2}>
|
||||
<Text element="h3" variant="h4">
|
||||
Speed up your alerts creation now by using one of our tailored apps
|
||||
</Text>
|
||||
<Stack gap={2} wrap="wrap" direction="row">
|
||||
{extensions.map((extension) => (
|
||||
<div key={extension.id} className={styles.box}>
|
||||
<extension.component />
|
||||
</div>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
box: css({
|
||||
padding: theme.spacing(2),
|
||||
flex: 1,
|
||||
backgroundColor: theme.colors.background.secondary,
|
||||
maxWidth: '460px',
|
||||
}),
|
||||
});
|
Reference in New Issue
Block a user