mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-18 07:56:56 +00:00
* feat: added dynamic variables creation flow (#7541) * feat: added dynamic variables creation flow * feat: added keys and value apis and hooks * feat: added api and select component changes * feat: added keys fetching and preview values * feat: added dynamic variable to variable items * feat: handled value persistence and tab switches * feat: added default value and formed a schema for dyn-variables * feat: added client and server side searches * feat: corrected the initial load getfieldKey api * feat: removed fetch on mount restriction * feat: added dynamic variable to the dashboard details (#7755) * feat: added dynamic variable to the dashboard details * feat: added new component to existing variables * feat: added enhancement to multiselect and select for dyn-variables * feat: added refetch method between all dynamic-variables * feat: correct error handling * feat: correct error handling * feat: enforced non-empty selectedvalues and default value * feat: added client and server side searches * feat: retry on error * feat: correct error handling * feat: handle defautl value in existing variables * feat: lowercase the source for payload * feat: fixed the incorrect assignment of active indices * feat: improved handling of all option * feat: improved the ALL option visuals * feat: handled default value enforcement in existing variables * feat: added unix time to values call * feat: added incomplete data message and info to search * feat: changed dashboard panel call handling with existing variables * feat: adjusted the response type and data with the new API schema for values * feat: code refactor * feat: made dyn-variable option as the default * feat: added test cases for dyn variable creation and completion * feat: updated test cases * feat: fix lint and test cases * feat: fix typo * feat: resolved comments and refactoring * feat: added dynamic variable suggestion in where clause (#8875) * feat: added dynamic variable suggestion in where clause * feat: added test cases for hooks and api call functions * feat: added test case for querybuildersearchv2 suggestion changes * feat: code refactor * feat: corrected the regex matcher for resolved titles * feat: fixed test cases * feat: added ability to add/remove variable filter to one or more existing panels (#8876) * feat: added ability to add/remove variable filter to one or more existing panels * feat: added widgetselector on variable creation * feat: show labels in widget selector * feat: added apply to all and variable removal logical * feat: refectch only related and affected panels in case of dynamic variables * feat: added button loader for apply-all * feat: light-mode styles * fix: added migration to filter expression for crud operations of variable * feat: added type in the variables in query_range payload for dynamic * feat: correct the variable addition to panel format for new qb expression * feat: added test cases for dynamic variable and add/remove panel feat * feat: implemented where clause suggestion in new qb v5 * feat: added retries for dyn variable and fixed on-enter selection issue * feat: added relatedValues and existing query in param related changes * feat: sanitized data storage and removed duplicates * fix: fixed typechecks * feat: updated panel wait and refetch logic and ALL option selection * feat: fixed variable tabel reordering issue * feat: added empty name validation in variable creation * feat: change value to searchtext in values API * feat: added option for regex in the component, disabled for now * feat: added beta and not rec. tag in variable tabs * feat: added check to prevent api and updates calls with same payload * feat: optimized localstorage for all selection in dynamic variable and updated __all__ case * feat: resolved variable tables infinite loop update error * feat: aded variable name auto-update based on attribute name entered for dynamic variables * feat: modified only/all click behaviour and set all selection always true for dynamic variable * feat: fix dropdown closing doesn't reset us back to our all available values when we have a search * feat: handled all state distinction and carry forward in existing variables * feat: trucate + n more tooltip content to 10 * feat: fixed infinite loop because of dependency of frequently changing object ref in var table * feat: fixed inconsist search implementations * feat: reverted only - all updated area implementation * feat: added more space for search in multiselect component * feat: checked for variable id instead of variable key for refetch * feat: improved performance around multiselect component and added confirm modal for apply to all * feat: rewrite functionality around add and remove panels * feat: changed color for apply to all modal * feat: added changes under flag to handle variable specific removal for removeKeysFromExpression func * feat: added validation in variable edit panel * feat: fixed failing test cases due to recent logic change * feat: added doc links in the dynamic variable feat * feat: resolved comments and refactoring * feat: resolved comments and refactoring * feat: fixed test cases * feat: fixed test cases
152 lines
4.3 KiB
TypeScript
152 lines
4.3 KiB
TypeScript
/* eslint-disable sonarjs/cognitive-complexity */
|
|
import { uniqueOptions } from 'container/NewDashboard/DashboardVariablesSelection/util';
|
|
|
|
import { OptionData } from './types';
|
|
|
|
export const SPACEKEY = ' ';
|
|
|
|
export const prioritizeOrAddOptionForSingleSelect = (
|
|
options: OptionData[],
|
|
value: string,
|
|
label?: string,
|
|
): OptionData[] => {
|
|
let foundOption: OptionData | null = null;
|
|
|
|
// Separate the found option and the rest
|
|
const filteredOptions = options
|
|
.map((option) => {
|
|
if ('options' in option && Array.isArray(option.options)) {
|
|
// Filter out the value from nested options
|
|
const remainingSubOptions = option.options.filter(
|
|
(subOption) => subOption.value !== value,
|
|
);
|
|
const extractedOption = option.options.find(
|
|
(subOption) => subOption.value === value,
|
|
);
|
|
|
|
if (extractedOption) foundOption = extractedOption;
|
|
|
|
// Keep the group if it still has remaining options
|
|
return remainingSubOptions.length > 0
|
|
? { ...option, options: remainingSubOptions }
|
|
: null;
|
|
}
|
|
|
|
// Check top-level options
|
|
if (option.value === value) {
|
|
foundOption = option;
|
|
return null; // Remove it from the list
|
|
}
|
|
|
|
return option;
|
|
})
|
|
.filter(Boolean) as OptionData[]; // Remove null values
|
|
|
|
// If not found, create a new option
|
|
if (!foundOption) {
|
|
foundOption = { value, label: label ?? value };
|
|
}
|
|
|
|
// Add the found/new option at the top
|
|
return [foundOption, ...filteredOptions];
|
|
};
|
|
|
|
export const prioritizeOrAddOptionForMultiSelect = (
|
|
options: OptionData[],
|
|
values: string[], // Only supports multiple values (string[])
|
|
labels?: Record<string, string>,
|
|
): OptionData[] => {
|
|
const foundOptions: OptionData[] = [];
|
|
|
|
// Separate the found options and the rest
|
|
const filteredOptions = options
|
|
.map((option) => {
|
|
if ('options' in option && Array.isArray(option.options)) {
|
|
// Filter out selected values from nested options
|
|
const remainingSubOptions = option.options.filter(
|
|
(subOption) => subOption.value && !values.includes(subOption.value),
|
|
);
|
|
const extractedOptions = option.options.filter(
|
|
(subOption) => subOption.value && values.includes(subOption.value),
|
|
);
|
|
|
|
if (extractedOptions.length > 0) {
|
|
foundOptions.push(...extractedOptions);
|
|
}
|
|
|
|
// Keep the group if it still has remaining options
|
|
return remainingSubOptions.length > 0
|
|
? { ...option, options: remainingSubOptions }
|
|
: null;
|
|
}
|
|
|
|
// Check top-level options
|
|
if (option.value && values.includes(option.value)) {
|
|
foundOptions.push(option);
|
|
return null; // Remove it from the list
|
|
}
|
|
|
|
return option;
|
|
})
|
|
.filter(Boolean) as OptionData[]; // Remove null values
|
|
|
|
// Find missing values that were not present in the original options and create new ones
|
|
const missingValues = values.filter(
|
|
(value) => !foundOptions.some((opt) => opt.value === value),
|
|
);
|
|
|
|
const newOptions = missingValues.map((value) => ({
|
|
value,
|
|
label: labels?.[value] ?? value, // Use provided label or default to value
|
|
}));
|
|
|
|
const flatOutSelectedOptions = uniqueOptions([...newOptions, ...foundOptions]);
|
|
|
|
// Add found & new options to the top
|
|
return [...flatOutSelectedOptions, ...filteredOptions];
|
|
};
|
|
|
|
/**
|
|
* Filters options based on search text
|
|
*/
|
|
export const filterOptionsBySearch = (
|
|
options: OptionData[],
|
|
searchText: string,
|
|
): OptionData[] => {
|
|
if (!searchText.trim()) return options;
|
|
|
|
const lowerSearchText = searchText.toLowerCase();
|
|
|
|
return options
|
|
.map((option) => {
|
|
if ('options' in option && Array.isArray(option.options)) {
|
|
// Filter nested options
|
|
const filteredSubOptions = option.options.filter((subOption) =>
|
|
subOption.label.toLowerCase().includes(lowerSearchText),
|
|
);
|
|
|
|
return filteredSubOptions.length > 0
|
|
? { ...option, options: filteredSubOptions }
|
|
: undefined;
|
|
}
|
|
|
|
// Filter top-level options
|
|
return option.label.toLowerCase().includes(lowerSearchText)
|
|
? option
|
|
: undefined;
|
|
})
|
|
.filter(Boolean) as OptionData[];
|
|
};
|
|
|
|
/**
|
|
* Utility function to handle dropdown scroll and detect when scrolled to bottom
|
|
* Returns true when scrolled to within 20px of the bottom
|
|
*/
|
|
export const handleScrollToBottom = (
|
|
e: React.UIEvent<HTMLDivElement>,
|
|
): boolean => {
|
|
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
|
|
// Consider "scrolled to bottom" when within 20px of the bottom or at the bottom
|
|
return scrollHeight - scrollTop - clientHeight < 20;
|
|
};
|