{"version":3,"file":"MetricsModalContext.mjs","sources":["../../../../../src/querybuilder/components/metrics-modal/MetricsModalContext.tsx"],"sourcesContent":["import debounce from 'debounce-promise';\nimport {\n  createContext,\n  type FC,\n  type PropsWithChildren,\n  useCallback,\n  useContext,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\n\nimport { type SelectableValue, type TimeRange } from '@grafana/data';\n\nimport { METRIC_LABEL, PROMETHEUS_QUERY_BUILDER_MAX_RESULTS } from '../../../constants';\nimport { type PrometheusLanguageProviderInterface } from '../../../language_provider';\nimport { regexifyLabelValuesQueryString } from '../../parsingUtils';\nimport { type QueryBuilderLabelFilter } from '../../shared/types';\nimport { formatPrometheusLabelFilters } from '../formatter';\n\nimport { generateMetricData } from './helpers';\nimport { type MetricData, type MetricsData } from './types';\nimport { fuzzySearch } from './uFuzzy';\n\nexport const DEFAULT_RESULTS_PER_PAGE = 25;\n\ntype Pagination = {\n  pageNum: number;\n  resultsPerPage: number;\n  totalPageNum: number;\n};\n\ntype MetricsModalContextValue = {\n  isLoading: boolean;\n  setIsLoading: (val: boolean) => void;\n  filteredMetricsData: MetricData[];\n  debouncedBackendSearch: (\n    timeRange: TimeRange,\n    metricText: string,\n    queryLabels?: QueryBuilderLabelFilter[]\n  ) => Promise<void>;\n  pagination: Pagination;\n  setPagination: (val: Pagination) => void;\n  selectedTypes: Array<SelectableValue<string>>;\n  setSelectedTypes: (val: Array<SelectableValue<string>>) => void;\n  searchedText: string;\n  setSearchedText: (val: string) => void;\n};\n\nconst MetricsModalContext = createContext<MetricsModalContextValue | undefined>(undefined);\n\ntype MetricsModalContextProviderProps = {\n  languageProvider: PrometheusLanguageProviderInterface;\n  timeRange: TimeRange;\n};\n\nexport const MetricsModalContextProvider: FC<PropsWithChildren<MetricsModalContextProviderProps>> = ({\n  children,\n  languageProvider,\n  timeRange,\n}) => {\n  const [isLoading, setIsLoading] = useState(true);\n  const [metricsData, setMetricsData] = useState<MetricsData>([]);\n  const [pagination, setPagination] = useState<Pagination>({\n    pageNum: 1,\n    totalPageNum: 1,\n    resultsPerPage: DEFAULT_RESULTS_PER_PAGE,\n  });\n  const [selectedTypes, setSelectedTypes] = useState<Array<SelectableValue<string>>>([]);\n  const [searchedText, setSearchedText] = useState('');\n\n  const filteredMetricsData = useMemo(() => {\n    if (selectedTypes.length === 0) {\n      return metricsData;\n    }\n\n    // Filter metrics based on selected types\n    return metricsData.filter((metric: MetricData) => {\n      return selectedTypes.some((selectedType) => {\n        // Handle metrics with defined types\n        if (metric.type && selectedType.value) {\n          return metric.type.includes(selectedType.value);\n        }\n\n        // Handle metrics without type when \"no type\" is selected\n        if (!metric.type && selectedType.value === 'no type') {\n          return true;\n        }\n\n        return false;\n      });\n    });\n  }, [metricsData, selectedTypes]);\n\n  useEffect(() => {\n    const totalPageNum =\n      filteredMetricsData.length === 0 ? 1 : Math.ceil(filteredMetricsData.length / pagination.resultsPerPage);\n    const pageNum = pagination.pageNum > totalPageNum ? 1 : pagination.pageNum;\n\n    setPagination((prevPagination) => ({\n      ...prevPagination,\n      totalPageNum,\n      pageNum,\n    }));\n  }, [filteredMetricsData.length, pagination.resultsPerPage, pagination.pageNum]);\n\n  // Track the latest search ID to handle race conditions\n  const latestSearchIdRef = useRef<number>(0);\n\n  const fetchMetadata = useCallback(async () => {\n    try {\n      setIsLoading(true);\n      const metadata = await languageProvider.queryMetricsMetadata(PROMETHEUS_QUERY_BUILDER_MAX_RESULTS);\n\n      // We receive ALERTS metadata in any case\n      if (Object.keys(metadata).length <= 1) {\n        const fetchedMetrics = await languageProvider.queryLabelValues(\n          timeRange,\n          METRIC_LABEL,\n          undefined,\n          PROMETHEUS_QUERY_BUILDER_MAX_RESULTS\n        );\n        const processedData = fetchedMetrics.map((m) => generateMetricData(m, languageProvider));\n        setMetricsData(processedData);\n      } else {\n        const processedData = Object.keys(metadata).map((m) => generateMetricData(m, languageProvider));\n        setMetricsData(processedData);\n      }\n    } catch (error) {\n      setMetricsData([]);\n    } finally {\n      setIsLoading(false);\n    }\n  }, [languageProvider, timeRange]);\n\n  const debouncedBackendSearch = useMemo(\n    () =>\n      debounce(async (timeRange: TimeRange, metricText: string, queryLabels?: QueryBuilderLabelFilter[]) => {\n        // Generate unique search ID to handle race conditions\n        const searchId = ++latestSearchIdRef.current;\n\n        try {\n          if (metricText === '') {\n            await fetchMetadata();\n            return;\n          }\n\n          setIsLoading(true);\n\n          const queryString = regexifyLabelValuesQueryString(metricText);\n          const filterArray = queryLabels ? formatPrometheusLabelFilters(queryLabels) : [];\n          const match = `{__name__=~\"(?i).*${queryString}\"${filterArray ? filterArray.join('') : ''}}`;\n\n          const results = await languageProvider.queryLabelValues(timeRange, METRIC_LABEL, match);\n\n          // Check if this is still the most recent search\n          if (searchId !== latestSearchIdRef.current) {\n            return; // Ignore outdated results\n          }\n\n          const [fuzzyOrderedMetrics] = fuzzySearch(results, queryString);\n          const resultsOptions: MetricsData = fuzzyOrderedMetrics.map((m) => generateMetricData(m, languageProvider));\n\n          setMetricsData(resultsOptions);\n          setIsLoading(false);\n        } catch (error) {\n          // Only update state if this is still the latest search\n          if (searchId === latestSearchIdRef.current) {\n            console.error('Backend search failed:', error);\n            setMetricsData([]); // Clear results on error\n            setIsLoading(false);\n          }\n        }\n      }, 300),\n    [fetchMetadata, languageProvider]\n  );\n\n  useEffect(() => {\n    fetchMetadata();\n\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  return (\n    <MetricsModalContext.Provider\n      value={{\n        isLoading,\n        setIsLoading,\n        filteredMetricsData,\n        debouncedBackendSearch,\n        pagination,\n        setPagination,\n        selectedTypes,\n        setSelectedTypes,\n        searchedText,\n        setSearchedText,\n      }}\n    >\n      {children}\n    </MetricsModalContext.Provider>\n  );\n};\n\nexport function useMetricsModal() {\n  const context = useContext(MetricsModalContext);\n  if (context === undefined) {\n    throw new Error('useMetricsModal must be used within a MetricsModalContextProvider');\n  }\n  return context;\n}\n"],"names":["timeRange"],"mappings":"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"}