Skip to content

Commit

Permalink
Added solution toolbar to Canvas
Browse files Browse the repository at this point in the history
  • Loading branch information
cqliu1 committed Sep 28, 2021
1 parent 8cf20cd commit 2671699
Show file tree
Hide file tree
Showing 11 changed files with 256 additions and 221 deletions.
22 changes: 12 additions & 10 deletions src/plugins/dashboard/public/application/top_nav/editor_menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,16 +235,18 @@ export const EditorMenu = ({ dashboardContainer, createNewVisType }: Props) => {
panelPaddingSize="none"
data-test-subj="dashboardEditorMenuButton"
>
<EuiContextMenu
initialPanelId={0}
panels={editorMenuPanels}
className={`dshSolutionToolbar__editorContextMenu ${
IS_DARK_THEME
? 'dshSolutionToolbar__editorContextMenu--dark'
: 'dshSolutionToolbar__editorContextMenu--light'
}`}
data-test-subj="dashboardEditorContextMenu"
/>
{() => (
<EuiContextMenu
initialPanelId={0}
panels={editorMenuPanels}
className={`dshSolutionToolbar__editorContextMenu ${
IS_DARK_THEME
? 'dshSolutionToolbar__editorContextMenu--dark'
: 'dshSolutionToolbar__editorContextMenu--light'
}`}
data-test-subj="dashboardEditorContextMenu"
/>
)}
</SolutionToolbarPopover>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ type AllowedPopoverProps = Omit<
'button' | 'isOpen' | 'closePopover' | 'anchorPosition'
>;

export type Props = AllowedButtonProps & AllowedPopoverProps;
export type Props = AllowedButtonProps &
AllowedPopoverProps & {
children: (arg: { closePopover: () => void }) => React.ReactNode;
};

export const SolutionToolbarPopover = ({
label,
iconType,
primary,
iconSide,
children,
...popover
}: Props) => {
const [isOpen, setIsOpen] = useState(false);
Expand All @@ -37,6 +41,13 @@ export const SolutionToolbarPopover = ({
);

return (
<EuiPopover anchorPosition="downLeft" {...{ isOpen, button, closePopover }} {...popover} />
<EuiPopover
anchorPosition="downLeft"
panelPaddingSize="none"
{...{ isOpen, button, closePopover }}
{...popover}
>
{children({ closePopover })}
</EuiPopover>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -54,29 +54,31 @@ const primaryButtonConfigs = {
panelPaddingSize="none"
primary={true}
>
<EuiContextMenu
initialPanelId={0}
panels={[
{
id: 0,
title: 'Open editor',
items: [
{
name: 'Lens',
icon: 'lensApp',
},
{
name: 'Maps',
icon: 'logoMaps',
},
{
name: 'TSVB',
icon: 'visVisualBuilder',
},
],
},
]}
/>
{() => (
<EuiContextMenu
initialPanelId={0}
panels={[
{
id: 0,
title: 'Open editor',
items: [
{
name: 'Lens',
icon: 'lensApp',
},
{
name: 'Maps',
icon: 'logoMaps',
},
{
name: 'TSVB',
icon: 'visVisualBuilder',
},
],
},
]}
/>
)}
</SolutionToolbarPopover>
),
Dashboard: (
Expand All @@ -93,29 +95,31 @@ const extraButtonConfigs = {
Canvas: undefined,
Dashboard: [
<SolutionToolbarPopover iconType="visualizeApp" label="All editors" panelPaddingSize="none">
<EuiContextMenu
initialPanelId={0}
panels={[
{
id: 0,
title: 'Open editor',
items: [
{
name: 'Lens',
icon: 'lensApp',
},
{
name: 'Maps',
icon: 'logoMaps',
},
{
name: 'TSVB',
icon: 'visVisualBuilder',
},
],
},
]}
/>
{() => (
<EuiContextMenu
initialPanelId={0}
panels={[
{
id: 0,
title: 'Open editor',
items: [
{
name: 'Lens',
icon: 'lensApp',
},
{
name: 'Maps',
icon: 'logoMaps',
},
{
name: 'TSVB',
icon: 'visVisualBuilder',
},
],
},
]}
/>
)}
</SolutionToolbarPopover>,
],
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ $canvasLayoutFontSize: $euiFontSizeS;
.canvasLayout__stageHeader {
flex-grow: 0;
flex-basis: auto;
padding: 1px $euiSize 0;
padding: $euiSizeS;
font-size: $canvasLayoutFontSize;
border-bottom: $euiBorderThin;
background: $euiColorLightestShade;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,13 @@
*/

import { sortBy } from 'lodash';
import React, { Fragment, FunctionComponent, useState } from 'react';
import React, { FunctionComponent, useState } from 'react';
import PropTypes from 'prop-types';
import {
EuiButton,
EuiContextMenu,
EuiIcon,
EuiContextMenuPanelItemDescriptor,
} from '@elastic/eui';
import { EuiContextMenu, EuiIcon, EuiContextMenuPanelItemDescriptor } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { PrimaryActionPopover } from '../../../../../../../src/plugins/presentation_util/public';
import { getId } from '../../../lib/get_id';
import { Popover, ClosePopoverFn } from '../../popover';
import { ClosePopoverFn } from '../../popover';
import { CONTEXT_MENU_TOP_BORDER_CLASSNAME } from '../../../../common/lib';
import { ElementSpec } from '../../../../types';
import { flattenPanelTree } from '../../../lib/flatten_panel_tree';
Expand Down Expand Up @@ -116,34 +112,23 @@ const categorizeElementsByType = (elements: ElementSpec[]): { [key: string]: Ele
return categories;
};

export interface Props {
interface Props {
/**
* Dictionary of elements from elements registry
*/
elements: { [key: string]: ElementSpec };
elementsRegistry: { [key: string]: ElementSpec };
/**
* Handler for adding a selected element to the workpad
*/
addElement: (element: ElementSpec) => void;
/**
* Renders embeddable flyout
*/
renderEmbedPanel: (onClose: () => void) => JSX.Element;
}

export const ElementMenu: FunctionComponent<Props> = ({
elements,
addElement,
renderEmbedPanel,
}) => {
export const ElementMenu: FunctionComponent<Props> = ({ elementsRegistry, addElement }) => {
const [isAssetModalVisible, setAssetModalVisible] = useState(false);
const [isEmbedPanelVisible, setEmbedPanelVisible] = useState(false);
const [isSavedElementsModalVisible, setSavedElementsModalVisible] = useState(false);

const hideAssetModal = () => setAssetModalVisible(false);
const showAssetModal = () => setAssetModalVisible(true);
const hideEmbedPanel = () => setEmbedPanelVisible(false);
const showEmbedPanel = () => setEmbedPanelVisible(true);
const hideSavedElementsModal = () => setSavedElementsModalVisible(false);
const showSavedElementsModal = () => setSavedElementsModalVisible(true);

Expand All @@ -155,7 +140,7 @@ export const ElementMenu: FunctionComponent<Props> = ({
progress: progressElements,
shape: shapeElements,
text: textElements,
} = categorizeElementsByType(Object.values(elements));
} = categorizeElementsByType(Object.values(elementsRegistry));

const getPanelTree = (closePopover: ClosePopoverFn) => {
const elementToMenuItem = (element: ElementSpec): EuiContextMenuPanelItemDescriptor => ({
Expand Down Expand Up @@ -214,51 +199,31 @@ export const ElementMenu: FunctionComponent<Props> = ({
closePopover();
},
},
{
name: strings.getEmbedObjectMenuItemLabel(),
className: CONTEXT_MENU_TOP_BORDER_CLASSNAME,
icon: <EuiIcon type="logoKibana" size="m" />,
onClick: () => {
showEmbedPanel();
closePopover();
},
},
],
};
};

const exportControl = (togglePopover: React.MouseEventHandler<any>) => (
<EuiButton
fill
iconType="plusInCircle"
size="s"
aria-label={strings.getElementMenuLabel()}
onClick={togglePopover}
className="canvasElementMenu__popoverButton"
data-test-subj="add-element-button"
>
{strings.getElementMenuButtonLabel()}
</EuiButton>
);

return (
<Fragment>
<Popover button={exportControl} panelPaddingSize="none" anchorPosition="downLeft">
<>
<PrimaryActionPopover
panelPaddingSize="none"
label={strings.getElementMenuButtonLabel()}
iconType="plusInCircle"
>
{({ closePopover }: { closePopover: ClosePopoverFn }) => (
<EuiContextMenu
initialPanelId={0}
panels={flattenPanelTree(getPanelTree(closePopover))}
/>
)}
</Popover>
</PrimaryActionPopover>
{isAssetModalVisible ? <AssetManager onClose={hideAssetModal} /> : null}
{isEmbedPanelVisible ? renderEmbedPanel(hideEmbedPanel) : null}
{isSavedElementsModalVisible ? <SavedElementsModal onClose={hideSavedElementsModal} /> : null}
</Fragment>
</>
);
};

ElementMenu.propTypes = {
elements: PropTypes.object,
elementsRegistry: PropTypes.object,
addElement: PropTypes.func.isRequired,
};

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,4 @@
* 2.0.
*/

import React from 'react';
import { connect } from 'react-redux';
import { compose, withProps } from 'recompose';
import { Dispatch } from 'redux';
import { State, ElementSpec } from '../../../../types';
// @ts-expect-error untyped local
import { elementsRegistry } from '../../../lib/elements_registry';
import { ElementMenu as Component, Props as ComponentProps } from './element_menu.component';
// @ts-expect-error untyped local
import { addElement } from '../../../state/actions/elements';
import { getSelectedPage } from '../../../state/selectors/workpad';
import { AddEmbeddablePanel } from '../../embeddable_flyout';

interface StateProps {
pageId: string;
}

interface DispatchProps {
addElement: (pageId: string) => (partialElement: ElementSpec) => void;
}

const mapStateToProps = (state: State) => ({
pageId: getSelectedPage(state),
});

const mapDispatchToProps = (dispatch: Dispatch) => ({
addElement: (pageId: string) => (element: ElementSpec) => dispatch(addElement(pageId, element)),
});

const mergeProps = (stateProps: StateProps, dispatchProps: DispatchProps) => ({
...stateProps,
...dispatchProps,
addElement: dispatchProps.addElement(stateProps.pageId),
// Moved this section out of the main component to enable stories
renderEmbedPanel: (onClose: () => void) => <AddEmbeddablePanel onClose={onClose} />,
});

export const ElementMenu = compose<ComponentProps, {}>(
connect(mapStateToProps, mapDispatchToProps, mergeProps),
withProps(() => ({ elements: elementsRegistry.toJS() }))
)(Component);
export * from './element_menu.component';
Loading

0 comments on commit 2671699

Please sign in to comment.