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

[Screenshot mode] Create plugin to provide "screenshot mode" awareness #99627

Merged
merged 23 commits into from
May 19, 2021
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3bb2aca
initial version of the screenshot mode service
jloleysens May 10, 2021
0472bcf
Merge branch 'master' into screenshot-mode/create-plugin
kibanamachine May 11, 2021
c488af9
Merge branch 'master' into screenshot-mode/create-plugin
kibanamachine May 12, 2021
8a4e1d0
First iteration of client side of screenshot mode plugin
jloleysens May 12, 2021
c48417d
First implementation of server-side logic for detecting
jloleysens May 12, 2021
da45eef
fix some type issues and do a small refactor
jloleysens May 12, 2021
79ed40a
fix size limits, docs and ts issues
jloleysens May 12, 2021
15f05f2
fixed types issues and made sure screenshot mode is correctly detecte…
jloleysens May 14, 2021
c10905b
Merge branch 'master' into screenshot-mode/create-plugin
kibanamachine May 14, 2021
2b10497
Moved the screenshot mode header definition to common
jloleysens May 14, 2021
aaab2af
move require() to screenshotMode plugin
tsullivan May 14, 2021
7dc5c0f
Update chromium_driver.ts
tsullivan May 14, 2021
76242a6
Merge pull request #3 from tsullivan/screenshot-mode/create-plugin
jloleysens May 17, 2021
4f95774
Merge branch 'master' into screenshot-mode/create-plugin
kibanamachine May 17, 2021
69357bf
cleaned up some comments, minor refactor in ReportingCore and
jloleysens May 17, 2021
cb95a41
fix export
jloleysens May 17, 2021
a0b9e3b
Expanded server-side screenshot mode contract with function that
jloleysens May 17, 2021
755db33
added comments to explain use of literal value rather than external r…
jloleysens May 17, 2021
b96bf45
updated comment
jloleysens May 18, 2021
788078c
Merge branch 'master' into screenshot-mode/create-plugin
kibanamachine May 18, 2021
8eb5139
update reporting example
tsullivan May 18, 2021
a6eef5b
Merge pull request #4 from tsullivan/screenshot-mode/create-plugin
jloleysens May 19, 2021
e5af77f
Merge branch 'master' into screenshot-mode/create-plugin
kibanamachine May 19, 2021
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: 4 additions & 0 deletions docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ Content is fetched from the remote (https://feeds.elastic.co and https://feeds-s
oss plugins.


|{kib-repo}blob/{branch}/src/plugins/screenshot_mode/README.md[screenshotMode]
|The service exposed by this plugin informs consumers whether they should optimize for non-interactivity. In this way plugins can avoid loading unnecessary code, data or other services.


|{kib-repo}blob/{branch}/src/plugins/security_oss/README.md[securityOss]
|securityOss is responsible for educating users about Elastic's free security features,
so they can properly protect the data within their clusters.
Expand Down
7 changes: 7 additions & 0 deletions examples/screenshot_mode_example/.i18nrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"prefix": "screenshotModeExample",
"paths": {
"screenshotModeExample": "."
},
"translations": ["translations/ja-JP.json"]
}
9 changes: 9 additions & 0 deletions examples/screenshot_mode_example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# screenshotModeExample

A Kibana plugin

---

## Development

See the [kibana contributing guide](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md) for instructions setting up your development environment.
11 changes: 11 additions & 0 deletions examples/screenshot_mode_example/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* 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 const PLUGIN_NAME = 'Screenshot mode example app';

export const BASE_API_ROUTE = '/api/screenshot_mode_example';
9 changes: 9 additions & 0 deletions examples/screenshot_mode_example/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"id": "screenshotModeExample",
"version": "1.0.0",
"kibanaVersion": "kibana",
"server": true,
"ui": true,
"requiredPlugins": ["navigation", "screenshotMode", "usageCollection"],
"optionalPlugins": []
}
33 changes: 33 additions & 0 deletions examples/screenshot_mode_example/public/application.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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.
*/

