Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ export const FlyoutWrapper = ({
</EuiText>
</EuiFlexItem>
)}
{toolbar && <EuiFlexItem grow={false}>{toolbar}</EuiFlexItem>}
{toolbar && (
<EuiFlexItem grow={false} data-test-subj="lnsVisualizationToolbar">
{toolbar}
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiFlyoutHeader>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { LayerConfiguration } from './layer_configuration_section';
import type { EditConfigPanelProps } from './types';
import { FlyoutWrapper } from './flyout_wrapper';
import { SuggestionPanel } from '../../../editor_frame_service/editor_frame/suggestion_panel';
import { VisualizationToolbarWrapper } from '../../../editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper';
import { VisualizationToolbarWrapper } from '../../../editor_frame_service/editor_frame/visualization_toolbar';
import { useEditorFrameService } from '../../../editor_frame_service/editor_frame_service_context';
import { useApplicationUserMessages } from '../../get_application_user_messages';
import { trackSaveUiCounterEvents } from '../../../lens_ui_telemetry';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ describe('editor_frame', () => {
let datasourceMap: DatasourceMap;

beforeEach(() => {
mockVisualization = createMockVisualization();
mockVisualization = {
...createMockVisualization(),
ToolbarComponent: jest.fn(() => <div />),
};

mockVisualization2 = createMockVisualization('testVis2', ['second']);

mockDatasource = createMockDatasource();
Expand Down Expand Up @@ -156,12 +160,15 @@ describe('editor_frame', () => {
const queryWorkspacePanel = () => screen.queryByTestId('lnsWorkspace');
const queryDataPanel = () => screen.queryByTestId('lnsDataPanelWrapper');

const queryVisualizationToolbar = () => screen.queryByTestId('lnsVisualizationToolbar');

return {
...rtlRender,
store,
queryLayerPanel,
queryWorkspacePanel,
queryDataPanel,
queryVisualizationToolbar,
simulateLoadingDatasource: () =>
store.dispatch(
setState({
Expand All @@ -180,24 +187,31 @@ describe('editor_frame', () => {

describe('initialization', () => {
it('should render workspace panel, data panel and layer panel when all datasources are initialized', async () => {
const { queryWorkspacePanel, queryDataPanel, queryLayerPanel, simulateLoadingDatasource } =
renderEditorFrame(undefined, {
preloadedStateOverrides: {
datasourceStates: {
testDatasource: {
isLoading: true,
state: {
internalState: 'datasourceState',
},
const {
queryWorkspacePanel,
queryDataPanel,
queryLayerPanel,
queryVisualizationToolbar,
simulateLoadingDatasource,
} = renderEditorFrame(undefined, {
preloadedStateOverrides: {
datasourceStates: {
testDatasource: {
isLoading: true,
state: {
internalState: 'datasourceState',
},
},
},
});
},
});

expect(mockVisualization.getConfiguration).not.toHaveBeenCalled();

expect(queryWorkspacePanel()).not.toBeInTheDocument();
expect(queryDataPanel()).not.toBeInTheDocument();
expect(queryLayerPanel()).not.toBeInTheDocument();
expect(queryVisualizationToolbar()).not.toBeInTheDocument();

act(() => {
simulateLoadingDatasource();
Expand All @@ -210,7 +224,9 @@ describe('editor_frame', () => {
expect(queryWorkspacePanel()).toBeInTheDocument();
expect(queryDataPanel()).toBeInTheDocument();
expect(queryLayerPanel()).toBeInTheDocument();
expect(queryVisualizationToolbar()).toBeInTheDocument();
});

it('should render the resulting expression using the expression renderer', async () => {
renderEditorFrame();
expect(screen.getByTestId('lnsExpressionRenderer')).toHaveTextContent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import type {
AddUserMessages,
LensInspector,
} from '@kbn/lens-common';
import type { UseEuiTheme } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { css } from '@emotion/react';
import { useMemoCss } from '@kbn/css-utils/public/use_memo_css';
import { getAbsoluteDateRange } from '../../utils';
import { trackUiCounterEvents } from '../../lens_ui_telemetry';
import { DataPanelWrapper } from './data_panel_wrapper';
Expand All @@ -40,6 +44,7 @@ import { ErrorBoundary, showMemoizedErrorNotification } from '../../lens_ui_erro
import type { IndexPatternServiceAPI } from '../../data_views_service/service';
import { getLongMessage } from '../../user_messages_utils';
import { useEditorFrameService } from '../editor_frame_service_context';
import { VisualizationToolbarWrapper } from './visualization_toolbar';

export interface EditorFrameProps {
ExpressionRenderer: ReactExpressionRendererType;
Expand All @@ -59,6 +64,9 @@ export function EditorFrame(props: EditorFrameProps) {
const datasourceStates = useLensSelector(selectDatasourceStates);
const visualization = useLensSelector(selectVisualization);
const areDatasourcesLoaded = useLensSelector(selectAreDatasourcesLoaded);

const styles = useMemoCss(componentStyles);

const isVisualizationLoaded = !!visualization.state;
const visualizationTypeIsKnown = Boolean(
visualization.activeId && visualizationMap[visualization.activeId]
Expand Down Expand Up @@ -147,15 +155,27 @@ export function EditorFrame(props: EditorFrameProps) {
configPanel={
areDatasourcesLoaded && (
<ErrorBoundary onError={onError}>
<ConfigPanelWrapper
core={props.core}
framePublicAPI={framePublicAPI}
uiActions={props.plugins.uiActions}
dataViews={props.plugins.dataViews}
data={props.plugins.data}
indexPatternService={props.indexPatternService}
getUserMessages={props.getUserMessages}
/>
<>
<EuiFlexGroup
css={styles.visualizationToolbar}
justifyContent="flexEnd"
responsive={false}
wrap={true}
>
<EuiFlexItem grow={false} data-test-subj="lnsVisualizationToolbar">
<VisualizationToolbarWrapper framePublicAPI={framePublicAPI} />
</EuiFlexItem>
</EuiFlexGroup>
<ConfigPanelWrapper
core={props.core}
framePublicAPI={framePublicAPI}
uiActions={props.plugins.uiActions}
dataViews={props.plugins.dataViews}
data={props.plugins.data}
indexPatternService={props.indexPatternService}
getUserMessages={props.getUserMessages}
/>
</>
</ErrorBoundary>
)
}
Expand Down Expand Up @@ -195,3 +215,8 @@ export function EditorFrame(props: EditorFrameProps) {
</RootDragDropProvider>
);
}

const componentStyles = {
visualizationToolbar: ({ euiTheme }: UseEuiTheme) =>
css({ margin: `${euiTheme.size.base} ${euiTheme.size.base} 0 ${euiTheme.size.base}` }),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React, { memo, useCallback } from 'react';
import type { FramePublicAPI, Visualization } from '@kbn/lens-common';
import {
useLensDispatch,
updateVisualizationState,
useLensSelector,
selectVisualizationState,
selectVisualization,
} from '../../state_management';
import { useEditorFrameService } from '../editor_frame_service_context';

const VisualizationToolbar = memo(function VisualizationToolbar({
activeVisualization,
framePublicAPI,
enableFlyoutToolbar = false,
}: {
activeVisualization: Visualization | null;
framePublicAPI: FramePublicAPI;
enableFlyoutToolbar?: boolean;
}) {
const dispatchLens = useLensDispatch();
const visualization = useLensSelector(selectVisualizationState);
const setVisualizationState = useCallback(
(newState: unknown) => {
if (!activeVisualization) {
return;
}
dispatchLens(
updateVisualizationState({
visualizationId: activeVisualization.id,
newState,
})
);
},
[dispatchLens, activeVisualization]
);

const { FlyoutToolbarComponent, ToolbarComponent: RegularToolbarComponent } =
activeVisualization ?? {};

let ToolbarComponent;
if (enableFlyoutToolbar) {
ToolbarComponent = FlyoutToolbarComponent ?? RegularToolbarComponent;
} else {
ToolbarComponent = RegularToolbarComponent;
}

if (!ToolbarComponent) {
return null;
}

return ToolbarComponent({
frame: framePublicAPI,
state: visualization.state,
setState: setVisualizationState,
});
});

export function VisualizationToolbarWrapper({
framePublicAPI,
}: {
framePublicAPI: FramePublicAPI;
}) {
const { visualizationMap } = useEditorFrameService();
const visualization = useLensSelector(selectVisualization);

const activeVisualization = visualization.activeId
? visualizationMap[visualization.activeId]
: null;

return activeVisualization && visualization.state ? (
<VisualizationToolbar
framePublicAPI={framePublicAPI}
activeVisualization={activeVisualization}
/>
) : null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@
*/

export { WorkspacePanel } from './workspace_panel';
export { VisualizationToolbar } from './workspace_panel_wrapper';
Original file line number Diff line number Diff line change
Expand Up @@ -678,11 +678,7 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({

return (
<WorkspacePanelWrapper
framePublicAPI={framePublicAPI}
visualizationId={visualization.activeId}
datasourceStates={datasourceStates}
isFullscreen={isFullscreen}
lensInspector={lensInspector}
getUserMessages={getUserMessages}
displayOptions={chartSizeSpec}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@
*/

import React from 'react';
import type { Visualization, LensInspector, LensAppState } from '@kbn/lens-common';
import type { FrameMock } from '../../../mocks';
import {
createMockVisualization,
createMockFramePublicAPI,
renderWithReduxStore,
} from '../../../mocks';
import type { Visualization, LensAppState } from '@kbn/lens-common';
import { createMockVisualization, renderWithReduxStore } from '../../../mocks';
import { WorkspacePanelWrapper } from './workspace_panel_wrapper';
import { updateVisualizationState } from '../../../state_management';
import { setChangesApplied } from '../../../state_management/lens_slice';
Expand All @@ -24,8 +19,6 @@ import { EditorFrameServiceProvider } from '../../editor_frame_service_context';

describe('workspace_panel_wrapper', () => {
let mockVisualization: jest.Mocked<Visualization>;
let mockFrameAPI: FrameMock;
const ToolbarComponentMock = jest.fn(() => null);

const renderWorkspacePanelWrapper = (
propsOverrides = {},
Expand All @@ -34,16 +27,12 @@ describe('workspace_panel_wrapper', () => {
const { store, ...rtlRender } = renderWithReduxStore(
<EditorFrameServiceProvider
visualizationMap={{
myVis: { ...mockVisualization, ToolbarComponent: ToolbarComponentMock },
myVis: { ...mockVisualization },
}}
datasourceMap={{}}
>
<WorkspacePanelWrapper
framePublicAPI={mockFrameAPI}
visualizationId="myVis"
datasourceStates={{}}
isFullscreen={false}
lensInspector={{} as unknown as LensInspector}
getUserMessages={() => []}
children={<span />}
displayOptions={undefined}
Expand Down Expand Up @@ -95,8 +84,6 @@ describe('workspace_panel_wrapper', () => {

beforeEach(() => {
mockVisualization = createMockVisualization();
mockFrameAPI = createMockFramePublicAPI();
ToolbarComponentMock.mockClear();
});

it('should render its children', async () => {
Expand All @@ -105,25 +92,6 @@ describe('workspace_panel_wrapper', () => {
expect(screen.getByText(customElementText)).toBeInTheDocument();
});

it('should call the toolbar renderer if provided', async () => {
const visState = { internalState: 123 };
renderWorkspacePanelWrapper(
{},
{
preloadedState: {
visualization: { activeId: 'myVis', state: visState },
datasourceStates: {},
},
}
);

expect(ToolbarComponentMock).toHaveBeenCalledWith({
state: visState,
frame: mockFrameAPI,
setState: expect.anything(),
});
});

describe('auto-apply controls', () => {
it('shows and hides apply-changes button depending on whether auto-apply is enabled', async () => {
const { toggleAutoApply, getApplyChangesToolbar } = renderWorkspacePanelWrapper();
Expand All @@ -146,14 +114,14 @@ describe('workspace_panel_wrapper', () => {
editVisualization();
});

// // simulate workspace panel behavior
// simulate workspace panel behavior
act(() => {
store.dispatch(setChangesApplied(false));
});

expect(getApplyChangesToolbar()).not.toBeDisabled();

// // simulate workspace panel behavior
// simulate workspace panel behavior
act(() => {
store.dispatch(setChangesApplied(true));
});
Expand Down
Loading