diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx index 4868c21bc5c5a..95eacf3483d62 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx @@ -200,7 +200,7 @@ export function ChartSwitch(props: Props) { > ( {i18n.translate('xpack.lens.configPanel.changeVisualization', { - defaultMessage: 'Change', + defaultMessage: 'change', })} ) diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx index 7d9ff8918ab29..716ea75e39824 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx @@ -17,6 +17,7 @@ import { DatasourceMock, } from '../mocks'; import { ExpressionRenderer } from 'src/legacy/core_plugins/data/public'; +import { EuiPanel, EuiToolTip } from '@elastic/eui'; // calling this function will wait for all pending Promises from mock // datasources to be processed by its callers. @@ -1119,13 +1120,12 @@ describe('editor_frame', () => { // TODO why is this necessary? instance.update(); - const suggestions = instance.find('[data-test-subj="suggestion-title"]'); - expect(suggestions.map(el => el.text())).toEqual([ - 'Suggestion1', - 'Suggestion2', - 'Suggestion3', - 'Suggestion4', - ]); + expect( + instance + .find('[data-test-subj="lnsSuggestion"]') + .find(EuiPanel) + .map(el => el.parents(EuiToolTip).prop('content')) + ).toEqual(['Suggestion1', 'Suggestion2', 'Suggestion3', 'Suggestion4']); }); it('should switch to suggested visualization', async () => { @@ -1167,7 +1167,10 @@ describe('editor_frame', () => { instance.update(); act(() => { - instance.find('[data-test-subj="suggestion-title"]').simulate('click'); + instance + .find('[data-test-subj="lnsSuggestion"]') + .first() + .simulate('click'); }); expect(mockVisualization.renderConfigPanel).toHaveBeenCalledTimes(1); diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/frame_layout.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/frame_layout.tsx index c630bc96704f3..8a33178de70cf 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/frame_layout.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/frame_layout.tsx @@ -23,10 +23,10 @@ export function FrameLayout(props: FrameLayoutProps) { {props.dataPanel} {props.workspacePanel} + {props.suggestionsPanel} {props.configPanel} - {props.suggestionsPanel} diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/index.scss b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/index.scss index ba6ae3bf71bd7..72b5f1eb79638 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/index.scss +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/index.scss @@ -1,3 +1,4 @@ +$lnsPanelMinWidth: $euiSize * 18; .lnsPage { padding: 0; @@ -24,7 +25,7 @@ .lnsSidebar { margin: 0; flex: 1 0 18%; - min-width: ($euiSize * 22); + min-width: $lnsPanelMinWidth + $euiSize; display: flex; flex-direction: column; position: relative; @@ -45,10 +46,13 @@ } .lnsSidebar--right { - min-width: ($euiSize * 22); @include euiScrollBar; - overflow: hidden auto; - padding: $euiSize; + min-width: $lnsPanelMinWidth + $euiSize; + overflow-x: hidden; + overflow-y: auto; + padding-top: $euiSize; + padding-right: $euiSize; + max-height: 100%; } .lnsSidebarContainer { @@ -64,31 +68,37 @@ .lnsPageBody { @include euiScrollBar; - padding-top: $euiSize; - padding-bottom: $euiSize; - overflow: hidden auto; + min-width: $lnsPanelMinWidth + $euiSizeXL; + overflow: hidden; + // Leave out bottom padding so the suggestions scrollbar stays flush to window edge + // This also means needing to add same amount of margin to page content and suggestion items + padding: $euiSize $euiSize 0; &:first-child { padding-left: $euiSize; } .lnsPageContent { + @include euiScrollBar; + overflow: hidden; padding: 0; + margin-bottom: $euiSize; display: flex; flex-direction: column; .lnsPageContentHeader { - padding: $euiSize; + padding: $euiSizeS; border-bottom: $euiBorderThin; margin-bottom: 0; } .lnsPageContentBody { + @include euiScrollBar; flex-grow: 1; - padding: $euiSizeXL; display: flex; align-items: stretch; justify-content: stretch; + overflow: auto; > * { flex: 1 1 100%; @@ -108,6 +118,7 @@ align-items: center; justify-content: center; overflow-x: hidden; + padding: $euiSize; } .lnsTitleInput { diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.scss b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.scss index 2139b314ae314..add9df3f10dbd 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.scss +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.scss @@ -1,21 +1,59 @@ -.lnsSidebar__suggestions { - > * { - margin-top: $euiSizeS; + // SASSTODO: Create this in EUI + @mixin lnsOverflowShadowHorizontal { + $hideHeight: $euiScrollBarCorner * 1.25; + mask-image: linear-gradient(to right, + transparentize(red, .9) 0%, + transparentize(red, 0) $hideHeight, + transparentize(red, 0) calc(100% - #{$hideHeight}), + transparentize(red, .9) 100% + ); +} + +.lnsSuggestionsPanel__title { + margin: $euiSizeS 0 $euiSizeXS; +} + +.lnsSuggestionsPanel__suggestions { + @include euiScrollBar; + @include lnsOverflowShadowHorizontal; + padding-top: $euiSizeXS; + overflow-x: auto; + overflow-y: hidden; + display: flex; + + // Padding / negative margins to make room for overflow shadow + padding-left: $euiSizeXS; + margin-left: -$euiSizeXS; + + // Add margin to the next of the same type + > * + * { + margin-left: $euiSizeS; } } -$suggestionHeight: 120px; +// These sizes also match canvas' page thumbnails for consistency +$lnsSuggestionHeight: 100px; +$lnsSuggestionWidth: 150px; + +.lnsSuggestionPanel__button { + flex: 0 0 auto; + width: $lnsSuggestionWidth !important; + height: $lnsSuggestionHeight; + // Allows the scrollbar to stay flush to window + margin-bottom: $euiSize; +} .lnsSidebar__suggestionIcon { + color: $euiColorDarkShade; width: 100%; - height: $suggestionHeight; + height: 100%; display: flex; align-items: center; justify-content: center; - padding: $euiSize; + padding: $euiSizeS; } - .lnsSuggestionChartWrapper { - height: $suggestionHeight; - pointer-events: none; - } \ No newline at end of file +.lnsSuggestionChartWrapper { + height: $lnsSuggestionHeight - $euiSize; + pointer-events: none; +} diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx index effadb27ddb43..d2f3b8e895aa6 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.test.tsx @@ -17,7 +17,7 @@ import { ExpressionRenderer } from 'src/legacy/core_plugins/data/public'; import { SuggestionPanel, SuggestionPanelProps } from './suggestion_panel'; import { getSuggestions, Suggestion } from './suggestion_helpers'; import { fromExpression } from '@kbn/interpreter/target/common'; -import { EuiIcon } from '@elastic/eui'; +import { EuiIcon, EuiPanel, EuiToolTip } from '@elastic/eui'; jest.mock('./suggestion_helpers'); @@ -82,17 +82,19 @@ describe('suggestion_panel', () => { it('should list passed in suggestions', () => { const wrapper = mount(); - expect(wrapper.find('[data-test-subj="suggestion-title"]').map(el => el.text())).toEqual([ - 'Suggestion1', - 'Suggestion2', - ]); + expect( + wrapper + .find('[data-test-subj="lnsSuggestion"]') + .find(EuiPanel) + .map(el => el.parents(EuiToolTip).prop('content')) + ).toEqual(['Suggestion1', 'Suggestion2']); }); it('should dispatch visualization switch action if suggestion is clicked', () => { const wrapper = mount(); wrapper - .find('[data-test-subj="suggestion-title"]') + .find('[data-test-subj="lnsSuggestion"]') .first() .simulate('click'); diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx index 1ee732df85908..aad24b4c3b9cd 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx @@ -6,7 +6,7 @@ import React, { useState, useEffect } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiIcon, EuiTitle, EuiPanel, EuiIconTip } from '@elastic/eui'; +import { EuiIcon, EuiTitle, EuiPanel, EuiIconTip, EuiToolTip } from '@elastic/eui'; import { toExpression } from '@kbn/interpreter/common'; import { i18n } from '@kbn/i18n'; import { Action } from './state_management'; @@ -51,46 +51,46 @@ const SuggestionPreview = ({ }, [previewExpression]); return ( - { - dispatch(toSwitchAction(suggestion)); - }} - > - -

{suggestion.title}

-
- {expressionError ? ( -
- + { + dispatch(toSwitchAction(suggestion)); + }} + > + {expressionError ? ( +
+ +
+ ) : previewExpression ? ( + { + // eslint-disable-next-line no-console + console.error(`Failed to render preview: `, e); + setExpressionError(true); + }} /> -
- ) : previewExpression ? ( - { - // eslint-disable-next-line no-console - console.error(`Failed to render preview: `, e); - setExpressionError(true); - }} - /> - ) : ( -
- -
- )} -
+ ) : ( +
+ +
+ )} + + ); }; @@ -125,8 +125,8 @@ function InnerSuggestionPanel({ } return ( -
- +
+

- {suggestions.map(suggestion => { - const previewExpression = suggestion.previewExpression - ? prependDatasourceExpression( - suggestion.previewExpression, - datasourceMap, - datasourceStates - ) - : null; - return ( - - ); - })} +
+ {suggestions.map(suggestion => { + const previewExpression = suggestion.previewExpression + ? prependDatasourceExpression( + suggestion.previewExpression, + datasourceMap, + datasourceStates + ) + : null; + return ( + + ); + })} +
); } diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx index 07b48c0479b46..8451704f455f5 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx @@ -124,7 +124,12 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ if (Object.keys(indexPatterns).length === 0) { return ( - + - +
{!showIndexPatternSwitcher ? ( @@ -232,7 +242,11 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
- +