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

[Do not merge][POC] Analyzer in flyout POC #183094

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 240 additions & 0 deletions packages/kbn-expandable-flyout/src/components/content.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import React, { memo, useCallback, useEffect, useMemo } from 'react';
import { Interpolation, Theme } from '@emotion/react';
import { EuiFlyoutProps, EuiFlyoutResizable } from '@elastic/eui';
import { EuiFlyoutResizableProps } from '@elastic/eui/src/components/flyout/flyout_resizable';
import { useExpandableFlyoutContext } from '../context';
import { changeCollapsedWidthAction, changeExpandedWidthAction } from '../store/actions';
import {
selectDefaultWidths,
selectPushVsOverlayById,
selectWidthsById,
useDispatch,
useSelector,
} from '../store/redux';
import { RightSection } from './right_section';
import { useSections } from '../hooks/use_sections';
import { useExpandableFlyoutState } from '../hooks/use_expandable_flyout_state';
import { useExpandableFlyoutApi } from '../hooks/use_expandable_flyout_api';
import type { FlyoutPanelProps, Panel } from '../types';
import { SettingsMenu } from './settings_menu';
import { PreviewSection } from './preview_section';
import { ResizableContainer } from './resizable_container';

const COLLAPSED_FLYOUT_MIN_WIDTH = 380;
const EXPANDED_FLYOUT_MIN_WIDTH = 740;

export interface ContentProps extends Omit<EuiFlyoutResizableProps, 'onClose'> {
/**
* List of all registered panels available for render
*/
registeredPanels: Panel[];
/**
* Allows for custom styles to be passed to the EuiFlyout component
*/
customStyles?: Interpolation<Theme>;
/**
* Callback function to let application's code the flyout is closed
*/
onClose?: EuiFlyoutProps['onClose'];
/**
* Set of properties that drive a settings menu
*/
flyoutCustomProps?: {
/**
* Hide the gear icon and settings menu if true
*/
hideSettings?: boolean;
/**
* Control if the option to render in overlay or push mode is enabled or not
*/
pushVsOverlay?: {
/**
* Disables the option
*/
disabled: boolean;
/**
* Tooltip to display
*/
tooltip: string;
};
/**
* Control if the option to resize the flyout is enabled or not
*/
resize?: {
/**
* Disables the option
*/
disabled: boolean;
/**
* Tooltip to display
*/
tooltip: string;
};
};
}

/**
* Expandable flyout UI React component.
* Displays 3 sections (right, left, preview) depending on the panels in the context.
*
* The behavior expects that the left and preview sections should only be displayed is a right section
* is already rendered.
*/
export const Content: React.FC<ContentProps> = memo(
({ customStyles, registeredPanels, flyoutCustomProps, ...flyoutProps }) => {
console.log('render - Content');

const dispatch = useDispatch();

const { left, right, preview } = useExpandableFlyoutState();
const { urlKey } = useExpandableFlyoutContext();
const { closeFlyout } = useExpandableFlyoutApi();

const flyoutType = useSelector(selectPushVsOverlayById(urlKey));
const flyoutWidths = useSelector(selectWidthsById(urlKey));
const defaultWidths = useSelector(selectDefaultWidths);

// retrieves the sections to be displayed
const { leftSection, rightSection, previewSection, mostRecentPreview, previewBanner } =
useSections({
registeredPanels,
});

// calculates what needs to be rendered
const showLeft = useMemo(() => leftSection != null && left != null, [leftSection, left]);
const showRight = useMemo(() => rightSection != null && right != null, [rightSection, right]);
const showPreview = useMemo(
() => previewSection != null && preview != null,
[previewSection, preview]
);

const showCollapsed = useMemo(() => !showLeft && showRight, [showLeft, showRight]);
const showExpanded = useMemo(() => showLeft && showRight, [showLeft, showRight]);

const rightComponent = useMemo(
() => (rightSection ? rightSection.component({ ...(right as FlyoutPanelProps) }) : null),
[rightSection, right]
);
useEffect(() => {
console.log('render - rightSection is changed -------');
}, [rightSection]);
useEffect(() => {
console.log('render - right is changed -------');
}, [right]);
useEffect(() => {
console.log('render - leftSection is changed -------');
}, [leftSection]);
useEffect(() => {
console.log('render - left is changed -------');
}, [left]);
useEffect(() => {
console.log('render - previewSection is changed -------');
}, [previewSection]);
useEffect(() => {
console.log('render - preview is changed -------');
}, [preview]);
const previewComponent = useMemo(
() =>
previewSection
? previewSection.component({
...(mostRecentPreview as FlyoutPanelProps),
})
: null,
[previewSection, mostRecentPreview]
);

// we want to set a minimum flyout width different when in collapsed and expanded mode
const minFlyoutWidth = useMemo(
() => (showExpanded ? EXPANDED_FLYOUT_MIN_WIDTH : COLLAPSED_FLYOUT_MIN_WIDTH),
[showExpanded]
);

const flyoutWidth = useMemo(() => {
if (showCollapsed) {
return flyoutWidths.collapsedWidth || defaultWidths.rightWidth;
}
if (showExpanded) {
return flyoutWidths.expandedWidth || defaultWidths.rightWidth + defaultWidths.leftWidth;
}
}, [
showCollapsed,
showExpanded,
flyoutWidths.collapsedWidth,
flyoutWidths.expandedWidth,
defaultWidths.rightWidth,
defaultWidths.leftWidth,
]);

// callback function called when user changes the flyout's width
const onResize = useCallback(
(width: number) => {
if (showExpanded && urlKey) {
dispatch(changeExpandedWidthAction({ width, id: urlKey, savedToLocalStorage: true }));
} else if (showCollapsed && urlKey) {
dispatch(changeCollapsedWidthAction({ width, id: urlKey, savedToLocalStorage: true }));
}
},
[dispatch, showCollapsed, showExpanded, urlKey]
);

// don't need to render if the windowWidth is 0 or if nothing needs to be rendered
if (!showLeft && !showRight && !showPreview) {
return null;
}

return (
// @ts-ignore // TODO figure out why it's throwing an ref error
<EuiFlyoutResizable
{...flyoutProps}
data-panel-id={right?.id ?? ''}
type={flyoutType}
size={flyoutWidth}
ownFocus={false}
onClose={(e) => {
closeFlyout();
if (flyoutProps.onClose) {
flyoutProps.onClose(e);
}
}}
css={customStyles}
onResize={onResize}
minWidth={minFlyoutWidth}
>
{showCollapsed && <RightSection component={rightComponent} />}

{showExpanded && (
<ResizableContainer
leftSection={leftSection}
rightSection={rightSection}
left={left}
right={right}
showPreview={showPreview}
/>
)}

{showPreview && (
<PreviewSection
component={previewComponent}
banner={previewBanner}
showExpanded={showExpanded}
/>
)}

{!flyoutCustomProps?.hideSettings && (
<SettingsMenu urlKey={urlKey} flyoutCustomProps={flyoutCustomProps} />
)}
</EuiFlyoutResizable>
);
}
);

