Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Next Next commit
[engagement] Create engagement plugin PoC
  • Loading branch information
clintandrewhall committed Jan 19, 2022
commit 3aa3697a2538e35bcb96a3c334bff27a3f51858d
1 change: 1 addition & 0 deletions .buildkite/scripts/steps/storybooks/build_and_upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const STORYBOOKS = [
'dashboard_enhanced',
'dashboard',
'data_enhanced',
'engagement',
'embeddable',
'expression_error',
'expression_image',
Expand Down
1 change: 1 addition & 0 deletions .i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"dataViews": "src/plugins/data_views",
"devTools": "src/plugins/dev_tools",
"discover": "src/plugins/discover",
"engagement": "src/plugins/engagement",
"embeddableApi": "src/plugins/embeddable",
"embeddableExamples": "examples/embeddable_examples",
"esQuery": "packages/kbn-es-query/src",
Expand Down
1 change: 1 addition & 0 deletions src/dev/storybook/aliases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const storybookAliases = {
dashboard_enhanced: 'x-pack/plugins/dashboard_enhanced/.storybook',
dashboard: 'src/plugins/dashboard/.storybook',
data_enhanced: 'x-pack/plugins/data_enhanced/.storybook',
engagement: 'src/plugins/engagement/.storybook',
embeddable: 'src/plugins/embeddable/.storybook',
expression_error: 'src/plugins/expression_error/.storybook',
expression_image: 'src/plugins/expression_image/.storybook',
Expand Down
7 changes: 7 additions & 0 deletions src/plugins/engagement/.i18nrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"prefix": "engagement",
"paths": {
"engagement": "."
},
"translations": ["translations/ja-JP.json"]
}
27 changes: 27 additions & 0 deletions src/plugins/engagement/.storybook/decorators.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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 { DecoratorFn } from '@storybook/react';
import { servicesDecorator as sharedUXServicesDecorator } from '../../shared_ux/.storybook/decorators';
import { ServicesProvider } from '../public/services';

const config = {
drift: {
enabled: true,
chatURL: 'https://elasticcloud-production-chat-us-east-1.s3.amazonaws.com/drift-iframe.html',
pocID: '53877975',
pocEmail: 'sergei.poluektov+drift-chat@elasticsearch.com',
pocJWT:
'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1Mzg3Nzk3NSIsImV4cCI6MTY0MjUxNDc0Mn0.CcAZbD8R865UmoHGi27wKn0aH1bzkZXhX449yyDH2Vk',
},
};

export const servicesDecorator: DecoratorFn = (storyFn, context) => (
<ServicesProvider {...config}>{sharedUXServicesDecorator(storyFn, context)}</ServicesProvider>
);
11 changes: 11 additions & 0 deletions src/plugins/engagement/.storybook/main.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.
*/

import { defaultConfig } from '@kbn/storybook';

module.exports = defaultConfig;
21 changes: 21 additions & 0 deletions src/plugins/engagement/.storybook/manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 { addons } from '@storybook/addons';
import { create } from '@storybook/theming';
import { PANEL_ID } from '@storybook/addon-actions';

addons.setConfig({
theme: create({
base: 'light',
brandTitle: 'Engagement Storybook',
brandUrl: 'https://github.com/elastic/kibana/tree/main/src/plugins/engagement',
}),
showPanel: true.valueOf,
selectedPanel: PANEL_ID,
});
12 changes: 12 additions & 0 deletions src/plugins/engagement/.storybook/preview.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 { addDecorator } from '@storybook/react';
import { servicesDecorator } from './decorators';

addDecorator(servicesDecorator);
5 changes: 5 additions & 0 deletions src/plugins/engagement/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# engagement

A Kibana plugin

---
10 changes: 10 additions & 0 deletions src/plugins/engagement/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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_ID = 'engagement';
export const PLUGIN_NAME = 'engagement';
16 changes: 16 additions & 0 deletions src/plugins/engagement/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"id": "engagement",
"version": "1.0.0",
"kibanaVersion": "kibana",
"owner": {
"name": "Shared UX",
"githubTeam": "shared-ux"
},
"description": "A plugin for engaging with the active user.",
"server": true,
"ui": true,
"requiredPlugins": [
"sharedUX"
],
"optionalPlugins": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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 { DriftChat } from './drift_chat';

export default {
title: 'Drift Chat',
description: '',
parameters: {},
};

export const Component = () => {
return (
<div>
<DriftChat />
</div>
);
};
136 changes: 136 additions & 0 deletions src/plugins/engagement/public/components/drift_chat/drift_chat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* 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, useRef, useState, CSSProperties } from 'react';
import { css } from '@emotion/react';
import { useDrift } from '../../services';

