@seamly/web-ui 20.8.0-alpha.1 → 20.8.0-beta.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/build/dist/lib/index.debug.js +46 -46
- package/build/dist/lib/index.debug.min.js +1 -1
- package/build/dist/lib/index.debug.min.js.LICENSE.txt +1 -1
- package/build/dist/lib/index.js +351 -260
- package/build/dist/lib/index.min.js +1 -1
- package/build/dist/lib/standalone.js +542 -252
- package/build/dist/lib/standalone.min.js +1 -1
- package/build/dist/lib/style-guide.js +156 -69
- package/build/dist/lib/style-guide.min.js +1 -1
- package/build/dist/lib/styles.css +1 -1
- package/package.json +1 -1
- package/src/javascripts/config.types.ts +1 -0
- package/src/javascripts/domains/config/slice.ts +2 -0
- package/src/javascripts/domains/i18n/slice.ts +0 -3
- package/src/javascripts/domains/store/slice.ts +16 -13
- package/src/javascripts/domains/store/store.types.ts +12 -1
- package/src/javascripts/domains/translations/hooks.ts +54 -48
- package/src/javascripts/domains/translations/selectors.ts +12 -0
- package/src/javascripts/domains/translations/slice.ts +70 -17
- package/src/javascripts/domains/translations/translations.types.ts +8 -1
- package/src/javascripts/schema.ts +3 -10
- package/src/javascripts/style-guide/components/app.js +2 -2
- package/src/javascripts/style-guide/states.js +61 -3
- package/src/javascripts/ui/components/conversation/conversation.js +7 -3
- package/src/javascripts/ui/components/conversation/event/card-message.js +1 -1
- package/src/javascripts/ui/components/conversation/event/carousel-message/index.js +1 -1
- package/src/javascripts/ui/components/conversation/event/choice-prompt.js +1 -1
- package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +9 -2
- package/src/javascripts/ui/components/conversation/event/cta.js +1 -1
- package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js +39 -3
- package/src/javascripts/ui/components/conversation/event/image.js +1 -1
- package/src/javascripts/ui/components/conversation/event/participant.js +1 -1
- package/src/javascripts/ui/components/conversation/event/splash.js +1 -1
- package/src/javascripts/ui/components/conversation/event/text.js +1 -1
- package/src/javascripts/ui/components/conversation/event/translation.js +1 -1
- package/src/javascripts/ui/components/conversation/event/upload.js +1 -1
- package/src/javascripts/ui/components/conversation/event/video.js +1 -1
- package/src/javascripts/ui/components/conversation/message-container.js +1 -23
- package/src/javascripts/ui/components/core/seamly-event-subscriber.js +3 -2
- package/src/javascripts/ui/components/faq/faq.js +3 -1
- package/src/javascripts/ui/components/options/options-button.js +3 -1
- package/src/javascripts/ui/components/suggestions/index.js +5 -2
- package/src/javascripts/ui/hooks/seamly-state-hooks.js +6 -0
- package/src/stylesheets/5-components/_message-carousel.scss +10 -8
- package/CHANGELOG.md +0 -987
- package/src/javascripts/domains/translations/selectors.js +0 -11
|
@@ -406,11 +406,7 @@ export interface components {
|
|
|
406
406
|
* @example true
|
|
407
407
|
*/
|
|
408
408
|
persist?: boolean
|
|
409
|
-
|
|
410
|
-
* @description Name of the attached service
|
|
411
|
-
* @example bot
|
|
412
|
-
*/
|
|
413
|
-
service?: string
|
|
409
|
+
service?: components['schemas']['Service']
|
|
414
410
|
transactionId?: components['schemas']['TransactionId']
|
|
415
411
|
/** @description In case a translations was active when this message originated, this object will contain the translated message in the translationLocale locale. */
|
|
416
412
|
translatedBody?: {
|
|
@@ -713,11 +709,6 @@ export interface components {
|
|
|
713
709
|
* @example image/jpeg
|
|
714
710
|
*/
|
|
715
711
|
contentType?: string
|
|
716
|
-
/**
|
|
717
|
-
* @description Timestamp until when the file is available for download (in microseconds).
|
|
718
|
-
* @example 1661165549122131
|
|
719
|
-
*/
|
|
720
|
-
deleteAt?: number
|
|
721
712
|
/**
|
|
722
713
|
* @description Filename of the upload
|
|
723
714
|
* @example dog.jpg
|
|
@@ -1453,3 +1444,5 @@ export interface operations {
|
|
|
1453
1444
|
}
|
|
1454
1445
|
}
|
|
1455
1446
|
}
|
|
1447
|
+
|
|
1448
|
+
export interface external {}
|
|
@@ -50,8 +50,7 @@ const StyleGuideApp = ({
|
|
|
50
50
|
const { headingText } = mainState[feature]
|
|
51
51
|
setSelectedStateDescription(headingText)
|
|
52
52
|
const bareState = mainState[feature][layoutMode]
|
|
53
|
-
const { overrideMessages, showFaq } = bareState.config
|
|
54
|
-
|
|
53
|
+
const { overrideMessages, showFaq, showSuggestions } = bareState.config
|
|
55
54
|
const agent = participants.find(
|
|
56
55
|
(participant) => participant.id === 'agent',
|
|
57
56
|
)
|
|
@@ -66,6 +65,7 @@ const StyleGuideApp = ({
|
|
|
66
65
|
layoutMode: bareState.config.layoutMode,
|
|
67
66
|
...(overrideMessages ? { messages: overrideMessages } : {}),
|
|
68
67
|
showFaq,
|
|
68
|
+
showSuggestions,
|
|
69
69
|
},
|
|
70
70
|
headerTitles: {
|
|
71
71
|
...bareState.headerTitles,
|
|
@@ -14,6 +14,7 @@ const baseState = {
|
|
|
14
14
|
hideOnNoUserResponse: false,
|
|
15
15
|
showFaq: false,
|
|
16
16
|
showDisclaimer: false,
|
|
17
|
+
showSuggestions: true,
|
|
17
18
|
},
|
|
18
19
|
initialState: {},
|
|
19
20
|
unreadEvents: 0,
|
|
@@ -126,6 +127,32 @@ const newTranslationDividerStart = {
|
|
|
126
127
|
type: 'divider',
|
|
127
128
|
},
|
|
128
129
|
}
|
|
130
|
+
|
|
131
|
+
const newTranslationDividerStartTwo = {
|
|
132
|
+
type: 'info',
|
|
133
|
+
payload: {
|
|
134
|
+
body: {
|
|
135
|
+
language: 'Nederlands',
|
|
136
|
+
subtype: 'new_translation',
|
|
137
|
+
text: '[NL] Automatic translation to Dutch started. Please note that automatic translations may contain errors.',
|
|
138
|
+
translationEnabled: true,
|
|
139
|
+
translationLocale: 'nl',
|
|
140
|
+
},
|
|
141
|
+
fromClient: false,
|
|
142
|
+
fromHistory: true,
|
|
143
|
+
id: randomId(),
|
|
144
|
+
occurredAt: 1625658300534259,
|
|
145
|
+
participant: null,
|
|
146
|
+
service: {
|
|
147
|
+
meta: {},
|
|
148
|
+
name: null,
|
|
149
|
+
serviceSessionId: null,
|
|
150
|
+
},
|
|
151
|
+
transactionId: null,
|
|
152
|
+
translatedBody: null,
|
|
153
|
+
type: 'divider',
|
|
154
|
+
},
|
|
155
|
+
}
|
|
129
156
|
const newTranslationDividerStop = {
|
|
130
157
|
type: 'info',
|
|
131
158
|
payload: {
|
|
@@ -736,7 +763,7 @@ const translationsSlice = {
|
|
|
736
763
|
currentLocale: undefined,
|
|
737
764
|
isAvailable: false,
|
|
738
765
|
languages: [],
|
|
739
|
-
|
|
766
|
+
translatedEventGroups: {},
|
|
740
767
|
containerId: randomId(),
|
|
741
768
|
}
|
|
742
769
|
|
|
@@ -1736,7 +1763,7 @@ const standardState = {
|
|
|
1736
1763
|
userMessage,
|
|
1737
1764
|
textMessageBoldItalicUnderline,
|
|
1738
1765
|
newTopicDivider,
|
|
1739
|
-
|
|
1766
|
+
newTranslationDividerStartTwo,
|
|
1740
1767
|
newTranslationDividerStop,
|
|
1741
1768
|
imageMessage,
|
|
1742
1769
|
fileDownloadAgentMessage,
|
|
@@ -1752,13 +1779,44 @@ const standardState = {
|
|
|
1752
1779
|
choicePromptMessage,
|
|
1753
1780
|
ctaMessage,
|
|
1754
1781
|
newTranslationDividerStop,
|
|
1755
|
-
newTranslationDividerStart,
|
|
1756
1782
|
].map(addTranslationData),
|
|
1757
1783
|
translations: {
|
|
1758
1784
|
...translationsSlice,
|
|
1759
1785
|
currentLocale: 'nl',
|
|
1760
1786
|
isActive: true,
|
|
1761
1787
|
isAvailable: true,
|
|
1788
|
+
translatedEventGroups: {
|
|
1789
|
+
[newTranslationDividerStart.payload.id]: [
|
|
1790
|
+
infoMessage,
|
|
1791
|
+
shortTextMessage,
|
|
1792
|
+
{
|
|
1793
|
+
...choicePromptMessage,
|
|
1794
|
+
payload: {
|
|
1795
|
+
...choicePromptMessage.payload,
|
|
1796
|
+
id: `${choicePromptMessage.payload.id}XXX`,
|
|
1797
|
+
},
|
|
1798
|
+
},
|
|
1799
|
+
longTextMessage,
|
|
1800
|
+
userMessage,
|
|
1801
|
+
textMessageBoldItalicUnderline,
|
|
1802
|
+
newTopicDivider,
|
|
1803
|
+
].map((p) => p.payload.id),
|
|
1804
|
+
[newTranslationDividerStartTwo.payload.id]: [
|
|
1805
|
+
imageMessage,
|
|
1806
|
+
fileDownloadAgentMessage,
|
|
1807
|
+
deletedFileDownloadAgentMessage,
|
|
1808
|
+
userMessageLong,
|
|
1809
|
+
videoMessage,
|
|
1810
|
+
textMessageWithLinks,
|
|
1811
|
+
textMessageWithLongLink,
|
|
1812
|
+
imageMessageWithLightbox,
|
|
1813
|
+
fileDownloadUserMessage,
|
|
1814
|
+
emptyUrlFileDownloadUserMessage,
|
|
1815
|
+
textMesageWithBullets,
|
|
1816
|
+
choicePromptMessage,
|
|
1817
|
+
ctaMessage,
|
|
1818
|
+
].map((p) => p.payload.id),
|
|
1819
|
+
},
|
|
1762
1820
|
languages: [
|
|
1763
1821
|
{ locale: 'nl', nativeName: 'Dutch' },
|
|
1764
1822
|
{ locale: 'en', nativeName: 'English' },
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useI18n } from 'domains/i18n/hooks'
|
|
2
2
|
import { useVisibility } from 'domains/visibility/hooks'
|
|
3
3
|
import { className } from 'lib/css'
|
|
4
|
-
import {
|
|
4
|
+
import { useLayoutEffect, useRef } from 'preact/hooks'
|
|
5
5
|
import PrivacyDisclaimer from 'ui/components/layout/privacy-disclaimer'
|
|
6
|
+
import { timeout } from 'ui/hooks/focus-helper-hooks'
|
|
6
7
|
import {
|
|
7
8
|
useSeamlyIsLoading,
|
|
8
9
|
useSkiplink,
|
|
@@ -51,10 +52,13 @@ const Conversation = () => {
|
|
|
51
52
|
const focusSkiplinkTarget = useSkiplinkTargetFocusing()
|
|
52
53
|
const loadedImageEventIds = useLoadedImageEventIds()
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
useLayoutEffect(() => {
|
|
55
56
|
const containerElement = chatBodyContainer.current
|
|
56
57
|
if (containerElement) {
|
|
57
|
-
|
|
58
|
+
requestAnimationFrame(async () => {
|
|
59
|
+
await timeout(30) // Wait for next frame tick
|
|
60
|
+
containerElement.scrollTop = containerElement.scrollHeight
|
|
61
|
+
})
|
|
58
62
|
}
|
|
59
63
|
}, [events, isLoading, isOpen, loadedImageEventIds])
|
|
60
64
|
|
|
@@ -4,7 +4,7 @@ import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
|
4
4
|
import CardComponent from './card-component'
|
|
5
5
|
|
|
6
6
|
const CardMessage = ({ event }) => {
|
|
7
|
-
const
|
|
7
|
+
const { body } = useTranslatedEventData(event)
|
|
8
8
|
const descriptionId = useGeneratedId()
|
|
9
9
|
|
|
10
10
|
return (
|
|
@@ -6,7 +6,7 @@ import CarouselMessageSlide from './components/slide'
|
|
|
6
6
|
const getItemKey = (item, idx, prefix = '') => `${prefix}${item.title}:${idx}`
|
|
7
7
|
const getItemLabel = (item) => item.title
|
|
8
8
|
const CarouselMessage = ({ event }) => {
|
|
9
|
-
const
|
|
9
|
+
const { body } = useTranslatedEventData(event)
|
|
10
10
|
const slides = body.cards
|
|
11
11
|
|
|
12
12
|
return (
|
|
@@ -19,7 +19,7 @@ export const useChoicePrompt = (event) => {
|
|
|
19
19
|
const { sendAction, addMessageBubble, addDivider } = useSeamlyCommands()
|
|
20
20
|
const { activeServiceSessionId } = useSeamlyServiceInfo()
|
|
21
21
|
const lastEventId = useLastMessageEventId()
|
|
22
|
-
const
|
|
22
|
+
const { body } = useTranslatedEventData(event)
|
|
23
23
|
const { service } = payload
|
|
24
24
|
|
|
25
25
|
const subEvent = useMemo(() => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useUserHasResponded } from 'domains/app/hooks'
|
|
2
2
|
import { setHasResponded } from 'domains/app/slice'
|
|
3
|
+
import { useConfig } from 'domains/config/hooks'
|
|
3
4
|
import { useI18n } from 'domains/i18n/hooks'
|
|
4
5
|
import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
5
6
|
import { className } from 'lib/css'
|
|
@@ -12,7 +13,7 @@ import { actionTypes } from 'ui/utils/seamly-utils'
|
|
|
12
13
|
|
|
13
14
|
export const useSuggestions = (event) => {
|
|
14
15
|
const { payload } = event
|
|
15
|
-
const
|
|
16
|
+
const { body: suggestions } = useTranslatedEventData(event)
|
|
16
17
|
|
|
17
18
|
return {
|
|
18
19
|
suggestions,
|
|
@@ -26,6 +27,7 @@ const ConversationSuggestions = ({ event, ...props }) => {
|
|
|
26
27
|
const userHasResponded = useUserHasResponded()
|
|
27
28
|
const { sendAction, addMessageBubble } = useSeamlyCommands()
|
|
28
29
|
const { suggestions, payload } = useSuggestions(event)
|
|
30
|
+
const { showSuggestions } = useConfig()
|
|
29
31
|
const events = useEvents()
|
|
30
32
|
|
|
31
33
|
const { t } = useI18n()
|
|
@@ -63,7 +65,12 @@ const ConversationSuggestions = ({ event, ...props }) => {
|
|
|
63
65
|
[dispatch, sendAction, payload.id, addMessageBubble],
|
|
64
66
|
)
|
|
65
67
|
|
|
66
|
-
if (
|
|
68
|
+
if (
|
|
69
|
+
!isExpanded ||
|
|
70
|
+
userHasResponded ||
|
|
71
|
+
!hasLastTransactionEvent ||
|
|
72
|
+
!showSuggestions
|
|
73
|
+
) {
|
|
67
74
|
return null
|
|
68
75
|
}
|
|
69
76
|
|
|
@@ -7,7 +7,7 @@ import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
|
7
7
|
import useEventLinkClickHandler from './hooks/use-event-link-click-handler'
|
|
8
8
|
|
|
9
9
|
const Cta = ({ event }) => {
|
|
10
|
-
const
|
|
10
|
+
const { body } = useTranslatedEventData(event)
|
|
11
11
|
const eventClick = useEventLinkClickHandler(event.payload.id)
|
|
12
12
|
const { emitEvent } = useSeamlyCommands()
|
|
13
13
|
|
package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js
CHANGED
|
@@ -5,17 +5,40 @@ import {
|
|
|
5
5
|
useTranslations,
|
|
6
6
|
useLocaleNativeName,
|
|
7
7
|
} from 'domains/translations/hooks'
|
|
8
|
+
import { useDispatch, useSelector } from 'react-redux'
|
|
9
|
+
import {
|
|
10
|
+
enableEventsTranslation,
|
|
11
|
+
disableEventsTranslation,
|
|
12
|
+
} from 'domains/translations/slice'
|
|
13
|
+
import { useCallback } from 'preact/hooks'
|
|
14
|
+
import { useEvents } from 'ui/hooks/seamly-hooks'
|
|
8
15
|
|
|
9
16
|
const NewTranslationDivider = ({ event }) => {
|
|
10
17
|
const { t } = useI18n()
|
|
11
|
-
const
|
|
18
|
+
const events = useEvents()
|
|
19
|
+
const {
|
|
20
|
+
body: { translationEnabled, translationLocale, text },
|
|
21
|
+
id,
|
|
22
|
+
} = event.payload
|
|
12
23
|
const { enableTranslations } = useTranslations()
|
|
13
24
|
const localeNativeName = useLocaleNativeName(translationLocale)
|
|
25
|
+
const translatedEventGroups = useSelector(
|
|
26
|
+
(state) => state.translations.translatedEventGroups,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
const dispatch = useDispatch()
|
|
30
|
+
const toggleTranslations = useCallback(() => {
|
|
31
|
+
if (!translatedEventGroups[id]) {
|
|
32
|
+
dispatch(disableEventsTranslation({ events, id }))
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
dispatch(enableEventsTranslation({ events, id }))
|
|
37
|
+
}, [dispatch, events, id, translatedEventGroups])
|
|
14
38
|
|
|
15
39
|
const handleRestartButtonclick = () => {
|
|
16
40
|
enableTranslations(translationLocale)
|
|
17
41
|
}
|
|
18
|
-
|
|
19
42
|
return (
|
|
20
43
|
<EventDivider iconName="newTranslation" dividerType="newtranslation">
|
|
21
44
|
<p className={className('divider__title')}>
|
|
@@ -27,10 +50,23 @@ const NewTranslationDivider = ({ event }) => {
|
|
|
27
50
|
)}
|
|
28
51
|
</p>
|
|
29
52
|
{translationEnabled ? (
|
|
30
|
-
|
|
53
|
+
<>
|
|
54
|
+
<p>{text}</p>
|
|
55
|
+
<button
|
|
56
|
+
className={className('button', 'button--secondary')}
|
|
57
|
+
onClick={toggleTranslations}
|
|
58
|
+
>
|
|
59
|
+
{t(
|
|
60
|
+
!translatedEventGroups[id]
|
|
61
|
+
? 'translations.toggle.hideTranslationsButtonText'
|
|
62
|
+
: 'translations.toggle.showTranslationsButtonText',
|
|
63
|
+
)}
|
|
64
|
+
</button>
|
|
65
|
+
</>
|
|
31
66
|
) : (
|
|
32
67
|
<button
|
|
33
68
|
className={className('button', 'button--secondary')}
|
|
69
|
+
data-testid="restartTranslationButton"
|
|
34
70
|
onClick={handleRestartButtonclick}
|
|
35
71
|
>
|
|
36
72
|
{t('translations.divider.restartButtonText')}
|
|
@@ -6,7 +6,7 @@ import MessageContainer from 'ui/components/conversation/message-container'
|
|
|
6
6
|
import ImageLightbox from './image-lightbox'
|
|
7
7
|
|
|
8
8
|
const Image = ({ event, descriptorId, ...props }) => {
|
|
9
|
-
const
|
|
9
|
+
const { body } = useTranslatedEventData(event)
|
|
10
10
|
const { description, url, isZoomable } = body
|
|
11
11
|
const [showLighbox, setShowLightbox] = useState(false)
|
|
12
12
|
const dispatch = useDispatch()
|
|
@@ -3,7 +3,7 @@ import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
|
3
3
|
|
|
4
4
|
const Participant = ({ event }) => {
|
|
5
5
|
const { participant } = event.payload
|
|
6
|
-
const
|
|
6
|
+
const { body: introduction } = useTranslatedEventData(event)
|
|
7
7
|
|
|
8
8
|
if (!introduction) {
|
|
9
9
|
return null
|
|
@@ -4,7 +4,7 @@ import MessageContainer from 'ui/components/conversation/message-container'
|
|
|
4
4
|
|
|
5
5
|
const Splash = ({ event, ...props }) => {
|
|
6
6
|
const { payload } = event
|
|
7
|
-
const
|
|
7
|
+
const { body } = useTranslatedEventData(event)
|
|
8
8
|
const eventClick = useEventLinkClickHandler(payload.id)
|
|
9
9
|
|
|
10
10
|
return (
|
|
@@ -4,7 +4,7 @@ import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
|
4
4
|
import useEventLinkClickHandler from './hooks/use-event-link-click-handler'
|
|
5
5
|
|
|
6
6
|
const Text = ({ event, ...props }) => {
|
|
7
|
-
const
|
|
7
|
+
const { body } = useTranslatedEventData(event)
|
|
8
8
|
const eventClick = useEventLinkClickHandler(event.payload.id)
|
|
9
9
|
|
|
10
10
|
const containerProps = useMemo(() => {
|
|
@@ -4,7 +4,7 @@ import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
|
4
4
|
|
|
5
5
|
const Translation = ({ event, ...props }) => {
|
|
6
6
|
const { t } = useI18n()
|
|
7
|
-
const
|
|
7
|
+
const { body } = useTranslatedEventData(event)
|
|
8
8
|
return (
|
|
9
9
|
<MessageContainer type="text" event={event} {...props}>
|
|
10
10
|
{t(body.key.join('.'), body.variables)}
|
|
@@ -21,7 +21,7 @@ const UploadContent = ({ children, url, target }) =>
|
|
|
21
21
|
|
|
22
22
|
const Upload = ({ event, ...props }) => {
|
|
23
23
|
const { t } = useI18n()
|
|
24
|
-
const
|
|
24
|
+
const { body } = useTranslatedEventData(event)
|
|
25
25
|
const { fromClient } = event.payload
|
|
26
26
|
const { filename, url } = body
|
|
27
27
|
|
|
@@ -4,7 +4,7 @@ import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
|
4
4
|
import MessageContainer from 'ui/components/conversation/message-container'
|
|
5
5
|
|
|
6
6
|
const Video = ({ event, descriptorId, ...props }) => {
|
|
7
|
-
const
|
|
7
|
+
const { body } = useTranslatedEventData(event)
|
|
8
8
|
const { description, url } = body
|
|
9
9
|
const classNames = useSeamlyMessageContainerClassNames(event)
|
|
10
10
|
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { className } from 'lib/css'
|
|
2
2
|
import { useSeamlyMessageContainerClassNames } from 'ui/hooks/component-helper-hooks'
|
|
3
3
|
import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
4
|
-
import { useI18n } from 'domains/i18n/hooks'
|
|
5
4
|
import EventParticipant from './event/event-participant'
|
|
6
5
|
|
|
7
6
|
function MessageContainer({
|
|
8
7
|
showParticipant = true,
|
|
9
|
-
showTranslationToggle = true,
|
|
10
8
|
event,
|
|
11
9
|
type,
|
|
12
10
|
modifiers,
|
|
@@ -16,10 +14,8 @@ function MessageContainer({
|
|
|
16
14
|
...props
|
|
17
15
|
}) {
|
|
18
16
|
const classNames = useSeamlyMessageContainerClassNames(event)
|
|
19
|
-
const { t } = useI18n()
|
|
20
17
|
|
|
21
|
-
const
|
|
22
|
-
useTranslatedEventData(event)
|
|
18
|
+
const { hasTranslation, isTranslated, locale } = useTranslatedEventData(event)
|
|
23
19
|
|
|
24
20
|
if (type) {
|
|
25
21
|
classNames.push(`message--type-${type}`)
|
|
@@ -60,24 +56,6 @@ function MessageContainer({
|
|
|
60
56
|
{info}
|
|
61
57
|
</div>
|
|
62
58
|
)}
|
|
63
|
-
{showTranslationToggle && hasTranslation && (
|
|
64
|
-
<div className={className('message__translation-info')}>
|
|
65
|
-
<button
|
|
66
|
-
className={className(
|
|
67
|
-
'message__translation-toggle',
|
|
68
|
-
'button',
|
|
69
|
-
'button--secondary',
|
|
70
|
-
)}
|
|
71
|
-
onClick={toggleTranslation}
|
|
72
|
-
>
|
|
73
|
-
{t(
|
|
74
|
-
isTranslated
|
|
75
|
-
? 'translations.toggle.hideButtonText'
|
|
76
|
-
: 'translations.toggle.showButtonText',
|
|
77
|
-
)}
|
|
78
|
-
</button>
|
|
79
|
-
</div>
|
|
80
|
-
)}
|
|
81
59
|
</div>
|
|
82
60
|
</>
|
|
83
61
|
)
|
|
@@ -123,12 +123,13 @@ const SeamlyEventSubscriber = ({ eventBus }) => {
|
|
|
123
123
|
case 'system':
|
|
124
124
|
if (payload.type === 'service_changed') {
|
|
125
125
|
const { serviceSettings, ...eventPayload } = payload
|
|
126
|
-
const {
|
|
126
|
+
const { entry } = serviceSettings
|
|
127
|
+
const { upload } = entry.options
|
|
127
128
|
|
|
128
129
|
dispatch(
|
|
129
130
|
setFeatureEnabledState({
|
|
130
131
|
key: featureKeys.uploads,
|
|
131
|
-
enabled: !!(
|
|
132
|
+
enabled: !!(upload && upload.enabled),
|
|
132
133
|
}),
|
|
133
134
|
)
|
|
134
135
|
|
|
@@ -32,7 +32,9 @@ const Faq = () => {
|
|
|
32
32
|
const { hasPrompt, continueChat } = useSeamlyResumeConversationPrompt()
|
|
33
33
|
|
|
34
34
|
const lastFaqEventPayload = useSeamlyServiceData('suggestion')
|
|
35
|
-
const
|
|
35
|
+
const { body: eventBody } = useTranslatedEventData({
|
|
36
|
+
payload: lastFaqEventPayload,
|
|
37
|
+
})
|
|
36
38
|
const faqs = useMemo(() => {
|
|
37
39
|
const newFaqs = lastFaqEventPayload && !hasInterrupt ? eventBody : []
|
|
38
40
|
const itemBaseClass = `faqs__item`
|
|
@@ -43,10 +43,11 @@ const OptionsButton = () => {
|
|
|
43
43
|
useEffect(() => {
|
|
44
44
|
if (menuIsOpen && !prevMenuIsOpen.current) {
|
|
45
45
|
requestAnimationFrame(async () => {
|
|
46
|
-
await timeout(
|
|
46
|
+
await timeout(60) // Wait for next frame tick
|
|
47
47
|
const firstActiveOptionIndex = menuOptions.findIndex(
|
|
48
48
|
(option) => option.available,
|
|
49
49
|
)
|
|
50
|
+
|
|
50
51
|
const focusIndex =
|
|
51
52
|
firstActiveOptionIndex === -1 ? 0 : firstActiveOptionIndex
|
|
52
53
|
focusElement(menuItemButtons.current[focusIndex])
|
|
@@ -155,6 +156,7 @@ const OptionsButton = () => {
|
|
|
155
156
|
if (!optionsLength) {
|
|
156
157
|
return null
|
|
157
158
|
}
|
|
159
|
+
|
|
158
160
|
return (
|
|
159
161
|
<div
|
|
160
162
|
className={className('options__container')}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useUserHasResponded } from 'domains/app/hooks'
|
|
2
|
+
import { useConfig } from 'domains/config/hooks'
|
|
2
3
|
import { useI18n } from 'domains/i18n/hooks'
|
|
3
4
|
import { useInterrupt } from 'domains/interrupt/hooks'
|
|
4
5
|
import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
@@ -29,6 +30,7 @@ const Suggestions = ({ isAside = false }) => {
|
|
|
29
30
|
const { t } = useI18n()
|
|
30
31
|
const { sendAction, addMessageBubble } = useSeamlyCommands()
|
|
31
32
|
const { isOpen, setVisibility } = useVisibility()
|
|
33
|
+
const { showSuggestions } = useConfig()
|
|
32
34
|
// a11y hooks
|
|
33
35
|
const sectionId = useGeneratedId()
|
|
34
36
|
const focusSkiplinkTarget = useSkiplinkTargetFocusing()
|
|
@@ -41,7 +43,7 @@ const Suggestions = ({ isAside = false }) => {
|
|
|
41
43
|
// data hooks
|
|
42
44
|
const userHasResponded = useUserHasResponded()
|
|
43
45
|
const payload = useSeamlyServiceData('suggestion')
|
|
44
|
-
const
|
|
46
|
+
const { body: eventBody } = useTranslatedEventData({ payload })
|
|
45
47
|
const suggestions = useMemo(
|
|
46
48
|
() => (payload && !hasInterrupt ? eventBody : []),
|
|
47
49
|
[payload, hasInterrupt, eventBody],
|
|
@@ -56,7 +58,8 @@ const Suggestions = ({ isAside = false }) => {
|
|
|
56
58
|
? (userHasResponded || isOpen) && !isAside
|
|
57
59
|
: userHasResponded
|
|
58
60
|
const prevHideSuggestions = useRef(hideSuggestions)
|
|
59
|
-
const showSuggestionsContainer =
|
|
61
|
+
const showSuggestionsContainer =
|
|
62
|
+
hasSuggestions && !hideSuggestions && showSuggestions
|
|
60
63
|
const renderedSuggestions = hasSuggestions
|
|
61
64
|
? suggestions
|
|
62
65
|
: previousRenderedSuggestions.current
|
|
@@ -65,6 +65,12 @@ export const selectEvents = createSelector(
|
|
|
65
65
|
)
|
|
66
66
|
export const useEvents = () => useSelector(selectEvents)
|
|
67
67
|
|
|
68
|
+
export const selectEventIds = createSelector(selectEvents, (events) => {
|
|
69
|
+
return events.map((event) => event.payload.id)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
export const useEventsIds = () => useSelector(selectEventIds)
|
|
73
|
+
|
|
68
74
|
export const useSeamlyIsLoading = () => useSeamlyStateContext().isLoading
|
|
69
75
|
|
|
70
76
|
export const useSeamlyHeaderData = () => useSeamlyStateContext().headerTitles
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
.#{$n}-carousel-controls {
|
|
42
42
|
display: flex;
|
|
43
43
|
position: relative;
|
|
44
|
+
align-items: center;
|
|
44
45
|
justify-content: space-between;
|
|
45
46
|
width: 100%;
|
|
46
47
|
height: fit-content;
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
/* stylelint-disable no-descending-specificity */
|
|
52
53
|
.#{$n}-carousel-controls .#{$n}-button {
|
|
53
54
|
display: flex;
|
|
55
|
+
flex: 0 0 $buttonsize;
|
|
54
56
|
align-items: center;
|
|
55
57
|
justify-content: center;
|
|
56
58
|
width: $buttonsize;
|
|
@@ -89,21 +91,21 @@
|
|
|
89
91
|
padding: 0 $spacer * 0.5;
|
|
90
92
|
}
|
|
91
93
|
|
|
92
|
-
.#{$n}-carousel-
|
|
94
|
+
.#{$n}-carousel-pagination__wrapper {
|
|
93
95
|
display: flex;
|
|
94
96
|
position: relative;
|
|
95
97
|
flex-direction: row;
|
|
96
98
|
justify-content: center;
|
|
97
|
-
width: 100%;
|
|
98
|
-
margin: 0 auto;
|
|
99
|
-
padding: 0;
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
.#{$n}-carousel-
|
|
101
|
+
.#{$n}-carousel-pagination {
|
|
103
102
|
display: flex;
|
|
104
103
|
position: relative;
|
|
105
|
-
flex-
|
|
104
|
+
flex-flow: row wrap;
|
|
106
105
|
justify-content: center;
|
|
106
|
+
width: 100%;
|
|
107
|
+
margin: 0 auto;
|
|
108
|
+
padding: 0;
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
.#{$n}-carousel-pagination__item {
|
|
@@ -114,8 +116,8 @@
|
|
|
114
116
|
.#{$n}-carousel-pagination__button {
|
|
115
117
|
display: block;
|
|
116
118
|
position: relative;
|
|
117
|
-
width: $buttonsize-small;
|
|
118
|
-
height: $buttonsize-small;
|
|
119
|
+
width: $buttonsize-small * 0.75;
|
|
120
|
+
height: $buttonsize-small * 0.75;
|
|
119
121
|
padding: 0;
|
|
120
122
|
border: 0;
|
|
121
123
|
border-radius: 0;
|