Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lens] Add reduced time range option for formula #142709

Merged
merged 10 commits into from
Oct 10, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ export interface DimensionEditorProps extends IndexPatternDimensionEditorProps {

const operationDisplay = getOperationDisplay();

function getHelpMessage(flag?: boolean | { helpMessage: string }) {
return flag && typeof flag !== 'boolean' ? flag.helpMessage : null;
}

export function DimensionEditor(props: DimensionEditorProps) {
const {
selectedColumn,
Expand Down Expand Up @@ -135,55 +139,58 @@ export function DimensionEditor(props: DimensionEditorProps) {
[layerId, setState]
);

const setStateWrapper = (
setter:
| IndexPatternLayer
| ((prevLayer: IndexPatternLayer) => IndexPatternLayer)
| GenericIndexPatternColumn,
options: { forceRender?: boolean } = {}
) => {
const layer = state.layers[layerId];
let hypotethicalLayer: IndexPatternLayer;
if (isColumn(setter)) {
hypotethicalLayer = {
...layer,
columns: {
...layer.columns,
[columnId]: setter,
},
};
} else {
hypotethicalLayer = typeof setter === 'function' ? setter(state.layers[layerId]) : setter;
}
const isDimensionComplete = Boolean(hypotethicalLayer.columns[columnId]);
const setStateWrapper = useCallback(
(
setter:
| IndexPatternLayer
| ((prevLayer: IndexPatternLayer) => IndexPatternLayer)
| GenericIndexPatternColumn,
options: { forceRender?: boolean } = {}
) => {
const layer = state.layers[layerId];
let hypotethicalLayer: IndexPatternLayer;
if (isColumn(setter)) {
hypotethicalLayer = {
...layer,
columns: {
...layer.columns,
[columnId]: setter,
},
};
} else {
hypotethicalLayer = typeof setter === 'function' ? setter(state.layers[layerId]) : setter;
}
const isDimensionComplete = Boolean(hypotethicalLayer.columns[columnId]);

setState(
(prevState) => {
let outputLayer: IndexPatternLayer;
const prevLayer = prevState.layers[layerId];
if (isColumn(setter)) {
outputLayer = {
...prevLayer,
columns: {
...prevLayer.columns,
[columnId]: setter,
},
};
} else {
outputLayer = typeof setter === 'function' ? setter(prevState.layers[layerId]) : setter;
setState(
(prevState) => {
let outputLayer: IndexPatternLayer;
const prevLayer = prevState.layers[layerId];
if (isColumn(setter)) {
outputLayer = {
...prevLayer,
columns: {
...prevLayer.columns,
[columnId]: setter,
},
};
} else {
outputLayer = typeof setter === 'function' ? setter(prevState.layers[layerId]) : setter;
}
return mergeLayer({
state: prevState,
layerId,
newLayer: adjustColumnReferencesForChangedColumn(outputLayer, columnId),
});
},
{
isDimensionComplete,
...options,
}
return mergeLayer({
state: prevState,
layerId,
newLayer: adjustColumnReferencesForChangedColumn(outputLayer, columnId),
});
},
{
isDimensionComplete,
...options,
}
);
};
);
},
[columnId, layerId, setState, state.layers]
);

const setIsCloseable = (isCloseable: boolean) => {
setState((prevState) => ({ ...prevState, isDimensionClosePrevented: !isCloseable }));
Expand Down Expand Up @@ -965,6 +972,30 @@ export function DimensionEditor(props: DimensionEditorProps) {
[layerId, selectedColumn, props.indexPatterns, state.layers]
);

/**
* Advanced options can cause side effects on other columns (i.e. formulas)
* so before updating the layer the full insertOrReplaceColumn needs to be performed
*/
const updateAdvancedOption = useCallback(
(newLayer) => {
if (selectedColumn) {
setStateWrapper(
// formula need to regenerate from scratch
selectedColumn.operationType === formulaOperationName
? insertOrReplaceColumn({
op: selectedColumn.operationType,
layer: newLayer,
columnId,
indexPattern: currentIndexPattern,
visualizationGroups: dimensionGroups,
})
: newLayer
);
}
},
[columnId, currentIndexPattern, dimensionGroups, selectedColumn, setStateWrapper]
);

const shouldDisplayAdvancedOptions =
!isFullscreen &&
!currentFieldIsInvalid &&
Expand Down Expand Up @@ -1020,7 +1051,7 @@ export function DimensionEditor(props: DimensionEditorProps) {
selectedColumn={selectedColumn}
columnId={columnId}
layer={state.layers[layerId]}
updateLayer={setStateWrapper}
updateLayer={updateAdvancedOption}
/>
) : null,
},
Expand All @@ -1032,13 +1063,8 @@ export function DimensionEditor(props: DimensionEditorProps) {
selectedColumn={selectedColumn}
columnId={columnId}
layer={state.layers[layerId]}
updateLayer={setStateWrapper}
helpMessage={
selectedOperationDefinition.filterable &&
typeof selectedOperationDefinition.filterable !== 'boolean'
? selectedOperationDefinition.filterable.helpMessage
: null
}
updateLayer={updateAdvancedOption}
helpMessage={getHelpMessage(selectedOperationDefinition.filterable)}
/>
) : null,
},
Expand All @@ -1050,7 +1076,9 @@ export function DimensionEditor(props: DimensionEditorProps) {
columnId={columnId}
indexPattern={currentIndexPattern}
layer={state.layers[layerId]}
updateLayer={setStateWrapper}
updateLayer={updateAdvancedOption}
skipLabelUpdate={hasFormula}
helpMessage={getHelpMessage(selectedOperationDefinition.canReduceTimeRange)}
/>
) : null,
},
Expand All @@ -1069,7 +1097,7 @@ export function DimensionEditor(props: DimensionEditorProps) {
selectedColumn={selectedColumn}
columnId={columnId}
layer={state.layers[layerId]}
updateLayer={setStateWrapper}
updateLayer={updateAdvancedOption}
activeData={props.activeData}
layerId={layerId}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { EuiFormRow, EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
import { EuiFormRow, EuiFlexItem, EuiFlexGroup, EuiIconTip } from '@elastic/eui';
import { EuiComboBox } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useEffect, useState } from 'react';
Expand All @@ -24,21 +24,23 @@ import { reducedTimeRangeOptions } from '../reduced_time_range_utils';
export function setReducedTimeRange(
columnId: string,
layer: IndexPatternLayer,
reducedTimeRange: string | undefined
reducedTimeRange: string | undefined,
skipLabelUpdate?: boolean
) {
const trimmedReducedTimeRange = reducedTimeRange?.trim();
const currentColumn = layer.columns[columnId];
const label = currentColumn.customLabel
? currentColumn.label
: adjustTimeScaleLabelSuffix(
currentColumn.label,
currentColumn.timeScale,
currentColumn.timeScale,
currentColumn.timeShift,
currentColumn.timeShift,
currentColumn.reducedTimeRange,
trimmedReducedTimeRange
);
const label =
currentColumn.customLabel || skipLabelUpdate
? currentColumn.label
: adjustTimeScaleLabelSuffix(
currentColumn.label,
currentColumn.timeScale,
currentColumn.timeScale,
currentColumn.timeShift,
currentColumn.timeShift,
currentColumn.reducedTimeRange,
trimmedReducedTimeRange
);
return {
...layer,
columns: {
Expand All @@ -62,12 +64,16 @@ export function ReducedTimeRange({
layer,
updateLayer,
indexPattern,
helpMessage,
skipLabelUpdate,
}: {
selectedColumn: GenericIndexPatternColumn;
columnId: string;
layer: IndexPatternLayer;
updateLayer: (newLayer: IndexPatternLayer) => void;
indexPattern: IndexPattern;
helpMessage: string | null;
skipLabelUpdate?: boolean;
}) {
const [localValue, setLocalValue] = useState(selectedColumn.reducedTimeRange);
useEffect(() => {
Expand Down Expand Up @@ -99,16 +105,35 @@ export function ReducedTimeRange({
},
];
}
const label = i18n.translate('xpack.lens.indexPattern.reducedTimeRange.label', {
defaultMessage: 'Reduced time range',
});

return (
<div>
<EuiFormRow
display="rowCompressed"
fullWidth
data-test-subj="indexPattern-dimension-reducedTimeRange-row"
label={i18n.translate('xpack.lens.indexPattern.reducedTimeRange.label', {
defaultMessage: 'Reduced time range',
})}
label={
helpMessage ? (
<>
{label}{' '}
<EuiIconTip
color="subdued"
content={helpMessage}
iconProps={{
className: 'eui-alignTop',
}}
position="top"
size="s"
type="questionInCircle"
/>
</>
) : (
label
)
}
helpText={i18n.translate('xpack.lens.indexPattern.reducedTimeRange.help', {
defaultMessage:
'Reduces the time range specified in the global time filter from the end of the global time filter.',
Expand Down Expand Up @@ -144,22 +169,22 @@ export function ReducedTimeRange({
onCreateOption={(val) => {
const parsedVal = parseTimeShift(val);
if (!isInvalid(parsedVal)) {
updateLayer(setReducedTimeRange(columnId, layer, val));
updateLayer(setReducedTimeRange(columnId, layer, val, skipLabelUpdate));
} else {
setLocalValue(val);
}
}}
onChange={(choices) => {
if (choices.length === 0) {
updateLayer(setReducedTimeRange(columnId, layer, ''));
updateLayer(setReducedTimeRange(columnId, layer, '', skipLabelUpdate));
setLocalValue('');
return;
}

const choice = choices[0].value as string;
const parsedVal = parseTimeShift(choice);
if (!isInvalid(parsedVal)) {
updateLayer(setReducedTimeRange(columnId, layer, choice));
updateLayer(setReducedTimeRange(columnId, layer, choice, skipLabelUpdate));
} else {
setLocalValue(choice);
}
Expand Down
Loading