widget-chatbot 1.0.0 → 1.0.1

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/cloudbuild.yaml DELETED
@@ -1,29 +0,0 @@
1
- steps:
2
- - name: 'gcr.io/cloud-builders/npm'
3
- args: ['ci']
4
-
5
- - name: 'gcr.io/cloud-builders/npm'
6
- args: ['run','build']
7
-
8
- - name: 'gcr.io/cloud-builders/gcloud'
9
- args:
10
- - kms
11
- - decrypt
12
- - --ciphertext-file=npmrc.enc
13
- - --plaintext-file=/root/.npmrc
14
- - --location=global
15
- - --keyring=my-keyring
16
- - --key=npm-key
17
- volumes:
18
- - name: 'home'
19
- path: /root/
20
-
21
- - name: 'gcr.io/cloud-builders/npm'
22
- args:
23
- - publish
24
- env:
25
- - HOME=/root/
26
- volumes:
27
- - name: 'home'
28
- path: /root/
29
-
@@ -1 +0,0 @@
1
- module.exports = { extends: ['@commitlint/config-conventional'] };
package/index.js DELETED
@@ -1,228 +0,0 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom';
3
- import PropTypes from 'prop-types';
4
- import RasaWebchatPro from './src/pro-src/rules-wrapper';
5
- // import 'bootstrap/dist/css/bootstrap.min.css';
6
- import './src/pro-src/index.css';
7
- // import 'antd/dist/antd.css';
8
-
9
- class RasaWebchatProWithRules extends React.Component {
10
- constructor(props) {
11
- super(props);
12
- const { connectOn } = props;
13
- let { withRules } = props;
14
- if (connectOn === 'open' && withRules === true) {
15
- throw new Error(
16
- "You can't use rules and connect on open, you have to use connect on mount"
17
- );
18
- }
19
- this.webchatRef = null;
20
- if (withRules === undefined) {
21
- withRules = true;
22
- }
23
- this.state = {
24
- propsRetrieved: !withRules,
25
- rulesApplied: !withRules
26
- };
27
- this.setRef = this.setRef.bind(this);
28
- this.handleSessionConfirm = this.handleSessionConfirm.bind(this);
29
- }
30
-
31
- setRef(element) {
32
- const { innerRef } = this.props;
33
- if (!innerRef) {
34
- this.webchatRef = element;
35
- } else if (innerRef && innerRef.constructor && innerRef.call && innerRef.apply) {
36
- // if this is true, innerRef is a function and thus it's a callback ref
37
- this.webchatRef = element;
38
- innerRef(element);
39
- } else {
40
- innerRef.current = element;
41
- }
42
- }
43
-
44
- handleSessionConfirm(sessionObject) {
45
- const { innerRef } = this.props;
46
- this.setState({
47
- // The OR makes it work even without the augmented webchat channel
48
- propsRetrieved: { ...sessionObject.props }
49
- });
50
- if (
51
- ((innerRef && innerRef.current) || this.webchatRef.updateRules) &&
52
- sessionObject.props &&
53
- sessionObject.props.rules
54
- ) {
55
- setTimeout(() => {
56
- if (innerRef && innerRef.current) {
57
- innerRef.current.updateRules(sessionObject.props.rules);
58
- } else {
59
- this.webchatRef.updateRules(sessionObject.props.rules);
60
- }
61
- }, 100);
62
- this.setState({ rulesApplied: true });
63
- }
64
- }
65
-
66
- render() {
67
- const { onSocketEvent } = this.props;
68
- let { withRules } = this.props;
69
- if (withRules === undefined) {
70
- withRules = true;
71
- }
72
- const { propsRetrieved } = this.state;
73
- let propsToApply = {};
74
- if (propsRetrieved) propsToApply = propsRetrieved;
75
- delete propsToApply.rules;
76
- return (
77
- <div
78
- style={{ display: propsRetrieved ? undefined : 'none' }}
79
- className={this.props.embedded || (propsToApply && propsToApply.embedded) ? 'rw-pro-widget-embedded' : ''}
80
- >
81
- <RasaWebchatPro
82
- ref={this.setRef}
83
- {...{
84
- ...propsToApply,
85
- ...this.props
86
- }}
87
- onSocketEvent={
88
- withRules
89
- ? {
90
- session_confirm: this.handleSessionConfirm,
91
- ...onSocketEvent
92
- }
93
- : { ...onSocketEvent }
94
- }
95
- />
96
- </div>
97
- );
98
- }
99
- }
100
-
101
- export const rasaWebchatProTypes = {
102
- initPayload: PropTypes.string,
103
- title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
104
- subtitle: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
105
- protocol: PropTypes.string,
106
- socketUrl: PropTypes.string.isRequired,
107
- socketPath: PropTypes.string,
108
- protocolOptions: PropTypes.shape({}),
109
- customData: PropTypes.shape({}),
110
- handleNewUserMessage: PropTypes.func,
111
- profileAvatar: PropTypes.string,
112
- inputTextFieldHint: PropTypes.string,
113
- connectingText: PropTypes.string,
114
- showCloseButton: PropTypes.bool,
115
- showFullScreenButton: PropTypes.bool,
116
- hideWhenNotConnected: PropTypes.bool,
117
- connectOn: PropTypes.oneOf(['mount', 'open']),
118
- autoClearCache: PropTypes.bool,
119
- onSocketEvent: PropTypes.objectOf(PropTypes.func),
120
- fullScreenMode: PropTypes.bool,
121
- badge: PropTypes.number,
122
- embedded: PropTypes.bool,
123
- // eslint-disable-next-line react/forbid-prop-types
124
- params: PropTypes.object,
125
- openLauncherImage: PropTypes.string,
126
- closeImage: PropTypes.string,
127
- docViewer: PropTypes.bool,
128
- customComponent: PropTypes.func,
129
- displayUnreadCount: PropTypes.bool,
130
- showMessageDate: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
131
- customMessageDelay: PropTypes.func,
132
- tooltipPayload: PropTypes.string,
133
- tooltipDelay: PropTypes.number,
134
- withRules: PropTypes.bool,
135
- rules: PropTypes.arrayOf(
136
- PropTypes.shape({
137
- payload: PropTypes.string.isRequired,
138
- text: PropTypes.string,
139
- trigger: PropTypes.shape({
140
- url: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
141
- timeOnPage: PropTypes.number,
142
- numberOfVisits: PropTypes.number,
143
- numberOfPageVisits: PropTypes.number,
144
- device: PropTypes.string,
145
- when: PropTypes.oneOf(['always', 'init']),
146
- queryString: PropTypes.arrayOf(
147
- PropTypes.shape({
148
- param: PropTypes.string,
149
- value: PropTypes.string,
150
- sendAsEntity: PropTypes.bool
151
- })
152
- ),
153
- eventListeners: PropTypes.arrayOf(
154
- PropTypes.shape({
155
- selector: PropTypes.string.isRequired,
156
- event: PropTypes.string.isRequired
157
- })
158
- )
159
- })
160
- })
161
- ),
162
- triggerEventListenerUpdateRate: PropTypes.number
163
- };
164
-
165
- RasaWebchatProWithRules.propTypes = {
166
- ...rasaWebchatProTypes,
167
- innerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.object })])
168
- };
169
-
170
- export const rasaWebchatProDefaultTypes = {
171
- title: 'Welcome',
172
- customData: {},
173
- inputTextFieldHint: 'Type a message...',
174
- connectingText: 'Waiting for server...',
175
- fullScreenMode: false,
176
- hideWhenNotConnected: true,
177
- autoClearCache: false,
178
- connectOn: 'mount',
179
- onSocketEvent: {},
180
- protocol: 'socketio',
181
- socketUrl: 'http://localhost',
182
- protocolOptions: {},
183
- badge: 0,
184
- embedded: false,
185
- params: {
186
- storage: 'local'
187
- },
188
- docViewer: false,
189
- showCloseButton: true,
190
- showFullScreenButton: false,
191
- displayUnreadCount: false,
192
- showMessageDate: false,
193
- customMessageDelay: (message) => {
194
- let delay = message.length * 30;
195
- if (delay > 3 * 1000) delay = 3 * 1000;
196
- if (delay < 800) delay = 800;
197
- return delay;
198
- },
199
- tooltipPayload: null,
200
- tooltipDelay: 500,
201
- withRules: true,
202
- rules: null,
203
- triggerEventListenerUpdateRate: 500
204
- };
205
-
206
- export default React.forwardRef((props, ref) => (
207
- <RasaWebchatProWithRules innerRef={ref} {...props} />
208
- ));
209
-
210
- export const selfMount = (props, element = null) => {
211
- const load = () => {
212
- if (element === null) {
213
- const node = document.createElement('div');
214
- node.setAttribute('id', 'rasaWebchatPro');
215
- document.body.appendChild(node);
216
- }
217
- const mountElement = element || document.getElementById('rasaWebchatPro')
218
- const webchatPro = React.createElement(RasaWebchatProWithRules, props);
219
- ReactDOM.render(webchatPro, mountElement);
220
- };
221
- if (document.readyState === 'complete') {
222
- load();
223
- } else {
224
- window.addEventListener('load', () => {
225
- load();
226
- });
227
- }
228
- };
@@ -1,323 +0,0 @@
1
- import React, { useRef, createContext, useContext, useState, useEffect } from 'react';
2
- import useWSChatbot from '../../../../hooks/useWSChatbot';
3
- import sortArr from '../../../../helpers/sortArr';
4
- import useDecodeJWT from '../../../../hooks/useDecodeJWT';
5
- import { scrollToBottom } from './components/Messages';
6
- import ModalResult from '../../../../helpers/ModalResult';
7
- import useFetch from '../../../../hooks/useFetch';
8
- import formatChat, { deFormatChat } from '../../../../helpers/formatChat';
9
- import { useMemo } from 'react';
10
- import { useConversationContext } from '../../../../context/ConversationContextProvider';
11
- import { useListTicketContext } from '../../../../context/ListTicketContextProvider';
12
- import useDictionary from '../../../../hooks/useDictionary';
13
-
14
- /** @type {import('react').Context<import('../../../../context/types').DetailTicketContext>} */
15
- const HelpdeskChatContext = createContext({});
16
-
17
- export const useHelpdeskChatContext = () => useContext(HelpdeskChatContext);
18
-
19
- const HelpdeskChatContextProvider = ({ children }) => {
20
- const {
21
- taskIDSelect,
22
- setTaskIDSelect,
23
- stopState,
24
- setStopState,
25
- isScrollFetch,
26
- keyActive,
27
- isBackClick,
28
- setModalState,
29
- } = useConversationContext();
30
-
31
- const { onWatchNotif, onStopLiveChat, onStopNotif, onWatchLiveChat } = useWSChatbot();
32
-
33
- const { setTicketState, taskIDs, ticketState } = useListTicketContext();
34
-
35
- const LabelSuccessCloseTicket = useDictionary(
36
- 'SuccessfullyCloseTicket',
37
- 'Successfully Close Ticket'
38
- );
39
- const LabelSomethingWrong = useDictionary('SomethingWrong', 'Something Wrong');
40
-
41
- const { EMP_ID } = useDecodeJWT();
42
-
43
- const fetch = useFetch();
44
-
45
- const [chatState, setChatState] = useState({
46
- loadingSend: false,
47
- loadingInit: false,
48
- loadingGet: false,
49
- list: [],
50
- fileInput: null,
51
- isShowModalPreviewFile: false,
52
- urlImagePreview: '',
53
- taskIDClose: 0,
54
- total: 0,
55
- pageFetch: 1,
56
- isInitChat: false,
57
- showScrollBottom: false,
58
- });
59
-
60
- const isFetchPrevChat = useMemo(() => {
61
- if (!chatState?.loadingGet) {
62
- return isScrollFetch && deFormatChat(chatState?.list)?.length < chatState?.total;
63
- }
64
- return false;
65
- }, [chatState?.total, chatState?.list, isScrollFetch, chatState?.loadingGet]);
66
-
67
- const onCloseTicket = () => {
68
- console.log("Attempting to close ticket with ID:", taskIDSelect || chatState?.taskIDClose);
69
- setTicketState((prev) => ({
70
- ...prev,
71
- loadingClose: true,
72
- }));
73
-
74
- fetch({
75
- endpoint: 'v1/sf7/general/helpdesk/admin/ticket/update',
76
- data: {
77
- STATUS: 'Closed',
78
- TASK_ID: chatState?.taskIDClose || taskIDSelect,
79
- },
80
- })
81
- ?.then(() => {
82
- console.log("Ticket closed successfully.");
83
- ModalResult({
84
- subtitle: LabelSuccessCloseTicket,
85
- type: 'success',
86
- });
87
-
88
- if (taskIDSelect !== 0) {
89
- setTaskIDSelect(0);
90
- }
91
-
92
- setChatState((prev) => ({
93
- ...prev,
94
- ...(chatState?.taskIDClose !== 0 && {
95
- list: [],
96
- taskIDClose: 0,
97
- }),
98
- }));
99
-
100
- onStopLiveChat();
101
-
102
- setModalState((prev) => ({
103
- ...prev,
104
- closeTicket: false,
105
- }));
106
-
107
- setTicketState((prev) => ({
108
- ...prev,
109
- isRefetch: true,
110
- }));
111
- })
112
- ?.catch((err) => {
113
- ModalResult({
114
- subtitle: LabelSomethingWrong,
115
- type: 'error',
116
- error: err,
117
- });
118
- })
119
- .finally(() => {
120
- setTicketState((prev) => ({
121
- ...prev,
122
- loadingClose: true,
123
- }));
124
- console.log("Close ticket loading state reset.");
125
- });
126
- };
127
-
128
- useEffect(() => {
129
- if (taskIDSelect !== 0) {
130
- const controller = new AbortController();
131
-
132
- onGetDetailChat(controller.signal);
133
-
134
- return () => {
135
- controller.abort();
136
- };
137
- }
138
- }, [taskIDSelect, chatState?.pageFetch]);
139
-
140
- const onGetDetailChat = () => {
141
- console.log("Fetching chat details for task ID:", taskIDSelect);
142
- setChatState((prev) => ({
143
- ...prev,
144
- loadingGet: true,
145
- }));
146
-
147
- fetch({
148
- endpoint: 'v1/sf7/general/helpdesk/chat/list',
149
- data: {
150
- LIMIT: 10,
151
- PAGE: chatState?.pageFetch,
152
- TASK_ID: taskIDSelect,
153
- },
154
- })
155
- ?.then(({ data }) => {
156
- if (data?.DATA && isMountedRef.current) {
157
- console.log("Chat data fetched:", data?.DATA);
158
- const chatDatas = data?.DATA?.LIST;
159
- const sortedChat = sortArr(chatDatas, 'ID');
160
- const unRead = sortedChat?.filter(
161
- (item) => item?.READ_BY === '' && item?.ACTOR?.EMP_ID !== EMP_ID
162
- );
163
-
164
- const appendedChat = [...deFormatChat(chatState?.list), ...sortedChat];
165
-
166
- const chats =
167
- chatState?.pageFetch > 1
168
- ? formatChat(appendedChat)
169
- : formatChat(sortedChat);
170
-
171
- setChatState((prev) => ({
172
- ...prev,
173
- list: chats,
174
- total: data?.DATA?.TOTAL_RECORD,
175
- }));
176
-
177
- setTicketState((prev) => ({
178
- ...prev,
179
- count: unRead?.length,
180
- }));
181
- }
182
- })
183
- ?.catch((err) => {
184
- if (err.name === 'AbortError') {
185
- console.log("Fetch aborted");
186
- } else if (isMountedRef.current) {
187
- }
188
- })
189
- ?.finally(() => {
190
- if (isMountedRef.current) {
191
- setChatState((prev) => ({
192
- ...prev,
193
- loadingInit: false,
194
- loadingGet: false,
195
- }));
196
- console.log("Chat loading state reset.");
197
-
198
- if (chatState?.pageFetch === 1) {
199
- scrollToBottom();
200
- }
201
- }
202
- });
203
- };
204
-
205
-
206
- const resetState = () => {
207
- console.log("Resetting chat state.");
208
- setChatState((prev) => ({
209
- ...prev,
210
- loadingSend: false,
211
- loadingInit: false,
212
- loadingGet: false,
213
- list: [],
214
- fileInput: null,
215
- isShowModalPreviewFile: false,
216
- urlImagePreview: '',
217
- taskIDClose: 0,
218
- total: 0,
219
- pageFetch: 1,
220
- isInitChat: false,
221
- showScrollBottom: false,
222
- }));
223
- };
224
-
225
- useEffect(() => {
226
- if (taskIDSelect !== 0) {
227
- onGetDetailChat();
228
- }
229
- }, [taskIDSelect, chatState?.pageFetch]);
230
-
231
- useEffect(() => {
232
- if (taskIDs?.length > 0 && taskIDSelect === 0 && !ticketState?.stopNotifWS) {
233
- onWatchNotif();
234
- }
235
- }, [
236
- JSON.stringify(taskIDs),
237
- taskIDSelect,
238
- ticketState?.count,
239
- ticketState?.stopNotifWS,
240
- ticketState?.isInitNotif,
241
- ]);
242
-
243
- useEffect(() => {
244
- if (stopState?.liveChat) {
245
- if (isBackClick) {
246
- setTaskIDSelect(0);
247
-
248
- resetState();
249
- }
250
-
251
- setChatState((prev) => ({
252
- ...prev,
253
- isInitChat: false,
254
- }));
255
-
256
- onStopLiveChat();
257
-
258
- setStopState((prev) => ({
259
- ...prev,
260
- liveChat: false,
261
- }));
262
- }
263
- }, [stopState?.liveChat]);
264
-
265
- useEffect(() => {
266
- if (ticketState?.stopNotifWS) {
267
- onStopNotif();
268
-
269
- setTimeout(() => {
270
- setTicketState((prev) => ({
271
- ...prev,
272
- stopNotifWS: false,
273
- }));
274
- }, 350);
275
- }
276
- }, [ticketState?.stopNotifWS, JSON.stringify(taskIDs), keyActive]);
277
-
278
- useEffect(() => {
279
- if (isFetchPrevChat && taskIDSelect !== 0) {
280
- setStopState((prev) => ({
281
- ...prev,
282
- liveChat: true,
283
- }));
284
-
285
- setChatState((prev) => {
286
- return {
287
- ...prev,
288
- pageFetch: chatState?.pageFetch + 1,
289
- };
290
- });
291
- }
292
- }, [isFetchPrevChat]);
293
-
294
- useEffect(() => {
295
- if (taskIDSelect !== 0 && !chatState?.isInitChat) {
296
- onWatchLiveChat();
297
- }
298
- }, [taskIDSelect, chatState?.isInitChat]);
299
-
300
- const isMountedRef = useRef(false);
301
-
302
- useEffect(() => {
303
- isMountedRef.current = true;
304
-
305
- return () => {
306
- isMountedRef.current = false;
307
- };
308
- }, []);
309
-
310
- return (
311
- <HelpdeskChatContext.Provider
312
- value={{
313
- isFetchPrevChat,
314
- onCloseTicket,
315
- chatState,
316
- setChatState,
317
- }}
318
- >
319
- {children}
320
- </HelpdeskChatContext.Provider>
321
- );
322
- };
323
- export default HelpdeskChatContextProvider;