Skip to content

Commit 4b56959

Browse files
Addressing feedback
1 parent 85f9504 commit 4b56959

File tree

12 files changed

+198
-89
lines changed

12 files changed

+198
-89
lines changed

x-pack/plugins/cloud/.storybook/decorator.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ const services: CloudServices = {
1414
chat: {
1515
enabled: true,
1616
chatURL: 'https://elasticcloud-production-chat-us-east-1.s3.amazonaws.com/drift-iframe.html',
17-
userID: 'user-id',
18-
userEmail: '[email protected]',
19-
// this doesn't affect chat appearance,
20-
// but a user identity in Drift only
21-
identityJWT: 'identity-jwt',
17+
user: {
18+
id: 'user-id',
19+
20+
// this doesn't affect chat appearance,
21+
// but a user identity in Drift only
22+
jwt: 'identity-jwt',
23+
},
2224
},
2325
};
2426

x-pack/plugins/cloud/public/components/chat/iframe.stories.tsx renamed to x-pack/plugins/cloud/public/components/chat/chat.stories.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77

88
import React from 'react';
99

10-
import { Chat } from './iframe';
10+
import { Chat } from './chat';
1111

1212
export default {
13-
title: 'IFRAME Chat',
13+
title: 'Chat Widget',
1414
description: '',
1515
parameters: {},
1616
};

x-pack/plugins/cloud/public/components/chat/iframe.tsx renamed to x-pack/plugins/cloud/public/components/chat/chat.tsx

Lines changed: 24 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import React, { useEffect, useRef, useState, CSSProperties } from 'react';
99
import { css } from '@emotion/react';
1010
import { useChat } from '../../services';
11+
import { getChatContext } from './get_chat_context';
1112

1213
type UseChatType =
1314
| { enabled: false }
@@ -16,55 +17,18 @@ type UseChatType =
1617
src: string;
1718
ref: React.MutableRefObject<HTMLIFrameElement | null>;
1819
style: CSSProperties;
20+
isReady: boolean;
1921
};
2022

2123
const MESSAGE_READY = 'driftIframeReady';
2224
const MESSAGE_RESIZE = 'driftIframeResize';
2325
const MESSAGE_SET_CONTEXT = 'driftSetContext';
2426