type UseDriftType =
| [false]
| [true, string, React.MutableRefObject<HTMLIFrameElement | null>, CSSProperties];

const MESSAGE_READY = 'driftIframeReady';
const MESSAGE_RESIZE = 'driftIframeResize';

const iframeStyle = css`
position: fixed;
botton: 30px;
right: 30px;
display: block;
`;

const getContext = () => {
const { location, navigator, innerHeight, innerWidth } = window;
const { hash, host, hostname, href, origin, pathname, port, protocol, search } = location;
const { language, userAgent } = navigator;
const { title, referrer } = document;

return {
window: {
location: {
hash,
host,
hostname,
href,
origin,
pathname,
port,
protocol,
search,
},
navigator: { language, userAgent },
innerHeight,
innerWidth,
},
document: {
title,
referrer,
},
};
};

const useDriftFrame = (): UseDriftType => {
const chatRef = useRef<HTMLIFrameElement>(null);
const drift = useDrift();
const [style, setStyle] = useState<CSSProperties>({});

useEffect(() => {
const handleMessage = (event: MessageEvent): void => {
const { current: chatIframe } = chatRef;

if (
!drift.enabled ||
!chatIframe?.contentWindow ||
event.source !== chatIframe?.contentWindow
) {
return;
}

const { data: message } = event;
const context = getContext();

switch (message.type) {
case MESSAGE_READY: {
const user = {
id: drift.pocID,
attributes: {
email: drift.pocEmail,
},
jwt: drift.pocJWT,
};

chatIframe.contentWindow.postMessage(
{
type: 'driftSetContext',
data: { context, user },
},
'*'
);
break;
}

case MESSAGE_RESIZE: {
const styles = message.data.styles || ({} as CSSProperties);
setStyle({ ...style, ...styles });
break;
}

default:
break;
}
};

window.addEventListener('message', handleMessage);
return () => window.removeEventListener('message', handleMessage);
}, [drift, style]);

if (drift.enabled) {
return [true, drift.chatURL, chatRef, style];
}

return [false];
};

export const DriftChat = () => {
const [enabled, chatUrl, chatRef, style] = useDriftFrame();

if (!enabled) {
return null;
}

return (
<iframe
css={iframeStyle}
style={style}
data-test-id="drift-chat"
ref={chatRef}
src={chatUrl}
title="Engagment"
/>
);
};
17 changes: 17 additions & 0 deletions src/plugins/engagement/public/components/drift_chat/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.
*/
/* eslint-disable import/no-default-export */

import { DriftChat } from './drift_chat';
export { DriftChat } from './drift_chat';

/**
* Exporting the DriftChat component as a default export so it can be
* loaded by React.lazy.
*/
export default DriftChat;
14 changes: 14 additions & 0 deletions src/plugins/engagement/public/components/index.ts
Original file line number Diff line number Diff line change
@@ -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.
*/

import React from 'react';
import { withSuspense } from '../../../shared_ux/public';

// This could be abstracted away, but defaulting to DriftChat for now.
export const LazyEngagementChat = React.lazy(() => import('./drift_chat'));
export const EngagementChat = withSuspense(LazyEngagementChat);
20 changes: 20 additions & 0 deletions src/plugins/engagement/public/index.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 { PluginInitializerContext } from '../../../core/public';

import { EngagementPlugin } from './plugin';

// This exports static code and TypeScript types,
// as well as, Kibana Platform `plugin()` initializer.
export function plugin(initializerContext: PluginInitializerContext) {
return new EngagementPlugin(initializerContext);
}

export { EngagementPluginSetup, EngagementPluginStart } from './types';
export { EngagementChat, LazyEngagementChat } from './components';
Loading