Skip to content

Commit

Permalink
Add embed mode options in the Share UI (#58435)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajwild committed Jun 8, 2020
1 parent 00cff3c commit 38b9a8d
Show file tree
Hide file tree
Showing 19 changed files with 564 additions and 71 deletions.
4 changes: 0 additions & 4 deletions src/legacy/ui/public/styles/_legacy/_base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ input[type='checkbox'],
padding-bottom: $euiSizeS;
}

.globalQueryBar {
padding: 0px $euiSizeS $euiSizeS $euiSizeS;
}

> nav,
> navbar {
z-index: 2 !important;
Expand Down
143 changes: 131 additions & 12 deletions src/plugins/dashboard/public/application/dashboard_app_controller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@

import _, { uniq } from 'lodash';
import { i18n } from '@kbn/i18n';
import { EUI_MODAL_CANCEL_BUTTON } from '@elastic/eui';
import React from 'react';
import { EUI_MODAL_CANCEL_BUTTON, EuiCheckboxGroup } from '@elastic/eui';
import { EuiCheckboxGroupIdToSelectedMap } from '@elastic/eui/src/components/form/checkbox/checkbox_group';
import React, { useState, ReactElement } from 'react';
import ReactDOM from 'react-dom';
import angular from 'angular';

Expand Down Expand Up @@ -94,6 +95,25 @@ export interface DashboardAppControllerDependencies extends RenderDeps {
navigation: NavigationStart;
}

enum UrlParams {
SHOW_TOP_MENU = 'show-top-menu',
SHOW_QUERY_INPUT = 'show-query-input',
SHOW_TIME_FILTER = 'show-time-filter',
SHOW_FILTER_BAR = 'show-filter-bar',
HIDE_FILTER_BAR = 'hide-filter-bar',
}

interface UrlParamsSelectedMap {
[UrlParams.SHOW_TOP_MENU]: boolean;
[UrlParams.SHOW_QUERY_INPUT]: boolean;
[UrlParams.SHOW_TIME_FILTER]: boolean;
[UrlParams.SHOW_FILTER_BAR]: boolean;
}

interface UrlParamValues extends Omit<UrlParamsSelectedMap, UrlParams.SHOW_FILTER_BAR> {
[UrlParams.HIDE_FILTER_BAR]: boolean;
}

export class DashboardAppController {
// Part of the exposed plugin API - do not remove without careful consideration.
appStatus: {
Expand Down Expand Up @@ -133,8 +153,16 @@ export class DashboardAppController {
const filterManager = queryService.filterManager;
const queryFilter = filterManager;
const timefilter = queryService.timefilter.timefilter;
let showSearchBar = true;
let showQueryBar = true;
const isEmbeddedExternally = Boolean($routeParams.embed);

// url param rules should only apply when embedded (e.g. url?embed=true)
const shouldForceDisplay = (param: string): boolean =>
isEmbeddedExternally && Boolean($routeParams[param]);

const forceShowTopNavMenu = shouldForceDisplay(UrlParams.SHOW_TOP_MENU);
const forceShowQueryInput = shouldForceDisplay(UrlParams.SHOW_QUERY_INPUT);
const forceShowDatePicker = shouldForceDisplay(UrlParams.SHOW_TIME_FILTER);
const forceHideFilterBar = shouldForceDisplay(UrlParams.HIDE_FILTER_BAR);

let lastReloadRequestTime = 0;
const dash = ($scope.dash = $route.current.locals.dash);
Expand Down Expand Up @@ -251,9 +279,6 @@ export class DashboardAppController {
}
};

const showFilterBar = () =>
$scope.model.filters.length > 0 || !dashboardStateManager.getFullScreenMode();

const getEmptyScreenProps = (
shouldShowEditHelp: boolean,
isEmptyInReadOnlyMode: boolean
Expand Down Expand Up @@ -299,6 +324,7 @@ export class DashboardAppController {
viewMode: dashboardStateManager.getViewMode(),
panels: embeddablesMap,
isFullScreenMode: dashboardStateManager.getFullScreenMode(),
isEmbeddedExternally,
isEmptyState: shouldShowEditHelp || shouldShowViewHelp || isEmptyInReadonlyMode,
useMargins: dashboardStateManager.getUseMargins(),
lastReloadRequestTime,
Expand Down Expand Up @@ -590,17 +616,33 @@ export class DashboardAppController {
dashboardStateManager.setSavedQueryId(savedQueryId);
};

const shouldShowFilterBar = (forceHide: boolean): boolean =>
!forceHide && ($scope.model.filters.length > 0 || !dashboardStateManager.getFullScreenMode());

const shouldShowNavBarComponent = (forceShow: boolean): boolean =>
(forceShow || $scope.isVisible) && !dashboardStateManager.getFullScreenMode();

const getNavBarProps = () => {
const isFullScreenMode = dashboardStateManager.getFullScreenMode();
const screenTitle = dashboardStateManager.getTitle();
const showTopNavMenu = shouldShowNavBarComponent(forceShowTopNavMenu);
const showQueryInput = shouldShowNavBarComponent(forceShowQueryInput);
const showDatePicker = shouldShowNavBarComponent(forceShowDatePicker);
const showQueryBar = showQueryInput || showDatePicker;
const showFilterBar = shouldShowFilterBar(forceHideFilterBar);
const showSearchBar = showQueryBar || showFilterBar;

return {
appName: 'dashboard',
config: $scope.isVisible ? $scope.topNavMenu : undefined,
config: showTopNavMenu ? $scope.topNavMenu : undefined,
className: isFullScreenMode ? 'kbnTopNavMenu-isFullScreen' : undefined,
screenTitle,
showTopNavMenu,
showSearchBar,
showQueryBar,
showFilterBar: showFilterBar(),
showQueryInput,
showDatePicker,
showFilterBar,
indexPatterns: $scope.indexPatterns,
showSaveQuery: $scope.showSaveQuery,
query: $scope.model.query,
Expand Down Expand Up @@ -798,7 +840,6 @@ export class DashboardAppController {
} = {};
navActions[TopNavIds.FULL_SCREEN] = () => {
dashboardStateManager.setFullScreenMode(true);
showQueryBar = false;
updateNavBar();
};
navActions[TopNavIds.EXIT_EDIT_MODE] = () => onChangeViewMode(ViewMode.VIEW);
Expand Down Expand Up @@ -923,6 +964,80 @@ export class DashboardAppController {
if (share) {
// the share button is only availabale if "share" plugin contract enabled
navActions[TopNavIds.SHARE] = (anchorElement) => {
const EmbedUrlParamExtension = ({
setParamValue,
}: {
setParamValue: (paramUpdate: UrlParamValues) => void;
}): ReactElement => {
const [urlParamsSelectedMap, setUrlParamsSelectedMap] = useState<UrlParamsSelectedMap>({
[UrlParams.SHOW_TOP_MENU]: false,
[UrlParams.SHOW_QUERY_INPUT]: false,
[UrlParams.SHOW_TIME_FILTER]: false,
[UrlParams.SHOW_FILTER_BAR]: true,
});

const checkboxes = [
{
id: UrlParams.SHOW_TOP_MENU,
label: i18n.translate('dashboard.embedUrlParamExtension.topMenu', {
defaultMessage: 'Top menu',
}),
},
{
id: UrlParams.SHOW_QUERY_INPUT,
label: i18n.translate('dashboard.embedUrlParamExtension.query', {
defaultMessage: 'Query',
}),
},
{
id: UrlParams.SHOW_TIME_FILTER,
label: i18n.translate('dashboard.embedUrlParamExtension.timeFilter', {
defaultMessage: 'Time filter',
}),
},
{
id: UrlParams.SHOW_FILTER_BAR,
label: i18n.translate('dashboard.embedUrlParamExtension.filterBar', {
defaultMessage: 'Filter bar',
}),
},
];

const handleChange = (param: string): void => {
const urlParamsSelectedMapUpdate = {
...urlParamsSelectedMap,
[param]: !urlParamsSelectedMap[param as keyof UrlParamsSelectedMap],
};
setUrlParamsSelectedMap(urlParamsSelectedMapUpdate);

const urlParamValues = {
[UrlParams.SHOW_TOP_MENU]: urlParamsSelectedMap[UrlParams.SHOW_TOP_MENU],
[UrlParams.SHOW_QUERY_INPUT]: urlParamsSelectedMap[UrlParams.SHOW_QUERY_INPUT],
[UrlParams.SHOW_TIME_FILTER]: urlParamsSelectedMap[UrlParams.SHOW_TIME_FILTER],
[UrlParams.HIDE_FILTER_BAR]: !urlParamsSelectedMap[UrlParams.SHOW_FILTER_BAR],
[param === UrlParams.SHOW_FILTER_BAR ? UrlParams.HIDE_FILTER_BAR : param]:
param === UrlParams.SHOW_FILTER_BAR
? urlParamsSelectedMap[UrlParams.SHOW_FILTER_BAR]
: !urlParamsSelectedMap[param as keyof UrlParamsSelectedMap],
};
setParamValue(urlParamValues);
};

return (
<EuiCheckboxGroup
options={checkboxes}
idToSelectedMap={(urlParamsSelectedMap as unknown) as EuiCheckboxGroupIdToSelectedMap}
onChange={handleChange}
legend={{
children: i18n.translate('dashboard.embedUrlParamExtension.include', {
defaultMessage: 'Include',
}),
}}
data-test-subj="embedUrlParamExtension"
/>
);
};

share.toggleShareContextMenu({
anchorElement,
allowEmbed: true,
Expand All @@ -935,6 +1050,12 @@ export class DashboardAppController {
title: dash.title,
},
isDirty: dashboardStateManager.getIsDirty(),
embedUrlParamExtensions: [
{
paramName: 'embed',
component: EmbedUrlParamExtension,
},
],
});
};
}
Expand All @@ -955,8 +1076,6 @@ export class DashboardAppController {
const visibleSubscription = chrome.getIsVisible$().subscribe((isVisible) => {
$scope.$evalAsync(() => {
$scope.isVisible = isVisible;
showSearchBar = isVisible || showFilterBar();
showQueryBar = !dashboardStateManager.getFullScreenMode() && isVisible;
updateNavBar();
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface DashboardContainerInput extends ContainerInput {
useMargins: boolean;
title: string;
description?: string;
isEmbeddedExternally: boolean;
isFullScreenMode: boolean;
panels: {
[panelId: string]: DashboardPanelState<EmbeddableInput & { [k: string]: unknown }>;
Expand Down Expand Up @@ -105,6 +106,7 @@ export class DashboardContainer extends Container<InheritedChildInput, Dashboard
super(
{
panels: {},
isEmbeddedExternally: false,
isFullScreenMode: false,
filters: [],
useMargins: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export class DashboardContainerFactory
public getDefaultInput(): Partial<DashboardContainerInput> {
return {
panels: {},
isEmbeddedExternally: false,
isFullScreenMode: false,
useMargins: true,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ interface State {
title: string;
description?: string;
panels: { [key: string]: PanelState };
isEmbeddedExternally?: boolean;
isEmptyState?: boolean;
}

Expand All @@ -52,6 +53,7 @@ export class DashboardViewport extends React.Component<DashboardViewportProps, S
panels,
useMargins,
title,
isEmbeddedExternally,
isEmptyState,
} = this.props.container.getInput();

Expand All @@ -60,6 +62,7 @@ export class DashboardViewport extends React.Component<DashboardViewportProps, S
panels,
useMargins,
title,
isEmbeddedExternally,
isEmptyState,
};
}
Expand All @@ -72,6 +75,7 @@ export class DashboardViewport extends React.Component<DashboardViewportProps, S
useMargins,
title,
description,
isEmbeddedExternally,
isEmptyState,
} = this.props.container.getInput();
if (this.mounted) {
Expand All @@ -80,6 +84,7 @@ export class DashboardViewport extends React.Component<DashboardViewportProps, S
description,
useMargins,
title,
isEmbeddedExternally,
isEmptyState,
});
}
Expand All @@ -101,12 +106,13 @@ export class DashboardViewport extends React.Component<DashboardViewportProps, S

private renderEmptyScreen() {
const { renderEmpty } = this.props;
const { isFullScreenMode } = this.state;
const { isEmbeddedExternally, isFullScreenMode } = this.state;
return (
<div className="dshDashboardEmptyScreen">
{isFullScreenMode && (
<this.context.services.ExitFullScreenButton
onExitFullScreenMode={this.onExitFullScreenMode}
toggleChrome={!isEmbeddedExternally}
/>
)}
{renderEmpty && renderEmpty()}
Expand All @@ -116,7 +122,14 @@ export class DashboardViewport extends React.Component<DashboardViewportProps, S

private renderContainerScreen() {
const { container, PanelComponent } = this.props;
const { isFullScreenMode, panels, title, description, useMargins } = this.state;
const {
isEmbeddedExternally,
isFullScreenMode,
panels,
title,
description,
useMargins,
} = this.state;
return (
<div
data-shared-items-count={Object.values(panels).length}
Expand All @@ -128,6 +141,7 @@ export class DashboardViewport extends React.Component<DashboardViewportProps, S
{isFullScreenMode && (
<this.context.services.ExitFullScreenButton
onExitFullScreenMode={this.onExitFullScreenMode}
toggleChrome={!isEmbeddedExternally}
/>
)}
<DashboardGrid container={container} PanelComponent={PanelComponent} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export function getSampleDashboardInput(
id: '123',
filters: [],
useMargins: false,
isEmbeddedExternally: false,
isFullScreenMode: false,
title: 'My Dashboard',
query: {
Expand Down
23 changes: 17 additions & 6 deletions src/plugins/dashboard/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,26 @@ export class DashboardPlugin
const getStartServices = async () => {
const [coreStart, deps] = await core.getStartServices();

const useHideChrome = () => {
const useHideChrome = ({ toggleChrome } = { toggleChrome: true }) => {
React.useEffect(() => {
coreStart.chrome.setIsVisible(false);
return () => coreStart.chrome.setIsVisible(true);
}, []);
if (toggleChrome) {
coreStart.chrome.setIsVisible(false);
}

return () => {
if (toggleChrome) {
coreStart.chrome.setIsVisible(true);
}
};
}, [toggleChrome]);
};

const ExitFullScreenButton: React.FC<ExitFullScreenButtonProps> = (props) => {
useHideChrome();
const ExitFullScreenButton: React.FC<
ExitFullScreenButtonProps & {
toggleChrome: boolean;
}
> = ({ toggleChrome, ...props }) => {
useHideChrome({ toggleChrome });
return <ExitFullScreenButtonUi {...props} />;
};
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
padding: 0px $euiSizeS $euiSizeS $euiSizeS;
}

.globalQueryBar:first-child {
padding-top: $euiSizeS;
}

.globalQueryBar:not(:empty) {
padding-bottom: $euiSizeS;
}
Expand Down
Loading

0 comments on commit 38b9a8d

Please sign in to comment.