mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Lens][Visualize] Adds option to disable cursor sync on dashboards (#143355)
* [Lens][Visualize] Disable cursor sync on dashboard level option * Increase XY limits as it fails for 1B :) * Fix jest tests * Apply PR nit
This commit is contained in:
parent
12acbaca91
commit
46c1250db7
55 changed files with 183 additions and 29 deletions
|
@ -337,6 +337,8 @@ Apply a set of design options to the entire dashboard.
|
|||
|
||||
* *Sync color pallettes across panels* — Applies the same color palette to all panels on the dashboard.
|
||||
|
||||
* *Sync cursor across panels* — When you hover your cursor over a *Lens*, *TSVB*, aggregation-based, or *Timelion* XY chart and a heatmap chart, the cursor on all other related dashboard charts automatically appear.
|
||||
|
||||
* *Sync tooltips across panels* — When you hover your cursor over a *Lens*, *TSVB*, aggregation-based, or *Timelion* XY chart, the tooltips on all other related dashboard charts automatically appear.
|
||||
|
||||
[float]
|
||||
|
|
|
@ -49,7 +49,7 @@ pageLoadAssetSize:
|
|||
expressions: 140958
|
||||
expressionShape: 34008
|
||||
expressionTagcloud: 27505
|
||||
expressionXY: 38000
|
||||
expressionXY: 38500
|
||||
features: 21723
|
||||
fieldFormats: 65209
|
||||
files: 22673
|
||||
|
|
|
@ -101,6 +101,7 @@ Object {
|
|||
],
|
||||
"type": "datatable",
|
||||
},
|
||||
"syncCursor": true,
|
||||
"syncTooltips": false,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -231,6 +231,7 @@ export const heatmapFunction = (): HeatmapExpressionFunctionDefinition => ({
|
|||
handlers.getExecutionContext?.()?.description,
|
||||
},
|
||||
syncTooltips: handlers?.isSyncTooltipsEnabled?.() ?? false,
|
||||
syncCursor: handlers?.isSyncCursorEnabled?.() ?? true,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
|
|
@ -93,6 +93,7 @@ export interface HeatmapExpressionProps {
|
|||
data: Datatable;
|
||||
args: HeatmapArguments;
|
||||
syncTooltips: boolean;
|
||||
syncCursor: boolean;
|
||||
}
|
||||
|
||||
export interface HeatmapRender {
|
||||
|
|
|
@ -39,5 +39,6 @@ export type HeatmapRenderProps = HeatmapExpressionProps & {
|
|||
uiState: PersistedState;
|
||||
interactive: boolean;
|
||||
syncTooltips: boolean;
|
||||
syncCursor: boolean;
|
||||
renderComplete: IInterpreterRenderHandlers['done'];
|
||||
};
|
||||
|
|
|
@ -125,6 +125,7 @@ describe('HeatmapComponent', function () {
|
|||
formatFactory: formatService.deserialize,
|
||||
interactive: true,
|
||||
syncTooltips: false,
|
||||
syncCursor: true,
|
||||
renderComplete: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
|
|
@ -146,6 +146,7 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = memo(
|
|||
uiState,
|
||||
interactive,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
renderComplete,
|
||||
}) => {
|
||||
const chartRef = useRef<Chart>(null);
|
||||
|
@ -576,7 +577,7 @@ export const HeatmapComponent: FC<HeatmapRenderProps> = memo(
|
|||
noResults={
|
||||
<EmptyPlaceholder icon={IconChartHeatmap} renderComplete={onRenderChange} />
|
||||
}
|
||||
onPointerUpdate={handleCursorUpdate}
|
||||
onPointerUpdate={syncCursor ? handleCursorUpdate : undefined}
|
||||
externalPointerEvents={{
|
||||
tooltip: { visible: syncTooltips },
|
||||
}}
|
||||
|
|
|
@ -90,6 +90,7 @@ export const heatmapRenderer: (
|
|||
interactive={isInteractive()}
|
||||
chartsActiveCursorService={plugins.charts.activeCursor}
|
||||
syncTooltips={config.syncTooltips}
|
||||
syncCursor={config.syncCursor}
|
||||
/>
|
||||
</div>
|
||||
</KibanaThemeProvider>,
|
||||
|
|
|
@ -28,6 +28,7 @@ describe('layeredXyVis', () => {
|
|||
args: { ...rest, layers: [sampleExtendedLayer] },
|
||||
syncColors: false,
|
||||
syncTooltips: false,
|
||||
syncCursor: true,
|
||||
canNavigateToLens: false,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -64,6 +64,7 @@ export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers)
|
|||
canNavigateToLens: Boolean(handlers.variables.canNavigateToLens),
|
||||
syncColors: handlers?.isSyncColorsEnabled?.() ?? false,
|
||||
syncTooltips: handlers?.isSyncTooltipsEnabled?.() ?? false,
|
||||
syncCursor: handlers?.isSyncCursorEnabled?.() ?? true,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -41,6 +41,7 @@ describe('xyVis', () => {
|
|||
canNavigateToLens: false,
|
||||
syncColors: false,
|
||||
syncTooltips: false,
|
||||
syncCursor: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -350,6 +351,7 @@ describe('xyVis', () => {
|
|||
canNavigateToLens: false,
|
||||
syncColors: false,
|
||||
syncTooltips: false,
|
||||
syncCursor: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -139,6 +139,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => {
|
|||
canNavigateToLens: Boolean(handlers.variables.canNavigateToLens),
|
||||
syncColors: handlers?.isSyncColorsEnabled?.() ?? false,
|
||||
syncTooltips: handlers?.isSyncTooltipsEnabled?.() ?? false,
|
||||
syncCursor: handlers?.isSyncCursorEnabled?.() ?? true,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@ import { XYProps } from './expression_functions';
|
|||
export interface XYChartProps {
|
||||
args: XYProps;
|
||||
syncTooltips: boolean;
|
||||
syncCursor: boolean;
|
||||
syncColors: boolean;
|
||||
canNavigateToLens?: boolean;
|
||||
}
|
||||
|
|
|
@ -117,6 +117,7 @@ describe('XYChart component', () => {
|
|||
onSelectRange,
|
||||
syncColors: false,
|
||||
syncTooltips: false,
|
||||
syncCursor: true,
|
||||
useLegacyTimeAxis: false,
|
||||
eventAnnotationService: eventAnnotationServiceMock,
|
||||
renderComplete: jest.fn(),
|
||||
|
|
|
@ -125,6 +125,7 @@ export type XYChartRenderProps = Omit<XYChartProps, 'canNavigateToLens'> & {
|
|||
renderMode: RenderMode;
|
||||
syncColors: boolean;
|
||||
syncTooltips: boolean;
|
||||
syncCursor: boolean;
|
||||
eventAnnotationService: EventAnnotationServiceType;
|
||||
renderComplete: () => void;
|
||||
uiState?: PersistedState;
|
||||
|
@ -199,6 +200,7 @@ export function XYChart({
|
|||
interactive = true,
|
||||
syncColors,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
useLegacyTimeAxis,
|
||||
renderComplete,
|
||||
uiState,
|
||||
|
@ -753,7 +755,7 @@ export function XYChart({
|
|||
/>
|
||||
}
|
||||
onRenderChange={onRenderChange}
|
||||
onPointerUpdate={handleCursorUpdate}
|
||||
onPointerUpdate={syncCursor ? handleCursorUpdate : undefined}
|
||||
externalPointerEvents={{
|
||||
tooltip: { visible: syncTooltips, placement: Placement.Right },
|
||||
}}
|
||||
|
|
|
@ -235,6 +235,7 @@ export const getXyChartRenderer = ({
|
|||
renderMode={handlers.getRenderMode()}
|
||||
syncColors={config.syncColors}
|
||||
syncTooltips={config.syncTooltips}
|
||||
syncCursor={config.syncCursor}
|
||||
uiState={handlers.uiState as PersistedState}
|
||||
renderComplete={renderComplete}
|
||||
/>
|
||||
|
|
|
@ -18,7 +18,12 @@ describe('calculateMinInterval', () => {
|
|||
beforeEach(() => {
|
||||
const { layers, ...restArgs } = sampleArgs().args;
|
||||
|
||||
xyProps = { args: { ...restArgs, layers }, syncColors: false, syncTooltips: false };
|
||||
xyProps = {
|
||||
args: { ...restArgs, layers },
|
||||
syncColors: false,
|
||||
syncTooltips: false,
|
||||
syncCursor: true,
|
||||
};
|
||||
layer = xyProps.args.layers[0] as DataLayerConfig;
|
||||
layer.xScaleType = 'time';
|
||||
});
|
||||
|
|
|
@ -68,6 +68,7 @@ export interface InheritedChildInput extends IndexSignature {
|
|||
id: string;
|
||||
searchSessionId?: string;
|
||||
syncColors?: boolean;
|
||||
syncCursor?: boolean;
|
||||
syncTooltips?: boolean;
|
||||
executionContext?: KibanaExecutionContext;
|
||||
}
|
||||
|
@ -351,6 +352,7 @@ export class DashboardContainer extends Container<InheritedChildInput, Dashboard
|
|||
filters,
|
||||
searchSessionId,
|
||||
syncColors,
|
||||
syncCursor,
|
||||
syncTooltips,
|
||||
executionContext,
|
||||
} = this.input;
|
||||
|
@ -371,6 +373,7 @@ export class DashboardContainer extends Container<InheritedChildInput, Dashboard
|
|||
searchSessionId,
|
||||
syncColors,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
executionContext,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ export class DashboardContainerFactoryDefinition
|
|||
isFullScreenMode: false,
|
||||
useMargins: true,
|
||||
syncColors: true,
|
||||
syncCursor: true,
|
||||
syncTooltips: true,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ const getDashboardState = (state?: Partial<DashboardState>): DashboardState => {
|
|||
useMargins: true,
|
||||
syncColors: false,
|
||||
syncTooltips: false,
|
||||
syncCursor: true,
|
||||
},
|
||||
panels: {
|
||||
panel_1: {
|
||||
|
@ -99,6 +100,7 @@ describe('Dashboard state diff function', () => {
|
|||
useMargins: false,
|
||||
syncColors: false,
|
||||
syncTooltips: false,
|
||||
syncCursor: true,
|
||||
},
|
||||
})
|
||||
).toEqual(['options']);
|
||||
|
@ -111,6 +113,7 @@ describe('Dashboard state diff function', () => {
|
|||
useMargins: true,
|
||||
syncColors: undefined,
|
||||
syncTooltips: undefined,
|
||||
syncCursor: true,
|
||||
} as unknown as DashboardOptions,
|
||||
})
|
||||
).toEqual([]);
|
||||
|
|
|
@ -61,6 +61,9 @@ export const dashboardStateSlice = createSlice({
|
|||
setSyncColors: (state, action: PayloadAction<boolean>) => {
|
||||
state.options.syncColors = action.payload;
|
||||
},
|
||||
setSyncCursor: (state, action: PayloadAction<boolean>) => {
|
||||
state.options.syncCursor = action.payload;
|
||||
},
|
||||
setSyncTooltips: (state, action: PayloadAction<boolean>) => {
|
||||
state.options.syncTooltips = action.payload;
|
||||
},
|
||||
|
@ -128,6 +131,7 @@ export const {
|
|||
setTimeRange,
|
||||
setSyncColors,
|
||||
setSyncTooltips,
|
||||
setSyncCursor,
|
||||
setUseMargins,
|
||||
setViewMode,
|
||||
setFilters,
|
||||
|
|
|
@ -39,6 +39,7 @@ import {
|
|||
setStateFromSaveModal,
|
||||
setSyncColors,
|
||||
setSyncTooltips,
|
||||
setSyncCursor,
|
||||
setUseMargins,
|
||||
setViewMode,
|
||||
useDashboardDispatch,
|
||||
|
@ -402,6 +403,10 @@ export function DashboardTopNav({
|
|||
onSyncColorsChange: (isChecked: boolean) => {
|
||||
dispatchDashboardStateChange(setSyncColors(isChecked));
|
||||
},
|
||||
syncCursor: currentState.options.syncCursor ?? true,
|
||||
onSyncCursorChange: (isChecked: boolean) => {
|
||||
dispatchDashboardStateChange(setSyncCursor(isChecked));
|
||||
},
|
||||
syncTooltips: Boolean(currentState.options.syncTooltips),
|
||||
onSyncTooltipsChange: (isChecked: boolean) => {
|
||||
dispatchDashboardStateChange(setSyncTooltips(isChecked));
|
||||
|
|
|
@ -18,6 +18,8 @@ interface Props {
|
|||
onHidePanelTitlesChange: (hideTitles: boolean) => void;
|
||||
syncColors: boolean;
|
||||
onSyncColorsChange: (syncColors: boolean) => void;
|
||||
syncCursor: boolean;
|
||||
onSyncCursorChange: (syncCursor: boolean) => void;
|
||||
syncTooltips: boolean;
|
||||
onSyncTooltipsChange: (syncTooltips: boolean) => void;
|
||||
}
|
||||
|
@ -26,6 +28,7 @@ interface State {
|
|||
useMargins: boolean;
|
||||
hidePanelTitles: boolean;
|
||||
syncColors: boolean;
|
||||
syncCursor: boolean;
|
||||
syncTooltips: boolean;
|
||||
}
|
||||
|
||||
|
@ -34,6 +37,7 @@ export class OptionsMenu extends Component<Props, State> {
|
|||
useMargins: this.props.useMargins,
|
||||
hidePanelTitles: this.props.hidePanelTitles,
|
||||
syncColors: this.props.syncColors,
|
||||
syncCursor: this.props.syncCursor,
|
||||
syncTooltips: this.props.syncTooltips,
|
||||
};
|
||||
|
||||
|
@ -59,6 +63,12 @@ export class OptionsMenu extends Component<Props, State> {
|
|||
this.setState({ syncColors: isChecked });
|
||||
};
|
||||
|
||||
handleSyncCursorChange = (evt: any) => {
|
||||
const isChecked = evt.target.checked;
|
||||
this.props.onSyncCursorChange(isChecked);
|
||||
this.setState({ syncCursor: isChecked });
|
||||
};
|
||||
|
||||
handleSyncTooltipsChange = (evt: any) => {
|
||||
const isChecked = evt.target.checked;
|
||||
this.props.onSyncTooltipsChange(isChecked);
|
||||
|
@ -89,27 +99,49 @@ export class OptionsMenu extends Component<Props, State> {
|
|||
data-test-subj="dashboardPanelTitlesCheckbox"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiFormRow>
|
||||
<EuiSwitch
|
||||
label={i18n.translate('dashboard.topNav.options.syncColorsBetweenPanelsSwitchLabel', {
|
||||
defaultMessage: 'Sync color palettes across panels',
|
||||
})}
|
||||
checked={this.state.syncColors}
|
||||
onChange={this.handleSyncColorsChange}
|
||||
data-test-subj="dashboardSyncColorsCheckbox"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiFormRow>
|
||||
<EuiSwitch
|
||||
label={i18n.translate('dashboard.topNav.options.syncTooltipsBetweenPanelsSwitchLabel', {
|
||||
defaultMessage: 'Sync tooltips across panels',
|
||||
})}
|
||||
checked={this.state.syncTooltips}
|
||||
onChange={this.handleSyncTooltipsChange}
|
||||
data-test-subj="dashboardSyncTooltipsCheckbox"
|
||||
/>
|
||||
<EuiFormRow label="Sync across panels">
|
||||
<>
|
||||
<EuiFormRow>
|
||||
<EuiSwitch
|
||||
label={i18n.translate(
|
||||
'dashboard.topNav.options.syncColorsBetweenPanelsSwitchLabel',
|
||||
{
|
||||
defaultMessage: 'Sync color palettes across panels',
|
||||
}
|
||||
)}
|
||||
checked={this.state.syncColors}
|
||||
onChange={this.handleSyncColorsChange}
|
||||
data-test-subj="dashboardSyncColorsCheckbox"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow>
|
||||
<EuiSwitch
|
||||
label={i18n.translate(
|
||||
'dashboard.topNav.options.syncCursorBetweenPanelsSwitchLabel',
|
||||
{
|
||||
defaultMessage: 'Sync cursor across panels',
|
||||
}
|
||||
)}
|
||||
checked={this.state.syncCursor}
|
||||
onChange={this.handleSyncCursorChange}
|
||||
data-test-subj="dashboardSyncCursorCheckbox"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow>
|
||||
<EuiSwitch
|
||||
label={i18n.translate(
|
||||
'dashboard.topNav.options.syncTooltipsBetweenPanelsSwitchLabel',
|
||||
{
|
||||
defaultMessage: 'Sync tooltips across panels',
|
||||
}
|
||||
)}
|
||||
checked={this.state.syncTooltips}
|
||||
disabled={!Boolean(this.state.syncCursor)}
|
||||
onChange={this.handleSyncTooltipsChange}
|
||||
data-test-subj="dashboardSyncTooltipsCheckbox"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</>
|
||||
</EuiFormRow>
|
||||
</EuiForm>
|
||||
);
|
||||
|
|
|
@ -31,6 +31,8 @@ export interface ShowOptionsPopoverProps {
|
|||
onUseMarginsChange: (useMargins: boolean) => void;
|
||||
syncColors: boolean;
|
||||
onSyncColorsChange: (syncColors: boolean) => void;
|
||||
syncCursor: boolean;
|
||||
onSyncCursorChange: (syncCursor: boolean) => void;
|
||||
syncTooltips: boolean;
|
||||
onSyncTooltipsChange: (syncTooltips: boolean) => void;
|
||||
hidePanelTitles: boolean;
|
||||
|
@ -45,6 +47,8 @@ export function showOptionsPopover({
|
|||
onHidePanelTitlesChange,
|
||||
syncColors,
|
||||
onSyncColorsChange,
|
||||
syncCursor,
|
||||
onSyncCursorChange,
|
||||
syncTooltips,
|
||||
onSyncTooltipsChange,
|
||||
}: ShowOptionsPopoverProps) {
|
||||
|
@ -78,6 +82,8 @@ export function showOptionsPopover({
|
|||
onHidePanelTitlesChange={onHidePanelTitlesChange}
|
||||
syncColors={syncColors}
|
||||
onSyncColorsChange={onSyncColorsChange}
|
||||
syncCursor={syncCursor}
|
||||
onSyncCursorChange={onSyncCursorChange}
|
||||
syncTooltips={syncTooltips}
|
||||
onSyncTooltipsChange={onSyncTooltipsChange}
|
||||
/>
|
||||
|
|
|
@ -109,6 +109,7 @@ describe('ShowShareModal', () => {
|
|||
hidePanelTitles: true,
|
||||
useMargins: true,
|
||||
syncColors: true,
|
||||
syncCursor: true,
|
||||
syncTooltips: true,
|
||||
},
|
||||
filters: [
|
||||
|
|
|
@ -46,6 +46,7 @@ export const defaultDashboardState: DashboardState = {
|
|||
options: {
|
||||
useMargins: true,
|
||||
syncColors: false,
|
||||
syncCursor: true,
|
||||
syncTooltips: false,
|
||||
hidePanelTitles: false,
|
||||
},
|
||||
|
|
|
@ -71,6 +71,7 @@ export interface DashboardContainerInput extends ContainerInput {
|
|||
useMargins: boolean;
|
||||
syncColors?: boolean;
|
||||
syncTooltips?: boolean;
|
||||
syncCursor?: boolean;
|
||||
viewMode: ViewMode;
|
||||
filters: Filter[];
|
||||
title: string;
|
||||
|
@ -118,6 +119,7 @@ export type DashboardOptions = {
|
|||
hidePanelTitles: boolean;
|
||||
useMargins: boolean;
|
||||
syncColors: boolean;
|
||||
syncCursor: boolean;
|
||||
syncTooltips: boolean;
|
||||
};
|
||||
|
||||
|
|
|
@ -58,6 +58,11 @@ export type EmbeddableInput = {
|
|||
*/
|
||||
syncColors?: boolean;
|
||||
|
||||
/**
|
||||
* Flag whether cursor should be synced with other panels on hover
|
||||
*/
|
||||
syncCursor?: boolean;
|
||||
|
||||
/**
|
||||
* Flag whether tooltips should be synced with other panels on hover
|
||||
*/
|
||||
|
|
|
@ -21,6 +21,7 @@ const getGenericEmbeddableState = (state?: Partial<EmbeddableInput>): Embeddable
|
|||
enhancements: undefined,
|
||||
syncColors: false,
|
||||
syncTooltips: false,
|
||||
syncCursor: true,
|
||||
viewMode: ViewMode.VIEW,
|
||||
title: 'So Very Generic',
|
||||
id: 'soVeryGeneric',
|
||||
|
@ -46,6 +47,7 @@ test('Omitting generic embeddable input omits all generic input keys', () => {
|
|||
'enhancements',
|
||||
'syncColors',
|
||||
'syncTooltips',
|
||||
'syncCursor',
|
||||
'viewMode',
|
||||
'title',
|
||||
'id',
|
||||
|
|
|
@ -20,6 +20,7 @@ const allGenericInputKeys: Readonly<Array<keyof EmbeddableInput>> = [
|
|||
'disableTriggers',
|
||||
'enhancements',
|
||||
'syncColors',
|
||||
'syncCursor',
|
||||
'syncTooltips',
|
||||
'viewMode',
|
||||
'title',
|
||||
|
@ -32,6 +33,7 @@ const genericInputKeysToCompare = [
|
|||
'disableTriggers',
|
||||
'enhancements',
|
||||
'syncColors',
|
||||
'syncCursor',
|
||||
'syncTooltips',
|
||||
'title',
|
||||
'id',
|
||||
|
|
|
@ -40,6 +40,9 @@ export const input = createSlice({
|
|||
setSyncColors(state, action: PayloadAction<EmbeddableInput['syncColors']>) {
|
||||
state.syncColors = action.payload;
|
||||
},
|
||||
setSyncCursor(state, action: PayloadAction<EmbeddableInput['syncCursor']>) {
|
||||
state.syncCursor = action.payload;
|
||||
},
|
||||
setSyncTooltips(state, action: PayloadAction<EmbeddableInput['syncTooltips']>) {
|
||||
state.syncTooltips = action.payload;
|
||||
},
|
||||
|
|
|
@ -225,6 +225,7 @@ export class Execution<
|
|||
inspectorAdapters.tables[name] = datatable;
|
||||
},
|
||||
isSyncColorsEnabled: () => execution.params.syncColors!,
|
||||
isSyncCursorEnabled: () => execution.params.syncCursor!,
|
||||
isSyncTooltipsEnabled: () => execution.params.syncTooltips!,
|
||||
...execution.executor.context,
|
||||
getExecutionContext: () => execution.params.executionContext,
|
||||
|
|
|
@ -65,6 +65,11 @@ export interface ExecutionContext<
|
|||
*/
|
||||
isSyncColorsEnabled?: () => boolean;
|
||||
|
||||
/**
|
||||
* Returns the state (true|false) of the sync cursor across panels switch.
|
||||
*/
|
||||
isSyncCursorEnabled?: () => boolean;
|
||||
|
||||
/**
|
||||
* Returns the state (true|false) of the sync tooltips across panels switch.
|
||||
*/
|
||||
|
|
|
@ -93,6 +93,8 @@ export interface IInterpreterRenderHandlers {
|
|||
|
||||
isSyncColorsEnabled(): boolean;
|
||||
|
||||
isSyncCursorEnabled(): boolean;
|
||||
|
||||
isSyncTooltipsEnabled(): boolean;
|
||||
/**
|
||||
* This uiState interface is actually `PersistedState` from the visualizations plugin,
|
||||
|
|
|
@ -152,6 +152,8 @@ export interface ExpressionExecutionParams {
|
|||
|
||||
syncColors?: boolean;
|
||||
|
||||
syncCursor?: boolean;
|
||||
|
||||
syncTooltips?: boolean;
|
||||
|
||||
inspectorAdapters?: Adapters;
|
||||
|
|
|
@ -114,6 +114,7 @@ export class ExpressionLoader {
|
|||
renderMode: params?.renderMode,
|
||||
syncColors: params?.syncColors,
|
||||
syncTooltips: params?.syncTooltips,
|
||||
syncCursor: params?.syncCursor,
|
||||
hasCompatibleActions: params?.hasCompatibleActions,
|
||||
executionContext: params?.executionContext,
|
||||
});
|
||||
|
@ -199,6 +200,7 @@ export class ExpressionLoader {
|
|||
searchSessionId: params.searchSessionId,
|
||||
debug: params.debug,
|
||||
syncColors: params.syncColors,
|
||||
syncCursor: params?.syncCursor,
|
||||
syncTooltips: params.syncTooltips,
|
||||
executionContext: params.executionContext,
|
||||
});
|
||||
|
@ -238,6 +240,7 @@ export class ExpressionLoader {
|
|||
this.params.searchSessionId = params.searchSessionId;
|
||||
}
|
||||
this.params.syncColors = params.syncColors;
|
||||
this.params.syncCursor = params.syncCursor;
|
||||
this.params.syncTooltips = params.syncTooltips;
|
||||
this.params.debug = Boolean(params.debug);
|
||||
this.params.partial = Boolean(params.partial);
|
||||
|
|
|
@ -116,6 +116,7 @@ export function useExpressionRenderer(
|
|||
debouncedLoaderParams.renderMode,
|
||||
debouncedLoaderParams.syncColors,
|
||||
debouncedLoaderParams.syncTooltips,
|
||||
debouncedLoaderParams.syncCursor,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -30,6 +30,7 @@ export interface ExpressionRenderHandlerParams {
|
|||
onRenderError?: RenderErrorHandlerFnType;
|
||||
renderMode?: RenderMode;
|
||||
syncColors?: boolean;
|
||||
syncCursor?: boolean;
|
||||
syncTooltips?: boolean;
|
||||
interactive?: boolean;
|
||||
hasCompatibleActions?: (event: ExpressionRendererEvent) => Promise<boolean>;
|
||||
|
@ -59,6 +60,7 @@ export class ExpressionRenderHandler {
|
|||
renderMode,
|
||||
syncColors,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
interactive,
|
||||
hasCompatibleActions = async () => false,
|
||||
executionContext,
|
||||
|
@ -106,6 +108,9 @@ export class ExpressionRenderHandler {
|
|||
isSyncTooltipsEnabled: () => {
|
||||
return syncTooltips || false;
|
||||
},
|
||||
isSyncCursorEnabled: () => {
|
||||
return syncCursor || true;
|
||||
},
|
||||
isInteractive: () => {
|
||||
return interactive ?? true;
|
||||
},
|
||||
|
|
|
@ -50,6 +50,7 @@ export interface IExpressionLoaderParams {
|
|||
searchSessionId?: string;
|
||||
renderMode?: RenderMode;
|
||||
syncColors?: boolean;
|
||||
syncCursor?: boolean;
|
||||
syncTooltips?: boolean;
|
||||
hasCompatibleActions?: ExpressionRenderHandlerParams['hasCompatibleActions'];
|
||||
executionContext?: KibanaExecutionContext;
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
export const defaultHandlers: IInterpreterRenderHandlers = {
|
||||
getRenderMode: () => 'view',
|
||||
isSyncColorsEnabled: () => false,
|
||||
isSyncCursorEnabled: () => true,
|
||||
isSyncTooltipsEnabled: () => false,
|
||||
isInteractive: () => true,
|
||||
getExecutionContext: () => undefined,
|
||||
|
|
|
@ -59,6 +59,7 @@ interface TimelionVisComponentProps {
|
|||
renderComplete: IInterpreterRenderHandlers['done'];
|
||||
ariaLabel?: string;
|
||||
syncTooltips?: boolean;
|
||||
syncCursor?: boolean;
|
||||
}
|
||||
|
||||
const DefaultYAxis = () => (
|
||||
|
@ -104,6 +105,7 @@ export const TimelionVisComponent = ({
|
|||
onBrushEvent,
|
||||
ariaLabel,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
}: TimelionVisComponentProps) => {
|
||||
const kibana = useKibana<TimelionVisDependencies>();
|
||||
const chartRef = useRef<Chart>(null);
|
||||
|
@ -203,7 +205,7 @@ export const TimelionVisComponent = ({
|
|||
showLegendExtra={true}
|
||||
legendPosition={legend.legendPosition}
|
||||
onRenderChange={onRenderChange}
|
||||
onPointerUpdate={handleCursorUpdate}
|
||||
onPointerUpdate={syncCursor ? handleCursorUpdate : undefined}
|
||||
externalPointerEvents={{
|
||||
tooltip: { visible: syncTooltips, placement: Placement.Right },
|
||||
}}
|
||||
|
|
|
@ -22,6 +22,7 @@ export interface TimelionRenderValue {
|
|||
visType: 'timelion';
|
||||
visParams: TimelionVisParams;
|
||||
syncTooltips: boolean;
|
||||
syncCursor: boolean;
|
||||
}
|
||||
|
||||
export interface TimelionVisParams {
|
||||
|
@ -75,6 +76,7 @@ export const getTimelionVisualizationConfig = (
|
|||
variables,
|
||||
abortSignal: expressionAbortSignal,
|
||||
isSyncTooltipsEnabled,
|
||||
isSyncCursorEnabled,
|
||||
}
|
||||
) {
|
||||
const { getTimelionRequestHandler } = await import('./async_services');
|
||||
|
@ -114,6 +116,7 @@ export const getTimelionVisualizationConfig = (
|
|||
visType: TIMELION_VIS_NAME,
|
||||
visData,
|
||||
syncTooltips: isSyncTooltipsEnabled?.() ?? false,
|
||||
syncCursor: isSyncTooltipsEnabled?.() ?? true,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
|
|
@ -43,7 +43,7 @@ export const getTimelionVisRenderer: (
|
|||
name: 'timelion_vis',
|
||||
displayName: 'Timelion visualization',
|
||||
reuseDomNode: true,
|
||||
render: (domNode, { visData, visParams, syncTooltips }, handlers) => {
|
||||
render: (domNode, { visData, visParams, syncTooltips, syncCursor }, handlers) => {
|
||||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
|
@ -99,6 +99,7 @@ export const getTimelionVisRenderer: (
|
|||
renderComplete={renderComplete}
|
||||
onBrushEvent={onBrushEvent}
|
||||
syncTooltips={syncTooltips}
|
||||
syncCursor={syncCursor}
|
||||
/>
|
||||
)}
|
||||
</KibanaContextProvider>
|
||||
|
|
|
@ -37,6 +37,7 @@ interface TimeseriesVisualizationProps {
|
|||
visData: TimeseriesVisData;
|
||||
uiState: PersistedState;
|
||||
syncColors: boolean;
|
||||
syncCursor: boolean;
|
||||
syncTooltips: boolean;
|
||||
initialRender: () => void;
|
||||
}
|
||||
|
@ -48,6 +49,7 @@ function TimeseriesVisualization({
|
|||
uiState,
|
||||
getConfig,
|
||||
syncColors,
|
||||
syncCursor,
|
||||
syncTooltips,
|
||||
initialRender,
|
||||
}: TimeseriesVisualizationProps) {
|
||||
|
@ -194,6 +196,7 @@ function TimeseriesVisualization({
|
|||
onUiState={handleUiState}
|
||||
syncColors={syncColors}
|
||||
syncTooltips={syncTooltips}
|
||||
syncCursor={syncCursor}
|
||||
palettesService={palettesService}
|
||||
indexPattern={indexPattern}
|
||||
fieldFormatMap={indexPattern?.fieldFormatMap}
|
||||
|
|
|
@ -64,6 +64,7 @@ export interface TimeseriesVisProps {
|
|||
getConfig: IUiSettingsClient['get'];
|
||||
syncColors: boolean;
|
||||
syncTooltips: boolean;
|
||||
syncCursor: boolean;
|
||||
palettesService: PaletteRegistry;
|
||||
indexPattern?: FetchedIndexPattern['indexPattern'];
|
||||
/** @deprecated please use indexPattern.fieldFormatMap instead **/
|
||||
|
|
|
@ -163,6 +163,7 @@ class TimeseriesVisualization extends Component {
|
|||
onFilterClick,
|
||||
syncColors,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
palettesService,
|
||||
fieldFormatMap,
|
||||
getConfig,
|
||||
|
@ -275,6 +276,7 @@ class TimeseriesVisualization extends Component {
|
|||
annotations={this.prepareAnnotations()}
|
||||
syncColors={syncColors}
|
||||
syncTooltips={syncTooltips}
|
||||
syncCursor={syncCursor}
|
||||
palettesService={palettesService}
|
||||
interval={interval}
|
||||
initialRender={initialRender}
|
||||
|
|
|
@ -73,6 +73,7 @@ export const TimeSeries = ({
|
|||
annotations,
|
||||
syncColors,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
palettesService,
|
||||
interval,
|
||||
isLastBucketDropped,
|
||||
|
@ -179,7 +180,7 @@ export const TimeSeries = ({
|
|||
onBrushEnd={onBrushEndListener}
|
||||
onElementClick={(args) => handleElementClick(args)}
|
||||
animateData={false}
|
||||
onPointerUpdate={handleCursorUpdate}
|
||||
onPointerUpdate={syncCursor ? handleCursorUpdate : undefined}
|
||||
pointerUpdateDebounce={0}
|
||||
theme={[
|
||||
{
|
||||
|
|
|
@ -26,6 +26,7 @@ export interface TimeseriesRenderValue {
|
|||
visData: TimeseriesVisData | {};
|
||||
visParams: TimeseriesVisParams;
|
||||
syncColors: boolean;
|
||||
syncCursor: boolean;
|
||||
syncTooltips: boolean;
|
||||
canNavigateToLens?: boolean;
|
||||
}
|
||||
|
@ -63,6 +64,7 @@ export const createMetricsFn = (): TimeseriesExpressionFunctionDefinition => ({
|
|||
getSearchSessionId,
|
||||
isSyncColorsEnabled,
|
||||
isSyncTooltipsEnabled,
|
||||
isSyncCursorEnabled,
|
||||
getExecutionContext,
|
||||
inspectorAdapters,
|
||||
abortSignal: expressionAbortSignal,
|
||||
|
@ -73,6 +75,7 @@ export const createMetricsFn = (): TimeseriesExpressionFunctionDefinition => ({
|
|||
const uiState = JSON.parse(args.uiState);
|
||||
const syncColors = isSyncColorsEnabled?.() ?? false;
|
||||
const syncTooltips = isSyncTooltipsEnabled?.() ?? false;
|
||||
const syncCursor = isSyncCursorEnabled?.() ?? true;
|
||||
|
||||
const response = await metricsRequestHandler({
|
||||
input,
|
||||
|
@ -92,6 +95,7 @@ export const createMetricsFn = (): TimeseriesExpressionFunctionDefinition => ({
|
|||
visData: response,
|
||||
syncColors,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
canNavigateToLens: variables.canNavigateToLens as boolean,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -62,7 +62,14 @@ export const getTimeseriesVisRenderer: (deps: {
|
|||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
const { visParams: model, visData, syncColors, syncTooltips, canNavigateToLens } = config;
|
||||
const {
|
||||
visParams: model,
|
||||
visData,
|
||||
syncColors,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
canNavigateToLens,
|
||||
} = config;
|
||||
const showNoResult = !checkIfDataExists(visData, model);
|
||||
|
||||
const renderComplete = () => {
|
||||
|
@ -106,6 +113,7 @@ export const getTimeseriesVisRenderer: (deps: {
|
|||
visData={visData as TimeseriesVisData}
|
||||
syncColors={syncColors}
|
||||
syncTooltips={syncTooltips}
|
||||
syncCursor={syncCursor}
|
||||
uiState={handlers.uiState! as PersistedState}
|
||||
initialRender={renderComplete}
|
||||
/>
|
||||
|
|
|
@ -110,6 +110,7 @@ export class VisualizeEmbeddable
|
|||
private searchSessionId?: string;
|
||||
private syncColors?: boolean;
|
||||
private syncTooltips?: boolean;
|
||||
private syncCursor?: boolean;
|
||||
private embeddableTitle?: string;
|
||||
private visCustomizations?: Pick<VisualizeInput, 'vis' | 'table'>;
|
||||
private subscriptions: Subscription[] = [];
|
||||
|
@ -154,6 +155,7 @@ export class VisualizeEmbeddable
|
|||
this.timefilter = timefilter;
|
||||
this.syncColors = this.input.syncColors;
|
||||
this.syncTooltips = this.input.syncTooltips;
|
||||
this.syncCursor = this.input.syncCursor;
|
||||
this.searchSessionId = this.input.searchSessionId;
|
||||
this.query = this.input.query;
|
||||
this.embeddableTitle = this.getTitle();
|
||||
|
@ -322,6 +324,11 @@ export class VisualizeEmbeddable
|
|||
dirty = true;
|
||||
}
|
||||
|
||||
if (this.syncCursor !== this.input.syncCursor) {
|
||||
this.syncCursor = this.input.syncCursor;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (this.embeddableTitle !== this.getTitle()) {
|
||||
this.embeddableTitle = this.getTitle();
|
||||
dirty = true;
|
||||
|
@ -574,6 +581,7 @@ export class VisualizeEmbeddable
|
|||
searchSessionId: this.input.searchSessionId,
|
||||
syncColors: this.input.syncColors,
|
||||
syncTooltips: this.input.syncTooltips,
|
||||
syncCursor: this.input.syncCursor,
|
||||
uiState: this.vis.uiState,
|
||||
interactive: !this.input.disableTriggers,
|
||||
inspectorAdapters: this.inspectorAdapters,
|
||||
|
|
|
@ -15,6 +15,7 @@ export const defaultHandlers: RendererHandlers = {
|
|||
getFilter: () => 'filter',
|
||||
getRenderMode: () => 'view',
|
||||
isSyncColorsEnabled: () => false,
|
||||
isSyncCursorEnabled: () => true,
|
||||
isSyncTooltipsEnabled: () => false,
|
||||
isInteractive: () => true,
|
||||
onComplete: (fn) => undefined,
|
||||
|
|
|
@ -28,6 +28,7 @@ export const createBaseHandlers = (): IInterpreterRenderHandlers => ({
|
|||
getRenderMode: () => 'view',
|
||||
isSyncColorsEnabled: () => false,
|
||||
isSyncTooltipsEnabled: () => false,
|
||||
isSyncCursorEnabled: () => true,
|
||||
isInteractive: () => true,
|
||||
getExecutionContext: () => undefined,
|
||||
});
|
||||
|
|
|
@ -677,6 +677,7 @@ export class Embeddable
|
|||
renderMode={input.renderMode}
|
||||
syncColors={input.syncColors}
|
||||
syncTooltips={input.syncTooltips}
|
||||
syncCursor={input.syncCursor}
|
||||
hasCompatibleActions={this.hasCompatibleActions}
|
||||
className={input.className}
|
||||
style={input.style}
|
||||
|
|
|
@ -39,6 +39,7 @@ export interface ExpressionWrapperProps {
|
|||
renderMode?: RenderMode;
|
||||
syncColors?: boolean;
|
||||
syncTooltips?: boolean;
|
||||
syncCursor?: boolean;
|
||||
hasCompatibleActions?: ReactExpressionRendererProps['hasCompatibleActions'];
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
|
@ -113,6 +114,7 @@ export function ExpressionWrapper({
|
|||
renderMode,
|
||||
syncColors,
|
||||
syncTooltips,
|
||||
syncCursor,
|
||||
hasCompatibleActions,
|
||||
style,
|
||||
className,
|
||||
|
@ -143,6 +145,7 @@ export function ExpressionWrapper({
|
|||
renderMode={renderMode}
|
||||
syncColors={syncColors}
|
||||
syncTooltips={syncTooltips}
|
||||
syncCursor={syncCursor}
|
||||
executionContext={executionContext}
|
||||
renderError={(errorMessage, error) => {
|
||||
onRuntimeError();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue