@defra/flood-webchat 0.0.1-beta.36 → 0.0.1-beta.38-draft
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/dist/client.js +255 -49
- package/dist/client.js.map +1 -1
- package/package.json +2 -1
- package/src/client/components/availability/availability.jsx +20 -2
- package/src/client/components/chat/chat.jsx +77 -22
- package/src/client/components/live-region.jsx +55 -0
- package/src/client/components/panel/panel.jsx +2 -0
- package/src/client/components/screens/end-chat.jsx +33 -3
- package/src/client/components/screens/feedback.jsx +29 -2
- package/src/client/components/screens/settings.jsx +30 -2
- package/src/client/lib/agent-status-headline.js +19 -0
- package/src/client/scss/_settings.scss +21 -0
- package/src/client/store/AppProvider.jsx +7 -1
- package/src/client/store/actions-map.js +13 -4
|
@@ -6,9 +6,10 @@ import { SkipLink } from '../skip-link.jsx'
|
|
|
6
6
|
|
|
7
7
|
import { useApp } from '../../store/useApp'
|
|
8
8
|
import { historyPushState, historyReplaceState } from '../../lib/history.js'
|
|
9
|
+
import { LiveRegion } from '../live-region.jsx'
|
|
9
10
|
|
|
10
11
|
export function Availability () {
|
|
11
|
-
const { availability, isChatOpen, setChatVisibility, unseenCount, threadId, setUnseenCount, setInstigatorId } = useApp()
|
|
12
|
+
const { availability, isChatOpen, setChatVisibility, unseenCount, threadId, setUnseenCount, setInstigatorId, setLiveRegionText } = useApp()
|
|
12
13
|
|
|
13
14
|
const buttonRef = useRef()
|
|
14
15
|
|
|
@@ -38,6 +39,16 @@ export function Availability () {
|
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!isChatOpen && unseenCount > 0) {
|
|
44
|
+
setLiveRegionText(`Floodline Webchat - ${unseenCount} new messages`)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return () => {
|
|
48
|
+
setLiveRegionText()
|
|
49
|
+
}
|
|
50
|
+
}, [unseenCount, isChatOpen])
|
|
51
|
+
|
|
41
52
|
useEffect(() => {
|
|
42
53
|
const onScroll = () => {
|
|
43
54
|
if (!threadId) {
|
|
@@ -93,7 +104,14 @@ export function Availability () {
|
|
|
93
104
|
data-module='govuk-button'
|
|
94
105
|
>
|
|
95
106
|
{TextComponent}
|
|
96
|
-
{unseenCount > 0 && !isChatOpen
|
|
107
|
+
{unseenCount > 0 && !isChatOpen
|
|
108
|
+
? (
|
|
109
|
+
<>
|
|
110
|
+
<span className='wc-availability__unseen'>{unseenCount}</span>
|
|
111
|
+
<LiveRegion />
|
|
112
|
+
</>
|
|
113
|
+
)
|
|
114
|
+
: null}
|
|
97
115
|
</a>
|
|
98
116
|
</div>
|
|
99
117
|
</div>
|
|
@@ -7,9 +7,10 @@ import { Message } from '../message/message.jsx'
|
|
|
7
7
|
import { useApp } from '../../store/useApp.js'
|
|
8
8
|
import { useTextareaAutosize } from '../../hooks/useTextareaAutosize.js'
|
|
9
9
|
import { formatTranscript } from '../../lib/transform-messages.js'
|
|
10
|
+
import { agentStatusHeadline } from '../../lib/agent-status-headline.js'
|
|
10
11
|
|
|
11
12
|
export function Chat ({ onEndChatScreen, onSettingsScreen }) {
|
|
12
|
-
const { availability, thread, messages, agent, agentStatus, isAgentTyping, settings, isKeyboard } = useApp()
|
|
13
|
+
const { availability, thread, messages, agent, agentStatus, isAgentTyping, isChatOpen, settings, isKeyboard, setLiveRegionText } = useApp()
|
|
13
14
|
|
|
14
15
|
const [userMessage, setUserMessage] = useState('')
|
|
15
16
|
const [focusVisibleWithin, setFocusVisibleWithin] = useState(false)
|
|
@@ -41,21 +42,39 @@ export function Chat ({ onEndChatScreen, onSettingsScreen }) {
|
|
|
41
42
|
|
|
42
43
|
const agentName = agent?.nickname || agent?.firstName
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
const connectionHeadlineText = agentStatusHeadline(availability, agentStatus, agentName)
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
connectionHeadlineText
|
|
48
|
-
|
|
49
|
-
if (agentName) {
|
|
50
|
-
connectionHeadlineText = `You are speaking with ${agentName}`
|
|
51
|
-
} else {
|
|
52
|
-
connectionHeadlineText = 'No advisers currently available'
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (connectionHeadlineText) {
|
|
49
|
+
setLiveRegionText(`Floodline Webchat - ${connectionHeadlineText}`)
|
|
53
50
|
}
|
|
54
|
-
}
|
|
55
51
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
return () => {
|
|
53
|
+
setLiveRegionText()
|
|
54
|
+
}
|
|
55
|
+
}, [connectionHeadlineText])
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (isAgentTyping && isChatOpen) {
|
|
59
|
+
setLiveRegionText(`${agentName} is typing...`)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return () => {
|
|
63
|
+
setLiveRegionText()
|
|
64
|
+
}
|
|
65
|
+
}, [isAgentTyping, isChatOpen])
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const lastAgentMessage = messages[messages.length - 1]
|
|
69
|
+
|
|
70
|
+
if (lastAgentMessage?.direction === 'outbound') {
|
|
71
|
+
setLiveRegionText(`${agentName} said: ${lastAgentMessage.text}`)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return () => {
|
|
75
|
+
setLiveRegionText()
|
|
76
|
+
}
|
|
77
|
+
}, [messages])
|
|
59
78
|
|
|
60
79
|
const sendMessage = () => {
|
|
61
80
|
if (messageRef.current.value.length === 0) {
|
|
@@ -63,19 +82,15 @@ export function Chat ({ onEndChatScreen, onSettingsScreen }) {
|
|
|
63
82
|
}
|
|
64
83
|
|
|
65
84
|
try {
|
|
66
|
-
|
|
85
|
+
const message = messageRef.current.value.trim()
|
|
86
|
+
thread.sendTextMessage(message)
|
|
87
|
+
setLiveRegionText(`You said: ${message}`)
|
|
67
88
|
} catch (err) {
|
|
68
89
|
console.log('[Chat Error] sendMessage', err)
|
|
69
90
|
}
|
|
70
91
|
|
|
71
92
|
setUserMessage('')
|
|
72
93
|
}
|
|
73
|
-
const handleKeyPress = e => {
|
|
74
|
-
if (e.key === 'Enter' && !e.shiftKey) {
|
|
75
|
-
e.preventDefault()
|
|
76
|
-
sendMessage()
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
94
|
|
|
80
95
|
const handleSubmit = e => {
|
|
81
96
|
e.preventDefault()
|
|
@@ -90,13 +105,51 @@ export function Chat ({ onEndChatScreen, onSettingsScreen }) {
|
|
|
90
105
|
saveChatLink.setAttribute('href', `data:text/plain;charset=utf-8,${transcript}`)
|
|
91
106
|
}
|
|
92
107
|
|
|
108
|
+
const handleKeyPress = e => {
|
|
109
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
110
|
+
switch (e.target.id) {
|
|
111
|
+
case 'text-area':
|
|
112
|
+
e.preventDefault()
|
|
113
|
+
sendMessage()
|
|
114
|
+
break
|
|
115
|
+
case 'end-chat':
|
|
116
|
+
onEndChatScreen(e)
|
|
117
|
+
break
|
|
118
|
+
case 'wc-settings':
|
|
119
|
+
onSettingsScreen(e)
|
|
120
|
+
break
|
|
121
|
+
case 'transcript-download':
|
|
122
|
+
saveChat()
|
|
123
|
+
break
|
|
124
|
+
default:
|
|
125
|
+
break
|
|
126
|
+
}
|
|
127
|
+
} else if (e.key === ' ') {
|
|
128
|
+
if (e.target.id === 'end-chat') {
|
|
129
|
+
onEndChatScreen(e)
|
|
130
|
+
} else if (e.target.id === 'wc-settings') {
|
|
131
|
+
onSettingsScreen(e)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
93
136
|
return (
|
|
94
137
|
<>
|
|
95
138
|
<PanelHeader />
|
|
96
139
|
|
|
97
140
|
<div className='wc-status'>
|
|
98
141
|
<p className='wc-status__availability'>{connectionHeadlineText}</p>
|
|
99
|
-
<a
|
|
142
|
+
<a
|
|
143
|
+
id='end-chat'
|
|
144
|
+
className='wc-status__link'
|
|
145
|
+
href='#'
|
|
146
|
+
data-module='govuk-button'
|
|
147
|
+
role='button'
|
|
148
|
+
onClick={onEndChatScreen}
|
|
149
|
+
onKeyDown={handleKeyPress}
|
|
150
|
+
>
|
|
151
|
+
End chat
|
|
152
|
+
</a>
|
|
100
153
|
</div>
|
|
101
154
|
|
|
102
155
|
<div className='wc-body' tabIndex='0'>
|
|
@@ -132,7 +185,7 @@ export function Chat ({ onEndChatScreen, onSettingsScreen }) {
|
|
|
132
185
|
rows='1'
|
|
133
186
|
aria-required='true'
|
|
134
187
|
className='wc-form__textarea'
|
|
135
|
-
id='
|
|
188
|
+
id='text-area'
|
|
136
189
|
name='message'
|
|
137
190
|
onChange={onChange}
|
|
138
191
|
onKeyDown={handleKeyPress}
|
|
@@ -155,6 +208,7 @@ export function Chat ({ onEndChatScreen, onSettingsScreen }) {
|
|
|
155
208
|
id='wc-settings'
|
|
156
209
|
className='wc-footer__settings-link'
|
|
157
210
|
data-module='govuk-button'
|
|
211
|
+
onKeyDown={handleKeyPress}
|
|
158
212
|
onClick={onSettingsScreen}
|
|
159
213
|
>
|
|
160
214
|
Settings
|
|
@@ -165,6 +219,7 @@ export function Chat ({ onEndChatScreen, onSettingsScreen }) {
|
|
|
165
219
|
className='wc-footer__settings-link'
|
|
166
220
|
data-module='govuk-button'
|
|
167
221
|
download='floodline-webchat-transcript.txt'
|
|
222
|
+
onKeyDown={handleKeyPress}
|
|
168
223
|
onClick={saveChat}
|
|
169
224
|
>
|
|
170
225
|
Save chat
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React, { useEffect, useState, useCallback } from 'react'
|
|
2
|
+
import debounce from 'lodash.debounce'
|
|
3
|
+
import { useApp } from '../store/useApp'
|
|
4
|
+
|
|
5
|
+
export const LiveRegion = () => {
|
|
6
|
+
const { agentStatus, liveRegionText, setLiveRegionText } = useApp()
|
|
7
|
+
|
|
8
|
+
const [textA, setTextA] = useState()
|
|
9
|
+
const [textB, setTextB] = useState()
|
|
10
|
+
|
|
11
|
+
const isSessionEnded = agentStatus === 'closed' || agentStatus === null
|
|
12
|
+
|
|
13
|
+
const clearText = () => {
|
|
14
|
+
setTextA()
|
|
15
|
+
setTextB()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const setText = useCallback(debounce(text => {
|
|
19
|
+
if (textA) {
|
|
20
|
+
setTextB(text)
|
|
21
|
+
} else {
|
|
22
|
+
setTextA(text)
|
|
23
|
+
}
|
|
24
|
+
}, 2000), [textA, textB])
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
console.log('liveRegionText', liveRegionText)
|
|
28
|
+
|
|
29
|
+
if (liveRegionText) {
|
|
30
|
+
clearText()
|
|
31
|
+
setText(liveRegionText)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (isSessionEnded) {
|
|
35
|
+
clearText()
|
|
36
|
+
setLiveRegionText()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return () => {
|
|
40
|
+
clearText()
|
|
41
|
+
setLiveRegionText()
|
|
42
|
+
}
|
|
43
|
+
}, [liveRegionText])
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<>
|
|
47
|
+
<div className='wc-live' aria-live='polite' aria-atomic='true'>
|
|
48
|
+
{textA}
|
|
49
|
+
</div>
|
|
50
|
+
<div className='wc-live' aria-live='polite' aria-atomic='true'>
|
|
51
|
+
{textB}
|
|
52
|
+
</div>
|
|
53
|
+
</>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
@@ -9,6 +9,7 @@ import { Unavailable } from '../screens/unavailable.jsx'
|
|
|
9
9
|
import { EndChat } from '../screens/end-chat.jsx'
|
|
10
10
|
import { Settings } from '../screens/settings.jsx'
|
|
11
11
|
import { Feedback } from '../screens/feedback.jsx'
|
|
12
|
+
import { LiveRegion } from '../live-region.jsx'
|
|
12
13
|
|
|
13
14
|
import { useApp } from '../../store/useApp.js'
|
|
14
15
|
import { useChatSdk } from '../../store/useChatSdk.js'
|
|
@@ -136,6 +137,7 @@ export function Panel () {
|
|
|
136
137
|
<div className='wc-panel__inner'>
|
|
137
138
|
{ScreenComponent}
|
|
138
139
|
</div>
|
|
140
|
+
<LiveRegion />
|
|
139
141
|
</div>
|
|
140
142
|
)
|
|
141
143
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useEffect } from 'react'
|
|
2
2
|
import { PanelHeader } from '../panel/panel-header.jsx'
|
|
3
3
|
import { useApp } from '../../store/useApp.js'
|
|
4
|
+
import { historyReplaceState } from '../../lib/history.js'
|
|
4
5
|
|
|
5
6
|
export function EndChat ({ onChatScreen, onEndChatConfirm }) {
|
|
6
7
|
const { setCustomerId, setThreadId, setMessages, agentStatus, thread, setUnseenCount, isKeyboard } = useApp()
|
|
@@ -19,17 +20,26 @@ export function EndChat ({ onChatScreen, onEndChatConfirm }) {
|
|
|
19
20
|
thread.endChat()
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
historyReplaceState()
|
|
22
24
|
onEndChatConfirm(e)
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
useEffect(() => {
|
|
26
28
|
if (isKeyboard) {
|
|
27
29
|
setTimeout(() => {
|
|
28
|
-
document.querySelector('#
|
|
30
|
+
document.querySelector('#confirm-endchat').focus()
|
|
29
31
|
}, 10)
|
|
30
32
|
}
|
|
31
33
|
}, [])
|
|
32
34
|
|
|
35
|
+
const handleKeyPress = e => {
|
|
36
|
+
if ((e.key === 'Enter' || e.key === ' ') && e.target.id === 'confirm-endchat') {
|
|
37
|
+
confirmEndChat(e)
|
|
38
|
+
} else if ((e.key === 'Enter' || e.key === ' ') && e.target.id === 'resume-chat') {
|
|
39
|
+
onChatScreen(e)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
33
43
|
return (
|
|
34
44
|
<>
|
|
35
45
|
<PanelHeader />
|
|
@@ -37,8 +47,28 @@ export function EndChat ({ onChatScreen, onEndChatConfirm }) {
|
|
|
37
47
|
<div className='wc-content'>
|
|
38
48
|
<h3 className='wc-heading' aria-live='polite'>Are you sure you want to end the chat?</h3>
|
|
39
49
|
<div className='govuk-button-group'>
|
|
40
|
-
<a
|
|
41
|
-
|
|
50
|
+
<a
|
|
51
|
+
id='confirm-endchat'
|
|
52
|
+
href='#endChat'
|
|
53
|
+
role='button'
|
|
54
|
+
className='wc-button govuk-button'
|
|
55
|
+
data-module='govuk-button'
|
|
56
|
+
onClick={confirmEndChat}
|
|
57
|
+
onKeyDown={handleKeyPress}
|
|
58
|
+
>
|
|
59
|
+
Yes, end chat
|
|
60
|
+
</a>
|
|
61
|
+
<a
|
|
62
|
+
id='resume-chat'
|
|
63
|
+
href='#resumeChat'
|
|
64
|
+
role='button'
|
|
65
|
+
className='wc-link govuk-link'
|
|
66
|
+
data-module='govuk-button'
|
|
67
|
+
onClick={onChatScreen}
|
|
68
|
+
onKeyDown={handleKeyPress}
|
|
69
|
+
>
|
|
70
|
+
No, resume chat
|
|
71
|
+
</a>
|
|
42
72
|
</div>
|
|
43
73
|
</div>
|
|
44
74
|
</div>
|
|
@@ -6,6 +6,12 @@ export function Feedback ({ onCancel }) {
|
|
|
6
6
|
onCancel(e)
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
const handleKeyPress = e => {
|
|
10
|
+
if ((e.key === 'Enter' || e.key === ' ') && e.target.id === 'feedback-cancel') {
|
|
11
|
+
onCancel(e)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
9
15
|
return (
|
|
10
16
|
<>
|
|
11
17
|
<PanelHeader />
|
|
@@ -14,8 +20,29 @@ export function Feedback ({ onCancel }) {
|
|
|
14
20
|
<div className='wc-content'>
|
|
15
21
|
<h3 id='wc-subtitle' className='wc-heading'>Give Feedback on Floodline webchat</h3>
|
|
16
22
|
<p>Please note we’re unable to respond to feedback.</p>
|
|
17
|
-
<p
|
|
18
|
-
|
|
23
|
+
<p>
|
|
24
|
+
<a
|
|
25
|
+
className='govuk-link'
|
|
26
|
+
href='#'
|
|
27
|
+
target='_blank'
|
|
28
|
+
rel='noreferrer'
|
|
29
|
+
>
|
|
30
|
+
Feedback Link
|
|
31
|
+
</a>
|
|
32
|
+
</p>
|
|
33
|
+
<p>
|
|
34
|
+
<a
|
|
35
|
+
id='feedback-cancel'
|
|
36
|
+
className='wc-link govuk-link'
|
|
37
|
+
href='#'
|
|
38
|
+
data-module='govuk-button'
|
|
39
|
+
role='button'
|
|
40
|
+
onKeyDown={handleKeyPress}
|
|
41
|
+
onClick={feedbackCancel}
|
|
42
|
+
>
|
|
43
|
+
Close
|
|
44
|
+
</a>
|
|
45
|
+
</p>
|
|
19
46
|
</div>
|
|
20
47
|
</div>
|
|
21
48
|
</>
|
|
@@ -16,6 +16,14 @@ export function Settings ({ onCancel }) {
|
|
|
16
16
|
onCancel(e)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
const handleKeyPress = e => {
|
|
20
|
+
if ((e.key === 'Enter' || e.key === ' ') && e.target.id === 'settings-save') {
|
|
21
|
+
onSave(e)
|
|
22
|
+
} else if ((e.key === 'Enter' || e.key === ' ') && e.target.id === 'settings-cancel') {
|
|
23
|
+
onCancel(e)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
return (
|
|
20
28
|
<>
|
|
21
29
|
<PanelHeader />
|
|
@@ -59,8 +67,28 @@ export function Settings ({ onCancel }) {
|
|
|
59
67
|
</fieldset>
|
|
60
68
|
|
|
61
69
|
<div className='govuk-button-group'>
|
|
62
|
-
<a
|
|
63
|
-
|
|
70
|
+
<a
|
|
71
|
+
id='settings-save'
|
|
72
|
+
href='#'
|
|
73
|
+
className='wc-button govuk-button'
|
|
74
|
+
data-module='govuk-button'
|
|
75
|
+
role='button'
|
|
76
|
+
onClick={onSave}
|
|
77
|
+
onKeyDown={handleKeyPress}
|
|
78
|
+
>
|
|
79
|
+
Save
|
|
80
|
+
</a>
|
|
81
|
+
<a
|
|
82
|
+
id='settings-cancel'
|
|
83
|
+
href='#'
|
|
84
|
+
className='wc-link govuk-link'
|
|
85
|
+
data-module='govuk-button'
|
|
86
|
+
role='button'
|
|
87
|
+
onClick={onCancel}
|
|
88
|
+
onKeyDown={handleKeyPress}
|
|
89
|
+
>
|
|
90
|
+
Cancel
|
|
91
|
+
</a>
|
|
64
92
|
</div>
|
|
65
93
|
</div>
|
|
66
94
|
</div>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const agentStatusHeadline = (availability, agentStatus, agentName) => {
|
|
2
|
+
let connectionHeadlineText = 'Connecting to Floodline'
|
|
3
|
+
|
|
4
|
+
if (agentStatus === 'closed') {
|
|
5
|
+
connectionHeadlineText = agentName ? `${agentName} ended the session` : 'Session ended by advisor'
|
|
6
|
+
} else if (agentStatus) {
|
|
7
|
+
if (agentName) {
|
|
8
|
+
connectionHeadlineText = `You are speaking with ${agentName}`
|
|
9
|
+
} else {
|
|
10
|
+
connectionHeadlineText = 'No advisers currently available'
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (availability === 'UNAVAILABLE') {
|
|
15
|
+
connectionHeadlineText = 'Webchat is not currently available'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return connectionHeadlineText
|
|
19
|
+
}
|
|
@@ -73,3 +73,24 @@
|
|
|
73
73
|
line-height: 1.25;
|
|
74
74
|
margin: 0 0 25px;
|
|
75
75
|
}
|
|
76
|
+
|
|
77
|
+
// stylelint-disable declaration-no-important
|
|
78
|
+
.wc-live {
|
|
79
|
+
position: absolute !important;
|
|
80
|
+
width: 1px !important;
|
|
81
|
+
height: 1px !important;
|
|
82
|
+
margin: 0 !important;
|
|
83
|
+
padding: 0 !important;
|
|
84
|
+
overflow: hidden !important;
|
|
85
|
+
clip: rect(0 0 0 0) !important;
|
|
86
|
+
-webkit-clip-path: inset(50%) !important;
|
|
87
|
+
clip-path: inset(50%) !important;
|
|
88
|
+
border: 0 !important;
|
|
89
|
+
white-space: nowrap !important;
|
|
90
|
+
|
|
91
|
+
&::before,
|
|
92
|
+
&::after {
|
|
93
|
+
content: ' ';
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// stylelint-enable declaration-no-important
|
|
@@ -27,12 +27,13 @@ export const AppProvider = ({ sdk, availability, options, children }) => {
|
|
|
27
27
|
dispatch({ type: 'SET_AGENT_STATUS', payload: e.detail.data.case.status })
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const onAgentTypingStarted =
|
|
30
|
+
const onAgentTypingStarted = e => {
|
|
31
31
|
dispatch({ type: 'SET_AGENT_TYPING', payload: true })
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const onAgentTypingEnded = () => {
|
|
35
35
|
dispatch({ type: 'SET_AGENT_TYPING', payload: false })
|
|
36
|
+
dispatch({ type: 'SET_LIVE_REGION_TEXT' })
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
const onMessageCreated = e => {
|
|
@@ -149,6 +150,10 @@ export const AppProvider = ({ sdk, availability, options, children }) => {
|
|
|
149
150
|
dispatch({ type: 'SET_INSTIGATOR_ID', payload: id })
|
|
150
151
|
}
|
|
151
152
|
|
|
153
|
+
const setLiveRegionText = text => {
|
|
154
|
+
dispatch({ type: 'SET_LIVE_REGION_TEXT', payload: text })
|
|
155
|
+
}
|
|
156
|
+
|
|
152
157
|
/**
|
|
153
158
|
* Application-wide state and state functions
|
|
154
159
|
*/
|
|
@@ -163,6 +168,7 @@ export const AppProvider = ({ sdk, availability, options, children }) => {
|
|
|
163
168
|
setUnseenCount,
|
|
164
169
|
setChatVisibility,
|
|
165
170
|
setInstigatorId,
|
|
171
|
+
setLiveRegionText,
|
|
166
172
|
onLiveChatRecovered,
|
|
167
173
|
onAssignedAgentChanged,
|
|
168
174
|
onAgentTypingStarted,
|
|
@@ -61,17 +61,18 @@ const setThread = (state, payload) => {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
const
|
|
64
|
+
const setMessages = (state, payload) => {
|
|
65
65
|
return {
|
|
66
66
|
...state,
|
|
67
|
-
messages:
|
|
67
|
+
messages: transformMessages(payload).reverse()
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
const
|
|
71
|
+
const setMessage = (state, payload) => {
|
|
72
72
|
return {
|
|
73
73
|
...state,
|
|
74
|
-
|
|
74
|
+
message: transformMessage(payload),
|
|
75
|
+
messages: [...state.messages, transformMessage(payload)]
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
|
|
@@ -110,6 +111,13 @@ const setInstigatorId = (state, payload) => {
|
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
|
|
114
|
+
const setLiveRegionText = (state, payload) => {
|
|
115
|
+
return {
|
|
116
|
+
...state,
|
|
117
|
+
liveRegionText: payload
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
113
121
|
const toggleIsMobile = (state, payload) => {
|
|
114
122
|
return {
|
|
115
123
|
...state,
|
|
@@ -138,6 +146,7 @@ export const actionsMap = {
|
|
|
138
146
|
SET_AGENT_STATUS: setAgentStatus,
|
|
139
147
|
SET_UNSEEN_COUNT: setUnseenCount,
|
|
140
148
|
SET_INSTIGATOR_ID: setInstigatorId,
|
|
149
|
+
SET_LIVE_REGION_TEXT: setLiveRegionText,
|
|
141
150
|
TOGGLE_IS_MOBILE: toggleIsMobile,
|
|
142
151
|
TOGGLE_IS_KEYBOARD: toggleIsKeyboard
|
|
143
152
|
}
|