diff --git a/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.tsx b/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.tsx index 84bb5ed4713..ea6fea591c4 100644 --- a/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.tsx +++ b/public/app/features/alerting/unified/components/import-to-gma/ConfirmConvertModal.tsx @@ -4,7 +4,7 @@ import { ComponentProps } from 'react'; import { useFormContext } from 'react-hook-form'; import { locationService } from '@grafana/runtime'; -import { Alert, CodeEditor, ConfirmModal, Stack, Text, useStyles2 } from '@grafana/ui'; +import { Alert, CodeEditor, ConfirmModal, Modal, Stack, Text, useStyles2 } from '@grafana/ui'; import { useAppNotification } from 'app/core/copy/appNotification'; import { Trans, t } from 'app/core/internationalization'; import { stringifyErrorLike } from 'app/features/alerting/unified/utils/misc'; @@ -12,6 +12,7 @@ import { RulerRulesConfigDTO } from 'app/types/unified-alerting-dto'; import { trackImportToGMAError, trackImportToGMASuccess } from '../../Analytics'; import { convertToGMAApi } from '../../api/convertToGMAApi'; +import { GRAFANA_ORIGIN_LABEL } from '../../utils/labels'; import { createListFilterLink } from '../../utils/navigation'; import { useGetRulerRules } from '../rule-editor/useAlertRuleSuggestions'; @@ -21,8 +22,22 @@ type ModalProps = Pick, 'isOpen' | 'onDismis isOpen: boolean; }; +const AlertSomeRulesSkipped = () => ( + + + + We have detected that some rules are managed by plugins. These rules will not be imported. + + + +); + export const ConfirmConversionModal = ({ isOpen, onDismiss }: ModalProps) => { const { watch } = useFormContext(); + const styles = useStyles2(getStyles); const [ targetFolder, @@ -46,7 +61,11 @@ export const ConfirmConversionModal = ({ isOpen, onDismiss }: ModalProps) => { const { rulerRules } = useGetRulerRules(selectedDatasourceName || undefined); const [convert] = convertToGMAApi.useConvertToGMAMutation(); const notifyApp = useAppNotification(); - const rulerRulesToPayload = filterRulerRulesConfig(rulerRules, namespace, ruleGroup); + const { filteredConfig: rulerRulesToPayload, someRulesAreSkipped } = filterRulerRulesConfig( + rulerRules, + namespace, + ruleGroup + ); async function onConvertConfirm() { try { @@ -79,6 +98,28 @@ export const ConfirmConversionModal = ({ isOpen, onDismiss }: ModalProps) => { } } + const noRulesToImport = isEmpty(rulerRulesToPayload); + if (noRulesToImport) { + return ( + + + {someRulesAreSkipped && } + + {t( + 'alerting.import-to-gma.confirm-modal.no-rules-body', + 'There are no rules to import. Please select a different namespace or rule group.' + )} + + + + ); + } + // translations for texts in the modal const title = t('alerting.import-to-gma.confirm-modal.title', 'Confirm import'); const confirmText = t('alerting.import-to-gma.confirm-modal.confirm', 'Yes, import'); @@ -88,6 +129,7 @@ export const ConfirmConversionModal = ({ isOpen, onDismiss }: ModalProps) => { title={title} confirmText={confirmText} confirmButtonVariant="primary" + modalClass={styles.modal} body={ @@ -98,6 +140,7 @@ export const ConfirmConversionModal = ({ isOpen, onDismiss }: ModalProps) => { + {someRulesAreSkipped && } These are the list of rules that will be imported: @@ -116,8 +159,9 @@ function filterRulerRulesConfig( rulerRulesConfig: RulerRulesConfigDTO, namespace?: string, groupName?: string -): RulerRulesConfigDTO { +): { filteredConfig: RulerRulesConfigDTO; someRulesAreSkipped: boolean } { const filteredConfig: RulerRulesConfigDTO = {}; + let someRulesAreSkipped = false; Object.entries(rulerRulesConfig).forEach(([ns, groups]) => { if (namespace && ns !== namespace) { @@ -128,7 +172,21 @@ function filterRulerRulesConfig( if (groupName && group.name !== groupName) { return false; } - return true; + + // Filter out rules that have the GRAFANA_ORIGIN_LABEL + const filteredRules = group.rules.filter((rule) => { + const hasGrafanaOriginLabel = rule.labels?.[GRAFANA_ORIGIN_LABEL]; + if (hasGrafanaOriginLabel) { + someRulesAreSkipped = true; + return false; + } + return true; + }); + + return { + ...group, + rules: filteredRules, + }; }); if (filteredGroups.length > 0) { @@ -136,7 +194,7 @@ function filterRulerRulesConfig( } }); - return filteredConfig; + return { filteredConfig, someRulesAreSkipped }; } function RulesPreview({ rules }: { rules: RulerRulesConfigDTO }) { @@ -166,6 +224,6 @@ const getStyles = () => ({ flex: '1 1 100%', }), modal: css({ - width: '700px', + width: '800px', }), }); diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 5841d2beeb6..344fbbe00ec 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -1048,6 +1048,12 @@ "alert-rules": "Alert rules", "confirm-modal": { "confirm": "Yes, import", + "no-rules-body": "There are no rules to import. Please select a different namespace or rule group.", + "no-rules-title": "No rules to import", + "plugin-rules-warning": { + "text": "We have detected that some rules are managed by plugins. These rules will not be imported.", + "title": "Some rules are excluded from import" + }, "title": "Confirm import" }, "datasource": {