@seamly/web-ui 20.8.1 → 21.0.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/build/dist/lib/deprecated-view.js +1 -1
- package/build/dist/lib/index.debug.js +585 -584
- package/build/dist/lib/index.debug.min.js +1 -1
- package/build/dist/lib/index.debug.min.js.LICENSE.txt +110 -110
- package/build/dist/lib/index.js +20269 -26441
- package/build/dist/lib/index.min.js +1 -1
- package/build/dist/lib/index.min.js.LICENSE.txt +6 -1
- package/build/dist/lib/standalone.js +27728 -34583
- package/build/dist/lib/standalone.min.js +1 -1
- package/build/dist/lib/standalone.min.js.LICENSE.txt +1 -1
- package/build/dist/lib/storage.js +6 -15
- package/build/dist/lib/style-guide.js +9660 -8970
- package/build/dist/lib/style-guide.min.js +1 -1
- package/build/dist/lib/styles-default-implementation.js +1 -1
- package/build/dist/lib/styles.js +1 -1
- package/build/dist/lib/utils.js +85 -3
- package/build/dist/lib/utils.min.js +1 -1
- package/package.json +54 -52
- package/src/icons/icon_check-16.svg +14 -0
- package/src/icons/icon_check-32.svg +14 -0
- package/src/javascripts/api/conversation-connector.ts +149 -0
- package/src/javascripts/api/errors/seamly-base-error.js +19 -0
- package/src/javascripts/api/errors/seamly-unavailable-error.js +5 -7
- package/src/javascripts/api/{index.js → index.ts} +163 -116
- package/src/javascripts/config.types.ts +5 -4
- package/src/javascripts/domains/app/actions.ts +47 -46
- package/src/javascripts/domains/app/hooks.js +1 -1
- package/src/javascripts/domains/config/actions.ts +2 -8
- package/src/javascripts/domains/config/hooks.ts +1 -1
- package/src/javascripts/domains/config/selectors.ts +6 -6
- package/src/javascripts/domains/config/slice.ts +3 -3
- package/src/javascripts/domains/errors/index.ts +66 -0
- package/src/javascripts/domains/forms/context.ts +1 -1
- package/src/javascripts/domains/forms/forms.types.ts +3 -3
- package/src/javascripts/domains/forms/hooks.ts +10 -10
- package/src/javascripts/domains/forms/provider.tsx +9 -9
- package/src/javascripts/domains/i18n/actions.ts +11 -5
- package/src/javascripts/domains/i18n/hooks.ts +11 -8
- package/src/javascripts/domains/i18n/selectors.ts +10 -4
- package/src/javascripts/domains/i18n/slice.ts +0 -1
- package/src/javascripts/domains/interrupt/hooks.ts +1 -1
- package/src/javascripts/domains/interrupt/middleware.ts +1 -1
- package/src/javascripts/domains/store/index.ts +1 -1
- package/src/javascripts/domains/store/selectors.ts +16 -0
- package/src/javascripts/domains/store/slice.ts +47 -41
- package/src/javascripts/domains/store/store.types.ts +38 -10
- package/src/javascripts/domains/translations/components/{options-button.js → options-button.tsx} +30 -20
- package/src/javascripts/domains/translations/components/options-dialog/index.tsx +33 -0
- package/src/javascripts/domains/translations/components/options-dialog/translation-option.tsx +37 -0
- package/src/javascripts/domains/translations/components/options-dialog/translation-options.tsx +85 -0
- package/src/javascripts/domains/translations/components/translation-status.tsx +15 -0
- package/src/javascripts/domains/translations/hooks.ts +77 -11
- package/src/javascripts/domains/translations/slice.ts +20 -9
- package/src/javascripts/domains/translations/translations.types.ts +4 -2
- package/src/javascripts/domains/visibility/actions.ts +6 -10
- package/src/javascripts/domains/visibility/hooks.ts +33 -14
- package/src/javascripts/domains/visibility/selectors.ts +3 -2
- package/src/javascripts/domains/visibility/slice.ts +2 -6
- package/src/javascripts/index.ts +19 -21
- package/src/javascripts/lib/engine/{index.js → index.tsx} +25 -7
- package/src/javascripts/lib/url-helpers.ts +112 -0
- package/src/javascripts/package/utils.js +5 -2
- package/src/javascripts/schema.ts +28 -0
- package/src/javascripts/style-guide/components/app.js +16 -12
- package/src/javascripts/style-guide/components/links.js +6 -6
- package/src/javascripts/style-guide/components/static-core.js +6 -3
- package/src/javascripts/style-guide/components/view.js +1 -1
- package/src/javascripts/style-guide/states.js +129 -31
- package/src/javascripts/style-guide/style-guide-engine.js +1 -1
- package/src/javascripts/ui/components/app-options/index.js +25 -6
- package/src/javascripts/ui/components/chat-app.js +1 -1
- package/src/javascripts/ui/components/chat-status/chat-status-action.tsx +30 -0
- package/src/javascripts/ui/components/chat-status/index.tsx +61 -0
- package/src/javascripts/ui/components/conversation/component-filter.js +9 -9
- package/src/javascripts/ui/components/conversation/{conversation.js → conversation.tsx} +32 -41
- package/src/javascripts/ui/components/conversation/event/card-component.js +2 -2
- package/src/javascripts/ui/components/conversation/event/card-message.js +1 -1
- package/src/javascripts/ui/components/conversation/event/carousel-component/components/controls.js +2 -2
- package/src/javascripts/ui/components/conversation/event/carousel-component/index.js +4 -4
- package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js +2 -2
- package/src/javascripts/ui/components/conversation/event/carousel-message/index.js +1 -1
- package/src/javascripts/ui/components/conversation/event/chat-scroll/chat-scroll-context.ts +12 -0
- package/src/javascripts/ui/components/conversation/event/chat-scroll/chat-scroll-provider.tsx +46 -0
- package/src/javascripts/ui/components/conversation/event/chat-scroll/unread-messages-button.tsx +27 -0
- package/src/javascripts/ui/components/conversation/event/choice-prompt.js +12 -8
- package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +6 -6
- package/src/javascripts/ui/components/conversation/event/cta.js +2 -2
- package/src/javascripts/ui/components/conversation/event/divider/index.js +0 -1
- package/src/javascripts/ui/components/conversation/event/divider/variants/default.js +1 -1
- package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js +17 -22
- package/src/javascripts/ui/components/conversation/event/divider/variants/time-indicator.js +2 -2
- package/src/javascripts/ui/components/conversation/event/event-participant.js +1 -1
- package/src/javascripts/ui/components/conversation/event/event.tsx +66 -0
- package/src/javascripts/ui/components/conversation/event/hooks/use-event-link-click-handler.js +1 -1
- package/src/javascripts/ui/components/conversation/event/hooks/use-formatted-date.js +1 -1
- package/src/javascripts/ui/components/conversation/event/image-lightbox.js +1 -1
- package/src/javascripts/ui/components/conversation/event/image.js +2 -2
- package/src/javascripts/ui/components/conversation/event/splash.js +1 -1
- package/src/javascripts/ui/components/conversation/event/translation.js +1 -1
- package/src/javascripts/ui/components/conversation/event/upload.js +2 -2
- package/src/javascripts/ui/components/conversation/event/video.js +2 -2
- package/src/javascripts/ui/components/conversation/event-divider.js +1 -1
- package/src/javascripts/ui/components/conversation/message-container.js +1 -1
- package/src/javascripts/ui/components/conversation/use-chat-scroll.ts +108 -0
- package/src/javascripts/ui/components/core/{seamly-activity-monitor.js → seamly-activity-monitor.tsx} +12 -5
- package/src/javascripts/ui/components/core/seamly-api-context.ts +7 -0
- package/src/javascripts/ui/components/core/seamly-chat.tsx +8 -0
- package/src/javascripts/ui/components/core/{seamly-core.js → seamly-core.tsx} +27 -14
- package/src/javascripts/ui/components/core/seamly-event-subscriber.ts +340 -0
- package/src/javascripts/ui/components/core/seamly-file-upload.js +2 -2
- package/src/javascripts/ui/components/core/seamly-idle-detach-counter.js +1 -1
- package/src/javascripts/ui/components/core/seamly-instance-functions-loader.js +24 -11
- package/src/javascripts/ui/components/core/seamly-live-region.js +4 -4
- package/src/javascripts/ui/components/core/seamly-new-notifications.js +3 -3
- package/src/javascripts/ui/components/core/seamly-read-state.js +2 -33
- package/src/javascripts/ui/components/entry/deprecated-toggle-button.js +4 -4
- package/src/javascripts/ui/components/entry/entry-container.js +8 -8
- package/src/javascripts/ui/components/entry/text-entry/hooks.js +3 -3
- package/src/javascripts/ui/components/entry/text-entry/index.js +3 -3
- package/src/javascripts/ui/components/entry/text-entry/text-entry-form.js +4 -4
- package/src/javascripts/ui/components/entry/upload/file-upload-form.js +3 -3
- package/src/javascripts/ui/components/entry/upload/index.js +5 -5
- package/src/javascripts/ui/components/entry/upload-toggle.js +6 -6
- package/src/javascripts/ui/components/faq/faq.js +14 -14
- package/src/javascripts/ui/components/form-controls/error.js +2 -2
- package/src/javascripts/ui/components/form-controls/file-input.js +3 -3
- package/src/javascripts/ui/components/layout/agent-info.js +3 -3
- package/src/javascripts/ui/components/layout/chat-frame.js +20 -12
- package/src/javascripts/ui/components/layout/chat.js +5 -5
- package/src/javascripts/ui/components/layout/deprecated-app-frame.js +6 -6
- package/src/javascripts/ui/components/layout/deprecated-chat-frame.js +34 -0
- package/src/javascripts/ui/components/layout/header.js +2 -2
- package/src/javascripts/ui/components/layout/icon.js +11 -9
- package/src/javascripts/ui/components/layout/interrupt.js +7 -5
- package/src/javascripts/ui/components/layout/pre-chat-messages.js +1 -1
- package/src/javascripts/ui/components/layout/privacy-disclaimer.js +2 -2
- package/src/javascripts/ui/components/options/options-button.js +5 -5
- package/src/javascripts/ui/components/options/{options-frame.js → options-frame.tsx} +52 -18
- package/src/javascripts/ui/components/options/transcript/index.js +9 -10
- package/src/javascripts/ui/components/options/transcript/transcript-form.js +2 -2
- package/src/javascripts/ui/components/suggestions/index.js +8 -8
- package/src/javascripts/ui/components/suggestions/suggestions-item.js +1 -1
- package/src/javascripts/{domains/translations/components/chat-status.js → ui/components/translation-chat-status/index.tsx} +13 -14
- package/src/javascripts/ui/components/translation-proposal/index.tsx +36 -0
- package/src/javascripts/ui/components/view/app-view.js +2 -7
- package/src/javascripts/ui/components/view/deprecated-view.js +8 -10
- package/src/javascripts/ui/components/view/index.js +6 -6
- package/src/javascripts/ui/components/view/inline-view.js +4 -8
- package/src/javascripts/ui/components/view/window-view/collapse-button.js +2 -2
- package/src/javascripts/ui/components/view/window-view/index.js +11 -17
- package/src/javascripts/ui/components/view/window-view/window-open-button.js +6 -6
- package/src/javascripts/ui/components/warnings/idle-detach-warning.js +3 -3
- package/src/javascripts/ui/components/warnings/prompt.js +1 -1
- package/src/javascripts/ui/components/warnings/resume-conversation-prompt.js +4 -4
- package/src/javascripts/ui/components/widgets/in-out-transition.js +20 -18
- package/src/javascripts/ui/components/widgets/lightbox.js +3 -3
- package/src/javascripts/ui/components/widgets/modal.js +2 -2
- package/src/javascripts/ui/components/widgets/upload-progress.js +2 -2
- package/src/javascripts/ui/hooks/file-upload-hooks.js +1 -1
- package/src/javascripts/ui/hooks/focus-helper-hooks.js +1 -1
- package/src/javascripts/ui/hooks/seamly-entry-hooks.js +6 -6
- package/src/javascripts/ui/hooks/seamly-hooks.js +11 -10
- package/src/javascripts/ui/hooks/seamly-option-hooks.js +6 -6
- package/src/javascripts/ui/hooks/{seamly-state-hooks.js → seamly-state-hooks.ts} +9 -6
- package/src/javascripts/ui/hooks/use-click-outside.ts +29 -0
- package/src/javascripts/ui/hooks/use-event-component-mapping.js +11 -10
- package/src/javascripts/ui/hooks/use-interval.js +1 -1
- package/src/javascripts/ui/hooks/use-seamly-actions.ts +29 -29
- package/src/javascripts/ui/hooks/use-seamly-chat.js +13 -23
- package/src/javascripts/ui/hooks/use-seamly-commands.js +20 -15
- package/src/javascripts/ui/hooks/use-seamly-idle-detach-countdown.js +8 -8
- package/src/javascripts/ui/hooks/use-seamly-resume-conversation-prompt.js +2 -2
- package/src/javascripts/ui/hooks/use-single-file-upload.js +1 -1
- package/src/javascripts/ui/hooks/utility-hooks.js +1 -1
- package/src/javascripts/ui/utils/general-utils.js +0 -23
- package/src/javascripts/ui/utils/seamly-utils.ts +10 -1
- package/src/javascripts/ui/utils/seamly-utils.types.ts +9 -0
- package/src/stylesheets/1-settings/_config.scss +1 -1
- package/src/stylesheets/3-chat/_chat.scss +23 -5
- package/src/stylesheets/5-components/_chat-status.scss +72 -16
- package/src/stylesheets/5-components/_conversation.scss +35 -1
- package/src/stylesheets/5-components/_disclaimer.scss +0 -5
- package/src/stylesheets/5-components/_options.scss +16 -2
- package/src/stylesheets/5-components/_translation-options.scss +39 -0
- package/src/stylesheets/6-default-implementation/_scrollbar.scss +1 -1
- package/src/stylesheets/7-deprecated/3-app/_app.scss +19 -4
- package/src/stylesheets/7-deprecated/5-components/_chat-status.scss +5 -0
- package/src/stylesheets/7-deprecated/5-components/_options.scss +1 -0
- package/src/stylesheets/7-deprecated/5-components/_translation-options.scss +39 -0
- package/src/stylesheets/deprecated-view.scss +1 -0
- package/src/stylesheets/styles.scss +1 -0
- package/webpack/config.common.js +4 -4
- package/webpack/config.package.js +10 -16
- package/webpack/config.site.js +4 -1
- package/webpack/config.test.js +2 -1
- package/build/dist/lib/deprecated-view.css +0 -1
- package/build/dist/lib/styles-default-implementation.css +0 -1
- package/build/dist/lib/styles.css +0 -1
- package/src/.DS_Store +0 -0
- package/src/javascripts/api/event-producer.js +0 -20
- package/src/javascripts/api/producer.js +0 -136
- package/src/javascripts/domains/errors/index.js +0 -37
- package/src/javascripts/domains/translations/components/options-dialog/form.js +0 -70
- package/src/javascripts/domains/translations/components/options-dialog/index.js +0 -87
- package/src/javascripts/ui/components/chat-status/index.js +0 -38
- package/src/javascripts/ui/components/conversation/event/event.js +0 -36
- package/src/javascripts/ui/components/core/seamly-api-context.js +0 -5
- package/src/javascripts/ui/components/core/seamly-event-subscriber.js +0 -279
|
@@ -1,15 +1,13 @@
|
|
|
1
|
+
import SeamlyBaseError from './seamly-base-error'
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* This error is used to alert the user that there's a problem with the connection
|
|
3
5
|
* when initialising the application because of a connection issue on either the server
|
|
4
6
|
* or the client side.
|
|
5
7
|
*/
|
|
6
|
-
export default class SeamlyUnavailableError extends
|
|
7
|
-
constructor(params) {
|
|
8
|
-
super(params)
|
|
9
|
-
|
|
10
|
-
if (Error.captureStackTrace) {
|
|
11
|
-
Error.captureStackTrace(this, SeamlyUnavailableError)
|
|
12
|
-
}
|
|
8
|
+
export default class SeamlyUnavailableError extends SeamlyBaseError {
|
|
9
|
+
constructor(originalError, ...params) {
|
|
10
|
+
super(originalError, ...params)
|
|
13
11
|
|
|
14
12
|
this.name = 'SeamlyUnavailableError'
|
|
15
13
|
this.langKey = 'errors.seamlyUnavailable'
|
|
@@ -1,22 +1,26 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { ApiConfig, Config, Context, LayoutMode } from 'config.types'
|
|
2
|
+
import { components, operations } from 'schema'
|
|
2
3
|
import superagent from 'superagent'
|
|
3
4
|
import { apiVersion } from 'config'
|
|
4
|
-
import
|
|
5
|
+
import SeamlyConfigurationError from 'api/errors/seamly-configuration-error'
|
|
6
|
+
import SeamlyGeneralError from 'api/errors/seamly-general-error'
|
|
7
|
+
import SeamlySessionExpiredError from 'api/errors/seamly-session-expired-error'
|
|
8
|
+
import SeamlyUnauthorizedError from 'api/errors/seamly-unauthorized-error'
|
|
9
|
+
import { omit } from 'ui/utils/general-utils'
|
|
10
|
+
import type { ChannelEvent } from 'domains/store/store.types'
|
|
11
|
+
import debug from 'lib/debug'
|
|
5
12
|
import { randomId } from 'lib/id'
|
|
13
|
+
import { objectStore } from 'lib/store/index'
|
|
6
14
|
import sessionStorageProvider from 'lib/store/providers/session-storage'
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import SeamlySessionExpiredError from './errors/seamly-session-expired-error'
|
|
12
|
-
import SeamlyConfigurationError from './errors/seamly-configuration-error'
|
|
13
|
-
import SeamlyGeneralError from './errors/seamly-general-error'
|
|
14
|
-
import SeamlyUnauthorizedError from './errors/seamly-unauthorized-error'
|
|
15
|
+
import ConversationConnector from './conversation-connector'
|
|
16
|
+
|
|
17
|
+
declare let PACKAGE_NAME: string
|
|
18
|
+
declare let PACKAGE_VERSION: string
|
|
15
19
|
|
|
16
20
|
const log = debug('seamly')
|
|
17
21
|
|
|
18
22
|
const DOMAIN = 'api.seamly-app.com'
|
|
19
|
-
const TRANSLATIONS_VERSION =
|
|
23
|
+
const TRANSLATIONS_VERSION = 2
|
|
20
24
|
|
|
21
25
|
function buildPayload(command, payload) {
|
|
22
26
|
if (command !== 'message') {
|
|
@@ -67,38 +71,76 @@ function getTimeZone() {
|
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
|
|
74
|
+
type UrlsType = components['schemas']['ConversationResponse']['_links'] &
|
|
75
|
+
operations['getAccountConfig']['responses']['201']['content']['application/json']['_links']
|
|
76
|
+
|
|
77
|
+
type InitialConversation = Omit<
|
|
78
|
+
components['schemas']['ConversationResponse']['conversation'],
|
|
79
|
+
'accessToken' | 'channelTopic'
|
|
80
|
+
>
|
|
81
|
+
export type ConversationHistoryResponse = Omit<
|
|
82
|
+
components['schemas']['ConversationHistoryResponse']['history'],
|
|
83
|
+
'messages' | 'ui.resumeConversationPrompt'
|
|
84
|
+
> & {
|
|
85
|
+
resumeConversationPrompt: components['schemas']['ConversationHistoryResponse']['history']['ui']['resumeConversationPrompt']
|
|
86
|
+
translationProposal: components['schemas']['ConversationHistoryResponse']['history']['ui']['translationProposal']
|
|
87
|
+
events: ChannelEvent[]
|
|
88
|
+
}
|
|
89
|
+
|
|
70
90
|
export class API {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
#ready: boolean
|
|
92
|
+
|
|
93
|
+
connected: boolean
|
|
94
|
+
|
|
95
|
+
#externalId: string
|
|
96
|
+
|
|
97
|
+
#layoutMode: LayoutMode
|
|
98
|
+
|
|
99
|
+
#config: ApiConfig & {
|
|
100
|
+
context: Context
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
store: {
|
|
104
|
+
get(_key: string): string
|
|
105
|
+
set(_key: string, _value: unknown): string
|
|
106
|
+
delete(_key: string): string
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
connectionInfo: { apiKey: string; domain: string; secure: boolean }
|
|
110
|
+
|
|
111
|
+
configReady: boolean
|
|
112
|
+
|
|
113
|
+
userResponded: boolean
|
|
114
|
+
|
|
115
|
+
URLS: UrlsType
|
|
116
|
+
|
|
117
|
+
locale: string
|
|
118
|
+
|
|
119
|
+
conversation?: ConversationConnector = new ConversationConnector()
|
|
120
|
+
|
|
121
|
+
constructor({
|
|
122
|
+
layoutMode,
|
|
123
|
+
namespace,
|
|
124
|
+
config,
|
|
125
|
+
context,
|
|
126
|
+
}: {
|
|
127
|
+
layoutMode: LayoutMode
|
|
128
|
+
namespace: string
|
|
129
|
+
config: ApiConfig
|
|
130
|
+
context: Context
|
|
131
|
+
}) {
|
|
90
132
|
this.store = objectStore(
|
|
91
133
|
`${namespace}.connection${context.locale ? `.${context.locale}` : ''}`,
|
|
92
134
|
config.storageProvider || sessionStorageProvider,
|
|
93
135
|
)
|
|
94
|
-
|
|
95
136
|
this.connectionInfo = {
|
|
96
137
|
apiKey: config.key,
|
|
97
138
|
domain: config.domain || DOMAIN,
|
|
98
139
|
secure: config.secure !== false ? config.secure || true : false,
|
|
99
140
|
}
|
|
100
141
|
|
|
101
|
-
this
|
|
142
|
+
this.#config = {
|
|
143
|
+
...config,
|
|
102
144
|
sendEnvironment: config.sendEnvironment ?? true,
|
|
103
145
|
context: {
|
|
104
146
|
...context,
|
|
@@ -106,25 +148,13 @@ export class API {
|
|
|
106
148
|
},
|
|
107
149
|
}
|
|
108
150
|
|
|
151
|
+
this.#ready = false
|
|
109
152
|
this.connected = false
|
|
110
153
|
this.configReady = false
|
|
111
|
-
this
|
|
112
|
-
this
|
|
154
|
+
this.#externalId = config.externalId
|
|
155
|
+
this.#layoutMode = layoutMode
|
|
113
156
|
this.userResponded = false
|
|
114
157
|
|
|
115
|
-
this.internalProducer = new EventProducer('API')
|
|
116
|
-
this.internal$ = xs.create(this.internalProducer).flatten()
|
|
117
|
-
this.connection$ = this.internal$.filter(
|
|
118
|
-
(event) => event.type === 'connection',
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
this.connection$.subscribe({
|
|
122
|
-
next: ({ connected, ready }) => {
|
|
123
|
-
this.connected = connected
|
|
124
|
-
this.ready = ready
|
|
125
|
-
},
|
|
126
|
-
})
|
|
127
|
-
|
|
128
158
|
this.URLS = {}
|
|
129
159
|
|
|
130
160
|
// We want to reconnect whenever the page is loaded from cache (bfcache).
|
|
@@ -136,37 +166,37 @@ export class API {
|
|
|
136
166
|
})
|
|
137
167
|
}
|
|
138
168
|
|
|
139
|
-
getAccessToken() {
|
|
169
|
+
#getAccessToken(): string {
|
|
140
170
|
return this.store.get('accessToken')
|
|
141
171
|
}
|
|
142
172
|
|
|
143
|
-
setAccessToken(accessToken) {
|
|
173
|
+
#setAccessToken(accessToken: string) {
|
|
144
174
|
this.store.set('accessToken', accessToken)
|
|
145
175
|
}
|
|
146
176
|
|
|
147
|
-
getConversationUrl() {
|
|
177
|
+
getConversationUrl(): string {
|
|
148
178
|
return this.store.get('conversationUrl')
|
|
149
179
|
}
|
|
150
180
|
|
|
151
|
-
setConversationUrl(url) {
|
|
181
|
+
#setConversationUrl(url: { href?: string }) {
|
|
152
182
|
this.store.set('conversationUrl', url)
|
|
153
183
|
}
|
|
154
184
|
|
|
155
|
-
hasConversation() {
|
|
185
|
+
hasConversation(): boolean {
|
|
156
186
|
return !!this.getConversationUrl()
|
|
157
187
|
}
|
|
158
188
|
|
|
159
|
-
getChannelTopic() {
|
|
189
|
+
#getChannelTopic() {
|
|
160
190
|
// The `channelName` fallback is needed for seamless client upgrades.
|
|
161
191
|
// TODO: Remove when all clients have been upgraded past v20.
|
|
162
192
|
return this.store.get('channelTopic') || this.store.get('channelName')
|
|
163
193
|
}
|
|
164
194
|
|
|
165
|
-
setChannelTopic(topic) {
|
|
195
|
+
#setChannelTopic(topic: string) {
|
|
166
196
|
this.store.set('channelTopic', topic)
|
|
167
197
|
}
|
|
168
198
|
|
|
169
|
-
getLocale = (locale) => locale || this.locale
|
|
199
|
+
#getLocale = (locale: string): string => locale || this.locale
|
|
170
200
|
|
|
171
201
|
clearStore() {
|
|
172
202
|
this.store.delete('accessToken')
|
|
@@ -176,12 +206,12 @@ export class API {
|
|
|
176
206
|
this.store.delete('channelTopic')
|
|
177
207
|
}
|
|
178
208
|
|
|
179
|
-
getUrlPrefix(protocol) {
|
|
209
|
+
#getUrlPrefix(protocol: string) {
|
|
180
210
|
const realProtocol = this.connectionInfo.secure ? `${protocol}s` : protocol
|
|
181
211
|
return `${realProtocol}://${this.connectionInfo.domain}`
|
|
182
212
|
}
|
|
183
213
|
|
|
184
|
-
updateUrls({ _links: responseLinks }) {
|
|
214
|
+
#updateUrls({ _links: responseLinks }: { _links: UrlsType }) {
|
|
185
215
|
this.URLS = Object.entries(responseLinks)
|
|
186
216
|
.filter(([key]) => key !== 'self')
|
|
187
217
|
.reduce((urls, [key, { href }]) => {
|
|
@@ -199,24 +229,24 @@ export class API {
|
|
|
199
229
|
}
|
|
200
230
|
|
|
201
231
|
async disconnect() {
|
|
202
|
-
if (this.
|
|
203
|
-
|
|
232
|
+
if (this.conversation?.disconnect) {
|
|
233
|
+
this.conversation.disconnect()
|
|
204
234
|
}
|
|
205
235
|
this.connected = false
|
|
206
236
|
this.configReady = false
|
|
207
237
|
}
|
|
208
238
|
|
|
209
|
-
async createConversation() {
|
|
239
|
+
async #createConversation(): Promise<InitialConversation> {
|
|
210
240
|
try {
|
|
211
241
|
const request = superagent
|
|
212
|
-
.post(`${this
|
|
242
|
+
.post(`${this.#getUrlPrefix('http')}${this.URLS.conversations}`)
|
|
213
243
|
.set('Content-Type', 'application/json')
|
|
214
244
|
.query({ v: apiVersion })
|
|
215
245
|
// withCredentials() is necessary to allow browsers to save received
|
|
216
246
|
// cookies in CORS requests.
|
|
217
247
|
.withCredentials()
|
|
218
248
|
.send({
|
|
219
|
-
externalId: this
|
|
249
|
+
externalId: this.#externalId || undefined,
|
|
220
250
|
})
|
|
221
251
|
|
|
222
252
|
const { body } = await request
|
|
@@ -225,10 +255,10 @@ export class API {
|
|
|
225
255
|
const initialState = { ...conversation }
|
|
226
256
|
delete initialState.accessToken
|
|
227
257
|
delete initialState.channelTopic
|
|
228
|
-
this
|
|
229
|
-
this
|
|
230
|
-
this
|
|
231
|
-
this
|
|
258
|
+
this.#setAccessToken(conversation.accessToken)
|
|
259
|
+
this.#setChannelTopic(conversation.channelTopic)
|
|
260
|
+
this.#updateUrls(body)
|
|
261
|
+
this.#setConversationUrl(this.URLS.conversation)
|
|
232
262
|
this.locale = conversation.translation?.locale
|
|
233
263
|
this.userResponded = conversation.userResponded
|
|
234
264
|
|
|
@@ -237,14 +267,15 @@ export class API {
|
|
|
237
267
|
if (error.status >= 500) {
|
|
238
268
|
throw new SeamlyGeneralError(error)
|
|
239
269
|
}
|
|
270
|
+
|
|
240
271
|
throw error
|
|
241
272
|
}
|
|
242
273
|
}
|
|
243
274
|
|
|
244
|
-
getConfig() {
|
|
275
|
+
getConfig(): Promise<Config> {
|
|
245
276
|
return superagent
|
|
246
277
|
.post(
|
|
247
|
-
`${this
|
|
278
|
+
`${this.#getUrlPrefix('http')}/client/${
|
|
248
279
|
this.connectionInfo.apiKey
|
|
249
280
|
}/configs`,
|
|
250
281
|
)
|
|
@@ -252,41 +283,43 @@ export class API {
|
|
|
252
283
|
.query({ v: apiVersion })
|
|
253
284
|
.send({
|
|
254
285
|
context: {
|
|
255
|
-
...this
|
|
286
|
+
...this.#config.context,
|
|
256
287
|
environment:
|
|
257
|
-
this
|
|
258
|
-
? this
|
|
259
|
-
: this
|
|
288
|
+
this.#config.sendEnvironment === true
|
|
289
|
+
? this.#getEnvironment()
|
|
290
|
+
: this.#config.sendEnvironment,
|
|
260
291
|
},
|
|
261
292
|
})
|
|
262
293
|
.then(({ body }) => {
|
|
263
|
-
this
|
|
294
|
+
this.#updateUrls(body)
|
|
264
295
|
this.configReady = true
|
|
265
296
|
return body.config
|
|
266
297
|
})
|
|
267
298
|
.catch((error) => {
|
|
268
299
|
if (error.status === 404) {
|
|
269
|
-
throw new SeamlyConfigurationError()
|
|
300
|
+
throw new SeamlyConfigurationError(error)
|
|
270
301
|
}
|
|
302
|
+
|
|
271
303
|
if (error.status >= 500) {
|
|
272
304
|
throw new SeamlyGeneralError(error)
|
|
273
305
|
}
|
|
306
|
+
|
|
274
307
|
throw error
|
|
275
308
|
})
|
|
276
309
|
}
|
|
277
310
|
|
|
278
|
-
async getConversation() {
|
|
311
|
+
async getConversation(): Promise<ConversationHistoryResponse> {
|
|
279
312
|
if (!this.hasConversation()) {
|
|
280
313
|
return null
|
|
281
314
|
}
|
|
282
315
|
|
|
283
316
|
try {
|
|
284
317
|
const { body } = await superagent
|
|
285
|
-
.get(`${this
|
|
286
|
-
.set('Authorization', `Bearer ${this
|
|
318
|
+
.get(`${this.#getUrlPrefix('http')}${this.URLS.history}`)
|
|
319
|
+
.set('Authorization', `Bearer ${this.#getAccessToken()}`)
|
|
287
320
|
.query({ v: apiVersion })
|
|
288
321
|
|
|
289
|
-
this
|
|
322
|
+
this.#updateUrls(body)
|
|
290
323
|
|
|
291
324
|
const {
|
|
292
325
|
messages,
|
|
@@ -314,48 +347,58 @@ export class API {
|
|
|
314
347
|
resumeConversationPrompt: ui
|
|
315
348
|
? Boolean(ui.resumeConversationPrompt)
|
|
316
349
|
: false,
|
|
350
|
+
translationProposal: ui.translationProposal,
|
|
317
351
|
translation,
|
|
318
352
|
}
|
|
319
353
|
} catch (error) {
|
|
320
354
|
if (error.status === 401) {
|
|
321
355
|
throw new SeamlyUnauthorizedError(error)
|
|
322
356
|
}
|
|
357
|
+
|
|
323
358
|
if (error.status === 404) {
|
|
324
359
|
throw new SeamlySessionExpiredError(error)
|
|
325
360
|
}
|
|
361
|
+
|
|
326
362
|
if (error.status >= 500) {
|
|
327
363
|
throw new SeamlyGeneralError(error)
|
|
328
364
|
}
|
|
365
|
+
|
|
329
366
|
throw error
|
|
330
367
|
}
|
|
331
368
|
}
|
|
332
369
|
|
|
333
|
-
async connect() {
|
|
370
|
+
async connect(): Promise<InitialConversation> {
|
|
334
371
|
this.connected = false
|
|
335
|
-
let conversationInitialState =
|
|
372
|
+
let conversationInitialState: InitialConversation = {}
|
|
336
373
|
|
|
337
374
|
if (!this.hasConversation()) {
|
|
338
|
-
conversationInitialState = await this
|
|
375
|
+
conversationInitialState = await this.#createConversation()
|
|
339
376
|
}
|
|
340
377
|
|
|
341
|
-
this.
|
|
342
|
-
`${this
|
|
343
|
-
this
|
|
344
|
-
this
|
|
345
|
-
this
|
|
378
|
+
this.conversation.connect(
|
|
379
|
+
`${this.#getUrlPrefix('ws')}${this.URLS.socket}`,
|
|
380
|
+
this.#config.context.channelName,
|
|
381
|
+
this.#getChannelTopic(),
|
|
382
|
+
this.#getAccessToken(),
|
|
346
383
|
)
|
|
347
384
|
|
|
348
|
-
this.
|
|
385
|
+
this.conversation.onConnection((connectionState) => {
|
|
386
|
+
this.connected = [
|
|
387
|
+
'attach_channel_succeeded',
|
|
388
|
+
'join_channel_succeeded',
|
|
389
|
+
].includes(connectionState)
|
|
390
|
+
this.#ready = connectionState === 'attach_channel_succeeded'
|
|
391
|
+
})
|
|
349
392
|
|
|
350
393
|
// Send environment
|
|
351
|
-
if (this
|
|
394
|
+
if (this.#config.sendEnvironment) {
|
|
352
395
|
this.send(
|
|
353
396
|
'context',
|
|
354
397
|
{
|
|
355
398
|
environment:
|
|
356
|
-
this
|
|
357
|
-
? this
|
|
358
|
-
: this
|
|
399
|
+
this.#config.sendEnvironment === true
|
|
400
|
+
? this.#getEnvironment()
|
|
401
|
+
: this.#config.sendEnvironment,
|
|
359
402
|
},
|
|
360
403
|
false,
|
|
361
404
|
)
|
|
@@ -369,8 +412,8 @@ export class API {
|
|
|
369
412
|
formData.append('upload', file)
|
|
370
413
|
|
|
371
414
|
const req = superagent
|
|
372
|
-
.post(`${this
|
|
373
|
-
.set('Authorization', `Bearer ${this
|
|
415
|
+
.post(`${this.#getUrlPrefix('http')}${this.URLS.uploads}`)
|
|
416
|
+
.set('Authorization', `Bearer ${this.#getAccessToken()}`)
|
|
374
417
|
.send(formData)
|
|
375
418
|
|
|
376
419
|
req.on('progress', function (e) {
|
|
@@ -399,11 +442,11 @@ export class API {
|
|
|
399
442
|
|
|
400
443
|
getConversationIntitialState() {
|
|
401
444
|
return superagent
|
|
402
|
-
.get(`${this
|
|
403
|
-
.set('Authorization', `Bearer ${this
|
|
445
|
+
.get(`${this.#getUrlPrefix('http')}${this.getConversationUrl()}`)
|
|
446
|
+
.set('Authorization', `Bearer ${this.#getAccessToken()}`)
|
|
404
447
|
.query({ v: apiVersion })
|
|
405
448
|
.then(({ body }) => {
|
|
406
|
-
this
|
|
449
|
+
this.#updateUrls(body)
|
|
407
450
|
this.userResponded = body.conversation.userResponded
|
|
408
451
|
return omit(body.conversation, ['accessToken', 'channelTopic'])
|
|
409
452
|
})
|
|
@@ -417,15 +460,20 @@ export class API {
|
|
|
417
460
|
if (error.status >= 500) {
|
|
418
461
|
throw new SeamlyGeneralError(error)
|
|
419
462
|
}
|
|
463
|
+
|
|
420
464
|
throw error
|
|
421
465
|
})
|
|
422
466
|
}
|
|
423
467
|
|
|
424
|
-
async getTranslations(locale) {
|
|
468
|
+
async getTranslations(locale: string): Promise<Record<string, string>> {
|
|
425
469
|
try {
|
|
426
|
-
|
|
470
|
+
if (!this.URLS.translations) {
|
|
471
|
+
throw new SeamlyConfigurationError()
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const url = `${this.#getUrlPrefix('http')}${this.URLS.translations}`
|
|
427
475
|
.replace('{version}', String(TRANSLATIONS_VERSION))
|
|
428
|
-
.replace('{locale}', this
|
|
476
|
+
.replace('{locale}', this.#getLocale(locale))
|
|
429
477
|
const request = superagent.get(url)
|
|
430
478
|
|
|
431
479
|
const { body } = await request
|
|
@@ -434,34 +482,36 @@ export class API {
|
|
|
434
482
|
if (error.status >= 500) {
|
|
435
483
|
throw new SeamlyGeneralError(error)
|
|
436
484
|
}
|
|
485
|
+
|
|
437
486
|
throw error
|
|
438
487
|
}
|
|
439
488
|
}
|
|
440
489
|
|
|
441
490
|
send(command, payload, waitForReady = true) {
|
|
442
|
-
if (!this.connected || (waitForReady && !this
|
|
443
|
-
// Wait for connection
|
|
444
|
-
this.
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
491
|
+
if (!this.connected || (waitForReady && !this.#ready)) {
|
|
492
|
+
// Wait for connection to be made
|
|
493
|
+
this.conversation?.onConnection((connectionState) => {
|
|
494
|
+
const connected = connectionState === 'join_channel_succeeded'
|
|
495
|
+
const ready = connectionState === 'attach_channel_succeeded'
|
|
496
|
+
if (waitForReady ? ready : connected || ready) {
|
|
497
|
+
this.send(command, payload, waitForReady)
|
|
498
|
+
}
|
|
499
|
+
})
|
|
450
500
|
return
|
|
451
501
|
}
|
|
452
502
|
|
|
453
503
|
log('[SEND]', command, payload)
|
|
454
504
|
|
|
455
|
-
this.
|
|
505
|
+
this.conversation.pushToChannel(
|
|
456
506
|
command,
|
|
457
507
|
buildPayload(command, payload),
|
|
458
508
|
10000,
|
|
459
509
|
)
|
|
460
510
|
}
|
|
461
511
|
|
|
462
|
-
sendContext(context
|
|
512
|
+
sendContext(context: Context) {
|
|
463
513
|
const { locale, variables } = context
|
|
464
|
-
const payload = {}
|
|
514
|
+
const payload: { locale?: string; variables?: any } = {}
|
|
465
515
|
|
|
466
516
|
if (locale) {
|
|
467
517
|
if (typeof locale !== 'string') {
|
|
@@ -485,19 +535,16 @@ export class API {
|
|
|
485
535
|
this.send('context', payload, false)
|
|
486
536
|
}
|
|
487
537
|
|
|
488
|
-
|
|
489
|
-
return this.internal$.filter((event) => event.type !== 'connection')
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
getEnvironment() {
|
|
538
|
+
#getEnvironment() {
|
|
493
539
|
return {
|
|
494
540
|
clientName: PACKAGE_NAME,
|
|
495
|
-
clientVariant: this
|
|
541
|
+
clientVariant: this.#layoutMode,
|
|
496
542
|
clientVersion: PACKAGE_VERSION,
|
|
497
543
|
currentUrl: window.location.toString(),
|
|
498
544
|
screenResolution: `${window.screen.width}x${window.screen.height}`,
|
|
499
545
|
timezone: getTimeZone(),
|
|
500
546
|
userAgent: navigator.userAgent,
|
|
547
|
+
preferredLocale: navigator.language,
|
|
501
548
|
}
|
|
502
549
|
}
|
|
503
550
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ChannelEvent } from 'domains/store/store.types'
|
|
2
1
|
import { FunctionComponent } from 'preact'
|
|
2
|
+
import type { ChannelEvent } from 'domains/store/store.types'
|
|
3
3
|
|
|
4
4
|
export type ApiConfig = {
|
|
5
5
|
key: string
|
|
@@ -19,8 +19,9 @@ export type ErrorCallbackMeta = {
|
|
|
19
19
|
api: ApiConfig
|
|
20
20
|
layoutMode: LayoutMode
|
|
21
21
|
conversationUrl: string
|
|
22
|
+
action?: string
|
|
22
23
|
}
|
|
23
|
-
export type ErrorCallback = (
|
|
24
|
+
export type ErrorCallback = (_error: Error, _meta: ErrorCallbackMeta) => void
|
|
24
25
|
|
|
25
26
|
export type Message = {
|
|
26
27
|
showName?: boolean
|
|
@@ -62,7 +63,7 @@ export type VisibilityCallbackOptions = {
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
export type VisibilityCallback = (
|
|
65
|
-
|
|
66
|
+
_options: VisibilityCallbackOptions,
|
|
66
67
|
) => VisibilityOptions
|
|
67
68
|
|
|
68
69
|
export type Config = {
|
|
@@ -79,7 +80,7 @@ export type Config = {
|
|
|
79
80
|
visibilityCallback?: VisibilityCallback
|
|
80
81
|
errorCallback?: ErrorCallback
|
|
81
82
|
api: ApiConfig
|
|
82
|
-
appContainerClassNames?: string[] | ((
|
|
83
|
+
appContainerClassNames?: string[] | ((_config: Config) => string[])
|
|
83
84
|
zIndex?: number
|
|
84
85
|
showFaq?: boolean
|
|
85
86
|
showSuggestions?: boolean
|