mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
* checkpoint 1: dashboard reading screenshot mode values is screenshot mode and screenshot layout
* checkpoint 2: dashboard handling preserve layout
* temp setting up print viewport
* slight clean up, detect a new view mode "print"
* fix types
* adde todo comment
* added "print" route to dashboard that does not rely on screenshotMode service
* updated jest tests and added screenshot mode public mock
* try to respect embed settings
* fix lint
* remove print mode from share data
* re-add ViewMode.VIEW to share data
* updated TODO comment
* remove injected print css
* remove double declaration of ScreenshotModePluginStart
* re-add missing import 🤦
* fix types issues
* changed css injection removal to use only viewMode.PRINT rather than a new route
* turn off defer below fold when in print mode
* elastic@ email address
* address some CI checks that were failing
* use .includes instead of || to check view mode
Co-authored-by: Michael Dokolin <dokmic@gmail.com>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Devon A Thomson <devon.thomson@hotmail.com>
Co-authored-by: Michael Dokolin <dokmic@gmail.com>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Devon A Thomson <devon.thomson@hotmail.com>
Co-authored-by: Michael Dokolin <dokmic@gmail.com>
This commit is contained in:
parent
9322069da7
commit
12d4882904
45 changed files with 197 additions and 199 deletions
|
@ -13,6 +13,7 @@
|
|||
"navigation",
|
||||
"savedObjects",
|
||||
"share",
|
||||
"screenshotMode",
|
||||
"uiActions",
|
||||
"urlForwarding",
|
||||
"presentationUtil",
|
||||
|
|
|
@ -15,6 +15,7 @@ import { CoreStart } from 'kibana/public';
|
|||
import { coreMock, uiSettingsServiceMock } from '../../../../../core/public/mocks';
|
||||
import { embeddablePluginMock } from 'src/plugins/embeddable/public/mocks';
|
||||
import { getStubPluginServices } from '../../../../presentation_util/public';
|
||||
import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
|
||||
|
||||
import {
|
||||
EmbeddableInput,
|
||||
|
@ -65,6 +66,7 @@ beforeEach(async () => {
|
|||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
http: coreStart.http,
|
||||
presentationUtil: getStubPluginServices(),
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
};
|
||||
|
||||
container = new DashboardContainer(getSampleDashboardInput(), containerOptions);
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
} from '../../services/embeddable_test_samples';
|
||||
import { ErrorEmbeddable, IContainer, isErrorEmbeddable } from '../../services/embeddable';
|
||||
import { getStubPluginServices } from '../../../../presentation_util/public';
|
||||
import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
|
||||
|
||||
const { setup, doStart } = embeddablePluginMock.createInstance();
|
||||
setup.registerEmbeddableFactory(
|
||||
|
@ -56,6 +57,7 @@ beforeEach(async () => {
|
|||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
http: coreStart.http,
|
||||
presentationUtil: getStubPluginServices(),
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
};
|
||||
const input = getSampleDashboardInput({
|
||||
panels: {
|
||||
|
|
|
@ -13,6 +13,7 @@ import { getSampleDashboardInput, getSampleDashboardPanel } from '../test_helper
|
|||
import { embeddablePluginMock } from 'src/plugins/embeddable/public/mocks';
|
||||
import { isErrorEmbeddable } from '../../services/embeddable';
|
||||
import { getStubPluginServices } from '../../../../presentation_util/public';
|
||||
import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
|
||||
|
||||
import {
|
||||
CONTACT_CARD_EMBEDDABLE,
|
||||
|
@ -48,6 +49,7 @@ beforeEach(async () => {
|
|||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
http: coreMock.createStart().http,
|
||||
presentationUtil: getStubPluginServices(),
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
};
|
||||
const input = getSampleDashboardInput({
|
||||
panels: {
|
||||
|
|
|
@ -25,6 +25,7 @@ import { DataPublicPluginStart } from '../../../../data/public/types';
|
|||
import { dataPluginMock } from '../../../../data/public/mocks';
|
||||
import { LINE_FEED_CHARACTER } from 'src/plugins/data/common/exports/export_csv';
|
||||
import { getStubPluginServices } from '../../../../presentation_util/public';
|
||||
import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
|
||||
|
||||
describe('Export CSV action', () => {
|
||||
const { setup, doStart } = embeddablePluginMock.createInstance();
|
||||
|
@ -61,6 +62,7 @@ describe('Export CSV action', () => {
|
|||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
http: coreStart.http,
|
||||
presentationUtil: getStubPluginServices(),
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
};
|
||||
const input = getSampleDashboardInput({
|
||||
panels: {
|
||||
|
|
|
@ -28,6 +28,7 @@ import {
|
|||
CONTACT_CARD_EMBEDDABLE,
|
||||
} from '../../services/embeddable_test_samples';
|
||||
import { getStubPluginServices } from '../../../../presentation_util/public';
|
||||
import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
|
||||
|
||||
const { setup, doStart } = embeddablePluginMock.createInstance();
|
||||
setup.registerEmbeddableFactory(
|
||||
|
@ -62,6 +63,7 @@ beforeEach(async () => {
|
|||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
http: coreStart.http,
|
||||
presentationUtil: getStubPluginServices(),
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
};
|
||||
|
||||
container = new DashboardContainer(getSampleDashboardInput(), containerOptions);
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
ContactCardEmbeddable,
|
||||
} from '../../services/embeddable_test_samples';
|
||||
import { getStubPluginServices } from '../../../../presentation_util/public';
|
||||
import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
|
||||
|
||||
describe('LibraryNotificationPopover', () => {
|
||||
const { setup, doStart } = embeddablePluginMock.createInstance();
|
||||
|
@ -58,6 +59,7 @@ describe('LibraryNotificationPopover', () => {
|
|||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
http: coreStart.http,
|
||||
presentationUtil: getStubPluginServices(),
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
};
|
||||
|
||||
container = new DashboardContainer(getSampleDashboardInput(), containerOptions);
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
ContactCardEmbeddableOutput,
|
||||
} from '../../services/embeddable_test_samples';
|
||||
import { getStubPluginServices } from '../../../../presentation_util/public';
|
||||
import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
|
||||
|
||||
const { setup, doStart } = embeddablePluginMock.createInstance();
|
||||
setup.registerEmbeddableFactory(
|
||||
|
@ -48,6 +49,7 @@ beforeEach(async () => {
|
|||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
http: coreStart.http,
|
||||
presentationUtil: getStubPluginServices(),
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
};
|
||||
const input = getSampleDashboardInput({
|
||||
panels: {
|
||||
|
|
|
@ -30,6 +30,7 @@ import {
|
|||
CONTACT_CARD_EMBEDDABLE,
|
||||
} from '../../services/embeddable_test_samples';
|
||||
import { getStubPluginServices } from '../../../../presentation_util/public';
|
||||
import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
|
||||
|
||||
const { setup, doStart } = embeddablePluginMock.createInstance();
|
||||
setup.registerEmbeddableFactory(
|
||||
|
@ -57,6 +58,7 @@ beforeEach(async () => {
|
|||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
http: coreStart.http,
|
||||
presentationUtil: getStubPluginServices(),
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
};
|
||||
|
||||
container = new DashboardContainer(getSampleDashboardInput(), containerOptions);
|
||||
|
|
|
@ -17,11 +17,11 @@ import {
|
|||
getDashboardTitle,
|
||||
leaveConfirmStrings,
|
||||
} from '../dashboard_strings';
|
||||
import { EmbeddableRenderer } from '../services/embeddable';
|
||||
import { createDashboardEditUrl } from '../dashboard_constants';
|
||||
import { EmbeddableRenderer, ViewMode } from '../services/embeddable';
|
||||
import { DashboardTopNav, isCompleteDashboardAppState } from './top_nav/dashboard_top_nav';
|
||||
import { DashboardAppServices, DashboardEmbedSettings, DashboardRedirect } from '../types';
|
||||
import { createKbnUrlStateStorage, withNotifyOnErrors } from '../services/kibana_utils';
|
||||
import { createDashboardEditUrl } from '../dashboard_constants';
|
||||
export interface DashboardAppProps {
|
||||
history: History;
|
||||
savedDashboardId?: string;
|
||||
|
@ -51,7 +51,6 @@ export function DashboardApp({
|
|||
const dashboardState = useDashboardSelector((state) => state.dashboardStateReducer);
|
||||
const dashboardAppState = useDashboardAppState({
|
||||
history,
|
||||
redirectTo,
|
||||
savedDashboardId,
|
||||
kbnUrlStateStorage,
|
||||
isEmbeddedExternally: Boolean(embedSettings),
|
||||
|
@ -101,15 +100,26 @@ export function DashboardApp({
|
|||
};
|
||||
}, [data.search.session]);
|
||||
|
||||
const printMode = useMemo(
|
||||
() => dashboardAppState.getLatestDashboardState?.().viewMode === ViewMode.PRINT,
|
||||
[dashboardAppState]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!embedSettings) chrome.setIsVisible(!printMode);
|
||||
}, [chrome, printMode, embedSettings]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isCompleteDashboardAppState(dashboardAppState) && (
|
||||
<>
|
||||
<DashboardTopNav
|
||||
redirectTo={redirectTo}
|
||||
embedSettings={embedSettings}
|
||||
dashboardAppState={dashboardAppState}
|
||||
/>
|
||||
{!printMode && (
|
||||
<DashboardTopNav
|
||||
redirectTo={redirectTo}
|
||||
embedSettings={embedSettings}
|
||||
dashboardAppState={dashboardAppState}
|
||||
/>
|
||||
)}
|
||||
|
||||
{dashboardAppState.savedDashboard.outcome === 'conflict' &&
|
||||
dashboardAppState.savedDashboard.id &&
|
||||
|
|
|
@ -109,6 +109,7 @@ export async function mountApp({
|
|||
embeddable: embeddableStart,
|
||||
uiSettings: coreStart.uiSettings,
|
||||
scopedHistory: () => scopedHistory,
|
||||
screenshotModeService: screenshotMode,
|
||||
indexPatterns: dataStart.indexPatterns,
|
||||
savedQueryService: dataStart.query.savedQueries,
|
||||
savedObjectsClient: coreStart.savedObjects.client,
|
||||
|
@ -131,7 +132,6 @@ export async function mountApp({
|
|||
activeSpaceId || 'default'
|
||||
),
|
||||
spacesService: spacesApi,
|
||||
screenshotModeService: screenshotMode,
|
||||
};
|
||||
|
||||
const getUrlStateStorage = (history: RouteComponentProps['history']) =>
|
||||
|
|
|
@ -43,11 +43,13 @@ import { getStubPluginServices } from '../../../../presentation_util/public';
|
|||
const presentationUtil = getStubPluginServices();
|
||||
|
||||
const options: DashboardContainerServices = {
|
||||
// TODO: clean up use of any
|
||||
application: {} as any,
|
||||
embeddable: {} as any,
|
||||
notifications: {} as any,
|
||||
overlays: {} as any,
|
||||
inspector: {} as any,
|
||||
screenshotMode: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
ExitFullScreenButton: () => null,
|
||||
uiActions: {} as any,
|
||||
|
|
|
@ -40,6 +40,7 @@ import {
|
|||
import { PLACEHOLDER_EMBEDDABLE } from './placeholder';
|
||||
import { DashboardAppCapabilities, DashboardContainerInput } from '../../types';
|
||||
import { PresentationUtilPluginStart } from '../../services/presentation_util';
|
||||
import type { ScreenshotModePluginStart } from '../../services/screenshot_mode';
|
||||
import { PanelPlacementMethod, IPanelPlacementArgs } from './panel/dashboard_panel_placement';
|
||||
import {
|
||||
combineDashboardFiltersWithControlGroupFilters,
|
||||
|
@ -55,6 +56,7 @@ export interface DashboardContainerServices {
|
|||
application: CoreStart['application'];
|
||||
inspector: InspectorStartContract;
|
||||
overlays: CoreStart['overlays'];
|
||||
screenshotMode: ScreenshotModePluginStart;
|
||||
uiSettings: IUiSettingsClient;
|
||||
embeddable: EmbeddableStart;
|
||||
uiActions: UiActionsStart;
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
} from '../../../services/embeddable_test_samples';
|
||||
import { coreMock, uiSettingsServiceMock } from '../../../../../../core/public/mocks';
|
||||
import { getStubPluginServices } from '../../../../../presentation_util/public';
|
||||
import { screenshotModePluginMock } from '../../../../../screenshot_mode/public/mocks';
|
||||
|
||||
let dashboardContainer: DashboardContainer | undefined;
|
||||
const presentationUtil = getStubPluginServices();
|
||||
|
@ -71,6 +72,7 @@ function prepare(props?: Partial<DashboardGridProps>) {
|
|||
uiSettings: uiSettingsServiceMock.createStartContract(),
|
||||
http: coreMock.createStart().http,
|
||||
presentationUtil,
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
};
|
||||
dashboardContainer = new DashboardContainer(initialInput, options);
|
||||
const defaultTestProps: DashboardGridProps = {
|
||||
|
|
|
@ -154,7 +154,7 @@ class DashboardGridUi extends React.Component<DashboardGridProps, State> {
|
|||
id: 'dashboard.dashboardGrid.toast.unableToLoadDashboardDangerMessage',
|
||||
defaultMessage: 'Unable to load dashboard.',
|
||||
}),
|
||||
body: error.message,
|
||||
body: (error as { message: string }).message,
|
||||
toastLifeTimeMs: 5000,
|
||||
});
|
||||
}
|
||||
|
@ -254,6 +254,11 @@ class DashboardGridUi extends React.Component<DashboardGridProps, State> {
|
|||
/>
|
||||
));
|
||||
|
||||
// in print mode, dashboard layout is not controlled by React Grid Layout
|
||||
if (viewMode === ViewMode.PRINT) {
|
||||
return <>{dashboardPanels}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<ResponsiveSizedGrid
|
||||
isViewMode={isViewMode}
|
||||
|
|
|
@ -10,9 +10,10 @@ import React, { useState, useRef, useEffect, FC } from 'react';
|
|||
import { EuiLoadingChart } from '@elastic/eui';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { EmbeddableChildPanel } from '../../../services/embeddable';
|
||||
import { EmbeddableChildPanel, ViewMode } from '../../../services/embeddable';
|
||||
import { useLabs } from '../../../services/presentation_util';
|
||||
import { DashboardPanelState } from '../types';
|
||||
import { DashboardContainer } from '..';
|
||||
|
||||
type PanelProps = Pick<EmbeddableChildPanel, 'container' | 'PanelComponent'>;
|
||||
type DivProps = Pick<React.HTMLAttributes<HTMLDivElement>, 'className' | 'style' | 'children'>;
|
||||
|
@ -20,6 +21,7 @@ type DivProps = Pick<React.HTMLAttributes<HTMLDivElement>, 'className' | 'style'
|
|||
interface Props extends PanelProps, DivProps {
|
||||
id: DashboardPanelState['explicitInput']['id'];
|
||||
type: DashboardPanelState['type'];
|
||||
container: DashboardContainer;
|
||||
focusedPanelId?: string;
|
||||
expandedPanelId?: string;
|
||||
key: string;
|
||||
|
@ -52,6 +54,8 @@ const Item = React.forwardRef<HTMLDivElement, Props>(
|
|||
'dshDashboardGrid__item--expanded': expandPanel,
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
'dshDashboardGrid__item--hidden': hidePanel,
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
printViewport__vis: container.getInput().viewMode === ViewMode.PRINT,
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -116,7 +120,8 @@ export const ObservedItem: FC<Props> = (props: Props) => {
|
|||
|
||||
export const DashboardGridItem: FC<Props> = (props: Props) => {
|
||||
const { isProjectEnabled } = useLabs();
|
||||
const isEnabled = isProjectEnabled('labs:dashboard:deferBelowFold');
|
||||
const isPrintMode = props.container.getInput().viewMode === ViewMode.PRINT;
|
||||
const isEnabled = !isPrintMode && isProjectEnabled('labs:dashboard:deferBelowFold');
|
||||
|
||||
return isEnabled ? <ObservedItem {...props} /> : <Item {...props} />;
|
||||
};
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
@import './dashboard_viewport';
|
||||
@import './print_viewport';
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
.printViewport {
|
||||
&__vis {
|
||||
height: 600px; // These values might need to be passed in as dimensions for the report. I.e., print should use layout dimensions.
|
||||
width: 975px;
|
||||
|
||||
// Some vertical space between vis, but center horizontally
|
||||
margin: 10px auto;
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import {
|
|||
CONTACT_CARD_EMBEDDABLE,
|
||||
} from '../../../../../embeddable/public/lib/test_samples';
|
||||
import { getStubPluginServices } from '../../../../../presentation_util/public';
|
||||
import { screenshotModePluginMock } from '../../../../../screenshot_mode/public/mocks';
|
||||
|
||||
let dashboardContainer: DashboardContainer | undefined;
|
||||
const presentationUtil = getStubPluginServices();
|
||||
|
@ -65,6 +66,7 @@ function getProps(props?: Partial<DashboardViewportProps>): {
|
|||
getTriggerCompatibleActions: (() => []) as any,
|
||||
} as any,
|
||||
presentationUtil,
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
};
|
||||
|
||||
const input = getSampleDashboardInput({
|
||||
|
|
|
@ -52,7 +52,6 @@ const createDashboardAppStateProps = (): UseDashboardStateProps => ({
|
|||
savedDashboardId: 'testDashboardId',
|
||||
history: createBrowserHistory(),
|
||||
isEmbeddedExternally: false,
|
||||
redirectTo: jest.fn(),
|
||||
});
|
||||
|
||||
const createDashboardAppStateServices = () => {
|
||||
|
|
|
@ -22,7 +22,6 @@ import {
|
|||
DashboardBuildContext,
|
||||
DashboardAppServices,
|
||||
DashboardAppState,
|
||||
DashboardRedirect,
|
||||
DashboardState,
|
||||
} from '../../types';
|
||||
import { DashboardAppLocatorParams } from '../../locator';
|
||||
|
@ -44,14 +43,12 @@ import {
|
|||
export interface UseDashboardStateProps {
|
||||
history: History;
|
||||
savedDashboardId?: string;
|
||||
redirectTo: DashboardRedirect;
|
||||
isEmbeddedExternally: boolean;
|
||||
kbnUrlStateStorage: IKbnUrlStateStorage;
|
||||
}
|
||||
|
||||
export const useDashboardAppState = ({
|
||||
history,
|
||||
redirectTo,
|
||||
savedDashboardId,
|
||||
kbnUrlStateStorage,
|
||||
isEmbeddedExternally,
|
||||
|
@ -184,12 +181,20 @@ export const useDashboardAppState = ({
|
|||
savedDashboard,
|
||||
});
|
||||
|
||||
// Backwards compatible way of detecting that we are taking a screenshot
|
||||
const legacyPrintLayoutDetected =
|
||||
screenshotModeService?.isScreenshotMode() &&
|
||||
screenshotModeService.getScreenshotLayout() === 'print';
|
||||
|
||||
const initialDashboardState = {
|
||||
...savedDashboardState,
|
||||
...dashboardSessionStorageState,
|
||||
...initialDashboardStateFromUrl,
|
||||
...forwardedAppState,
|
||||
|
||||
// if we are in legacy print mode, dashboard needs to be in print viewMode
|
||||
...(legacyPrintLayoutDetected ? { viewMode: ViewMode.PRINT } : {}),
|
||||
|
||||
// if there is an incoming embeddable, dashboard always needs to be in edit mode to receive it.
|
||||
...(incomingEmbeddable ? { viewMode: ViewMode.EDIT } : {}),
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@ import { DashboardAppServices, DashboardAppCapabilities } from '../../types';
|
|||
import { embeddablePluginMock } from '../../../../embeddable/public/mocks';
|
||||
import { IndexPatternsContract, SavedQueryService } from '../../services/data';
|
||||
import { savedObjectsPluginMock } from '../../../../saved_objects/public/mocks';
|
||||
import { screenshotModePluginMock } from '../../../../screenshot_mode/public/mocks';
|
||||
import { visualizationsPluginMock } from '../../../../visualizations/public/mocks';
|
||||
import { PluginInitializerContext, ScopedHistory } from '../../../../../core/public';
|
||||
import { SavedObjectLoader, SavedObjectLoaderFindOptions } from '../../services/saved_objects';
|
||||
|
@ -72,6 +73,7 @@ export function makeDefaultServices(): DashboardAppServices {
|
|||
} as PluginInitializerContext;
|
||||
|
||||
return {
|
||||
screenshotModeService: screenshotModePluginMock.createSetupContract(),
|
||||
visualizations: visualizationsPluginMock.createStartContract(),
|
||||
savedObjects: savedObjectsPluginMock.createStartContract(),
|
||||
embeddable: embeddablePluginMock.createInstance().doStart(),
|
||||
|
|
|
@ -14,6 +14,7 @@ export const DashboardConstants = {
|
|||
LANDING_PAGE_PATH: '/list',
|
||||
CREATE_NEW_DASHBOARD_URL: '/create',
|
||||
VIEW_DASHBOARD_URL: '/view',
|
||||
PRINT_DASHBOARD_URL: '/print',
|
||||
ADD_EMBEDDABLE_ID: 'addEmbeddableId',
|
||||
ADD_EMBEDDABLE_TYPE: 'addEmbeddableType',
|
||||
DASHBOARDS_ID: 'dashboards',
|
||||
|
|
|
@ -128,6 +128,7 @@ export class DashboardAppLocatorDefinition implements LocatorDefinition<Dashboar
|
|||
...restParams
|
||||
} = params;
|
||||
const useHash = paramsUseHash ?? this.deps.useHashedUrl;
|
||||
|
||||
const hash = dashboardId ? `view/${dashboardId}` : `create`;
|
||||
|
||||
const getSavedFiltersFromDestinationDashboardIfNeeded = async (): Promise<Filter[]> => {
|
||||
|
|
|
@ -12,7 +12,6 @@ import { filter, map } from 'rxjs/operators';
|
|||
|
||||
import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
|
||||
import { UrlForwardingSetup, UrlForwardingStart } from 'src/plugins/url_forwarding/public';
|
||||
import { ScreenshotModePluginStart } from 'src/plugins/screenshot_mode/public';
|
||||
import { APP_WRAPPER_CLASS } from '../../../core/public';
|
||||
import {
|
||||
App,
|
||||
|
@ -37,6 +36,10 @@ import { NavigationPublicPluginStart as NavigationStart } from './services/navig
|
|||
import { DataPublicPluginSetup, DataPublicPluginStart, esFilters } from './services/data';
|
||||
import { SharePluginSetup, SharePluginStart, UrlGeneratorContract } from './services/share';
|
||||
import type { SavedObjectTaggingOssPluginStart } from './services/saved_objects_tagging_oss';
|
||||
import type {
|
||||
ScreenshotModePluginSetup,
|
||||
ScreenshotModePluginStart,
|
||||
} from './services/screenshot_mode';
|
||||
import {
|
||||
getSavedObjectFinder,
|
||||
SavedObjectLoader,
|
||||
|
@ -102,6 +105,7 @@ export interface DashboardSetupDependencies {
|
|||
share?: SharePluginSetup;
|
||||
uiActions: UiActionsSetup;
|
||||
usageCollection?: UsageCollectionSetup;
|
||||
screenshotMode: ScreenshotModePluginSetup;
|
||||
}
|
||||
|
||||
export interface DashboardStartDependencies {
|
||||
|
@ -116,9 +120,9 @@ export interface DashboardStartDependencies {
|
|||
savedObjects: SavedObjectsStart;
|
||||
presentationUtil: PresentationUtilPluginStart;
|
||||
savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart;
|
||||
screenshotMode?: ScreenshotModePluginStart;
|
||||
spaces?: SpacesPluginStart;
|
||||
visualizations: VisualizationsStart;
|
||||
screenshotMode: ScreenshotModePluginStart;
|
||||
}
|
||||
|
||||
export interface DashboardSetup {
|
||||
|
@ -162,7 +166,15 @@ export class DashboardPlugin
|
|||
|
||||
public setup(
|
||||
core: CoreSetup<DashboardStartDependencies, DashboardStart>,
|
||||
{ share, embeddable, home, urlForwarding, data, usageCollection }: DashboardSetupDependencies
|
||||
{
|
||||
share,
|
||||
embeddable,
|
||||
home,
|
||||
urlForwarding,
|
||||
data,
|
||||
usageCollection,
|
||||
screenshotMode,
|
||||
}: DashboardSetupDependencies
|
||||
): DashboardSetup {
|
||||
this.dashboardFeatureFlagConfig =
|
||||
this.initializerContext.config.get<DashboardFeatureFlagConfig>();
|
||||
|
@ -197,6 +209,7 @@ export class DashboardPlugin
|
|||
embeddable: deps.embeddable,
|
||||
uiActions: deps.uiActions,
|
||||
inspector: deps.inspector,
|
||||
screenshotMode: deps.screenshotMode,
|
||||
http: coreStart.http,
|
||||
ExitFullScreenButton,
|
||||
presentationUtil: deps.presentationUtil,
|
||||
|
|
14
src/plugins/dashboard/public/services/screenshot_mode.ts
Normal file
14
src/plugins/dashboard/public/services/screenshot_mode.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export type {
|
||||
ScreenshotModePluginStart,
|
||||
ScreenshotModePluginSetup,
|
||||
} from '../../../screenshot_mode/public';
|
||||
|
||||
export type { Layout } from '../../../screenshot_mode/common';
|
|
@ -19,7 +19,6 @@ import type {
|
|||
import { History } from 'history';
|
||||
import { AnyAction, Dispatch } from 'redux';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
import { ScreenshotModePluginStart } from 'src/plugins/screenshot_mode/public';
|
||||
import { Query, Filter, IndexPattern, RefreshInterval, TimeRange } from './services/data';
|
||||
import { ContainerInput, EmbeddableInput, ViewMode } from './services/embeddable';
|
||||
import { SharePluginStart } from './services/share';
|
||||
|
@ -33,6 +32,7 @@ import { SavedObjectsTaggingApi } from './services/saved_objects_tagging_oss';
|
|||
import { DataPublicPluginStart, IndexPatternsContract } from './services/data';
|
||||
import { SavedObjectLoader, SavedObjectsStart } from './services/saved_objects';
|
||||
import { IKbnUrlStateStorage } from './services/kibana_utils';
|
||||
import type { ScreenshotModePluginStart } from './services/screenshot_mode';
|
||||
import type { DashboardContainer, DashboardSavedObject } from '.';
|
||||
import { VisualizationsStart } from '../../visualizations/public';
|
||||
import { DashboardAppLocatorParams } from './locator';
|
||||
|
@ -206,9 +206,9 @@ export interface DashboardAppServices {
|
|||
onAppLeave: AppMountParameters['onAppLeave'];
|
||||
savedObjectsTagging?: SavedObjectsTaggingApi;
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
screenshotModeService: ScreenshotModePluginStart;
|
||||
dashboardSessionStorage: DashboardSessionStorage;
|
||||
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
|
||||
savedQueryService: DataPublicPluginStart['query']['savedQueries'];
|
||||
spacesService?: SpacesPluginStart;
|
||||
screenshotModeService?: ScreenshotModePluginStart;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import { PersistableStateService, PersistableState } from '../../kibana_utils/co
|
|||
export enum ViewMode {
|
||||
EDIT = 'edit',
|
||||
PREVIEW = 'preview',
|
||||
PRINT = 'print',
|
||||
VIEW = 'view',
|
||||
}
|
||||
|
||||
|
|
|
@ -251,7 +251,7 @@ export class EmbeddablePanel extends React.Component<Props, State> {
|
|||
};
|
||||
|
||||
public render() {
|
||||
const viewOnlyMode = this.state.viewMode === ViewMode.VIEW;
|
||||
const viewOnlyMode = [ViewMode.VIEW, ViewMode.PRINT].includes(this.state.viewMode);
|
||||
const classes = classNames('embPanel', {
|
||||
'embPanel--editing': !viewOnlyMode,
|
||||
'embPanel--loading': this.state.loading,
|
||||
|
|
|
@ -10,6 +10,7 @@ import { take } from 'rxjs/operators';
|
|||
import { coreMock } from '../../../core/public/mocks';
|
||||
import { NewsfeedPublicPlugin } from './plugin';
|
||||
import { NewsfeedApiEndpoint } from './lib/api';
|
||||
import { screenshotModePluginMock } from '../../screenshot_mode/public/mocks';
|
||||
|
||||
describe('Newsfeed plugin', () => {
|
||||
let plugin: NewsfeedPublicPlugin;
|
||||
|
@ -46,7 +47,7 @@ describe('Newsfeed plugin', () => {
|
|||
describe('base case', () => {
|
||||
it('makes fetch requests', () => {
|
||||
const startContract = plugin.start(coreMock.createStart(), {
|
||||
screenshotMode: { isScreenshotMode: () => false },
|
||||
screenshotMode: screenshotModePluginMock.createSetupContract(),
|
||||
});
|
||||
const sub = startContract
|
||||
.createNewsFeed$(NewsfeedApiEndpoint.KIBANA) // Any endpoint will do
|
||||
|
@ -60,8 +61,10 @@ describe('Newsfeed plugin', () => {
|
|||
|
||||
describe('when in screenshot mode', () => {
|
||||
it('makes no fetch requests in screenshot mode', () => {
|
||||
const screenshotMode = screenshotModePluginMock.createSetupContract();
|
||||
screenshotMode.isScreenshotMode.mockReturnValue(true);
|
||||
const startContract = plugin.start(coreMock.createStart(), {
|
||||
screenshotMode: { isScreenshotMode: () => true },
|
||||
screenshotMode,
|
||||
});
|
||||
const sub = startContract
|
||||
.createNewsFeed$(NewsfeedApiEndpoint.KIBANA) // Any endpoint will do
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
// **PLEASE NOTE**
|
||||
// The functionality in this file targets a browser environment and is intended to be used both in public and server.
|
||||
// The functionality in this file targets a browser environment AND is intended to be used both in public and server.
|
||||
// For instance, reporting uses these functions when starting puppeteer to set the current browser into "screenshot" mode.
|
||||
|
||||
export const KBN_SCREENSHOT_MODE_ENABLED_KEY = '__KBN_SCREENSHOT_MODE_ENABLED_KEY__';
|
||||
|
@ -61,3 +61,31 @@ export const setScreenshotModeDisabled = () => {
|
|||
}
|
||||
);
|
||||
};
|
||||
|
||||
/** @deprecated */
|
||||
export const KBN_SCREENSHOT_MODE_LAYOUT_KEY = '__KBN_SCREENSHOT_MODE_LAYOUT_KEY__';
|
||||
|
||||
/** @deprecated */
|
||||
export type Layout = 'canvas' | 'preserve_layout' | 'print';
|
||||
|
||||
/** @deprecated */
|
||||
export const setScreenshotLayout = (value: Layout) => {
|
||||
Object.defineProperty(
|
||||
window,
|
||||
'__KBN_SCREENSHOT_MODE_LAYOUT_KEY__', // Literal value to prevent adding an external reference
|
||||
{
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
configurable: false,
|
||||
value,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/** @deprecated */
|
||||
export const getScreenshotLayout = (): undefined | Layout => {
|
||||
return (
|
||||
(window as unknown as Record<string, Layout>)[KBN_SCREENSHOT_MODE_LAYOUT_KEY] ||
|
||||
(window.localStorage.getItem(KBN_SCREENSHOT_MODE_LAYOUT_KEY) as Layout)
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,6 +11,11 @@ export {
|
|||
setScreenshotModeEnabled,
|
||||
setScreenshotModeDisabled,
|
||||
KBN_SCREENSHOT_MODE_ENABLED_KEY,
|
||||
KBN_SCREENSHOT_MODE_LAYOUT_KEY,
|
||||
setScreenshotLayout,
|
||||
getScreenshotLayout,
|
||||
} from './get_set_browser_screenshot_mode';
|
||||
|
||||
export type { Layout } from './get_set_browser_screenshot_mode';
|
||||
|
||||
export { KBN_SCREENSHOT_MODE_HEADER } from './constants';
|
||||
|
|
|
@ -11,9 +11,11 @@ import type { ScreenshotModePluginSetup, ScreenshotModePluginStart } from './typ
|
|||
|
||||
export const screenshotModePluginMock = {
|
||||
createSetupContract: (): DeeplyMockedKeys<ScreenshotModePluginSetup> => ({
|
||||
getScreenshotLayout: jest.fn(),
|
||||
isScreenshotMode: jest.fn(() => false),
|
||||
}),
|
||||
createStartContract: (): DeeplyMockedKeys<ScreenshotModePluginStart> => ({
|
||||
getScreenshotLayout: jest.fn(),
|
||||
isScreenshotMode: jest.fn(() => false),
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -10,11 +10,12 @@ import { CoreSetup, CoreStart, Plugin } from '../../../core/public';
|
|||
|
||||
import { ScreenshotModePluginSetup, ScreenshotModePluginStart } from './types';
|
||||
|
||||
import { getScreenshotMode } from '../common';
|
||||
import { getScreenshotMode, getScreenshotLayout } from '../common';
|
||||
|
||||
export class ScreenshotModePlugin implements Plugin<ScreenshotModePluginSetup> {
|
||||
private publicContract = Object.freeze({
|
||||
isScreenshotMode: () => getScreenshotMode() === true,
|
||||
getScreenshotLayout,
|
||||
});
|
||||
|
||||
public setup(core: CoreSetup): ScreenshotModePluginSetup {
|
||||
|
|
|
@ -6,12 +6,17 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { Layout } from '../common';
|
||||
|
||||
export interface IScreenshotModeService {
|
||||
/**
|
||||
* Returns a boolean indicating whether the current user agent (browser) would like to view UI optimized for
|
||||
* screenshots or printing.
|
||||
*/
|
||||
isScreenshotMode: () => boolean;
|
||||
|
||||
/** @deprecated */
|
||||
getScreenshotLayout: () => undefined | Layout;
|
||||
}
|
||||
|
||||
export type ScreenshotModePluginSetup = IScreenshotModeService;
|
||||
|
|
|
@ -30,10 +30,11 @@ export class ScreenshotModePlugin
|
|||
// We use "require" here to ensure the import does not have external references due to code bundling that
|
||||
// commonly happens during transpiling. External references would be missing in the environment puppeteer creates.
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { setScreenshotModeEnabled } = require('../common');
|
||||
const { setScreenshotModeEnabled, setScreenshotLayout } = require('../common');
|
||||
|
||||
return {
|
||||
setScreenshotModeEnabled,
|
||||
setScreenshotLayout,
|
||||
isScreenshotMode,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { RequestHandlerContext, KibanaRequest } from 'src/core/server';
|
||||
import type { RequestHandlerContext, KibanaRequest } from 'src/core/server';
|
||||
import type { Layout } from '../common';
|
||||
|
||||
/**
|
||||
* Any context that requires access to the screenshot mode flag but does not have access
|
||||
|
@ -23,6 +24,9 @@ export interface ScreenshotModePluginSetup {
|
|||
* on the page have run to ensure that screenshot mode is detected as early as possible.
|
||||
*/
|
||||
setScreenshotModeEnabled: () => void;
|
||||
|
||||
/** @deprecated */
|
||||
setScreenshotLayout: (value: Layout) => void;
|
||||
}
|
||||
|
||||
export interface ScreenshotModePluginStart {
|
||||
|
|
|
@ -17,7 +17,7 @@ import { ReportingCore } from '../../..';
|
|||
import { KBN_SCREENSHOT_MODE_HEADER } from '../../../../../../../src/plugins/screenshot_mode/server';
|
||||
import { ConditionalHeaders, ConditionalHeadersConditions } from '../../../export_types/common';
|
||||
import { LevelLogger } from '../../../lib';
|
||||
import { ViewZoomWidthHeight } from '../../../lib/layouts/layout';
|
||||
import { Layout, ViewZoomWidthHeight } from '../../../lib/layouts/layout';
|
||||
import { ElementPosition } from '../../../lib/screenshots';
|
||||
import { allowRequest, NetworkPolicy } from '../../network_policy';
|
||||
|
||||
|
@ -97,11 +97,13 @@ export class HeadlessChromiumDriver {
|
|||
waitForSelector: pageLoadSelector,
|
||||
timeout,
|
||||
locator,
|
||||
layout,
|
||||
}: {
|
||||
conditionalHeaders: ConditionalHeaders;
|
||||
waitForSelector: string;
|
||||
timeout: number;
|
||||
locator?: LocatorParams;
|
||||
layout?: Layout;
|
||||
},
|
||||
logger: LevelLogger
|
||||
): Promise<void> {
|
||||
|
@ -116,6 +118,10 @@ export class HeadlessChromiumDriver {
|
|||
*/
|
||||
await this.page.evaluateOnNewDocument(this.core.getEnableScreenshotMode());
|
||||
|
||||
if (layout) {
|
||||
await this.page.evaluateOnNewDocument(this.core.getSetScreenshotLayout(), layout.id);
|
||||
}
|
||||
|
||||
if (locator) {
|
||||
await this.page.evaluateOnNewDocument(
|
||||
(key: string, value: unknown) => {
|
||||
|
|
|
@ -253,9 +253,16 @@ export class ReportingCore {
|
|||
.toPromise();
|
||||
}
|
||||
|
||||
private getScreenshotModeDep() {
|
||||
return this.getPluginSetupDeps().screenshotMode;
|
||||
}
|
||||
|
||||
public getEnableScreenshotMode() {
|
||||
const { screenshotMode } = this.getPluginSetupDeps();
|
||||
return screenshotMode.setScreenshotModeEnabled;
|
||||
return this.getScreenshotModeDep().setScreenshotModeEnabled;
|
||||
}
|
||||
|
||||
public getSetScreenshotLayout() {
|
||||
return this.getScreenshotModeDep().setScreenshotLayout;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
******
|
||||
*/
|
||||
|
||||
/**
|
||||
/**
|
||||
* global
|
||||
*/
|
||||
|
||||
|
@ -27,7 +27,6 @@ filter-bar,
|
|||
* Discover Tweaks
|
||||
*/
|
||||
|
||||
|
||||
/* hide unusable controls */
|
||||
discover-app .dscTimechart,
|
||||
discover-app .dscSidebar__container,
|
||||
|
@ -36,7 +35,6 @@ discover-app .discover-table-footer {
|
|||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The global banner (e.g. "Help us improve Elastic...") should not print.
|
||||
*/
|
||||
|
@ -73,7 +71,8 @@ discover-app .discover-table-footer {
|
|||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0; left: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import { CustomPageSize } from 'pdfmake/interfaces';
|
||||
import { LAYOUT_TYPES } from '../../../common/constants';
|
||||
|
@ -37,6 +36,7 @@ export class PreserveLayout extends Layout implements LayoutInstance {
|
|||
}
|
||||
|
||||
public getCssOverridesPath() {
|
||||
// TODO: Remove this path once we have migrated all plugins away from depending on this hiding page elements.
|
||||
return path.join(__dirname, 'preserve_layout.css');
|
||||
}
|
||||
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
******
|
||||
****** This is a collection of CSS overrides that make Kibana look better for
|
||||
****** generating PDF reports with headless browser
|
||||
******
|
||||
*/
|
||||
|
||||
/**
|
||||
* global
|
||||
*/
|
||||
|
||||
/* elements can hide themselves when shared */
|
||||
.hide-for-sharing {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* hide unusable controls */
|
||||
kbn-top-nav,
|
||||
filter-bar,
|
||||
.kbnTopNavMenu__wrapper,
|
||||
::-webkit-scrollbar,
|
||||
.euiNavDrawer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover Tweaks
|
||||
*/
|
||||
|
||||
/* hide unusable controls */
|
||||
discover-app .dscTimechart,
|
||||
discover-app .dscSidebar__container,
|
||||
discover-app .dscCollapsibleSidebar__collapseButton,
|
||||
discover-app .discover-table-footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* The global banner (e.g. "Help us improve Elastic...") should not print.
|
||||
*/
|
||||
|
||||
#globalBannerList {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visualize Editor Tweaks
|
||||
*/
|
||||
|
||||
/* hide unusable controls
|
||||
* !important is required to override resizable panel inline display */
|
||||
.visEditor__content .visEditor--default > :not(.visEditor__visualization__wrapper) {
|
||||
display: none !important;
|
||||
}
|
||||
/** THIS IS FOR TSVB UNTIL REFACTOR **/
|
||||
.tvbEditorVisualization {
|
||||
position: static !important;
|
||||
}
|
||||
.visualize .tvbVisTimeSeries__legendToggle,
|
||||
.tvbEditor--hideForReporting {
|
||||
/* all non-content rows in interface */
|
||||
display: none;
|
||||
}
|
||||
/** END TSVB BAD BAD HACKS **/
|
||||
|
||||
/* remove left padding from visualizations so that map lines up with .leaflet-container and
|
||||
* setting the position to be fixed and to take up the entire screen, because some zoom levels/viewports
|
||||
* are triggering the media breakpoints that cause the .visEditor__canvas to take up more room than the viewport */
|
||||
.visEditor .visEditor__canvas {
|
||||
padding-left: 0px;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visualization tweaks
|
||||
*/
|
||||
|
||||
/* hide unusable controls */
|
||||
.visualize .visLegend__toggle,
|
||||
.visualize .kbnAggTable__controls/* export raw, export formatted, etc. */,
|
||||
.visualize .leaflet-container .leaflet-top.leaflet-left/* tilemap controls */,
|
||||
.visualize paginate-controls {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Ensure the min-height of the small breakpoint isn't used */
|
||||
.vis-editor visualization {
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard tweaks
|
||||
*/
|
||||
|
||||
.dashboardViewport .embPanel__header {
|
||||
/* hide the panel heading with the controls and title */
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.dashboardViewport .euiPanel {
|
||||
/* Remove the border from the eui panel */
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Reporting manually makes each visualization it wants to screenshot larger, so we need to hide
|
||||
* the visualizations in the other panels. We can only use properties that will be manually set in
|
||||
* reporting/export_types/printable_pdf/lib/screenshot.js or this will also hide the visualization
|
||||
* we want to capture.
|
||||
* 2. React grid item's transform affects the visualizations, even when they are using fixed positioning. Chrome seems
|
||||
* to handle this fine, but firefox moves the visualizations around.
|
||||
*/
|
||||
.dashboardViewport .react-grid-item {
|
||||
height: 0 !important; /* 1. */
|
||||
width: 0 !important; /* 1. */
|
||||
transform: none !important; /* 2. */
|
||||
-webkit-transform: none !important; /* 2. */
|
||||
}
|
|
@ -5,13 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import { PageOrientation, PredefinedPageSize } from 'pdfmake/interfaces';
|
||||
import { EvaluateFn, SerializableOrJSHandle } from 'puppeteer';
|
||||
import { LevelLogger } from '../';
|
||||
import { DEFAULT_VIEWPORT, LAYOUT_TYPES } from '../../../common/constants';
|
||||
import { Size } from '../../../common/types';
|
||||
import { HeadlessChromiumDriver } from '../../browsers';
|
||||
import { CaptureConfig } from '../../types';
|
||||
import { getDefaultLayoutSelectors, LayoutInstance, LayoutSelectorDictionary } from './';
|
||||
import { Layout } from './layout';
|
||||
|
@ -31,7 +26,7 @@ export class PrintLayout extends Layout implements LayoutInstance {
|
|||
}
|
||||
|
||||
public getCssOverridesPath() {
|
||||
return path.join(__dirname, 'print.css');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public getBrowserViewport() {
|
||||
|
@ -49,40 +44,6 @@ export class PrintLayout extends Layout implements LayoutInstance {
|
|||
height: this.viewport.height * itemsCount,
|
||||
};
|
||||
}
|
||||
|
||||
public async positionElements(
|
||||
browser: HeadlessChromiumDriver,
|
||||
logger: LevelLogger
|
||||
): Promise<void> {
|
||||
logger.debug('positioning elements');
|
||||
|
||||
const elementSize: Size = {
|
||||
width: this.viewport.width / this.captureConfig.zoom,
|
||||
height: this.viewport.height / this.captureConfig.zoom,
|
||||
};
|
||||
const evalOptions: { fn: EvaluateFn; args: SerializableOrJSHandle[] } = {
|
||||
fn: (selector: string, height: number, width: number) => {
|
||||
const visualizations = document.querySelectorAll(selector) as NodeListOf<HTMLElement>;
|
||||
const visualizationsLength = visualizations.length;
|
||||
|
||||
for (let i = 0; i < visualizationsLength; i++) {
|
||||
const visualization = visualizations[i];
|
||||
const style = visualization.style;
|
||||
style.position = 'fixed';
|
||||
style.top = `${height * i}px`;
|
||||
style.left = '0';
|
||||
style.width = `${width}px`;
|
||||
style.height = `${height}px`;
|
||||
style.zIndex = '1';
|
||||
style.backgroundColor = 'inherit';
|
||||
}
|
||||
},
|
||||
args: [this.selectors.screenshot, elementSize.height, elementSize.width],
|
||||
};
|
||||
|
||||
await browser.evaluate(evalOptions, { context: 'PositionElements' }, logger);
|
||||
}
|
||||
|
||||
public getPdfImageSize() {
|
||||
return {
|
||||
width: 500,
|
||||
|
|
|
@ -76,6 +76,7 @@ export class ScreenshotObservableHandler {
|
|||
index,
|
||||
urlOrUrlLocatorTuple,
|
||||
this.conditionalHeaders,
|
||||
this.layout,
|
||||
this.logger
|
||||
)
|
||||
).pipe(this.waitUntil(this.timeouts.openUrl));
|
||||
|
|
|
@ -10,6 +10,7 @@ import { LevelLogger, startTrace } from '../';
|
|||
import { LocatorParams, UrlOrUrlLocatorTuple } from '../../../common/types';
|
||||
import { HeadlessChromiumDriver } from '../../browsers';
|
||||
import { ConditionalHeaders } from '../../export_types/common';
|
||||
import { Layout } from '../layouts';
|
||||
import { DEFAULT_PAGELOAD_SELECTOR } from './constants';
|
||||
|
||||
export const openUrl = async (
|
||||
|
@ -18,6 +19,7 @@ export const openUrl = async (
|
|||
index: number,
|
||||
urlOrUrlLocatorTuple: UrlOrUrlLocatorTuple,
|
||||
conditionalHeaders: ConditionalHeaders,
|
||||
layout: undefined | Layout,
|
||||
logger: LevelLogger
|
||||
): Promise<void> => {
|
||||
// If we're moving to another page in the app, we'll want to wait for the app to tell us
|
||||
|
@ -36,7 +38,11 @@ export const openUrl = async (
|
|||
}
|
||||
|
||||
try {
|
||||
await browser.open(url, { conditionalHeaders, waitForSelector, timeout, locator }, logger);
|
||||
await browser.open(
|
||||
url,
|
||||
{ conditionalHeaders, waitForSelector, timeout, locator, layout },
|
||||
logger
|
||||
);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
throw new Error(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue