Submit
Path:
~
/
/
proc
/
thread-self
/
root
/
usr
/
share
/
grafana
/
public
/
app
/
features
/
variables
/
pickers
/
OptionsPicker
/
File Content:
actions.ts
import { debounce, trim } from 'lodash'; import { isEmptyObject, containsSearchFilter } from '@grafana/data'; import { StoreState, ThunkDispatch, ThunkResult } from 'app/types'; import { variableAdapters } from '../../adapters'; import { hasOptions } from '../../guard'; import { toKeyedAction } from '../../state/keyedVariablesReducer'; import { getVariable, getVariablesState } from '../../state/selectors'; import { changeVariableProp, setCurrentVariableValue } from '../../state/sharedReducer'; import { KeyedVariableIdentifier } from '../../state/types'; import { VariableOption, VariableWithOptions } from '../../types'; import { getCurrentValue, toVariablePayload } from '../../utils'; import { NavigationKey } from '../types'; import { hideOptions, moveOptionsHighlight, OptionsPickerState, showOptions, toggleOption, updateOptionsAndFilter, updateOptionsFromSearch, updateSearchQuery, } from './reducer'; export const navigateOptions = (rootStateKey: string, key: NavigationKey, clearOthers: boolean): ThunkResult<void> => { return async (dispatch, getState) => { if (key === NavigationKey.cancel) { return await dispatch(commitChangesToVariable(rootStateKey)); } if (key === NavigationKey.select) { return dispatch(toggleOptionByHighlight(rootStateKey, clearOthers)); } if (key === NavigationKey.selectAndClose) { const picker = getVariablesState(rootStateKey, getState()).optionsPicker; if (picker.multi) { return dispatch(toggleOptionByHighlight(rootStateKey, clearOthers)); } dispatch(toggleOptionByHighlight(rootStateKey, clearOthers, true)); return dispatch(commitChangesToVariable(rootStateKey)); } if (key === NavigationKey.moveDown) { return dispatch(toKeyedAction(rootStateKey, moveOptionsHighlight(1))); } if (key === NavigationKey.moveUp) { return dispatch(toKeyedAction(rootStateKey, moveOptionsHighlight(-1))); } return undefined; }; }; export const filterOrSearchOptions = ( passedIdentifier: KeyedVariableIdentifier, searchQuery = '' ): ThunkResult<void> => { return async (dispatch, getState) => { const { rootStateKey } = passedIdentifier; const { id, queryValue } = getVariablesState(rootStateKey, getState()).optionsPicker; const identifier: KeyedVariableIdentifier = { id, rootStateKey: rootStateKey, type: 'query' }; const variable = getVariable(identifier, getState()); if (!('options' in variable)) { return; } dispatch(toKeyedAction(rootStateKey, updateSearchQuery(searchQuery))); if (trim(queryValue) === trim(searchQuery)) { return; } const { query, options } = variable; const queryTarget = typeof query === 'string' ? query : query.target; if (containsSearchFilter(queryTarget)) { return searchForOptionsWithDebounce(dispatch, getState, searchQuery, rootStateKey); } return dispatch(toKeyedAction(rootStateKey, updateOptionsAndFilter(options))); }; }; const setVariable = async (updated: VariableWithOptions) => { if (isEmptyObject(updated.current)) { return; } const adapter = variableAdapters.get(updated.type); await adapter.setValue(updated, updated.current, true); return; }; export const commitChangesToVariable = (key: string, callback?: (updated: any) => void): ThunkResult<void> => { return async (dispatch, getState) => { const picker = getVariablesState(key, getState()).optionsPicker; const identifier: KeyedVariableIdentifier = { id: picker.id, rootStateKey: key, type: 'query' }; const existing = getVariable(identifier, getState()); if (!hasOptions(existing)) { return; } const currentPayload = { option: mapToCurrent(picker) }; const searchQueryPayload = { propName: 'queryValue', propValue: picker.queryValue }; dispatch(toKeyedAction(key, setCurrentVariableValue(toVariablePayload(existing, currentPayload)))); dispatch(toKeyedAction(key, changeVariableProp(toVariablePayload(existing, searchQueryPayload)))); const updated = getVariable(identifier, getState()); if (!hasOptions(updated)) { return; } dispatch(toKeyedAction(key, hideOptions())); if (getCurrentValue(existing) === getCurrentValue(updated)) { return; } if (callback) { return callback(updated); } return await setVariable(updated); }; }; export const openOptions = (identifier: KeyedVariableIdentifier, callback?: (updated: any) => void): ThunkResult<void> => async (dispatch, getState) => { const { id, rootStateKey: uid } = identifier; const picker = getVariablesState(uid, getState()).optionsPicker; if (picker.id && picker.id !== id) { await dispatch(commitChangesToVariable(uid, callback)); } const variable = getVariable(identifier, getState()); if (!hasOptions(variable)) { return; } dispatch(toKeyedAction(uid, showOptions(variable))); }; export const toggleOptionByHighlight = (key: string, clearOthers: boolean, forceSelect = false): ThunkResult<void> => { return (dispatch, getState) => { const { highlightIndex, options } = getVariablesState(key, getState()).optionsPicker; const option = options[highlightIndex]; dispatch(toKeyedAction(key, toggleOption({ option, forceSelect, clearOthers }))); }; }; const searchForOptions = async ( dispatch: ThunkDispatch, getState: () => StoreState, searchQuery: string, key: string ) => { try { const { id } = getVariablesState(key, getState()).optionsPicker; const identifier: KeyedVariableIdentifier = { id, rootStateKey: key, type: 'query' }; const existing = getVariable(identifier, getState()); if (!hasOptions(existing)) { return; } const adapter = variableAdapters.get(existing.type); await adapter.updateOptions(existing, searchQuery); const updated = getVariable(identifier, getState()); if (!hasOptions(updated)) { return; } dispatch(toKeyedAction(key, updateOptionsFromSearch(updated.options))); } catch (error) { console.error(error); } }; const searchForOptionsWithDebounce = debounce(searchForOptions, 500); export function mapToCurrent(picker: OptionsPickerState): VariableOption | undefined { const { options, selectedValues, queryValue: searchQuery, multi } = picker; if (options.length === 0 && searchQuery && searchQuery.length > 0) { return { text: searchQuery, value: searchQuery, selected: false }; } if (!multi) { return selectedValues.find((o) => o.selected); } const texts: string[] = []; const values: string[] = []; for (const option of selectedValues) { if (!option.selected) { continue; } texts.push(option.text.toString()); values.push(option.value.toString()); } return { value: values, text: texts, selected: true, }; }
Submit
FILE
FOLDER
INFO
Name
Size
Permission
Action
OptionPicker.test.tsx
4868 bytes
0644
OptionsPicker.tsx
6399 bytes
0644
actions.test.ts
25637 bytes
0644
actions.ts
6894 bytes
0644
reducer.test.ts
33460 bytes
0644
reducer.ts
10763 bytes
0644
N4ST4R_ID | Naxtarrr