QueryVariable: Support preview and autocomplete of multi-props
This commit is contained in:
@@ -91,6 +91,7 @@ export interface VariableOption {
|
||||
text: string | string[];
|
||||
value: string | string[];
|
||||
isNone?: boolean;
|
||||
properties?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface IntervalVariableModel extends VariableWithOptions {
|
||||
|
||||
@@ -284,6 +284,7 @@ function variableValueOptionsToVariableOptions(varState: MultiValueVariable['sta
|
||||
value: String(o.value),
|
||||
text: o.label,
|
||||
selected: Array.isArray(varState.value) ? varState.value.includes(o.value) : varState.value === o.value,
|
||||
...(o.properties && { properties: o.properties }),
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ export function VariableEditorForm({ variable, onTypeChange, onGoBack, onDelete
|
||||
|
||||
const isHasVariableOptions = hasVariableOptions(variable);
|
||||
const optionsForSelect = isHasVariableOptions ? variable.getOptionsForSelect(false) : [];
|
||||
const hasMultiProps = 'valuesFormat' in variable.state && variable.state.valuesFormat === 'json';
|
||||
|
||||
const onDeleteVariable = (hideModal: () => void) => () => {
|
||||
reportInteraction('Delete variable');
|
||||
@@ -125,7 +124,7 @@ export function VariableEditorForm({ variable, onTypeChange, onGoBack, onDelete
|
||||
|
||||
{EditorToRender && <EditorToRender variable={variable} onRunQuery={onRunQuery} />}
|
||||
|
||||
{isHasVariableOptions && <VariableValuesPreview options={optionsForSelect} hasMultiProps={hasMultiProps} />}
|
||||
{isHasVariableOptions && <VariableValuesPreview options={optionsForSelect} />}
|
||||
|
||||
<div className={styles.buttonContainer}>
|
||||
<Stack gap={2}>
|
||||
|
||||
+8
-5
@@ -10,13 +10,16 @@ import { Button, InlineFieldRow, InlineLabel, InteractiveTable, Text, useStyles2
|
||||
|
||||
export interface Props {
|
||||
options: VariableValueOption[];
|
||||
hasMultiProps?: boolean;
|
||||
}
|
||||
|
||||
export const VariableValuesPreview = ({ options, hasMultiProps }: Props) => {
|
||||
const hasMultiProps = (options: Props['options']) => {
|
||||
return Object.keys(options[1]?.properties ?? options[0]?.properties ?? {}).length > 0;
|
||||
};
|
||||
|
||||
export const VariableValuesPreview = ({ options }: Props) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
const hasOptions = options.length > 0;
|
||||
const displayMultiPropsPreview = config.featureToggles.multiPropsVariables && hasMultiProps;
|
||||
const displayMultiPropsPreview = config.featureToggles.multiPropsVariables && hasOptions && hasMultiProps(options);
|
||||
|
||||
return (
|
||||
<div className={styles.previewContainer} style={{ gap: '8px' }}>
|
||||
@@ -43,7 +46,8 @@ function VariableValuesWithPropsPreview({ options }: { options: VariableValueOpt
|
||||
|
||||
return {
|
||||
data,
|
||||
columns: Object.keys(data[0] ?? {}).map((id) => ({
|
||||
// the option at index 0 can be "All" so we try to grab the column names from the 2nd option
|
||||
columns: Object.keys(data[1] ?? data[0] ?? {}).map((id) => ({
|
||||
id,
|
||||
// see https://github.com/TanStack/table/issues/1671
|
||||
header: unsanitizeKey(id),
|
||||
@@ -62,7 +66,6 @@ function VariableValuesWithPropsPreview({ options }: { options: VariableValueOpt
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const sanitizeKey = (key: string) => key.replace(/\./g, '__dot__');
|
||||
const unsanitizeKey = (key: string) => key.replace(/__dot__/g, '.');
|
||||
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ function ModalEditorMultiProps(props: ModalEditorProps) {
|
||||
{queryValidationError && <FieldValidationMessage>{queryValidationError.message}</FieldValidationMessage>}
|
||||
</div>
|
||||
<div>
|
||||
<VariableValuesPreview options={options} hasMultiProps={valuesFormat === 'json'} />
|
||||
<VariableValuesPreview options={options} />
|
||||
</div>
|
||||
</Stack>
|
||||
<Modal.ButtonRow>
|
||||
|
||||
@@ -81,16 +81,16 @@ const buildLabelPath = (label: string) => {
|
||||
};
|
||||
|
||||
const getVariableValueProperties = (variable: TypedVariableModel): string[] => {
|
||||
if (!('valuesFormat' in variable) || variable.valuesFormat !== 'json') {
|
||||
if (!('options' in variable) || !variable.options[0].properties) {
|
||||
return [];
|
||||
}
|
||||
|
||||
function collectFieldPaths(option: Record<string, string>, currentPath: string) {
|
||||
function collectFieldPaths(properties: Record<string, any>, currentPath: string) {
|
||||
let paths: string[] = [];
|
||||
for (const field in option) {
|
||||
if (option.hasOwnProperty(field)) {
|
||||
for (const field in properties) {
|
||||
if (properties.hasOwnProperty(field)) {
|
||||
const newPath = `${currentPath}.${field}`;
|
||||
const value = option[field];
|
||||
const value = properties[field];
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
paths = [...paths, ...collectFieldPaths(value, newPath)];
|
||||
}
|
||||
@@ -100,11 +100,7 @@ const getVariableValueProperties = (variable: TypedVariableModel): string[] => {
|
||||
return paths;
|
||||
}
|
||||
|
||||
try {
|
||||
return collectFieldPaths(JSON.parse(variable.query)[0], variable.name);
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
return collectFieldPaths(variable.options[0].properties, variable.name);
|
||||
};
|
||||
|
||||
export const getPanelLinksVariableSuggestions = (): VariableSuggestion[] => [
|
||||
|
||||
@@ -503,13 +503,16 @@ describe('linkSrv', () => {
|
||||
});
|
||||
|
||||
describe('getPanelLinksVariableSuggestions', () => {
|
||||
it('then it should return template variables, json properties and built-ins', () => {
|
||||
it('then it should return template variables, options properties and built-ins', () => {
|
||||
const templateSrvWithJsonValues = initTemplateSrv('key', [
|
||||
{
|
||||
type: 'custom',
|
||||
name: 'customServers',
|
||||
valuesFormat: 'json',
|
||||
query: '[{"name":"web","ip":"192.168.0.100"},{"name":"ads","ip":"192.168.0.142"}]',
|
||||
options: [
|
||||
{ text: 'web', value: 'web', properties: { name: 'web', ip: '192.168.0.100' } },
|
||||
{ text: 'ads', value: 'ads', properties: { name: 'ads', ip: '192.168.0.142' } },
|
||||
],
|
||||
},
|
||||
]);
|
||||
setTemplateSrv(templateSrvWithJsonValues);
|
||||
|
||||
Reference in New Issue
Block a user