@grafana/alerting
Version:
Grafana Alerting Library – Build vertical integrations on top of the industry-leading alerting solution
1 lines • 7.81 kB
Source Map (JSON)
{"version":3,"file":"RoutingTreeSelector.mjs","sources":["../../../../../../src/grafana/notificationPolicies/components/RoutingTreeSelector/RoutingTreeSelector.tsx"],"sourcesContent":["import { type ComponentProps, useMemo } from 'react';\n\nimport { type RoutingTree } from '@grafana/api-clients/rtkq/notifications.alerting/v0alpha1';\nimport { t } from '@grafana/i18n';\nimport { Alert, Combobox, type ComboboxOption, MultiCombobox } from '@grafana/ui';\n\nimport { type CustomComboBoxProps } from '../../../common/ComboBox.types';\nimport { USER_DEFINED_TREE_NAME } from '../../consts';\nimport { useListRoutingTrees } from '../../hooks/useRoutingTrees';\n\nconst collator = new Intl.Collator('en', { sensitivity: 'accent' });\n\ntype SingleSelectProps = CustomComboBoxProps<RoutingTree> & { multi?: false };\ntype MultiSelectProps = Omit<ComponentProps<typeof MultiCombobox<string>>, 'options' | 'loading' | 'onChange'> & {\n multi: true;\n onChange: (trees: RoutingTree[]) => void;\n};\n\nexport type RoutingTreeSelectorProps = SingleSelectProps | MultiSelectProps;\n\n/**\n * Routing Tree Combobox which lists all available notification policy trees.\n *\n * When the `alertingMultiplePolicies` feature toggle is enabled on the backend,\n * this shows all available routing trees. Otherwise, it shows only the default\n * \"user-defined\" tree.\n *\n * The default routing tree (named \"user-defined\") is displayed as \"Default policy\"\n * and is always listed first.\n *\n * Supports both single-select (default) and multi-select modes via the `multi` prop.\n *\n * @example\n * ```tsx\n * // Single select\n * <RoutingTreeSelector\n * value={selectedTreeName}\n * onChange={(tree) => setSelectedTree(tree)}\n * />\n *\n * // Multi select\n * <RoutingTreeSelector\n * multi\n * value={selectedTreeNames}\n * onChange={(trees) => setSelectedTrees(trees)}\n * />\n * ```\n */\nfunction RoutingTreeSelector(props: RoutingTreeSelectorProps) {\n const {\n currentData: routingTrees,\n isLoading,\n isError,\n } = useListRoutingTrees({}, { refetchOnFocus: true, refetchOnMountOrArgChange: true });\n\n // Build a lookup map from option value → RoutingTree for resolving onChange\n const { options, treeLookup } = useMemo(() => {\n if (!routingTrees?.items) {\n const empty: { options: Array<ComboboxOption<string>>; treeLookup: Map<string, RoutingTree> } = {\n options: [],\n treeLookup: new Map(),\n };\n return empty;\n }\n\n const lookup = new Map<string, RoutingTree>();\n const opts: Array<ComboboxOption<string>> = routingTrees.items\n .map((tree) => {\n const name = tree.metadata.name ?? '';\n const isDefault = name === USER_DEFINED_TREE_NAME;\n\n lookup.set(name, tree);\n\n return {\n label: isDefault ? t('alerting.routing-tree-selector.default-policy', 'Default policy') : name,\n value: name,\n description: isDefault\n ? t(\n 'alerting.routing-tree-selector.default-policy-desc',\n 'Routes alerts using the default notification policy tree'\n )\n : t('alerting.routing-tree-selector.custom-policy-desc', 'Route alerts through the {{name}} policy tree', {\n name,\n }),\n } satisfies ComboboxOption<string>;\n })\n .sort((a, b) => {\n // Default policy always first\n if (a.value === USER_DEFINED_TREE_NAME) {\n return -1;\n }\n if (b.value === USER_DEFINED_TREE_NAME) {\n return 1;\n }\n return collator.compare(a.label, b.label);\n });\n\n return { options: opts, treeLookup: lookup };\n }, [routingTrees?.items]);\n\n if (isError) {\n return (\n <Alert\n severity=\"warning\"\n title={t('alerting.routing-tree-selector.error', 'Failed to load notification policies')}\n />\n );\n }\n\n if (props.multi) {\n const { multi: _, onChange, ...rest } = props;\n\n const handleChange = (selectedOptions: Array<ComboboxOption<string>>) => {\n const trees = selectedOptions\n .map((opt) => treeLookup.get(opt.value))\n .filter((tree): tree is RoutingTree => tree != null);\n onChange(trees);\n };\n\n // @ts-expect-error TypeScript cannot narrow rest-spread from discriminated unions with conditional width types\n return <MultiCombobox {...rest} loading={isLoading} options={options} onChange={handleChange} />;\n }\n\n const handleChange = (selectedOption: ComboboxOption<string> | null) => {\n if (selectedOption == null && props.isClearable) {\n props.onChange(null);\n return;\n }\n\n if (selectedOption) {\n const tree = treeLookup.get(selectedOption.value);\n if (!tree) {\n console.warn(`RoutingTreeSelector: could not find routing tree for value \"${selectedOption.value}\"`);\n return;\n }\n\n props.onChange(tree);\n }\n };\n\n return <Combobox {...props} loading={isLoading} options={options} onChange={handleChange} />;\n}\n\nexport { RoutingTreeSelector };\n"],"names":["handleChange"],"mappings":"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"}