import React from 'react';
import ReactDOM from 'react-dom';
import { AppMountParameters, CoreStart } from '../../../src/core/public';
import { AppPluginSetupDependencies, AppPluginStartDependencies } from './types';
import { ScreenshotModeExampleApp } from './components/app';

export const renderApp = (
{ notifications, http }: CoreStart,
{ screenshotMode }: AppPluginSetupDependencies,
{ navigation }: AppPluginStartDependencies,
{ appBasePath, element }: AppMountParameters
) => {
ReactDOM.render(
<ScreenshotModeExampleApp
basename={appBasePath}
notifications={notifications}
http={http}
navigation={navigation}
screenshotMode={screenshotMode}
/>,
element
);

return () => ReactDOM.unmountComponentAtNode(element);
};
122 changes: 122 additions & 0 deletions examples/screenshot_mode_example/public/components/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* 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.
*/

import React, { useEffect } from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';

import {
EuiPage,
EuiPageBody,
EuiPageContent,
EuiPageContentBody,
EuiPageContentHeader,
EuiPageHeader,
EuiTitle,
EuiText,
} from '@elastic/eui';

import { CoreStart } from '../../../../src/core/public';
import { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public';
import {
ScreenshotModePluginSetup,
KBN_SCREENSHOT_MODE_HEADER,
} from '../../../../src/plugins/screenshot_mode/public';

import { PLUGIN_NAME, BASE_API_ROUTE } from '../../common';

interface ScreenshotModeExampleAppDeps {
basename: string;
notifications: CoreStart['notifications'];
http: CoreStart['http'];
navigation: NavigationPublicPluginStart;
screenshotMode: ScreenshotModePluginSetup;
}

export const ScreenshotModeExampleApp = ({
basename,
notifications,
http,
navigation,
screenshotMode,
}: ScreenshotModeExampleAppDeps) => {
const isScreenshotMode = screenshotMode.isScreenshotMode();

useEffect(() => {
// fire and forget
http.get(`${BASE_API_ROUTE}/check_is_screenshot`, {
headers: isScreenshotMode ? { [KBN_SCREENSHOT_MODE_HEADER]: 'true' } : undefined,
});
notifications.toasts.addInfo({
title: 'Welcome to the screenshot example app!',
text: isScreenshotMode
? 'In screenshot mode we want this to remain visible'
: 'In normal mode this toast will disappear eventually',
toastLifeTimeMs: isScreenshotMode ? 360000 : 3000,
});
}, [isScreenshotMode, notifications, http]);
return (
<Router basename={basename}>
<I18nProvider>
<>
<navigation.ui.TopNavMenu
appName={PLUGIN_NAME}
showSearchBar={true}
useDefaultBehaviors={true}
/>
<EuiPage restrictWidth="1000px">
<EuiPageBody>
<EuiPageHeader>
<EuiTitle size="l">
<h1>
<FormattedMessage
id="screenshotModeExample.helloWorldText"
defaultMessage="{name}"
values={{ name: PLUGIN_NAME }}
/>
</h1>
</EuiTitle>
</EuiPageHeader>
<EuiPageContent>
<EuiPageContentHeader>
<EuiTitle>
<h2>
{isScreenshotMode ? (
<FormattedMessage
id="screenshotModeExample.screenshotModeTitle"
defaultMessage="We are in screenshot mode!"
/>
) : (
<FormattedMessage
id="screenshotModeExample.normalModeTitle"
defaultMessage="We are not in screenshot mode!"
/>
)}
</h2>
</EuiTitle>
</EuiPageContentHeader>
<EuiPageContentBody>
<EuiText>
{isScreenshotMode ? (
<p>We detected screenshot mode. The chrome navbar should be hidden.</p>
) : (
<p>
This is how the app looks in normal mode. The chrome navbar should be
visible.
</p>
)}
</EuiText>
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
</>
</I18nProvider>
</Router>
);
};
Empty file.
17 changes: 17 additions & 0 deletions examples/screenshot_mode_example/public/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* 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.
*/

import './index.scss';

import { ScreenshotModeExamplePlugin } from './plugin';

// This exports static code and TypeScript types,
// as well as, Kibana Platform `plugin()` initializer.
export function plugin() {
return new ScreenshotModeExamplePlugin();
}
48 changes: 48 additions & 0 deletions examples/screenshot_mode_example/public/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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.
*/

import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '../../../src/core/public';
import { AppPluginSetupDependencies, AppPluginStartDependencies } from './types';
import { MetricsTracking } from './services';
import { PLUGIN_NAME } from '../common';

export class ScreenshotModeExamplePlugin implements Plugin<void, void> {
uiTracking = new MetricsTracking();

public setup(core: CoreSetup, depsSetup: AppPluginSetupDependencies): void {
const { screenshotMode, usageCollection } = depsSetup;
const isScreenshotMode = screenshotMode.isScreenshotMode();

this.uiTracking.setup({
disableTracking: isScreenshotMode, // In screenshot mode there will be no user interactions to track
usageCollection,
});

// Register an application into the side navigation menu
core.application.register({
id: 'screenshotModeExample',
title: PLUGIN_NAME,
async mount(params: AppMountParameters) {
// Load application bundle
const { renderApp } = await import('./application');
// Get start services as specified in kibana.json
const [coreStart, depsStart] = await core.getStartServices();

// For screenshots we don't need to have the top bar visible
coreStart.chrome.setIsVisible(!isScreenshotMode);

// Render the application
return renderApp(coreStart, depsSetup, depsStart as AppPluginStartDependencies, params);
},
});
}

public start(core: CoreStart): void {}

public stop() {}
}
9 changes: 9 additions & 0 deletions examples/screenshot_mode_example/public/services/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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 { MetricsTracking } from './metrics_tracking';
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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.
*/

import { UiCounterMetricType, METRIC_TYPE } from '@kbn/analytics';
import { PLUGIN_NAME } from '../../common';
import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public';

export class MetricsTracking {
private trackingDisabled = false;
private usageCollection?: UsageCollectionSetup;

private track(eventName: string, type: UiCounterMetricType) {
if (this.trackingDisabled) return;

this.usageCollection?.reportUiCounter(PLUGIN_NAME, type, eventName);
}

public setup({
disableTracking,
usageCollection,
}: {
disableTracking?: boolean;
usageCollection: UsageCollectionSetup;
}) {
this.usageCollection = usageCollection;
if (disableTracking) this.trackingDisabled = true;
}

public trackInit() {
this.track('init', METRIC_TYPE.LOADED);
}
}
20 changes: 20 additions & 0 deletions examples/screenshot_mode_example/public/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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.
*/

import { NavigationPublicPluginStart } from '../../../src/plugins/navigation/public';
import { ScreenshotModePluginSetup } from '../../../src/plugins/screenshot_mode/public';
import { UsageCollectionSetup } from '../../../src/plugins/usage_collection/public';

export interface AppPluginSetupDependencies {
usageCollection: UsageCollectionSetup;
screenshotMode: ScreenshotModePluginSetup;
}

export interface AppPluginStartDependencies {
navigation: NavigationPublicPluginStart;
}
12 changes: 12 additions & 0 deletions examples/screenshot_mode_example/server/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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.
*/

import { PluginInitializerContext } from 'kibana/server';
import { ScreenshotModeExamplePlugin } from './plugin';

export const plugin = (ctx: PluginInitializerContext) => new ScreenshotModeExamplePlugin(ctx);
31 changes: 31 additions & 0 deletions examples/screenshot_mode_example/server/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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.
*/

import { Plugin, PluginInitializerContext, CoreSetup, Logger } from 'kibana/server';
import { ScreenshotModePluginSetup } from '../../../src/plugins/screenshot_mode/server';
import { RouteDependencies } from './types';
import { registerRoutes } from './routes';

export class ScreenshotModeExamplePlugin implements Plugin<void, void> {
log: Logger;
constructor(ctx: PluginInitializerContext) {
this.log = ctx.logger.get();
}
setup(core: CoreSetup, { screenshotMode }: { screenshotMode: ScreenshotModePluginSetup }): void {
const deps: RouteDependencies = {
screenshotMode,
router: core.http.createRouter(),
log: this.log,
};

registerRoutes(deps);
}

start() {}
stop() {}
}
Loading