@botpress/webchat 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/components/Composer.d.ts +4 -5
- package/dist/components/Composer.js +13 -23
- package/dist/components/Container.d.ts +1 -1
- package/dist/components/Container.js +1 -6
- package/dist/components/ConversationList.d.ts +1 -1
- package/dist/components/ConversationList.js +5 -46
- package/dist/components/Header.d.ts +1 -3
- package/dist/components/Header.js +17 -64
- package/dist/components/VoiceRecorder.js +6 -2
- package/dist/components/common/{Avatar.d.ts → Avatar/index.d.ts} +0 -0
- package/dist/components/common/Avatar/index.js +13 -0
- package/dist/components/common/{BotInfo.d.ts → BotInfo/index.d.ts} +3 -3
- package/dist/components/common/BotInfo/index.js +102 -0
- package/dist/components/common/ConfirmDialog/index.d.ts +11 -0
- package/dist/components/common/ConfirmDialog/index.js +78 -0
- package/dist/components/common/Dialog/index.d.ts +17 -0
- package/dist/components/common/Dialog/index.js +57 -0
- package/dist/components/common/ToolTip/index.d.ts +10 -0
- package/dist/components/common/ToolTip/index.js +163 -0
- package/dist/components/common/ToolTip/utils.d.ts +15 -0
- package/dist/components/common/ToolTip/utils.js +78 -0
- package/dist/components/messages/InlineFeedback.d.ts +2 -1
- package/dist/components/messages/Message.js +2 -25
- package/dist/components/messages/MessageGroup.d.ts +1 -13
- package/dist/components/messages/MessageGroup.js +6 -40
- package/dist/components/messages/MessageList.d.ts +1 -1
- package/dist/components/messages/MessageList.js +8 -31
- package/dist/core/api.d.ts +4 -18
- package/dist/core/api.js +25 -150
- package/dist/core/constants.d.ts +4 -32
- package/dist/core/constants.js +18 -32
- package/dist/core/socket.d.ts +1 -12
- package/dist/core/socket.js +7 -73
- package/dist/{components/Stylesheet.d.ts → icons/Cancel.d.ts} +2 -2
- package/dist/icons/Cancel.js +10 -0
- package/dist/icons/Microphone.d.ts +5 -0
- package/dist/icons/Microphone.js +12 -0
- package/dist/index.d.ts +2 -8
- package/dist/index.js +9 -29
- package/dist/main.d.ts +2 -2
- package/dist/main.js +100 -168
- package/dist/store/composer.js +3 -6
- package/dist/store/index.d.ts +8 -18
- package/dist/store/index.js +98 -136
- package/dist/store/view.d.ts +3 -6
- package/dist/store/view.js +6 -23
- package/dist/translations/index.d.ts +3 -1
- package/dist/translations/index.js +44 -4
- package/dist/typings.d.ts +121 -71
- package/dist/utils/analytics.d.ts +5 -0
- package/dist/utils/analytics.js +37 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +27 -0
- package/dist/utils/storage.d.ts +16 -0
- package/dist/utils/storage.js +129 -0
- package/package.json +4 -3
- package/dist/components/ContextMenu.d.ts +0 -2
- package/dist/components/ContextMenu.js +0 -33
- package/dist/components/OverridableComponent.d.ts +0 -24
- package/dist/components/OverridableComponent.js +0 -50
- package/dist/components/Stylesheet.js +0 -7
- package/dist/components/common/Avatar.js +0 -29
- package/dist/components/common/BotInfo.js +0 -110
- package/dist/icons/CloseChat.d.ts +0 -6
- package/dist/icons/CloseChat.js +0 -9
- package/dist/icons/Send.d.ts +0 -6
- package/dist/icons/Send.js +0 -8
- package/dist/utils.d.ts +0 -8
- package/dist/utils.js +0 -111
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
exports.default = ({ fill = 'black' }) => (react_1.default.createElement("i", null,
|
|
8
|
+
react_1.default.createElement("svg", { version: "1.1", xmlns: "http://www.w3.org/2000/svg", x: "0px", y: "0px", width: "16px", height: "16px", viewBox: "0 0 475.085 475.085", fill: `${fill}` },
|
|
9
|
+
react_1.default.createElement("g", null,
|
|
10
|
+
react_1.default.createElement("g", null,
|
|
11
|
+
react_1.default.createElement("path", { d: "M237.541,328.897c25.128,0,46.632-8.946,64.523-26.83c17.888-17.884,26.833-39.399,26.833-64.525V91.365\n c0-25.126-8.938-46.632-26.833-64.525C284.173,8.951,262.669,0,237.541,0c-25.125,0-46.632,8.951-64.524,26.84\n c-17.893,17.89-26.838,39.399-26.838,64.525v146.177c0,25.125,8.949,46.641,26.838,64.525\n C190.906,319.951,212.416,328.897,237.541,328.897z" }),
|
|
12
|
+
react_1.default.createElement("path", { d: "M396.563,188.15c-3.606-3.617-7.898-5.426-12.847-5.426c-4.944,0-9.226,1.809-12.847,5.426\n c-3.613,3.616-5.421,7.898-5.421,12.845v36.547c0,35.214-12.518,65.333-37.548,90.362c-25.022,25.03-55.145,37.545-90.36,37.545\n c-35.214,0-65.334-12.515-90.365-37.545c-25.028-25.022-37.541-55.147-37.541-90.362v-36.547c0-4.947-1.809-9.229-5.424-12.845\n c-3.617-3.617-7.895-5.426-12.847-5.426c-4.952,0-9.235,1.809-12.85,5.426c-3.618,3.616-5.426,7.898-5.426,12.845v36.547\n c0,42.065,14.04,78.659,42.112,109.776c28.073,31.118,62.762,48.961,104.068,53.526v37.691h-73.089\n c-4.949,0-9.231,1.811-12.847,5.428c-3.617,3.614-5.426,7.898-5.426,12.847c0,4.941,1.809,9.233,5.426,12.847\n c3.616,3.614,7.898,5.428,12.847,5.428h182.719c4.948,0,9.236-1.813,12.847-5.428c3.621-3.613,5.431-7.905,5.431-12.847\n c0-4.948-1.81-9.232-5.431-12.847c-3.61-3.617-7.898-5.428-12.847-5.428h-73.08v-37.691\n c41.299-4.565,75.985-22.408,104.061-53.526c28.076-31.117,42.12-67.711,42.12-109.776v-36.547\n C401.998,196.049,400.185,191.77,396.563,188.15z" }))))));
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { RootStore } from './store';
|
|
3
3
|
import { Config } from './typings';
|
|
4
|
-
export declare const Embedded: (props: any) => ExposedWebChat;
|
|
5
|
-
export declare const Fullscreen: (props: any) => ExposedWebChat;
|
|
6
4
|
interface State {
|
|
7
5
|
store: RootStore;
|
|
8
6
|
}
|
|
@@ -14,10 +12,6 @@ export declare class ExposedWebChat extends React.Component<Props, State> {
|
|
|
14
12
|
constructor(props: Props);
|
|
15
13
|
render(): JSX.Element;
|
|
16
14
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* https://botpress.com/docs/developers/migrate/
|
|
20
|
-
*/
|
|
21
|
-
export { Embedded as embedded } from '.';
|
|
22
|
-
export { Fullscreen as fullscreen } from '.';
|
|
15
|
+
export declare const Embedded: (props: Props) => ExposedWebChat;
|
|
16
|
+
export declare const Fullscreen: (props: Props) => ExposedWebChat;
|
|
23
17
|
export * from './typings';
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
14
|
};
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.
|
|
16
|
+
exports.Fullscreen = exports.Embedded = exports.ExposedWebChat = void 0;
|
|
17
17
|
const mobx_1 = require("mobx");
|
|
18
18
|
const mobx_react_1 = require("mobx-react");
|
|
19
19
|
const react_1 = __importDefault(require("react"));
|
|
@@ -21,14 +21,12 @@ const react_intl_1 = require("react-intl");
|
|
|
21
21
|
const main_1 = __importDefault(require("./main"));
|
|
22
22
|
const store_1 = require("./store");
|
|
23
23
|
const translations_1 = require("./translations");
|
|
24
|
+
const storage_1 = __importDefault(require("./utils/storage"));
|
|
24
25
|
(0, mobx_1.configure)({ enforceActions: 'observed' });
|
|
25
|
-
const Embedded = (props) => new Wrapper(Object.assign(Object.assign({}, props), { fullscreen: false }));
|
|
26
|
-
exports.Embedded = Embedded;
|
|
27
|
-
const Fullscreen = (props) => new Wrapper(Object.assign(Object.assign({}, props), { fullscreen: true }));
|
|
28
|
-
exports.Fullscreen = Fullscreen;
|
|
29
26
|
class ExposedWebChat extends react_1.default.Component {
|
|
30
27
|
constructor(props) {
|
|
31
28
|
super(props);
|
|
29
|
+
window.BP_STORAGE = new storage_1.default(props.config);
|
|
32
30
|
this.state = {
|
|
33
31
|
store: new store_1.RootStore({ fullscreen: props.fullscreen }, props.config)
|
|
34
32
|
};
|
|
@@ -37,32 +35,14 @@ class ExposedWebChat extends react_1.default.Component {
|
|
|
37
35
|
const store = this.state.store;
|
|
38
36
|
const { botUILanguage: locale } = store;
|
|
39
37
|
return (react_1.default.createElement(mobx_react_1.Provider, { store: store },
|
|
40
|
-
react_1.default.createElement(react_intl_1.IntlProvider, { locale: locale, messages: translations_1.translations[locale], defaultLocale: translations_1.defaultLocale },
|
|
41
|
-
react_1.default.createElement(
|
|
42
|
-
react_1.default.createElement(main_1.default, Object.assign({ store: store }, this.props))))));
|
|
38
|
+
react_1.default.createElement(react_intl_1.IntlProvider, { locale: locale, messages: translations_1.translations[locale || translations_1.defaultLocale], defaultLocale: translations_1.defaultLocale },
|
|
39
|
+
react_1.default.createElement(main_1.default, Object.assign({}, this.props)))));
|
|
43
40
|
}
|
|
44
41
|
}
|
|
45
42
|
exports.ExposedWebChat = ExposedWebChat;
|
|
46
|
-
// TODO: what does this observer do?
|
|
47
43
|
const Wrapper = (0, mobx_react_1.observer)(ExposedWebChat);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
var _1 = require(".");
|
|
53
|
-
Object.defineProperty(exports, "embedded", { enumerable: true, get: function () { return _1.Embedded; } });
|
|
54
|
-
var _2 = require(".");
|
|
55
|
-
Object.defineProperty(exports, "fullscreen", { enumerable: true, get: function () { return _2.Fullscreen; } });
|
|
44
|
+
const Embedded = (props) => new Wrapper(Object.assign(Object.assign({}, props), { fullscreen: false }));
|
|
45
|
+
exports.Embedded = Embedded;
|
|
46
|
+
const Fullscreen = (props) => new Wrapper(Object.assign(Object.assign({}, props), { fullscreen: true }));
|
|
47
|
+
exports.Fullscreen = Fullscreen;
|
|
56
48
|
__exportStar(require("./typings"), exports);
|
|
57
|
-
// TODO: export this
|
|
58
|
-
/*
|
|
59
|
-
export {
|
|
60
|
-
Carousel,
|
|
61
|
-
QuickReplies,
|
|
62
|
-
LoginPrompt,
|
|
63
|
-
Text,
|
|
64
|
-
FileMessage,
|
|
65
|
-
FileInput,
|
|
66
|
-
Button
|
|
67
|
-
} from './components/messages/renderer'
|
|
68
|
-
*/
|
package/dist/main.d.ts
CHANGED
|
@@ -9,5 +9,5 @@ declare const _default: React.ForwardRefExoticComponent<import("react-intl").Omi
|
|
|
9
9
|
} & import("mobx-react").IWrappedComponent<unknown>;
|
|
10
10
|
export default _default;
|
|
11
11
|
declare type MainProps = {
|
|
12
|
-
store
|
|
13
|
-
} & WrappedComponentProps & Pick<StoreDef, 'config' | 'initializeChat' | 'botInfo' | 'fetchBotInfo' | 'sendMessage' | '
|
|
12
|
+
store?: RootStore;
|
|
13
|
+
} & WrappedComponentProps & Pick<StoreDef, 'config' | 'initializeChat' | 'botInfo' | 'fetchBotInfo' | 'sendMessage' | 'sendData' | 'intl' | 'updateTyping' | 'updateBotUILanguage' | 'hideChat' | 'showChat' | 'toggleBotInfo' | 'widgetTransition' | 'activeView' | 'isFullscreen' | 'unreadCount' | 'hasUnreadMessages' | 'showWidgetButton' | 'addEventToConversation' | 'clearMessages' | 'updateConfig' | 'mergeConfig' | 'isWebchatReady' | 'incrementUnread' | 'displayWidgetView' | 'resetUnread' | 'setLoadingCompleted' | 'dimensions' | 'updateLastMessage' | 'fetchConversation' | 'setIntlProvider' | 'setSocket' | 'currentConversationId'>;
|
package/dist/main.js
CHANGED
|
@@ -41,161 +41,128 @@ const query_string_1 = __importDefault(require("query-string"));
|
|
|
41
41
|
const react_1 = __importDefault(require("react"));
|
|
42
42
|
const react_intl_1 = require("react-intl");
|
|
43
43
|
const Container_1 = __importDefault(require("./components/Container"));
|
|
44
|
-
const Stylesheet_1 = __importDefault(require("./components/Stylesheet"));
|
|
45
44
|
const constants_1 = __importDefault(require("./core/constants"));
|
|
46
45
|
const socket_1 = __importDefault(require("./core/socket"));
|
|
47
46
|
const Chat_1 = __importDefault(require("./icons/Chat"));
|
|
48
47
|
const utils_1 = require("./utils");
|
|
48
|
+
const analytics_1 = require("./utils/analytics");
|
|
49
49
|
exports.DEFAULT_TYPING_DELAY = 1000;
|
|
50
50
|
class Web extends react_1.default.Component {
|
|
51
51
|
constructor(props) {
|
|
52
52
|
super(props);
|
|
53
53
|
this.hasBeenInitialized = false;
|
|
54
54
|
this.isCurrentConversation = (event) => {
|
|
55
|
-
|
|
56
|
-
return !((_a = this.props.config) === null || _a === void 0 ? void 0 : _a.conversationId) || this.props.config.conversationId === event.conversationId;
|
|
55
|
+
return this.props.currentConversationId === event.conversationId;
|
|
57
56
|
};
|
|
58
|
-
this.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
else if (action === 'mergeConfig') {
|
|
63
|
-
this.props.mergeConfig(payload);
|
|
64
|
-
}
|
|
65
|
-
else if (action === 'sendPayload') {
|
|
66
|
-
yield this.props.sendData(payload);
|
|
57
|
+
this.handleKeyDown = (e) => __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
var _a;
|
|
59
|
+
if (!((_a = this.props.config) === null || _a === void 0 ? void 0 : _a.closeOnEscape)) {
|
|
60
|
+
return;
|
|
67
61
|
}
|
|
68
|
-
|
|
69
|
-
this.props.
|
|
70
|
-
}
|
|
71
|
-
else if (action === 'event') {
|
|
72
|
-
const { type, text } = payload;
|
|
73
|
-
if (type === 'show') {
|
|
74
|
-
this.props.showChat();
|
|
75
|
-
(0, utils_1.trackWebchatState)('show');
|
|
76
|
-
}
|
|
77
|
-
else if (type === 'hide') {
|
|
78
|
-
this.props.hideChat();
|
|
79
|
-
(0, utils_1.trackWebchatState)('hide');
|
|
80
|
-
}
|
|
81
|
-
else if (type === 'toggle') {
|
|
82
|
-
this.props.displayWidgetView ? this.props.showChat() : this.props.hideChat();
|
|
83
|
-
(0, utils_1.trackWebchatState)('toggle');
|
|
84
|
-
}
|
|
85
|
-
else if (type === 'message') {
|
|
86
|
-
(0, utils_1.trackMessage)('sent');
|
|
87
|
-
yield this.props.sendMessage(text);
|
|
88
|
-
}
|
|
89
|
-
else if (type === 'loadConversation') {
|
|
90
|
-
yield this.props.store.fetchConversation(payload.conversationId);
|
|
91
|
-
}
|
|
92
|
-
else if (type === 'toggleBotInfo') {
|
|
93
|
-
this.props.toggleBotInfo();
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
yield this.props.sendData({ type, payload });
|
|
97
|
-
}
|
|
62
|
+
if (e.key === 'Escape') {
|
|
63
|
+
this.props.hideChat();
|
|
98
64
|
}
|
|
99
65
|
});
|
|
100
|
-
this.
|
|
101
|
-
|
|
102
|
-
|
|
66
|
+
this.handleIframeApi = ({ data }) => __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
switch (data.action) {
|
|
68
|
+
case 'configure':
|
|
69
|
+
return this.props.updateConfig(Object.assign({}, constants_1.default.DEFAULT_CONFIG, data.payload));
|
|
70
|
+
case 'mergeConfig':
|
|
71
|
+
return this.props.mergeConfig(data.payload);
|
|
72
|
+
case 'sendPayload':
|
|
73
|
+
return this.props.sendData(data.payload);
|
|
74
|
+
case 'event':
|
|
75
|
+
const { type, text, conversationId } = data.payload;
|
|
76
|
+
if (type === 'show') {
|
|
77
|
+
this.props.showChat();
|
|
78
|
+
(0, analytics_1.trackWebchatState)('show');
|
|
79
|
+
}
|
|
80
|
+
else if (type === 'hide') {
|
|
81
|
+
this.props.hideChat();
|
|
82
|
+
(0, analytics_1.trackWebchatState)('hide');
|
|
83
|
+
}
|
|
84
|
+
else if (type === 'toggle') {
|
|
85
|
+
this.props.displayWidgetView ? this.props.showChat() : this.props.hideChat();
|
|
86
|
+
(0, analytics_1.trackWebchatState)('toggle');
|
|
87
|
+
}
|
|
88
|
+
else if (type === 'message') {
|
|
89
|
+
(0, analytics_1.trackMessage)('sent');
|
|
90
|
+
yield this.props.sendMessage(text);
|
|
91
|
+
}
|
|
92
|
+
else if (type === 'loadConversation') {
|
|
93
|
+
yield this.props.fetchConversation(conversationId);
|
|
94
|
+
}
|
|
95
|
+
else if (type === 'toggleBotInfo') {
|
|
96
|
+
this.props.toggleBotInfo();
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
yield this.props.sendData({ type, payload: data.payload });
|
|
100
|
+
}
|
|
101
|
+
default:
|
|
102
|
+
break;
|
|
103
103
|
}
|
|
104
|
-
};
|
|
104
|
+
});
|
|
105
105
|
this.handleNewMessage = (event) => __awaiter(this, void 0, void 0, function* () {
|
|
106
|
-
var
|
|
106
|
+
var _b;
|
|
107
|
+
if (!this.isCurrentConversation(event)) {
|
|
108
|
+
// don't do anything, it's a message from another conversation
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
107
111
|
if (event.authorId === undefined) {
|
|
108
112
|
const value = (event.payload.type === 'typing' ? event.payload.value : undefined) || exports.DEFAULT_TYPING_DELAY;
|
|
109
113
|
yield this.handleTyping(Object.assign(Object.assign({}, event), { timeInMs: value }));
|
|
110
114
|
}
|
|
111
|
-
if (((
|
|
115
|
+
if (((_b = event.payload) === null || _b === void 0 ? void 0 : _b.type) === 'visit') {
|
|
112
116
|
// don't do anything, it's the system message
|
|
113
117
|
return;
|
|
114
118
|
}
|
|
115
|
-
|
|
116
|
-
// don't do anything, it's a message from another conversation
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
(0, utils_1.trackMessage)('received');
|
|
119
|
+
(0, analytics_1.trackMessage)('received');
|
|
120
120
|
this.props.updateLastMessage(event.conversationId, event);
|
|
121
121
|
yield this.props.addEventToConversation(event);
|
|
122
122
|
// there's no focus on the actual conversation
|
|
123
|
-
if (
|
|
123
|
+
if (!document.hasFocus() || this.props.activeView !== 'side') {
|
|
124
124
|
yield this.playSound();
|
|
125
125
|
this.props.incrementUnread();
|
|
126
126
|
}
|
|
127
127
|
this.handleResetUnreadCount();
|
|
128
|
-
if (!['session_reset'].includes(event.payload.type) && event.id !== this.lastMessageId) {
|
|
129
|
-
this.lastMessageId = event.id;
|
|
130
|
-
yield this.props.store.loadEventInDebugger(event.id);
|
|
131
|
-
}
|
|
132
128
|
});
|
|
133
129
|
this.handleTyping = (event) => __awaiter(this, void 0, void 0, function* () {
|
|
134
|
-
if (!this.isCurrentConversation(event)) {
|
|
135
|
-
// don't do anything, it's a message from another conversation
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
130
|
yield this.props.updateTyping(event);
|
|
139
131
|
});
|
|
140
|
-
this.handleDataMessage = (event) => {
|
|
141
|
-
if (!event || !event.payload) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
const { language } = event.payload;
|
|
145
|
-
if (!language) {
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
this.props.updateBotUILanguage(language);
|
|
149
|
-
};
|
|
150
132
|
this.playSound = (0, debounce_1.default)(() => __awaiter(this, void 0, void 0, function* () {
|
|
151
|
-
|
|
152
|
-
const disableNotificationSound = this.config.disableNotificationSound ===
|
|
153
|
-
? this.props.config.disableNotificationSound
|
|
154
|
-
: this.config.disableNotificationSound;
|
|
133
|
+
var _c;
|
|
134
|
+
const disableNotificationSound = this.config.disableNotificationSound || ((_c = this.props.config) === null || _c === void 0 ? void 0 : _c.disableNotificationSound);
|
|
155
135
|
if (disableNotificationSound || this.audio.readyState < 2) {
|
|
156
136
|
return;
|
|
157
137
|
}
|
|
158
138
|
yield this.audio.play();
|
|
159
139
|
}), constants_1.default.MIN_TIME_BETWEEN_SOUNDS);
|
|
160
140
|
this.handleResetUnreadCount = () => {
|
|
161
|
-
|
|
162
|
-
if (((_a = document.hasFocus) === null || _a === void 0 ? void 0 : _a.call(document)) && this.props.activeView === 'side') {
|
|
141
|
+
if (document.hasFocus() && this.props.activeView === 'side') {
|
|
163
142
|
this.props.resetUnread();
|
|
164
143
|
}
|
|
165
144
|
};
|
|
166
|
-
(0,
|
|
167
|
-
(0, utils_1.initializeAnalytics)();
|
|
145
|
+
(0, analytics_1.initializeAnalytics)();
|
|
168
146
|
}
|
|
169
147
|
componentDidMount() {
|
|
170
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
171
149
|
this.audio = new Audio(require('url:../assets/notification.mp3'));
|
|
172
|
-
this.props.
|
|
150
|
+
this.props.setIntlProvider(this.props.intl);
|
|
173
151
|
window.store = this.props.store;
|
|
174
152
|
window.addEventListener('message', this.handleIframeApi);
|
|
175
|
-
window.addEventListener('keydown',
|
|
176
|
-
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
if (e.key === 'Escape') {
|
|
180
|
-
this.props.hideChat();
|
|
181
|
-
// TODO: what to do with emulator mode?
|
|
182
|
-
if (this.props.config.isEmulator) {
|
|
183
|
-
window.parent.document.getElementById('mainLayout').focus();
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
yield this.load();
|
|
153
|
+
window.addEventListener('keydown', this.handleKeyDown);
|
|
154
|
+
yield this.loadConfig();
|
|
188
155
|
yield this.initializeIfChatDisplayed();
|
|
189
156
|
this.props.setLoadingCompleted();
|
|
190
157
|
});
|
|
191
158
|
}
|
|
192
159
|
componentWillUnmount() {
|
|
193
160
|
window.removeEventListener('message', this.handleIframeApi);
|
|
161
|
+
window.removeEventListener('keydown', this.handleKeyDown);
|
|
194
162
|
}
|
|
195
163
|
componentDidUpdate() {
|
|
196
164
|
if (this.config) {
|
|
197
|
-
|
|
198
|
-
this.initializeIfChatDisplayed();
|
|
165
|
+
void this.initializeIfChatDisplayed();
|
|
199
166
|
}
|
|
200
167
|
}
|
|
201
168
|
initializeIfChatDisplayed() {
|
|
@@ -208,30 +175,24 @@ class Web extends react_1.default.Component {
|
|
|
208
175
|
if (this.isLazySocket() || !this.socket) {
|
|
209
176
|
yield this.initializeSocket();
|
|
210
177
|
}
|
|
211
|
-
yield this.socket.
|
|
212
|
-
this.props.
|
|
178
|
+
yield this.socket.connect();
|
|
179
|
+
this.props.setSocket(this.socket);
|
|
213
180
|
yield this.props.initializeChat();
|
|
214
181
|
}
|
|
215
182
|
});
|
|
216
183
|
}
|
|
217
|
-
|
|
184
|
+
loadConfig() {
|
|
218
185
|
return __awaiter(this, void 0, void 0, function* () {
|
|
219
186
|
this.config = this.extractConfig();
|
|
187
|
+
this.props.updateConfig(this.config);
|
|
220
188
|
if (this.config.exposeStore) {
|
|
221
189
|
const storePath = this.config.chatId ? `${this.config.chatId}.webchat_store` : 'webchat_store';
|
|
222
190
|
(0, set_1.default)(window.parent, storePath, this.props.store);
|
|
223
191
|
}
|
|
224
|
-
if (this.config.overrides) {
|
|
225
|
-
this.loadOverrides(this.config.overrides);
|
|
226
|
-
}
|
|
227
192
|
if (this.config.containerWidth) {
|
|
228
193
|
this.postMessageToParent('setWidth', this.config.containerWidth);
|
|
229
194
|
}
|
|
230
|
-
|
|
231
|
-
yield this.props.setReference();
|
|
232
|
-
}
|
|
233
|
-
// TODO: replace this by frontend configuration
|
|
234
|
-
// await this.props.fetchBotInfo!()
|
|
195
|
+
yield this.props.fetchBotInfo();
|
|
235
196
|
if (!this.isLazySocket()) {
|
|
236
197
|
yield this.initializeSocket();
|
|
237
198
|
}
|
|
@@ -239,69 +200,38 @@ class Web extends react_1.default.Component {
|
|
|
239
200
|
});
|
|
240
201
|
}
|
|
241
202
|
postMessageToParent(type, value) {
|
|
242
|
-
var _a
|
|
243
|
-
(_a = window.parent) === null || _a === void 0 ? void 0 : _a.postMessage({ type, value, chatId:
|
|
203
|
+
var _a;
|
|
204
|
+
(_a = window.parent) === null || _a === void 0 ? void 0 : _a.postMessage({ type, value, chatId: this.config.chatId }, '*');
|
|
244
205
|
}
|
|
245
206
|
extractConfig() {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
207
|
+
let userConfig = Object.assign({}, constants_1.default.DEFAULT_CONFIG, this.props.config);
|
|
208
|
+
const { options } = query_string_1.default.parse(location.search);
|
|
209
|
+
if (!options || typeof options !== 'string') {
|
|
210
|
+
console.warn(`Cannot decode option. Invalid format: ${typeof options}, expecting 'string'.`);
|
|
211
|
+
return userConfig;
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
const parsedOptions = JSON.parse(decodeURIComponent(options));
|
|
215
|
+
userConfig = Object.assign(userConfig, parsedOptions.config);
|
|
216
|
+
return userConfig;
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
// TODO: Handle those errors so they don't directly bubble up to the users
|
|
220
|
+
throw new Error(`An error occurred while extracting the configurations ${err}`);
|
|
221
|
+
}
|
|
260
222
|
}
|
|
261
223
|
initializeSocket() {
|
|
262
224
|
return __awaiter(this, void 0, void 0, function* () {
|
|
263
225
|
this.socket = new socket_1.default(this.config);
|
|
264
|
-
this.socket.onClear = this.handleClearMessages;
|
|
265
226
|
this.socket.onMessage = this.handleNewMessage;
|
|
266
|
-
this.socket.onTyping = this.handleTyping;
|
|
267
|
-
this.socket.onData = this.handleDataMessage;
|
|
268
|
-
this.socket.onUserIdChanged = this.props.setUserId;
|
|
269
|
-
// TODO: Can't do that
|
|
270
|
-
// this.config.userId && this.socket.changeUserId(this.config.userId)
|
|
271
227
|
this.socket.setup();
|
|
272
|
-
yield this.socket.
|
|
273
|
-
this.props.
|
|
228
|
+
yield this.socket.connect();
|
|
229
|
+
this.props.setSocket(this.socket);
|
|
274
230
|
});
|
|
275
231
|
}
|
|
276
|
-
loadOverrides(overrides) {
|
|
277
|
-
try {
|
|
278
|
-
for (const override of Object.values(overrides)) {
|
|
279
|
-
// TODO: load module view this can't work
|
|
280
|
-
// override.map(({ module }) => this.props.bp!.loadModuleView(module, true))
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
catch (err) {
|
|
284
|
-
console.error('Error while loading overrides', err.message);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
232
|
setupObserver() {
|
|
288
|
-
(0, mobx_1.observe)(this.props.config, 'userId', (data) => __awaiter(this, void 0, void 0, function* () {
|
|
289
|
-
if (!data.oldValue || data.oldValue === data.newValue) {
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
// TODO: Can't work right now
|
|
293
|
-
// this.socket.changeUserId(data.newValue)
|
|
294
|
-
this.socket.setup();
|
|
295
|
-
yield this.socket.waitForUserId();
|
|
296
|
-
yield this.props.initializeChat();
|
|
297
|
-
}));
|
|
298
|
-
(0, mobx_1.observe)(this.props.config, 'overrides', (data) => {
|
|
299
|
-
if (data.newValue && window.parent) {
|
|
300
|
-
this.loadOverrides(data.newValue);
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
233
|
(0, mobx_1.observe)(this.props.dimensions, 'container', (data) => {
|
|
304
|
-
if (data.newValue
|
|
234
|
+
if (data.newValue) {
|
|
305
235
|
this.postMessageToParent('setWidth', data.newValue);
|
|
306
236
|
}
|
|
307
237
|
});
|
|
@@ -324,21 +254,22 @@ class Web extends react_1.default.Component {
|
|
|
324
254
|
this.props.hasUnreadMessages && react_1.default.createElement("span", { className: 'bpw-floating-button-unread' }, this.props.unreadCount)));
|
|
325
255
|
}
|
|
326
256
|
applyAndRenderStyle() {
|
|
327
|
-
|
|
328
|
-
const parentClass = (0, classnames_1.default)(`bp-widget-web bp-widget-${this.props.activeView}
|
|
257
|
+
var _a, _b, _c;
|
|
258
|
+
const parentClass = (0, classnames_1.default)(`bp-widget-web bp-widget-${this.props.activeView}`, {
|
|
329
259
|
'bp-widget-hidden': !this.props.showWidgetButton && this.props.displayWidgetView,
|
|
330
|
-
[this.props.config.className]: !!this.props.config.className
|
|
260
|
+
[(_a = this.props.config) === null || _a === void 0 ? void 0 : _a.className]: !!((_b = this.props.config) === null || _b === void 0 ? void 0 : _b.className)
|
|
331
261
|
});
|
|
332
262
|
if (this.parentClass !== parentClass) {
|
|
333
263
|
this.postMessageToParent('setClass', parentClass);
|
|
334
264
|
this.parentClass = parentClass;
|
|
335
265
|
}
|
|
336
|
-
const
|
|
266
|
+
const stylesheet = this.props.config.stylesheet;
|
|
267
|
+
const extraStylesheet = (_c = this.props.botInfo) === null || _c === void 0 ? void 0 : _c.extraStylesheet;
|
|
337
268
|
const RobotoFont = react_1.default.lazy(() => Promise.resolve().then(() => __importStar(require('./fonts/roboto'))));
|
|
338
269
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
339
|
-
!!(stylesheet === null || stylesheet === void 0 ? void 0 : stylesheet.length) && react_1.default.createElement(
|
|
270
|
+
!!(stylesheet === null || stylesheet === void 0 ? void 0 : stylesheet.length) && react_1.default.createElement("link", { rel: "stylesheet", type: "text/css", href: stylesheet }),
|
|
340
271
|
react_1.default.createElement(react_1.default.Suspense, { fallback: react_1.default.createElement(react_1.default.Fragment, null) }, !utils_1.isIE && react_1.default.createElement(RobotoFont, null)),
|
|
341
|
-
!!(extraStylesheet === null || extraStylesheet === void 0 ? void 0 : extraStylesheet.length) && react_1.default.createElement(
|
|
272
|
+
!!(extraStylesheet === null || extraStylesheet === void 0 ? void 0 : extraStylesheet.length) && react_1.default.createElement("link", { rel: "stylesheet", type: "text/css", href: extraStylesheet })));
|
|
342
273
|
}
|
|
343
274
|
render() {
|
|
344
275
|
if (!this.props.isWebchatReady) {
|
|
@@ -364,11 +295,8 @@ exports.default = (0, mobx_react_1.inject)(({ store }) => ({
|
|
|
364
295
|
mergeConfig: store.mergeConfig,
|
|
365
296
|
addEventToConversation: store.addEventToConversation,
|
|
366
297
|
clearMessages: store.clearMessages,
|
|
367
|
-
setUserId: store.setUserId,
|
|
368
298
|
updateTyping: store.updateTyping,
|
|
369
299
|
sendMessage: store.sendMessage,
|
|
370
|
-
setReference: store.setReference,
|
|
371
|
-
isEmulator: store.isEmulator,
|
|
372
300
|
updateBotUILanguage: store.updateBotUILanguage,
|
|
373
301
|
isWebchatReady: store.view.isWebchatReady,
|
|
374
302
|
showWidgetButton: store.view.showWidgetButton,
|
|
@@ -386,5 +314,9 @@ exports.default = (0, mobx_react_1.inject)(({ store }) => ({
|
|
|
386
314
|
displayWidgetView: store.view.displayWidgetView,
|
|
387
315
|
setLoadingCompleted: store.view.setLoadingCompleted,
|
|
388
316
|
sendFeedback: store.sendFeedback,
|
|
389
|
-
updateLastMessage: store.updateLastMessage
|
|
317
|
+
updateLastMessage: store.updateLastMessage,
|
|
318
|
+
fetchConversation: store.fetchConversation,
|
|
319
|
+
setIntlProvider: store.setIntlProvider,
|
|
320
|
+
setSocket: store.setSocket,
|
|
321
|
+
currentConversationId: store.currentConversationId
|
|
390
322
|
}))((0, react_intl_1.injectIntl)((0, mobx_react_1.observer)(Web)));
|
package/dist/store/composer.js
CHANGED
|
@@ -14,7 +14,7 @@ const takeRight_1 = __importDefault(require("lodash/takeRight"));
|
|
|
14
14
|
const mobx_1 = require("mobx");
|
|
15
15
|
const constants_1 = __importDefault(require("../core/constants"));
|
|
16
16
|
const HISTORY_UP = 'ArrowUp';
|
|
17
|
-
const SENT_HISTORY_KEY =
|
|
17
|
+
const SENT_HISTORY_KEY = 'sent-history';
|
|
18
18
|
class ComposerStore {
|
|
19
19
|
constructor(rootStore) {
|
|
20
20
|
this.message = '';
|
|
@@ -23,9 +23,7 @@ class ComposerStore {
|
|
|
23
23
|
this._sentHistory = [];
|
|
24
24
|
this._sentHistoryIndex = 0;
|
|
25
25
|
this.rootStore = rootStore;
|
|
26
|
-
|
|
27
|
-
this._sentHistory = window.BP_STORAGE.get(SENT_HISTORY_KEY) || [];
|
|
28
|
-
}
|
|
26
|
+
this._sentHistory = window.BP_STORAGE.get(SENT_HISTORY_KEY) || [];
|
|
29
27
|
}
|
|
30
28
|
get composerPlaceholder() {
|
|
31
29
|
var _a;
|
|
@@ -35,12 +33,11 @@ class ComposerStore {
|
|
|
35
33
|
this.message = msg;
|
|
36
34
|
}
|
|
37
35
|
addMessageToHistory(text) {
|
|
38
|
-
var _a;
|
|
39
36
|
if ((0, last_1.default)(this._sentHistory) !== text) {
|
|
40
37
|
this._sentHistory.push(text);
|
|
41
38
|
this._sentHistoryIndex = 0;
|
|
42
39
|
if (this.rootStore.config.enablePersistHistory) {
|
|
43
|
-
|
|
40
|
+
window.BP_STORAGE.set(SENT_HISTORY_KEY, (0, takeRight_1.default)(this._sentHistory, constants_1.default.SENT_HISTORY_SIZE));
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
}
|
package/dist/store/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { IntlShape } from 'react-intl';
|
|
3
3
|
import BpSocket from '../core/socket';
|
|
4
|
-
import { BotInfo, Config, CurrentConversation, EventFeedback, Message,
|
|
4
|
+
import { BotInfo, Config, CurrentConversation, EventFeedback, Message, QueuedMessage, RecentConversation, uuid } from '../typings';
|
|
5
5
|
import ComposerStore from './composer';
|
|
6
6
|
import ViewStore from './view';
|
|
7
|
-
/** Includes the
|
|
7
|
+
/** Includes the definitions of all store classes */
|
|
8
8
|
export declare type StoreDef = Partial<RootStore> & Partial<ViewStore> & Partial<ComposerStore> & Partial<Config>;
|
|
9
9
|
declare class RootStore {
|
|
10
10
|
composer: ComposerStore;
|
|
@@ -12,7 +12,7 @@ declare class RootStore {
|
|
|
12
12
|
private _typingInterval;
|
|
13
13
|
private api;
|
|
14
14
|
conversations: RecentConversation[];
|
|
15
|
-
currentConversation
|
|
15
|
+
currentConversation?: CurrentConversation;
|
|
16
16
|
botInfo: BotInfo;
|
|
17
17
|
config: Config;
|
|
18
18
|
preferredLanguage: string;
|
|
@@ -20,8 +20,6 @@ declare class RootStore {
|
|
|
20
20
|
messageFeedbacks: EventFeedback[];
|
|
21
21
|
intl: IntlShape;
|
|
22
22
|
isBotTyping: import("mobx").IObservableValue<boolean>;
|
|
23
|
-
/** When a wrapper is defined, every messages are wrapped by the specified component */
|
|
24
|
-
messageWrapper: MessageWrapper | undefined;
|
|
25
23
|
botUILanguage: string;
|
|
26
24
|
delayedMessages: QueuedMessage[];
|
|
27
25
|
constructor(options: {
|
|
@@ -31,25 +29,23 @@ declare class RootStore {
|
|
|
31
29
|
setSocket(socket: BpSocket): void;
|
|
32
30
|
get isConversationStarted(): boolean;
|
|
33
31
|
get botName(): string;
|
|
34
|
-
get isEmulator(): boolean;
|
|
35
32
|
get hasBotInfoDescription(): boolean;
|
|
36
33
|
get botAvatarUrl(): string | undefined;
|
|
37
34
|
get rtl(): boolean;
|
|
38
35
|
get escapeHTML(): boolean;
|
|
39
36
|
get currentMessages(): Message[];
|
|
40
|
-
get currentConversationId(): uuid;
|
|
37
|
+
get currentConversationId(): uuid | undefined;
|
|
41
38
|
postMessage(name: string, payload?: any): void;
|
|
42
39
|
updateMessages(messages: Message[]): void;
|
|
43
40
|
updateLastMessage(conversationId: string, message?: Message): void;
|
|
44
41
|
clearMessages(): void;
|
|
45
42
|
deleteConversation(): Promise<void>;
|
|
46
|
-
loadEventInDebugger(messageId: uuid, isManual?: boolean): Promise<void>;
|
|
47
43
|
addEventToConversation(event: Message): Promise<void>;
|
|
48
44
|
updateTyping(event: Message): Promise<void>;
|
|
49
45
|
/** Loads the initial state, for the first time or when the user ID is changed. */
|
|
50
46
|
initializeChat(): Promise<void>;
|
|
51
47
|
fetchBotInfo(): Promise<void>;
|
|
52
|
-
|
|
48
|
+
fetchLanguage(): void;
|
|
53
49
|
/** Fetches the list of conversation, and update the corresponding config values */
|
|
54
50
|
fetchConversations(): Promise<void>;
|
|
55
51
|
/** Fetch the specified conversation ID, or try to fetch a valid one from the list */
|
|
@@ -60,33 +56,27 @@ declare class RootStore {
|
|
|
60
56
|
startConversation(): Promise<void>;
|
|
61
57
|
/** Creates a new conversation and switches to it */
|
|
62
58
|
createConversation(): Promise<uuid>;
|
|
63
|
-
setReference(): Promise<void>;
|
|
64
59
|
resetConversation(): void;
|
|
65
|
-
resetSession(): Promise<void>;
|
|
66
60
|
extractFeedback(messages: Message[]): Promise<void>;
|
|
67
61
|
sendFeedback(feedback: number, messageId: string): Promise<void>;
|
|
68
62
|
downloadConversation(): Promise<void>;
|
|
69
63
|
/** Sends an event or a message, depending on how the backend manages those types */
|
|
70
64
|
sendData(data: any): Promise<void>;
|
|
71
|
-
uploadFile(title: string, payload: string, file: File): Promise<void>;
|
|
72
65
|
/** Sends a message of type voice */
|
|
73
66
|
sendVoiceMessage(voice: Buffer, ext: string): Promise<void>;
|
|
74
67
|
/** Use this method to replace a value or add a new config */
|
|
75
68
|
mergeConfig(config: Partial<Config>): void;
|
|
76
69
|
/** This replaces all the configurations by this object */
|
|
77
|
-
updateConfig(config: Config
|
|
70
|
+
updateConfig(config: Config): void;
|
|
78
71
|
private _applyConfig;
|
|
79
|
-
/** When this method is used, the user ID is changed in the configuration, then the socket is updated */
|
|
80
|
-
setUserId(userId: string): void;
|
|
81
72
|
publishConfigChanged(): void;
|
|
82
|
-
|
|
83
|
-
updatePreferredLanguage(lang: string): Promise<void>;
|
|
73
|
+
updatePreferredLanguage(lang: string): void;
|
|
84
74
|
/** Starts a timer to remove the typing animation when it's completed */
|
|
85
75
|
private _startTypingTimer;
|
|
86
76
|
private _expireTyping;
|
|
87
77
|
updateBotUILanguage(lang: string): void;
|
|
88
78
|
private emptyDelayedMessagesQueue;
|
|
89
|
-
/** Returns the current conversation ID, or the last one
|
|
79
|
+
/** Returns the current conversation ID, or the last one. */
|
|
90
80
|
private _getCurrentConvoId;
|
|
91
81
|
}
|
|
92
82
|
export { RootStore };
|