Content.displayName = 'Content';
27 changes: 9 additions & 18 deletions packages/kbn-expandable-flyout/src/components/left_section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,26 @@
*/

import { EuiFlexItem } from '@elastic/eui';
import React, { memo, useMemo } from 'react';
import React, { memo } from 'react';
import { LEFT_SECTION_TEST_ID } from './test_ids';

interface LeftSectionProps {
/**
* Component to be rendered
*/
component: React.ReactElement;
/**
* Width used when rendering the panel
*/
width: number;
}

/**
* Left section of the expanded flyout rendering a panel
*/
export const LeftSection: React.FC<LeftSectionProps> = memo(
({ component, width }: LeftSectionProps) => {
const style = useMemo<React.CSSProperties>(
() => ({ height: '100%', width: `${width}px` }),
[width]
);
return (
<EuiFlexItem grow data-test-subj={LEFT_SECTION_TEST_ID} style={style}>
{component}
</EuiFlexItem>
);
}
);
export const LeftSection: React.FC<LeftSectionProps> = memo(({ component }: LeftSectionProps) => {
console.log('render - LeftSection');
return (
<EuiFlexItem grow data-test-subj={LEFT_SECTION_TEST_ID} style={{ height: '100%' }}>
{component}
</EuiFlexItem>
);
});

LeftSection.displayName = 'LeftSection';
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,18 @@ describe('PreviewSection', () => {
} as unknown as State;

const component = <div>{'component'}</div>;
const left = 500;
const defaultLeftSectionWidth = 500;
const defaultRightSectionWidth = 300;

it('should render back button and close button in header', () => {
const { getByTestId } = render(
<TestProvider state={context}>
<PreviewSection component={component} leftPosition={left} />
<PreviewSection
component={component}
defaultLeftSectionWidth={defaultLeftSectionWidth}
defaultRightSectionWidth={defaultRightSectionWidth}
showLeft={true}
/>
</TestProvider>
);

Expand All @@ -53,7 +59,13 @@ describe('PreviewSection', () => {

const { getByTestId, getByText } = render(
<TestProvider state={context}>
<PreviewSection component={component} leftPosition={left} banner={banner} />
<PreviewSection
component={component}
defaultLeftSectionWidth={defaultLeftSectionWidth}
defaultRightSectionWidth={defaultRightSectionWidth}
showLeft={true}
banner={banner}
/>
</TestProvider>
);

Expand Down
Loading