import { useState, ChangeEvent, useEffect } from 'react'; import { Trans } from '@grafana/i18n'; import { Button, Icon, Stack, Checkbox, Text, Box, IconName, Space, Tooltip } from '@grafana/ui'; import { ResourceDependencyDto } from '../api'; import { ResourceTypeId, buildDependencyMaps, handleSelection, handleDeselection } from './resourceDependency'; import { iconNameForResource, pluralizeResourceName } from './resourceInfo'; interface ConfigureSnapshotProps { disabled: boolean; isLoading: boolean; onClick: (resourceTypes: ResourceTypeId[]) => void; resourceDependencies: ResourceDependencyDto[] | never[]; } // Manual order of resource types to display in the UI for better UX. const alertsSubResources = [ 'ALERT_RULE', 'NOTIFICATION_POLICY', 'NOTIFICATION_TEMPLATE', 'CONTACT_POINT', 'MUTE_TIMING', ] as const; const displayOrder = [ 'DASHBOARD', 'LIBRARY_ELEMENT', 'DATASOURCE', 'PLUGIN', 'FOLDER', 'ALERT_RULE_GROUP', ...alertsSubResources, ] as const; // This guarantees that displayOrder includes all ResourceTypeId values. type IsExhaustive = Exclude extends never ? true : false; const hasAllResourceTypes: IsExhaustive = true; // prettier-ignore function resourceTypeOrder(resourceTypes: ResourceTypeId[]): ResourceTypeId[] { return hasAllResourceTypes && displayOrder.filter((type) => resourceTypes.includes(type)); } export function ConfigureSnapshot(props: ConfigureSnapshotProps) { const { disabled, isLoading, onClick, resourceDependencies } = props; const [selectedTypes, setSelectedTypes] = useState>(new Set()); const [includeAll, setIncludeAll] = useState(true); const { dependencyMap, dependentMap } = buildDependencyMaps(resourceDependencies); const resourceTypes = resourceTypeOrder(Array.from(dependencyMap.keys())); // Initialize with all items selected when component mounts once. useEffect(() => { setSelectedTypes(new Set(resourceTypes)); }, []); // eslint-disable-line react-hooks/exhaustive-deps const handleIncludeAllChange = (e: ChangeEvent) => { const checked = e.target.checked; setIncludeAll(checked); if (checked) { // When directly checking include all, select all other items as well. setSelectedTypes(new Set(resourceTypes)); } else { // When directly unchecking include all, clear all other items as well. setSelectedTypes(new Set()); } }; const handleTypeChange = (id: ResourceTypeId) => (e: ChangeEvent) => { const updatedList = e.target.checked ? handleSelection(dependencyMap, selectedTypes, id) : handleDeselection(dependentMap, selectedTypes, id); setSelectedTypes(updatedList); setIncludeAll(updatedList.size === resourceTypes.length); }; const handleBuildSnapshot = () => { onClick(Array.from(selectedTypes)); }; return ( Configure snapshot Select which resources you want to include in the snapshot to migrate.
Some resources may depend on others and will be automatically selected or deselected.
0 && !includeAll} value={includeAll} onChange={handleIncludeAllChange} data-testid="migrate-to-cloud-configure-snapshot-checkbox-resource-include-all" //@ts-ignore label={ Include all } /> {resourceTypes.map((type) => ( {pluralizeResourceName(type) ?? type} } /> ))} Creating a snapshot typically takes less than two minutes. } placement="right" interactive={true} >
); }