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

Add embed mode options in the Share UI #58435

Merged
merged 29 commits into from
Jun 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
66ac67e
Add embed mode options in the Share UI
ajwild Feb 25, 2020
ab23f52
Skip chrome visibility changes when embedded
ajwild Mar 4, 2020
4699307
Update URL parameter checks
ajwild Mar 4, 2020
335277b
Add prop for date picker content alignment
ajwild Mar 4, 2020
ffdc84d
Use menu items for top nav menu display logic
ajwild Mar 15, 2020
6bba94a
Use checkbox group for URL share params
ajwild Mar 17, 2020
f5f1d8a
Rename URL params
ajwild Mar 17, 2020
f4a5c4a
Rename isEmbedded to isEmbeddedExternally
ajwild Mar 17, 2020
e45723c
Remove app specific logic from share plugin
ajwild Apr 6, 2020
098de51
Fix date picker content alignment after rebase
ajwild May 11, 2020
7f4af46
Fix failing TopNavMenu test due to missing items
ajwild May 11, 2020
e49a230
Remove unused props from DashboardAppScope
ajwild May 11, 2020
cb6af62
Fix saved object share URL
ajwild May 11, 2020
d01ad17
Remove isEmbedded from chrome service
ajwild May 11, 2020
c227a10
Rearrange share panel and regenerate short URLs
ajwild May 11, 2020
99587f3
Fix .globalQueryBar style specificity
May 14, 2020
f94a99f
Reduce margin between switch and tooltip
May 14, 2020
65222c6
And snaps
May 14, 2020
3df6202
Return null from TopNavMenu render functions
ajwild May 19, 2020
1867d9e
Refactor getUrlParamExtensions function
ajwild May 19, 2020
61f16cb
Remove toggleChrome prop from ExitFullScreenButton
ajwild May 19, 2020
3b9bc78
Remove justifyContent prop from SearchBar
ajwild May 19, 2020
aca575d
Add functional test for embed mode options
ajwild May 20, 2020
6f18ca8
Update i18n translation IDs
ajwild May 20, 2020
9bb73dd
Use helpers in functional test
ajwild May 20, 2020
d1ff102
Pass strings to i18n.translate function
ajwild May 20, 2020
aac8b12
Fix ESLint errors
ajwild Jun 3, 2020
417abf0
Hide components in full screen when embedded
ajwild Jun 7, 2020
33e8fc4
Merge branch 'master' into embed-mode-options
elasticmachine Jun 8, 2020
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
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