|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
import { defaults } from 'lodash'; |
|
|
|
|
import React, { ChangeEvent } from 'react'; |
|
|
|
|
import React, { ChangeEvent, useEffect, useState } from 'react'; |
|
|
|
|
import { identity, of, OperatorFunction } from 'rxjs'; |
|
|
|
|
import { map } from 'rxjs/operators'; |
|
|
|
|
|
|
|
|
@ -52,7 +52,6 @@ import { NumberInput } from 'app/core/components/OptionsUI/NumberInput'; |
|
|
|
|
interface CalculateFieldTransformerEditorProps extends TransformerUIProps<CalculateFieldTransformerOptions> {} |
|
|
|
|
|
|
|
|
|
interface CalculateFieldTransformerEditorState { |
|
|
|
|
include: string[]; |
|
|
|
|
names: string[]; |
|
|
|
|
selected: string[]; |
|
|
|
|
} |
|
|
|
@ -75,47 +74,30 @@ const okTypes = new Set<FieldType>([FieldType.time, FieldType.number, FieldType. |
|
|
|
|
|
|
|
|
|
const labelWidth = 16; |
|
|
|
|
|
|
|
|
|
export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
CalculateFieldTransformerEditorProps, |
|
|
|
|
CalculateFieldTransformerEditorState |
|
|
|
|
> { |
|
|
|
|
constructor(props: CalculateFieldTransformerEditorProps) { |
|
|
|
|
super(props); |
|
|
|
|
|
|
|
|
|
this.state = { |
|
|
|
|
include: props.options?.reduce?.include || [], |
|
|
|
|
names: [], |
|
|
|
|
selected: [], |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
componentDidMount() { |
|
|
|
|
this.initOptions(); |
|
|
|
|
} |
|
|
|
|
export const CalculateFieldTransformerEditor = (props: CalculateFieldTransformerEditorProps) => { |
|
|
|
|
const { options, onChange, input } = props; |
|
|
|
|
const configuredOptions = options?.reduce?.include; |
|
|
|
|
|
|
|
|
|
componentDidUpdate(oldProps: CalculateFieldTransformerEditorProps) { |
|
|
|
|
if (this.props.input !== oldProps.input) { |
|
|
|
|
this.initOptions(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
const [state, setState] = useState<CalculateFieldTransformerEditorState>({ names: [], selected: [] }); |
|
|
|
|
|
|
|
|
|
private initOptions() { |
|
|
|
|
const { options } = this.props; |
|
|
|
|
const configuredOptions = options?.reduce?.include || []; |
|
|
|
|
useEffect(() => { |
|
|
|
|
const ctx = { interpolate: (v: string) => v }; |
|
|
|
|
const subscription = of(this.props.input) |
|
|
|
|
const subscription = of(input) |
|
|
|
|
.pipe( |
|
|
|
|
standardTransformers.ensureColumnsTransformer.operator(null, ctx), |
|
|
|
|
this.extractAllNames(), |
|
|
|
|
this.getVariableNames(), |
|
|
|
|
this.extractNamesAndSelected(configuredOptions) |
|
|
|
|
extractAllNames(), |
|
|
|
|
getVariableNames(), |
|
|
|
|
extractNamesAndSelected(configuredOptions || []) |
|
|
|
|
) |
|
|
|
|
.subscribe(({ selected, names }) => { |
|
|
|
|
this.setState({ names, selected }, () => subscription.unsubscribe()); |
|
|
|
|
setState({ names, selected }); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
return () => { |
|
|
|
|
subscription.unsubscribe(); |
|
|
|
|
}; |
|
|
|
|
}, [input, configuredOptions]); |
|
|
|
|
|
|
|
|
|
private getVariableNames(): OperatorFunction<string[], string[]> { |
|
|
|
|
const getVariableNames = (): OperatorFunction<string[], string[]> => { |
|
|
|
|
if (!cfg.featureToggles.transformationsVariableSupport) { |
|
|
|
|
return identity; |
|
|
|
|
} |
|
|
|
@ -127,9 +109,9 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
return input; |
|
|
|
|
}) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
private extractAllNames(): OperatorFunction<DataFrame[], string[]> { |
|
|
|
|
const extractAllNames = (): OperatorFunction<DataFrame[], string[]> => { |
|
|
|
|
return (source) => |
|
|
|
|
source.pipe( |
|
|
|
|
map((input) => { |
|
|
|
@ -154,11 +136,11 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
return allNames; |
|
|
|
|
}) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
private extractNamesAndSelected( |
|
|
|
|
const extractNamesAndSelected = ( |
|
|
|
|
configuredOptions: string[] |
|
|
|
|
): OperatorFunction<string[], { names: string[]; selected: string[] }> { |
|
|
|
|
): OperatorFunction<string[], { names: string[]; selected: string[] }> => { |
|
|
|
|
return (source) => |
|
|
|
|
source.pipe( |
|
|
|
|
map((allNames) => { |
|
|
|
@ -179,28 +161,16 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
return { names, selected }; |
|
|
|
|
}) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
onToggleReplaceFields = (e: React.FormEvent<HTMLInputElement>) => { |
|
|
|
|
const { options } = this.props; |
|
|
|
|
this.props.onChange({ |
|
|
|
|
...options, |
|
|
|
|
replaceFields: e.currentTarget.checked, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onToggleRowIndexAsPercentile = (e: React.FormEvent<HTMLInputElement>) => { |
|
|
|
|
const { options } = this.props; |
|
|
|
|
this.props.onChange({ |
|
|
|
|
const onToggleReplaceFields = (e: React.FormEvent<HTMLInputElement>) => { |
|
|
|
|
onChange({ |
|
|
|
|
...options, |
|
|
|
|
index: { |
|
|
|
|
asPercentile: e.currentTarget.checked, |
|
|
|
|
}, |
|
|
|
|
replaceFields: e.currentTarget.checked, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onModeChanged = (value: SelectableValue<CalculateFieldMode>) => { |
|
|
|
|
const { options, onChange } = this.props; |
|
|
|
|
const onModeChanged = (value: SelectableValue<CalculateFieldMode>) => { |
|
|
|
|
const mode = value.value ?? CalculateFieldMode.BinaryOperation; |
|
|
|
|
if (mode === CalculateFieldMode.WindowFunctions) { |
|
|
|
|
options.window = options.window ?? defaultWindowOptions; |
|
|
|
@ -211,67 +181,42 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onAliasChanged = (evt: ChangeEvent<HTMLInputElement>) => { |
|
|
|
|
const { options } = this.props; |
|
|
|
|
this.props.onChange({ |
|
|
|
|
const onAliasChanged = (evt: ChangeEvent<HTMLInputElement>) => { |
|
|
|
|
onChange({ |
|
|
|
|
...options, |
|
|
|
|
alias: evt.target.value, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// Cumulative functions
|
|
|
|
|
// Row index
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
updateReduceOptions = (v: ReduceOptions) => { |
|
|
|
|
const { options, onChange } = this.props; |
|
|
|
|
const onToggleRowIndexAsPercentile = (e: React.FormEvent<HTMLInputElement>) => { |
|
|
|
|
onChange({ |
|
|
|
|
...options, |
|
|
|
|
reduce: v, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onFieldToggle = (fieldName: string) => { |
|
|
|
|
const { selected } = this.state; |
|
|
|
|
if (selected.indexOf(fieldName) > -1) { |
|
|
|
|
this.onChange(selected.filter((s) => s !== fieldName)); |
|
|
|
|
} else { |
|
|
|
|
this.onChange([...selected, fieldName]); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onChange = (selected: string[]) => { |
|
|
|
|
this.setState({ selected }); |
|
|
|
|
const { reduce } = this.props.options; |
|
|
|
|
this.updateReduceOptions({ |
|
|
|
|
...reduce!, |
|
|
|
|
include: selected, |
|
|
|
|
index: { |
|
|
|
|
asPercentile: e.currentTarget.checked, |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onStatsChange = (stats: string[]) => { |
|
|
|
|
const reducer = stats.length ? (stats[0] as ReducerID) : ReducerID.sum; |
|
|
|
|
|
|
|
|
|
const { reduce } = this.props.options; |
|
|
|
|
this.updateReduceOptions({ ...reduce, reducer }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
renderRowIndex(options?: IndexOptions) { |
|
|
|
|
const renderRowIndex = (options?: IndexOptions) => { |
|
|
|
|
return ( |
|
|
|
|
<> |
|
|
|
|
<InlineField labelWidth={labelWidth} label="As percentile" tooltip="Transform the row index as a percentile."> |
|
|
|
|
<InlineSwitch value={!!options?.asPercentile} onChange={this.onToggleRowIndexAsPercentile} /> |
|
|
|
|
<InlineSwitch value={!!options?.asPercentile} onChange={onToggleRowIndexAsPercentile} /> |
|
|
|
|
</InlineField> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// Window functions
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
updateWindowOptions = (v: WindowOptions) => { |
|
|
|
|
const { options, onChange } = this.props; |
|
|
|
|
const updateWindowOptions = (v: WindowOptions) => { |
|
|
|
|
const { options, onChange } = props; |
|
|
|
|
onChange({ |
|
|
|
|
...options, |
|
|
|
|
mode: CalculateFieldMode.WindowFunctions, |
|
|
|
@ -279,26 +224,26 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onWindowFieldChange = (v: SelectableValue<string>) => { |
|
|
|
|
const { window } = this.props.options; |
|
|
|
|
this.updateWindowOptions({ |
|
|
|
|
const onWindowFieldChange = (v: SelectableValue<string>) => { |
|
|
|
|
const { window } = options; |
|
|
|
|
updateWindowOptions({ |
|
|
|
|
...window!, |
|
|
|
|
field: v.value!, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onWindowSizeChange = (v?: number) => { |
|
|
|
|
const { window } = this.props.options; |
|
|
|
|
this.updateWindowOptions({ |
|
|
|
|
const onWindowSizeChange = (v?: number) => { |
|
|
|
|
const { window } = options; |
|
|
|
|
updateWindowOptions({ |
|
|
|
|
...window!, |
|
|
|
|
windowSize: v && window?.windowSizeMode === WindowSizeMode.Percentage ? v / 100 : v, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onWindowSizeModeChange = (val: string) => { |
|
|
|
|
const { window } = this.props.options; |
|
|
|
|
const onWindowSizeModeChange = (val: string) => { |
|
|
|
|
const { window } = options; |
|
|
|
|
const mode = val as WindowSizeMode; |
|
|
|
|
this.updateWindowOptions({ |
|
|
|
|
updateWindowOptions({ |
|
|
|
|
...window!, |
|
|
|
|
windowSize: window?.windowSize |
|
|
|
|
? mode === WindowSizeMode.Percentage |
|
|
|
@ -309,23 +254,23 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onWindowStatsChange = (stats: string[]) => { |
|
|
|
|
const onWindowStatsChange = (stats: string[]) => { |
|
|
|
|
const reducer = stats.length ? (stats[0] as ReducerID) : ReducerID.sum; |
|
|
|
|
|
|
|
|
|
const { window } = this.props.options; |
|
|
|
|
this.updateWindowOptions({ ...window, reducer }); |
|
|
|
|
const { window } = options; |
|
|
|
|
updateWindowOptions({ ...window, reducer }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onTypeChange = (val: string) => { |
|
|
|
|
const { window } = this.props.options; |
|
|
|
|
this.updateWindowOptions({ |
|
|
|
|
const onTypeChange = (val: string) => { |
|
|
|
|
const { window } = options; |
|
|
|
|
updateWindowOptions({ |
|
|
|
|
...window!, |
|
|
|
|
windowAlignment: val as WindowAlignment, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
renderWindowFunctions(options?: WindowOptions) { |
|
|
|
|
const { names } = this.state; |
|
|
|
|
const renderWindowFunctions = (options?: WindowOptions) => { |
|
|
|
|
const { names } = state; |
|
|
|
|
options = defaults(options, { reducer: ReducerID.sum }); |
|
|
|
|
const selectOptions = names.map((v) => ({ label: v, value: v })); |
|
|
|
|
const typeOptions = [ |
|
|
|
@ -345,7 +290,7 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
options={selectOptions} |
|
|
|
|
className="min-width-18" |
|
|
|
|
value={options?.field} |
|
|
|
|
onChange={this.onWindowFieldChange} |
|
|
|
|
onChange={onWindowFieldChange} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
<InlineField label="Calculation" labelWidth={labelWidth}> |
|
|
|
@ -353,7 +298,7 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
allowMultiple={false} |
|
|
|
|
className="width-18" |
|
|
|
|
stats={[options.reducer]} |
|
|
|
|
onChange={this.onWindowStatsChange} |
|
|
|
|
onChange={onWindowStatsChange} |
|
|
|
|
defaultStat={ReducerID.mean} |
|
|
|
|
filterOptions={(ext) => |
|
|
|
|
ext.id === ReducerID.mean || ext.id === ReducerID.variance || ext.id === ReducerID.stdDev |
|
|
|
@ -364,14 +309,14 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
<RadioButtonGroup |
|
|
|
|
value={options.windowAlignment ?? WindowAlignment.Trailing} |
|
|
|
|
options={typeOptions} |
|
|
|
|
onChange={this.onTypeChange} |
|
|
|
|
onChange={onTypeChange} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
<InlineField label="Window size mode"> |
|
|
|
|
<RadioButtonGroup |
|
|
|
|
value={options.windowSizeMode ?? WindowSizeMode.Percentage} |
|
|
|
|
options={windowSizeModeOptions} |
|
|
|
|
onChange={this.onWindowSizeModeChange} |
|
|
|
|
onChange={onWindowSizeModeChange} |
|
|
|
|
></RadioButtonGroup> |
|
|
|
|
</InlineField> |
|
|
|
|
<InlineField |
|
|
|
@ -391,26 +336,52 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
? options.windowSize * 100 |
|
|
|
|
: options.windowSize |
|
|
|
|
} |
|
|
|
|
onChange={this.onWindowSizeChange} |
|
|
|
|
onChange={onWindowSizeChange} |
|
|
|
|
></NumberInput> |
|
|
|
|
</InlineField> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// Reduce by Row
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
onReducerStatsChange = (stats: string[]) => { |
|
|
|
|
const updateReduceOptions = (v: ReduceOptions) => { |
|
|
|
|
const { onChange } = props; |
|
|
|
|
onChange({ |
|
|
|
|
...options, |
|
|
|
|
reduce: v, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const onFieldToggle = (fieldName: string) => { |
|
|
|
|
const { selected } = state; |
|
|
|
|
if (selected.indexOf(fieldName) > -1) { |
|
|
|
|
onReduceFieldsChanged(selected.filter((s) => s !== fieldName)); |
|
|
|
|
} else { |
|
|
|
|
onReduceFieldsChanged([...selected, fieldName]); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const onReduceFieldsChanged = (selected: string[]) => { |
|
|
|
|
setState({ ...state, ...{ selected } }); |
|
|
|
|
const { reduce } = options; |
|
|
|
|
updateReduceOptions({ |
|
|
|
|
...reduce!, |
|
|
|
|
include: selected, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const onStatsChange = (stats: string[]) => { |
|
|
|
|
const reducer = stats.length ? (stats[0] as ReducerID) : ReducerID.sum; |
|
|
|
|
|
|
|
|
|
const { reduce } = this.props.options; |
|
|
|
|
this.updateReduceOptions({ ...reduce, reducer }); |
|
|
|
|
const { reduce } = options; |
|
|
|
|
updateReduceOptions({ ...reduce, reducer }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
renderReduceRow(options?: ReduceOptions) { |
|
|
|
|
const { names, selected } = this.state; |
|
|
|
|
const renderReduceRow = (options?: ReduceOptions) => { |
|
|
|
|
const { names, selected } = state; |
|
|
|
|
options = defaults(options, { reducer: ReducerID.sum }); |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
@ -422,7 +393,7 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
<FilterPill |
|
|
|
|
key={`${o}/${i}`} |
|
|
|
|
onClick={() => { |
|
|
|
|
this.onFieldToggle(o); |
|
|
|
|
onFieldToggle(o); |
|
|
|
|
}} |
|
|
|
|
label={o} |
|
|
|
|
selected={selected.indexOf(o) > -1} |
|
|
|
@ -436,27 +407,26 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
allowMultiple={false} |
|
|
|
|
className="width-18" |
|
|
|
|
stats={[options.reducer]} |
|
|
|
|
onChange={this.onStatsChange} |
|
|
|
|
onChange={onStatsChange} |
|
|
|
|
defaultStat={ReducerID.sum} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// Cumulative Operator
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
onCumulativeStatsChange = (stats: string[]) => { |
|
|
|
|
const onCumulativeStatsChange = (stats: string[]) => { |
|
|
|
|
const reducer = stats.length ? (stats[0] as ReducerID) : ReducerID.sum; |
|
|
|
|
|
|
|
|
|
const { reduce } = this.props.options; |
|
|
|
|
this.updateCumulativeOptions({ ...reduce, reducer }); |
|
|
|
|
const { cumulative } = options; |
|
|
|
|
updateCumulativeOptions({ ...cumulative, reducer }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
updateCumulativeOptions = (v: CumulativeOptions) => { |
|
|
|
|
const { options, onChange } = this.props; |
|
|
|
|
const updateCumulativeOptions = (v: CumulativeOptions) => { |
|
|
|
|
onChange({ |
|
|
|
|
...options, |
|
|
|
|
mode: CalculateFieldMode.CumulativeFunctions, |
|
|
|
@ -464,16 +434,16 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onCumulativeFieldChange = (v: SelectableValue<string>) => { |
|
|
|
|
const { cumulative } = this.props.options; |
|
|
|
|
this.updateCumulativeOptions({ |
|
|
|
|
const onCumulativeFieldChange = (v: SelectableValue<string>) => { |
|
|
|
|
const { cumulative } = options; |
|
|
|
|
updateCumulativeOptions({ |
|
|
|
|
...cumulative!, |
|
|
|
|
field: v.value!, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
renderCumulativeFunctions(options?: CumulativeOptions) { |
|
|
|
|
const { names } = this.state; |
|
|
|
|
const renderCumulativeFunctions = (options?: CumulativeOptions) => { |
|
|
|
|
const { names } = state; |
|
|
|
|
options = defaults(options, { reducer: ReducerID.sum }); |
|
|
|
|
const selectOptions = names.map((v) => ({ label: v, value: v })); |
|
|
|
|
|
|
|
|
@ -485,7 +455,7 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
options={selectOptions} |
|
|
|
|
className="min-width-18" |
|
|
|
|
value={options?.field} |
|
|
|
|
onChange={this.onCumulativeFieldChange} |
|
|
|
|
onChange={onCumulativeFieldChange} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
<InlineField label="Calculation" labelWidth={labelWidth}> |
|
|
|
@ -493,21 +463,20 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
allowMultiple={false} |
|
|
|
|
className="width-18" |
|
|
|
|
stats={[options.reducer]} |
|
|
|
|
onChange={this.onCumulativeStatsChange} |
|
|
|
|
onChange={onCumulativeStatsChange} |
|
|
|
|
defaultStat={ReducerID.sum} |
|
|
|
|
filterOptions={(ext) => ext.id === ReducerID.sum || ext.id === ReducerID.mean} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// Binary Operator
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
updateBinaryOptions = (v: BinaryOptions) => { |
|
|
|
|
const { options, onChange } = this.props; |
|
|
|
|
const updateBinaryOptions = (v: BinaryOptions) => { |
|
|
|
|
onChange({ |
|
|
|
|
...options, |
|
|
|
|
mode: CalculateFieldMode.BinaryOperation, |
|
|
|
@ -515,36 +484,36 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onBinaryLeftChanged = (v: SelectableValue<string>) => { |
|
|
|
|
const { binary } = this.props.options; |
|
|
|
|
this.updateBinaryOptions({ |
|
|
|
|
const onBinaryLeftChanged = (v: SelectableValue<string>) => { |
|
|
|
|
const { binary } = options; |
|
|
|
|
updateBinaryOptions({ |
|
|
|
|
...binary!, |
|
|
|
|
left: v.value!, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onBinaryRightChanged = (v: SelectableValue<string>) => { |
|
|
|
|
const { binary } = this.props.options; |
|
|
|
|
this.updateBinaryOptions({ |
|
|
|
|
const onBinaryRightChanged = (v: SelectableValue<string>) => { |
|
|
|
|
const { binary } = options; |
|
|
|
|
updateBinaryOptions({ |
|
|
|
|
...binary!, |
|
|
|
|
right: v.value!, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onBinaryOperationChanged = (v: SelectableValue<BinaryOperationID>) => { |
|
|
|
|
const { binary } = this.props.options; |
|
|
|
|
this.updateBinaryOptions({ |
|
|
|
|
const onBinaryOperationChanged = (v: SelectableValue<BinaryOperationID>) => { |
|
|
|
|
const { binary } = options; |
|
|
|
|
updateBinaryOptions({ |
|
|
|
|
...binary!, |
|
|
|
|
operator: v.value!, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
renderBinaryOperation(options?: BinaryOptions) { |
|
|
|
|
const renderBinaryOperation = (options?: BinaryOptions) => { |
|
|
|
|
options = defaults(options, { operator: BinaryOperationID.Add }); |
|
|
|
|
|
|
|
|
|
let foundLeft = !options?.left; |
|
|
|
|
let foundRight = !options?.right; |
|
|
|
|
const names = this.state.names.map((v) => { |
|
|
|
|
const names = state.names.map((v) => { |
|
|
|
|
if (v === options?.left) { |
|
|
|
|
foundLeft = true; |
|
|
|
|
} |
|
|
|
@ -570,7 +539,7 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
options={leftNames} |
|
|
|
|
className="min-width-18" |
|
|
|
|
value={options?.left} |
|
|
|
|
onChange={this.onBinaryLeftChanged} |
|
|
|
|
onChange={onBinaryLeftChanged} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
<InlineField> |
|
|
|
@ -578,7 +547,7 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
className="width-4" |
|
|
|
|
options={ops} |
|
|
|
|
value={options.operator ?? ops[0].value} |
|
|
|
|
onChange={this.onBinaryOperationChanged} |
|
|
|
|
onChange={onBinaryOperationChanged} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
<InlineField> |
|
|
|
@ -588,20 +557,19 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
className="min-width-10" |
|
|
|
|
options={rightNames} |
|
|
|
|
value={options?.right} |
|
|
|
|
onChange={this.onBinaryRightChanged} |
|
|
|
|
onChange={onBinaryRightChanged} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
</InlineFieldRow> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// Unary Operator
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
updateUnaryOptions = (v: UnaryOptions) => { |
|
|
|
|
const { options, onChange } = this.props; |
|
|
|
|
const updateUnaryOptions = (v: UnaryOptions) => { |
|
|
|
|
onChange({ |
|
|
|
|
...options, |
|
|
|
|
mode: CalculateFieldMode.UnaryOperation, |
|
|
|
@ -609,27 +577,27 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onUnaryOperationChanged = (v: SelectableValue<UnaryOperationID>) => { |
|
|
|
|
const { unary } = this.props.options; |
|
|
|
|
this.updateUnaryOptions({ |
|
|
|
|
const onUnaryOperationChanged = (v: SelectableValue<UnaryOperationID>) => { |
|
|
|
|
const { unary } = options; |
|
|
|
|
updateUnaryOptions({ |
|
|
|
|
...unary!, |
|
|
|
|
operator: v.value!, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onUnaryValueChanged = (v: SelectableValue<string>) => { |
|
|
|
|
const { unary } = this.props.options; |
|
|
|
|
this.updateUnaryOptions({ |
|
|
|
|
const onUnaryValueChanged = (v: SelectableValue<string>) => { |
|
|
|
|
const { unary } = options; |
|
|
|
|
updateUnaryOptions({ |
|
|
|
|
...unary!, |
|
|
|
|
fieldName: v.value!, |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
renderUnaryOperation(options?: UnaryOptions) { |
|
|
|
|
const renderUnaryOperation = (options?: UnaryOptions) => { |
|
|
|
|
options = defaults(options, { operator: UnaryOperationID.Abs }); |
|
|
|
|
|
|
|
|
|
let found = !options?.fieldName; |
|
|
|
|
const names = this.state.names.map((v) => { |
|
|
|
|
const names = state.names.map((v) => { |
|
|
|
|
if (v === options?.fieldName) { |
|
|
|
|
found = true; |
|
|
|
|
} |
|
|
|
@ -646,7 +614,7 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
<> |
|
|
|
|
<InlineFieldRow> |
|
|
|
|
<InlineField label="Operation" labelWidth={labelWidth}> |
|
|
|
|
<Select options={ops} value={options.operator ?? ops[0].value} onChange={this.onUnaryOperationChanged} /> |
|
|
|
|
<Select options={ops} value={options.operator ?? ops[0].value} onChange={onUnaryOperationChanged} /> |
|
|
|
|
</InlineField> |
|
|
|
|
<InlineField label="(" labelWidth={2}> |
|
|
|
|
<Select |
|
|
|
@ -654,55 +622,47 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< |
|
|
|
|
className="min-width-11" |
|
|
|
|
options={fieldName} |
|
|
|
|
value={options?.fieldName} |
|
|
|
|
onChange={this.onUnaryValueChanged} |
|
|
|
|
onChange={onUnaryValueChanged} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
<InlineLabel width={2}>)</InlineLabel> |
|
|
|
|
</InlineFieldRow> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// Render
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
render() { |
|
|
|
|
const { options } = this.props; |
|
|
|
|
|
|
|
|
|
const mode = options.mode ?? CalculateFieldMode.BinaryOperation; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<> |
|
|
|
|
<InlineField labelWidth={labelWidth} label="Mode"> |
|
|
|
|
<Select |
|
|
|
|
className="width-18" |
|
|
|
|
options={calculationModes} |
|
|
|
|
value={calculationModes.find((v) => v.value === mode)} |
|
|
|
|
onChange={this.onModeChanged} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
{mode === CalculateFieldMode.BinaryOperation && this.renderBinaryOperation(options.binary)} |
|
|
|
|
{mode === CalculateFieldMode.UnaryOperation && this.renderUnaryOperation(options.unary)} |
|
|
|
|
{mode === CalculateFieldMode.ReduceRow && this.renderReduceRow(options.reduce)} |
|
|
|
|
{mode === CalculateFieldMode.CumulativeFunctions && this.renderCumulativeFunctions(options.cumulative)} |
|
|
|
|
{mode === CalculateFieldMode.WindowFunctions && this.renderWindowFunctions(options.window)} |
|
|
|
|
{mode === CalculateFieldMode.Index && this.renderRowIndex(options.index)} |
|
|
|
|
<InlineField labelWidth={labelWidth} label="Alias"> |
|
|
|
|
<Input |
|
|
|
|
className="width-18" |
|
|
|
|
value={options.alias ?? ''} |
|
|
|
|
placeholder={getNameFromOptions(options)} |
|
|
|
|
onChange={this.onAliasChanged} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
<InlineField labelWidth={labelWidth} label="Replace all fields"> |
|
|
|
|
<InlineSwitch value={!!options.replaceFields} onChange={this.onToggleReplaceFields} /> |
|
|
|
|
</InlineField> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
const mode = options.mode ?? CalculateFieldMode.BinaryOperation; |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<> |
|
|
|
|
<InlineField labelWidth={labelWidth} label="Mode"> |
|
|
|
|
<Select |
|
|
|
|
className="width-18" |
|
|
|
|
options={calculationModes} |
|
|
|
|
value={calculationModes.find((v) => v.value === mode)} |
|
|
|
|
onChange={onModeChanged} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
{mode === CalculateFieldMode.BinaryOperation && renderBinaryOperation(options.binary)} |
|
|
|
|
{mode === CalculateFieldMode.UnaryOperation && renderUnaryOperation(options.unary)} |
|
|
|
|
{mode === CalculateFieldMode.ReduceRow && renderReduceRow(options.reduce)} |
|
|
|
|
{mode === CalculateFieldMode.CumulativeFunctions && renderCumulativeFunctions(options.cumulative)} |
|
|
|
|
{mode === CalculateFieldMode.WindowFunctions && renderWindowFunctions(options.window)} |
|
|
|
|
{mode === CalculateFieldMode.Index && renderRowIndex(options.index)} |
|
|
|
|
<InlineField labelWidth={labelWidth} label="Alias"> |
|
|
|
|
<Input |
|
|
|
|
className="width-18" |
|
|
|
|
value={options.alias ?? ''} |
|
|
|
|
placeholder={getNameFromOptions(options)} |
|
|
|
|
onChange={onAliasChanged} |
|
|
|
|
/> |
|
|
|
|
</InlineField> |
|
|
|
|
<InlineField labelWidth={labelWidth} label="Replace all fields"> |
|
|
|
|
<InlineSwitch value={!!options.replaceFields} onChange={onToggleReplaceFields} /> |
|
|
|
|
</InlineField> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
export const calculateFieldTransformRegistryItem: TransformerRegistryItem<CalculateFieldTransformerOptions> = { |
|
|
|
|
id: DataTransformerID.calculateField, |
|
|
|
|