-
- (
-
{(ruleFormType === RuleFormType.cloudRecording || ruleFormType === RuleFormType.cloudAlerting) && (
void;
+}
+
+const CortexFlavoredType: FC = ({ selected = false, disabled = false, onClick }) => {
+ return (
+
+
+ Use a Cortex or Loki datasource.
+
+ Expressions are not supported.
+
+ }
+ image="/public/img/alerting/cortex_logo.svg"
+ selected={selected}
+ disabled={disabled}
+ value={RuleFormType.cloudAlerting}
+ onClick={onClick}
+ />
+
+ );
+};
+
+export { CortexFlavoredType };
diff --git a/public/app/features/alerting/unified/components/rule-editor/rule-types/CortexOrLokiRecordingRule.tsx b/public/app/features/alerting/unified/components/rule-editor/rule-types/CortexOrLokiRecordingRule.tsx
new file mode 100644
index 00000000000..23ba5fecb0d
--- /dev/null
+++ b/public/app/features/alerting/unified/components/rule-editor/rule-types/CortexOrLokiRecordingRule.tsx
@@ -0,0 +1,28 @@
+import React, { FC } from 'react';
+import { RuleType, SharedProps } from './RuleType';
+import { DisabledTooltip } from './DisabledTooltip';
+import { RuleFormType } from '../../../types/rule-form';
+
+const RecordingRuleType: FC = ({ selected = false, disabled = false, onClick }) => {
+ return (
+
+
+ Precompute expressions.
+
+ Should be combined with an alert rule.
+
+ }
+ image="/public/img/alerting/cortex_logo_recording.svg"
+ selected={selected}
+ disabled={disabled}
+ value={RuleFormType.cloudRecording}
+ onClick={onClick}
+ />
+
+ );
+};
+
+export { RecordingRuleType };
diff --git a/public/app/features/alerting/unified/components/rule-editor/rule-types/DisabledTooltip.tsx b/public/app/features/alerting/unified/components/rule-editor/rule-types/DisabledTooltip.tsx
new file mode 100644
index 00000000000..25110586a46
--- /dev/null
+++ b/public/app/features/alerting/unified/components/rule-editor/rule-types/DisabledTooltip.tsx
@@ -0,0 +1,20 @@
+import React, { FC } from 'react';
+import { Tooltip } from '@grafana/ui';
+
+type Props = {
+ visible: boolean;
+};
+
+const DisabledTooltip: FC = ({ children, visible = false }) => {
+ if (!visible) {
+ return <>{children}>;
+ }
+
+ return (
+
+ {children}
+
+ );
+};
+
+export { DisabledTooltip };
diff --git a/public/app/features/alerting/unified/components/rule-editor/rule-types/GrafanaManagedAlert.tsx b/public/app/features/alerting/unified/components/rule-editor/rule-types/GrafanaManagedAlert.tsx
new file mode 100644
index 00000000000..0c565856472
--- /dev/null
+++ b/public/app/features/alerting/unified/components/rule-editor/rule-types/GrafanaManagedAlert.tsx
@@ -0,0 +1,25 @@
+import React, { FC } from 'react';
+import { RuleType, SharedProps } from './RuleType';
+import { RuleFormType } from '../../../types/rule-form';
+
+const GrafanaManagedRuleType: FC = ({ selected = false, disabled, onClick }) => {
+ return (
+
+ Supports multiple data sources of any kind.
+
+ Transform data with expressions.
+
+ }
+ image="/public/img/grafana_icon.svg"
+ selected={selected}
+ disabled={disabled}
+ value={RuleFormType.grafana}
+ onClick={onClick}
+ />
+ );
+};
+
+export { GrafanaManagedRuleType };
diff --git a/public/app/features/alerting/unified/components/rule-editor/rule-types/RuleType.tsx b/public/app/features/alerting/unified/components/rule-editor/rule-types/RuleType.tsx
new file mode 100644
index 00000000000..066e000e7cf
--- /dev/null
+++ b/public/app/features/alerting/unified/components/rule-editor/rule-types/RuleType.tsx
@@ -0,0 +1,52 @@
+import { css, cx } from '@emotion/css';
+import { GrafanaTheme2 } from '@grafana/data';
+import { Card, useStyles2 } from '@grafana/ui';
+import React, { FC, ReactNode } from 'react';
+import { RuleFormType } from '../../../types/rule-form';
+
+interface Props extends SharedProps {
+ image: string;
+ name: string;
+ description: ReactNode;
+ value: RuleFormType;
+}
+
+// these properties are shared between all Rule Types
+export interface SharedProps {
+ selected?: boolean;
+ disabled?: boolean;
+ onClick: (value: RuleFormType) => void;
+}
+
+const RuleType: FC = (props) => {
+ const { name, description, image, selected = false, value, onClick, disabled = false } = props;
+ const styles = useStyles2(getStyles);
+
+ const cardStyles = cx({
+ [styles.wrapper]: true,
+ [styles.disabled]: disabled,
+ });
+
+ return (
+ onClick(value)} disabled={disabled}>
+
+
+
+ {name}
+ {description}
+
+ );
+};
+
+const getStyles = (theme: GrafanaTheme2) => ({
+ wrapper: css`
+ width: 380px;
+ cursor: pointer;
+ user-select: none;
+ `,
+ disabled: css`
+ opacity: 0.5;
+ `,
+});
+
+export { RuleType };
diff --git a/public/app/features/alerting/unified/components/rule-editor/rule-types/RuleTypePicker.tsx b/public/app/features/alerting/unified/components/rule-editor/rule-types/RuleTypePicker.tsx
new file mode 100644
index 00000000000..1801dd4bcd0
--- /dev/null
+++ b/public/app/features/alerting/unified/components/rule-editor/rule-types/RuleTypePicker.tsx
@@ -0,0 +1,52 @@
+import { useStyles2 } from '@grafana/ui';
+import { isEmpty } from 'lodash';
+import React, { FC } from 'react';
+import { useRulesSourcesWithRuler } from '../../../hooks/useRuleSourcesWithRuler';
+import { RuleFormType } from '../../../types/rule-form';
+import { GrafanaManagedRuleType } from './GrafanaManagedAlert';
+import { CortexFlavoredType } from './CortexOrLokiAlert';
+import { RecordingRuleType } from './CortexOrLokiRecordingRule';
+import { css } from '@emotion/css';
+import { GrafanaTheme2 } from '@grafana/data/src';
+import { Stack } from '@grafana/experimental';
+
+interface RuleTypePickerProps {
+ onChange: (value: RuleFormType) => void;
+ selected: RuleFormType;
+}
+
+const RuleTypePicker: FC = ({ selected, onChange }) => {
+ const rulesSourcesWithRuler = useRulesSourcesWithRuler();
+ const hasLotexDatasources = !isEmpty(rulesSourcesWithRuler);
+
+ const styles = useStyles2(getStyles);
+
+ return (
+ <>
+
+
+
+
+
+
+ Select “Grafana managed” unless you have a Cortex or Loki data source with the Ruler API enabled.
+
+ >
+ );
+};
+
+const getStyles = (theme: GrafanaTheme2) => ({
+ meta: css`
+ color: ${theme.colors.text.disabled};
+ `,
+});
+
+export { RuleTypePicker };
diff --git a/public/img/alerting/cortex_logo.svg b/public/img/alerting/cortex_logo.svg
new file mode 100644
index 00000000000..810b8ef3f2e
--- /dev/null
+++ b/public/img/alerting/cortex_logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/img/alerting/cortex_logo_recording.svg b/public/img/alerting/cortex_logo_recording.svg
new file mode 100644
index 00000000000..489b8cd3dd5
--- /dev/null
+++ b/public/img/alerting/cortex_logo_recording.svg
@@ -0,0 +1 @@
+
\ No newline at end of file