|
|
|
@ -1,17 +1,18 @@ |
|
|
|
|
import { |
|
|
|
|
BaseOperator, |
|
|
|
|
BasicConfig, |
|
|
|
|
Config, |
|
|
|
|
Field, |
|
|
|
|
ImmutableList, |
|
|
|
|
JsonTree, |
|
|
|
|
Operator, |
|
|
|
|
OperatorOptionsI, |
|
|
|
|
Settings, |
|
|
|
|
SimpleField, |
|
|
|
|
SqlFormatOperator, |
|
|
|
|
Utils, |
|
|
|
|
ValueSource, |
|
|
|
|
WidgetProps, |
|
|
|
|
Widgets, |
|
|
|
|
} from '@react-awesome-query-builder/ui'; |
|
|
|
|
import { List } from 'immutable'; |
|
|
|
|
import { isString } from 'lodash'; |
|
|
|
|
|
|
|
|
|
import { dateTime, toOption } from '@grafana/data'; |
|
|
|
@ -37,7 +38,7 @@ export const widgets: Widgets = { |
|
|
|
|
...BasicConfig.widgets, |
|
|
|
|
text: { |
|
|
|
|
...BasicConfig.widgets.text, |
|
|
|
|
factory: function TextInput(props) { |
|
|
|
|
factory: function TextInput(props: WidgetProps) { |
|
|
|
|
return ( |
|
|
|
|
<Input |
|
|
|
|
value={props?.value || ''} |
|
|
|
@ -49,7 +50,7 @@ export const widgets: Widgets = { |
|
|
|
|
}, |
|
|
|
|
number: { |
|
|
|
|
...BasicConfig.widgets.number, |
|
|
|
|
factory: function NumberInput(props) { |
|
|
|
|
factory: function NumberInput(props: WidgetProps) { |
|
|
|
|
return ( |
|
|
|
|
<Input |
|
|
|
|
value={props?.value} |
|
|
|
@ -62,7 +63,7 @@ export const widgets: Widgets = { |
|
|
|
|
}, |
|
|
|
|
datetime: { |
|
|
|
|
...BasicConfig.widgets.datetime, |
|
|
|
|
factory: function DateTimeInput(props) { |
|
|
|
|
factory: function DateTimeInput(props: WidgetProps) { |
|
|
|
|
if (props?.operator === Op.MACROS) { |
|
|
|
|
return ( |
|
|
|
|
<Select |
|
|
|
@ -238,75 +239,41 @@ export type { Config }; |
|
|
|
|
|
|
|
|
|
const noop = () => ''; |
|
|
|
|
|
|
|
|
|
const isSqlFormatOp = (func: unknown): func is SqlFormatOperator => { |
|
|
|
|
return typeof func === 'function'; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
function getCustomOperators(config: BasicConfig) { |
|
|
|
|
const { ...supportedOperators } = config.operators; |
|
|
|
|
|
|
|
|
|
// IN operator expects array, override IN formatter for multi-value variables
|
|
|
|
|
const sqlFormatInOpOrNoop = () => { |
|
|
|
|
const sqlFormatOp = supportedOperators[Op.IN].sqlFormatOp; |
|
|
|
|
if (isSqlFormatOp(sqlFormatOp)) { |
|
|
|
|
return sqlFormatOp; |
|
|
|
|
} |
|
|
|
|
return noop; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const sqlFormatInOp = supportedOperators[Op.IN].sqlFormatOp?.bind(config.ctx) || noop; |
|
|
|
|
const customSqlInFormatter = ( |
|
|
|
|
field: string, |
|
|
|
|
op: string, |
|
|
|
|
value: string | List<string>, |
|
|
|
|
valueSrc: ValueSource, |
|
|
|
|
valueType: string, |
|
|
|
|
opDef: Operator, |
|
|
|
|
operatorOptions: OperatorOptionsI, |
|
|
|
|
fieldDef: SimpleField |
|
|
|
|
value: string | string[] | ImmutableList<string>, |
|
|
|
|
valueSrc: ValueSource | undefined, |
|
|
|
|
valueType: string | undefined, |
|
|
|
|
opDef: Operator | undefined, |
|
|
|
|
operatorOptions: OperatorOptionsI | undefined, |
|
|
|
|
fieldDef: Field | undefined |
|
|
|
|
) => { |
|
|
|
|
return sqlFormatInOpOrNoop()( |
|
|
|
|
field, |
|
|
|
|
op, |
|
|
|
|
splitIfString(value), |
|
|
|
|
valueSrc, |
|
|
|
|
valueType, |
|
|
|
|
opDef, |
|
|
|
|
operatorOptions, |
|
|
|
|
fieldDef |
|
|
|
|
); |
|
|
|
|
return sqlFormatInOp(field, op, splitIfString(value), valueSrc, valueType, opDef, operatorOptions, fieldDef); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// NOT IN operator expects array, override NOT IN formatter for multi-value variables
|
|
|
|
|
const sqlFormatNotInOpOrNoop = () => { |
|
|
|
|
const sqlFormatOp = supportedOperators[Op.NOT_IN].sqlFormatOp; |
|
|
|
|
if (isSqlFormatOp(sqlFormatOp)) { |
|
|
|
|
return sqlFormatOp; |
|
|
|
|
} |
|
|
|
|
return noop; |
|
|
|
|
}; |
|
|
|
|
const sqlFormatNotInOp = supportedOperators[Op.NOT_IN].sqlFormatOp?.bind(config.ctx) || noop; |
|
|
|
|
|
|
|
|
|
const customSqlNotInFormatter = ( |
|
|
|
|
field: string, |
|
|
|
|
op: string, |
|
|
|
|
value: string | List<string>, |
|
|
|
|
valueSrc: ValueSource, |
|
|
|
|
valueType: string, |
|
|
|
|
opDef: Operator, |
|
|
|
|
operatorOptions: OperatorOptionsI, |
|
|
|
|
fieldDef: SimpleField |
|
|
|
|
value: string | string[] | ImmutableList<string>, |
|
|
|
|
valueSrc: ValueSource | undefined, |
|
|
|
|
valueType: string | undefined, |
|
|
|
|
opDef: Operator | undefined, |
|
|
|
|
operatorOptions: OperatorOptionsI | undefined, |
|
|
|
|
fieldDef: Field | undefined |
|
|
|
|
) => { |
|
|
|
|
return sqlFormatNotInOpOrNoop()( |
|
|
|
|
field, |
|
|
|
|
op, |
|
|
|
|
splitIfString(value), |
|
|
|
|
valueSrc, |
|
|
|
|
valueType, |
|
|
|
|
opDef, |
|
|
|
|
operatorOptions, |
|
|
|
|
fieldDef |
|
|
|
|
); |
|
|
|
|
return sqlFormatNotInOp(field, op, splitIfString(value), valueSrc, valueType, opDef, operatorOptions, fieldDef); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const customOperators = { |
|
|
|
|
const customOperators: Record<string, BaseOperator> = { |
|
|
|
|
...supportedOperators, |
|
|
|
|
[Op.IN]: { |
|
|
|
|
...supportedOperators[Op.IN], |
|
|
|
@ -318,11 +285,11 @@ function getCustomOperators(config: BasicConfig) { |
|
|
|
|
}, |
|
|
|
|
[Op.MACROS]: { |
|
|
|
|
label: 'Macros', |
|
|
|
|
sqlFormatOp: (field: string, _operator: string, value: string | List<string>) => { |
|
|
|
|
sqlFormatOp: (field: string, _operator: string, value: string | string[] | ImmutableList<string>) => { |
|
|
|
|
if (value === TIME_FILTER) { |
|
|
|
|
return `$__timeFilter(${field})`; |
|
|
|
|
} |
|
|
|
|
return value; |
|
|
|
|
throw new Error('Invalid macro'); |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
}; |
|
|
|
@ -331,7 +298,7 @@ function getCustomOperators(config: BasicConfig) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// value: string | List<string> but AQB uses a different version of Immutable
|
|
|
|
|
function splitIfString(value: any) { |
|
|
|
|
function splitIfString(value: string | string[] | ImmutableList<string>) { |
|
|
|
|
if (isString(value)) { |
|
|
|
|
return value.split(','); |
|
|
|
|
} |
|
|
|
|