@grafana/ui
Version:
Grafana Components Library
1 lines • 10.7 kB
Source Map (JSON)
{"version":3,"file":"FieldsByFrameRefIdMatcher.mjs","sources":["../../../../src/components/MatchersUI/FieldsByFrameRefIdMatcher.tsx"],"sourcesContent":["import { useMemo, useState, useCallback } from 'react';\n\nimport {\n DataFrame,\n getFrameDisplayName,\n FieldMatcherID,\n fieldMatchers,\n SelectableValue,\n toOption,\n} from '@grafana/data';\n\nimport { MultiSelect, Select } from '../Select/Select';\n\nimport { FieldMatcherUIRegistryItem, MatcherUIProps } from './types';\n\nconst recoverRefIdMissing = (\n newRefIds: SelectableValue[],\n oldRefIds: SelectableValue[],\n previousValue: string | undefined\n): SelectableValue | undefined => {\n if (!previousValue) {\n return;\n }\n // Previously selected value is missing from the new list.\n // Find the value that is in the new list but isn't in the old list\n let changedTo = newRefIds.find((refId) => {\n return !oldRefIds.some((refId2) => {\n return refId === refId2;\n });\n });\n if (changedTo) {\n // Found the new value, we assume the old value changed to this one, so we'll use it\n return changedTo;\n }\n return;\n};\n\nexport interface Props {\n value?: string; // refID\n data: DataFrame[];\n onChange: (value: string) => void;\n placeholder?: string;\n}\n\n// Not exported globally... but used in grafana core\nexport function RefIDPicker({ value, data, onChange, placeholder }: Props) {\n const listOfRefIds = useMemo(() => getListOfQueryRefIds(data), [data]);\n\n const [priorSelectionState, updatePriorSelectionState] = useState<{\n refIds: SelectableValue[];\n value: string | undefined;\n }>({\n refIds: [],\n value: undefined,\n });\n\n const currentValue = useMemo(() => {\n return (\n listOfRefIds.find((refId) => refId.value === value) ??\n recoverRefIdMissing(listOfRefIds, priorSelectionState.refIds, priorSelectionState.value)\n );\n }, [value, listOfRefIds, priorSelectionState]);\n\n const onFilterChange = useCallback(\n (v: SelectableValue<string>) => {\n onChange(v?.value!);\n },\n [onChange]\n );\n\n if (listOfRefIds !== priorSelectionState.refIds || currentValue?.value !== priorSelectionState.value) {\n updatePriorSelectionState({\n refIds: listOfRefIds,\n value: currentValue?.value,\n });\n }\n return (\n <Select\n options={listOfRefIds}\n onChange={onFilterChange}\n isClearable={true}\n placeholder={placeholder ?? 'Select query refId'}\n value={currentValue}\n />\n );\n}\n\nconst recoverMultiRefIdMissing = (\n newRefIds: Array<SelectableValue<string>>,\n oldRefIds: Array<SelectableValue<string>>,\n previousValue: Array<SelectableValue<string>> | undefined\n): Array<SelectableValue<string>> | undefined => {\n if (!previousValue || !previousValue.length) {\n return;\n }\n // Previously selected value is missing from the new list.\n // Find the value that is in the new list but isn't in the old list\n const changedTo = newRefIds.filter((newRefId) => {\n return oldRefIds.some((oldRefId) => {\n return newRefId === oldRefId;\n });\n });\n\n if (changedTo.length) {\n // Found the new value, we assume the old value changed to this one, so we'll use it\n return changedTo;\n }\n return;\n};\n\nexport interface MultiProps {\n value?: string; // 1 or more refID in reqExp format /A|B|C/\n data: DataFrame[];\n onChange: (value: string[]) => void;\n placeholder?: string;\n}\n\nexport function RefIDMultiPicker({ value, data, onChange, placeholder }: MultiProps) {\n const listOfRefIds = useMemo(() => getListOfQueryRefIds(data), [data]);\n\n const [priorSelectionState, updatePriorSelectionState] = useState<{\n refIds: SelectableValue[];\n value: Array<SelectableValue<string>> | undefined;\n }>({\n refIds: [],\n value: undefined,\n });\n\n const currentValue = useMemo(() => {\n let extractedRefIds = new Set<string>();\n\n if (value) {\n if (value.startsWith('/^')) {\n try {\n extractedRefIds = new Set(regexpToStrings(value));\n } catch {\n extractedRefIds.add(value);\n }\n } else if (value.includes('|')) {\n // old format that was simply unescaped pipe-joined strings -> regexp\n extractedRefIds = new Set(value.split('|'));\n } else {\n extractedRefIds.add(value);\n }\n }\n\n const matchedRefIds = listOfRefIds.filter((refId) => extractedRefIds.has(refId.value || ''));\n\n if (matchedRefIds.length) {\n return matchedRefIds;\n }\n\n const newRefIds = [...extractedRefIds].map(toOption);\n\n return recoverMultiRefIdMissing(newRefIds, priorSelectionState.refIds, priorSelectionState.value);\n }, [value, listOfRefIds, priorSelectionState]);\n\n const onFilterChange = useCallback(\n (v: Array<SelectableValue<string>>) => {\n onChange(v.map((v) => v.value!));\n },\n [onChange]\n );\n\n if (listOfRefIds !== priorSelectionState.refIds || currentValue?.length !== priorSelectionState.value?.length) {\n updatePriorSelectionState({\n refIds: listOfRefIds,\n value: currentValue,\n });\n }\n return (\n <MultiSelect\n options={listOfRefIds}\n onChange={onFilterChange}\n isClearable={true}\n placeholder={placeholder ?? 'Select query refId'}\n value={currentValue}\n />\n );\n}\n\nfunction getListOfQueryRefIds(data: DataFrame[]): Array<SelectableValue<string>> {\n const queries = new Map<string, DataFrame[]>();\n\n for (const frame of data) {\n const refId = frame.refId ?? '';\n const frames = queries.get(refId) ?? [];\n\n if (frames.length === 0) {\n queries.set(refId, frames);\n }\n\n frames.push(frame);\n }\n\n const values: Array<SelectableValue<string>> = [];\n\n for (const [refId, frames] of queries.entries()) {\n values.push({\n value: refId,\n label: `Query: ${refId ?? '(missing refId)'}`,\n description: getFramesDescription(frames),\n });\n }\n\n return values;\n}\n\nfunction getFramesDescription(frames: DataFrame[]): string {\n return `Frames (${frames.length}):\n ${frames\n .slice(0, Math.min(3, frames.length))\n .map((x) => getFrameDisplayName(x))\n .join(', ')} ${frames.length > 3 ? '...' : ''}`;\n}\n\n/**\n * Registry item for UI to configure \"fields by frame refId\"-matcher.\n * @public\n */\nexport const fieldsByFrameRefIdItem: FieldMatcherUIRegistryItem<string> = {\n id: FieldMatcherID.byFrameRefID,\n component: (props: MatcherUIProps<string>) => {\n return <RefIDPicker value={props.options} data={props.data} onChange={props.onChange} />;\n },\n matcher: fieldMatchers.get(FieldMatcherID.byFrameRefID),\n name: 'Fields returned by query',\n description: 'Set properties for fields from a specific query',\n optionsToLabel: (options) => options,\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#escaping\nfunction escapeRegExp(string: string) {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // $& means the whole matched string\n}\n\n// funcs below will parse/unparse a regexp like /^(?:foo|bar)$/ -> [\"foo\", \"bar\"]\n\n/** @internal */\nexport const regexpToStrings = (regexp: string) => {\n return (\n regexp\n // strip /^(?:)$/ wrapper\n .slice(5, -3)\n // split on unescaped |\n .split(/(?<!\\\\)\\|/g)\n // unescape remaining escaped chars\n .map((string) => string.replace(/\\\\(.)/g, '$1'))\n );\n};\n\n/** @internal */\nexport const stringsToRegexp = (strings: string[]) => {\n return `/^(?:${strings.map((string) => escapeRegExp(string)).join('|')})$/`;\n};\n"],"names":[],"mappings":";;;;;AAeA,MAAM,mBAAsB,GAAA,CAC1B,SACA,EAAA,SAAA,EACA,aACgC,KAAA;AAChC,EAAA,IAAI,CAAC,aAAe,EAAA;AAClB,IAAA;AAAA;AAIF,EAAA,IAAI,SAAY,GAAA,SAAA,CAAU,IAAK,CAAA,CAAC,KAAU,KAAA;AACxC,IAAA,OAAO,CAAC,SAAA,CAAU,IAAK,CAAA,CAAC,MAAW,KAAA;AACjC,MAAA,OAAO,KAAU,KAAA,MAAA;AAAA,KAClB,CAAA;AAAA,GACF,CAAA;AACD,EAAA,IAAI,SAAW,EAAA;AAEb,IAAO,OAAA,SAAA;AAAA;AAET,EAAA;AACF,CAAA;AAUO,SAAS,YAAY,EAAE,KAAA,EAAO,IAAM,EAAA,QAAA,EAAU,aAAsB,EAAA;AACzE,EAAM,MAAA,YAAA,GAAe,QAAQ,MAAM,oBAAA,CAAqB,IAAI,CAAG,EAAA,CAAC,IAAI,CAAC,CAAA;AAErE,EAAA,MAAM,CAAC,mBAAA,EAAqB,yBAAyB,CAAA,GAAI,QAGtD,CAAA;AAAA,IACD,QAAQ,EAAC;AAAA,IACT,KAAO,EAAA,KAAA;AAAA,GACR,CAAA;AAED,EAAM,MAAA,YAAA,GAAe,QAAQ,MAAM;AAxDrC,IAAA,IAAA,EAAA;AAyDI,IAAA,OAAA,CACE,EAAa,GAAA,YAAA,CAAA,IAAA,CAAK,CAAC,KAAA,KAAU,MAAM,KAAU,KAAA,KAAK,CAAlD,KAAA,IAAA,GAAA,EAAA,GACA,mBAAoB,CAAA,YAAA,EAAc,mBAAoB,CAAA,MAAA,EAAQ,oBAAoB,KAAK,CAAA;AAAA,GAExF,EAAA,CAAC,KAAO,EAAA,YAAA,EAAc,mBAAmB,CAAC,CAAA;AAE7C,EAAA,MAAM,cAAiB,GAAA,WAAA;AAAA,IACrB,CAAC,CAA+B,KAAA;AAC9B,MAAA,QAAA,CAAS,uBAAG,KAAM,CAAA;AAAA,KACpB;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,IAAI,iBAAiB,mBAAoB,CAAA,MAAA,IAAA,CAAU,YAAc,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,YAAA,CAAA,KAAA,MAAU,oBAAoB,KAAO,EAAA;AACpG,IAA0B,yBAAA,CAAA;AAAA,MACxB,MAAQ,EAAA,YAAA;AAAA,MACR,OAAO,YAAc,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,YAAA,CAAA;AAAA,KACtB,CAAA;AAAA;AAEH,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,YAAA;AAAA,MACT,QAAU,EAAA,cAAA;AAAA,MACV,WAAa,EAAA,IAAA;AAAA,MACb,aAAa,WAAe,IAAA,IAAA,GAAA,WAAA,GAAA,oBAAA;AAAA,MAC5B,KAAO,EAAA;AAAA;AAAA,GACT;AAEJ;AAgGA,SAAS,qBAAqB,IAAmD,EAAA;AArLjF,EAAA,IAAA,EAAA,EAAA,EAAA;AAsLE,EAAM,MAAA,OAAA,uBAAc,GAAyB,EAAA;AAE7C,EAAA,KAAA,MAAW,SAAS,IAAM,EAAA;AACxB,IAAM,MAAA,KAAA,GAAA,CAAQ,EAAM,GAAA,KAAA,CAAA,KAAA,KAAN,IAAe,GAAA,EAAA,GAAA,EAAA;AAC7B,IAAA,MAAM,UAAS,EAAQ,GAAA,OAAA,CAAA,GAAA,CAAI,KAAK,CAAA,KAAjB,YAAsB,EAAC;AAEtC,IAAI,IAAA,MAAA,CAAO,WAAW,CAAG,EAAA;AACvB,MAAQ,OAAA,CAAA,GAAA,CAAI,OAAO,MAAM,CAAA;AAAA;AAG3B,IAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA;AAGnB,EAAA,MAAM,SAAyC,EAAC;AAEhD,EAAA,KAAA,MAAW,CAAC,KAAO,EAAA,MAAM,CAAK,IAAA,OAAA,CAAQ,SAAW,EAAA;AAC/C,IAAA,MAAA,CAAO,IAAK,CAAA;AAAA,MACV,KAAO,EAAA,KAAA;AAAA,MACP,KAAA,EAAO,CAAU,OAAA,EAAA,KAAA,IAAA,IAAA,GAAA,KAAA,GAAS,iBAAiB,CAAA,CAAA;AAAA,MAC3C,WAAA,EAAa,qBAAqB,MAAM;AAAA,KACzC,CAAA;AAAA;AAGH,EAAO,OAAA,MAAA;AACT;AAEA,SAAS,qBAAqB,MAA6B,EAAA;AACzD,EAAO,OAAA,CAAA,QAAA,EAAW,OAAO,MAAM,CAAA;AAAA,IAC3B,EAAA,MAAA,CACC,KAAM,CAAA,CAAA,EAAG,IAAK,CAAA,GAAA,CAAI,GAAG,MAAO,CAAA,MAAM,CAAC,CAAA,CACnC,GAAI,CAAA,CAAC,MAAM,mBAAoB,CAAA,CAAC,CAAC,CAAA,CACjC,IAAK,CAAA,IAAI,CAAC,CAAA,CAAA,EAAI,MAAO,CAAA,MAAA,GAAS,CAAI,GAAA,KAAA,GAAQ,EAAE,CAAA,CAAA;AACnD;AAMO,MAAM,sBAA6D,GAAA;AAAA,EACxE,IAAI,cAAe,CAAA,YAAA;AAAA,EACnB,SAAA,EAAW,CAAC,KAAkC,KAAA;AAC5C,IAAO,uBAAA,GAAA,CAAC,WAAY,EAAA,EAAA,KAAA,EAAO,KAAM,CAAA,OAAA,EAAS,MAAM,KAAM,CAAA,IAAA,EAAM,QAAU,EAAA,KAAA,CAAM,QAAU,EAAA,CAAA;AAAA,GACxF;AAAA,EACA,OAAS,EAAA,aAAA,CAAc,GAAI,CAAA,cAAA,CAAe,YAAY,CAAA;AAAA,EACtD,IAAM,EAAA,0BAAA;AAAA,EACN,WAAa,EAAA,iDAAA;AAAA,EACb,cAAA,EAAgB,CAAC,OAAY,KAAA;AAC/B;;;;"}