25-
const iframeStyle = css`
26-
position: fixed;
27-
botton: 30px;
28-
right: 30px;
29-
display: block;
30-
`;
31-
32-
// We're sending a lot of information to the frame, so this method puts together the specific
33-
// properties, 1/ to avoid leaking too much, and 2/ to enumerate precisely what we're sending.
34-
const getContext = () => {
35-
const { location, navigator, innerHeight, innerWidth } = window;
36-
const { hash, host, hostname, href, origin, pathname, port, protocol, search } = location;
37-
const { language, userAgent } = navigator;
38-
const { title, referrer } = document;
39-
40-
return {
41-
window: {
42-
location: {
43-
hash,
44-
host,
45-
hostname,
46-
href,
47-
origin,
48-
pathname,
49-
port,
50-
protocol,
51-
search,
52-
},
53-
navigator: { language, userAgent },
54-
innerHeight,
55-
innerWidth,
56-
},
57-
document: {
58-
title,
59-
referrer,
60-
},
61-
};
62-
};
63-
64-
const useFrame = (): UseChatType => {
27+
const useChatConfig = (): UseChatType => {
6528
const ref = useRef<HTMLIFrameElement>(null);
6629
const chat = useChat();
6730
const [style, setStyle] = useState<CSSProperties>({});
31+
const [isReady, setIsReady] = useState(false);
6832

6933
useEffect(() => {
7034
const handleMessage = (event: MessageEvent): void => {
@@ -78,17 +42,19 @@ const useFrame = (): UseChatType => {
7842
return;
7943
}
8044

45+
const context = getChatContext();
8146
const { data: message } = event;
82-
const context = getContext();
47+
const { user: userConfig } = chat;
48+
const { id, email, jwt } = userConfig;
8349

8450
switch (message.type) {
8551
case MESSAGE_READY: {
8652
const user = {
87-
id: chat.userID,
53+
id,
8854
attributes: {
89-
email: chat.userEmail,
55+
email,
9056
},
91-
jwt: chat.identityJWT,
57+
jwt,
9258
};
9359

9460
chatIframe.contentWindow.postMessage(
@@ -98,6 +64,9 @@ const useFrame = (): UseChatType => {
9864
},
9965
'*'
10066
);
67+
68+
setIsReady(true);
69+
10170
break;
10271
}
10372

@@ -118,18 +87,25 @@ const useFrame = (): UseChatType => {
11887
}, [chat, style]);
11988

12089
if (chat.enabled) {
121-
return { enabled: true, src: chat.chatURL, ref, style };
90+
return { enabled: true, src: chat.chatURL, ref, style, isReady };
12291
}
12392

12493
return { enabled: false };
12594
};
12695

12796
export const Chat = () => {
128-
const frameProps = useFrame();
97+
const config = useChatConfig();
12998

130-
if (!frameProps.enabled) {
99+
if (!config.enabled) {
131100
return null;
132101
}
133102

134-
return <iframe css={iframeStyle} data-test-id="iframe-chat" title="chat" {...frameProps} />;
103+
const iframeStyle = css`
104+
position: fixed;
105+
botton: 30px;
106+
right: 30px;
107+
visibility: ${config.isReady ? 'visible' : 'hidden'};
108+
`;
109+
110+
return <iframe css={iframeStyle} title="chat" {...config} />;
135111
};
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { getChatContext } from './get_chat_context';
9+
10+
const PROTOCOL = 'http:';
11+
const PORT = '1234';
12+
const HASH = '#/discover?_g=()&_a=()';
13+
const HOST_NAME = 'www.kibana.com';
14+
const PATH_NAME = '/app/kibana';
15+
const HOST = `${HOST_NAME}:${PORT}`;
16+
const ORIGIN = `${PROTOCOL}//${HOST}`;
17+
const HREF = `${ORIGIN}${PATH_NAME}${HASH}`;
18+
const USER_AGENT = 'user-agent';
19+
const LANGUAGE = 'la-ng';
20+
const TITLE = 'title';
21+
const REFERRER = 'referrer';
22+
23+
describe('getChatContext', () => {
24+
const url = new URL(HREF);
25+
26+
test('retreive the context', () => {
27+
Object.defineProperty(window, 'location', { value: url });
28+
Object.defineProperty(window, 'navigator', {
29+
value: {
30+
language: LANGUAGE,
31+
userAgent: USER_AGENT,
32+
},
33+
});
34+
Object.defineProperty(window.document, 'referrer', { value: REFERRER });
35+
window.document.title = TITLE;
36+
37+
const context = getChatContext();
38+
39+
expect(context).toStrictEqual({
40+
window: {
41+
location: {
42+
hash: HASH,
43+
host: HOST,
44+
hostname: HOST_NAME,
45+
href: HREF,
46+
origin: ORIGIN,
47+
pathname: PATH_NAME,
48+
port: PORT,
49+
protocol: PROTOCOL,
50+
search: '',
51+
},
52+
navigator: {
53+
language: LANGUAGE,
54+
userAgent: USER_AGENT,
55+
},
56+
innerHeight: 768,
57+
innerWidth: 1024,
58+
},
59+
document: {
60+
title: TITLE,
61+
referrer: REFERRER,
62+
},
63+
});
64+
});
65+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
export const getChatContext = () => {
9+
const { location, navigator, innerHeight, innerWidth } = window;
10+
const { hash, host, hostname, href, origin, pathname, port, protocol, search } = location;
11+
const { language, userAgent } = navigator;
12+
const { title, referrer } = document;
13+
14+
return {
15+
window: {
16+
location: {
17+
hash,
18+
host,
19+
hostname,
20+
href,
21+
origin,
22+
pathname,
23+
port,
24+
protocol,
25+
search,
26+
},
27+
navigator: { language, userAgent },
28+
innerHeight,
29+
innerWidth,
30+
},
31+
document: {
32+
title,
33+
referrer,
34+
},
35+
};
36+
};

x-pack/plugins/cloud/public/components/chat/index.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,4 @@
55
* 2.0.
66
*/
77

8-
/* eslint-disable import/no-default-export */
9-
10-
import { Chat } from './iframe';
11-
export { Chat } from './iframe';
12-
13-
/**
14-
* Exporting the Chat component as a default export so it can be loaded by React.lazy.
15-
*/
16-
export default Chat;
8+
export { Chat } from './chat';

x-pack/plugins/cloud/public/components/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import React, { Suspense } from 'react';
99
import { EuiErrorBoundary } from '@elastic/eui';
1010

11-
export const LazyChat = React.lazy(() => import('./chat'));
11+
export const LazyChat = React.lazy(() => import('./chat').then(({ Chat }) => ({ default: Chat })));
12+
1213
export const Chat = () => (
1314
<EuiErrorBoundary>
1415
<Suspense fallback={<div />}>

x-pack/plugins/cloud/public/mocks.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ const config = {
2626
chat: {
2727
enabled: true,
2828
chatURL: 'chat-url',
29-
userID: 'user-id',
30-
userEmail: '[email protected]',
31-
identityJWT: 'identity-jwt',
29+
user: {
30+
id: 'user-id',
31+
32+
jwt: 'identity-jwt',
33+
},
3234
},
3335
};
3436

x-pack/plugins/cloud/public/plugin.tsx

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import type { GetChatUserDataResponseBody } from '../common/types';
3232
import { HomePublicPluginSetup } from '../../../../src/plugins/home/public';
3333
import { createUserMenuLinks } from './user_menu_links';
3434
import { getFullCloudUrl } from './utils';
35-
import { ChatService, ServicesProvider } from './services';
35+
import { ChatConfig, ServicesProvider } from './services';
3636

3737
export interface CloudConfigType {
3838
id?: string;
@@ -91,7 +91,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {
9191
private config!: CloudConfigType;
9292
private isCloudEnabled: boolean;
9393
private appSubscription?: Subscription;
94-
private chatService: ChatService = { enabled: false };
94+
private chatConfig: ChatConfig = { enabled: false };
9595

9696
constructor(private readonly initializerContext: PluginInitializerContext) {
9797
this.config = this.initializerContext.config.get<CloudConfigType>();
@@ -179,7 +179,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {
179179

180180
return {
181181
CloudContextProvider: ({ children }) => (
182-
<ServicesProvider chat={this.chatService}>{children}</ServicesProvider>
182+
<ServicesProvider chat={this.chatConfig}>{children}</ServicesProvider>
183183
),
184184
};
185185
}
@@ -303,20 +303,30 @@ export class CloudPlugin implements Plugin<CloudSetup> {
303303
}
304304

305305
private async setupChat({ http, security }: SetupChatDeps) {
306+
if (!this.isCloudEnabled) {
307+
return;
308+
}
309+
306310
const { enabled, chatURL } = this.config.chat;
307311

308312
if (!security || !enabled || !chatURL) {
309313
return;
310314
}
311315

312-
const chatUserData = await http.get<GetChatUserDataResponseBody>(GET_CHAT_USER_DATA_ROUTE_PATH);
316+
const {
317+
email,
318+
id,
319+
token: jwt,
320+
} = await http.get<GetChatUserDataResponseBody>(GET_CHAT_USER_DATA_ROUTE_PATH);
313321

314-
this.chatService = {
322+
this.chatConfig = {
315323
enabled,
316324
chatURL,
317-
userEmail: chatUserData.email,
318-
userID: chatUserData.id,
319-
identityJWT: chatUserData.token,
325+
user: {
326+
email,
327+
id,
328+
jwt,
329+
},
320330
};
321331
}
322332
}

x-pack/plugins/cloud/public/services/index.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,17 @@ interface WithoutChat {
1414
interface WithChat {
1515
enabled: true;
1616
chatURL: string;
17-
identityJWT: string;
18-
userID: string;
19-
userEmail: string;
17+
user: {
18+
jwt: string;
19+
id: string;
20+
email: string;
21+
};
2022
}
2123

22-
export type ChatService = WithChat | WithoutChat;
24+
export type ChatConfig = WithChat | WithoutChat;
2325

2426
export interface CloudServices {
25-
chat: ChatService;
27+
chat: ChatConfig;
2628
}
2729

2830
const ServicesContext = createContext<CloudServices>({ chat: { enabled: false } });
@@ -38,7 +40,7 @@ export function useServices() {
3840
return useContext(ServicesContext);
3941
}
4042

41-
export function useChat(): ChatService {
43+
export function useChat(): ChatConfig {
4244
const { chat } = useServices();
4345
return chat;
4446
}

0 commit comments

Comments
 (0)