这是indexloc提供的服务,不要输入任何密码
Skip to content

Commit edac7c6

Browse files
fix(channel-web): fix useSessionStorage config option (#5118)
* fix(channel-web): fix useSessionStorage config option * small fix * merge master * fix using session storage * fix build * reject with error when visutor id cannot be acquired * added missing typings * added automatic serialize and deserialize when using storage utils class * callers now use storage own serialize + deserialize * small fix * pr comments * update locale with config + setup socket only once on init * chore(shared-lite): added unit tests for storage utils (#5405) * chore(sharedLite): added unit tests for storage utils * fix build * updated unit tests * removed ability to reconfigure useSessionStorage * removed unecessary async/await * better typings * PR comments + bump studio v0.0.37 Co-authored-by: Samuel Massé <59894025+samuelmasse@users.noreply.github.com>
1 parent f976538 commit edac7c6

File tree

24 files changed

+347
-82
lines changed

24 files changed

+347
-82
lines changed

modules/channel-web/src/views/lite/core/socket.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { Config } from '../typings'
1+
import { Config, StudioConnector } from '../typings'
22

33
export default class BpSocket {
44
private events: any
5-
private userId: string
65
private userIdScope: string
76
private chatId: string | undefined
87

@@ -12,16 +11,12 @@ export default class BpSocket {
1211
public onData: (event: any) => void
1312
public onUserIdChanged: (userId: string) => void
1413

15-
constructor(bp, config: Config) {
14+
constructor(bp: StudioConnector, config: Config) {
1615
this.events = bp?.events
1716
this.userIdScope = config.userIdScope
1817
this.chatId = config.chatId
1918
}
2019

21-
private isString(str: string | any): str is string {
22-
return typeof str === 'string' && str !== 'undefined'
23-
}
24-
2520
public setup() {
2621
if (!this.events) {
2722
return
@@ -39,7 +34,7 @@ export default class BpSocket {
3934
this.events.onAny(this.postToParent)
4035
}
4136

42-
public postToParent = (type: string, payload: any) => {
37+
public postToParent = (_type: string, payload: any) => {
4338
// we could filter on event type if necessary
4439
window.parent?.postMessage({ ...payload, chatId: this.chatId }, '*')
4540
}
@@ -51,23 +46,28 @@ export default class BpSocket {
5146
}
5247

5348
/** Waits until the VISITOR ID and VISITOR SOCKET ID is set */
54-
public waitForUserId(): Promise<void> {
49+
public async waitForUserId(): Promise<void> {
5550
return new Promise((resolve, reject) => {
5651
const interval = setInterval(() => {
57-
if (this.isString(window.__BP_VISITOR_ID) && this.isString(window.__BP_VISITOR_SOCKET_ID)) {
52+
if (isString(window.__BP_VISITOR_ID) && isString(window.__BP_VISITOR_SOCKET_ID)) {
5853
clearInterval(interval)
5954

60-
this.userId = window.__BP_VISITOR_ID
61-
this.onUserIdChanged(this.userId)
62-
this.postToParent('', { userId: this.userId })
55+
const userId = window.__BP_VISITOR_ID
56+
this.onUserIdChanged(userId)
57+
this.postToParent('', { userId })
58+
6359
resolve()
6460
}
6561
}, 250)
6662

6763
setTimeout(() => {
6864
clearInterval(interval)
69-
reject()
70-
}, 300000)
65+
reject('Timeout to acquire VISITOR ID and VISITOR SOCKET ID exceeded.')
66+
}, 30000)
7167
})
7268
}
7369
}
70+
71+
const isString = (str: string | any): str is string => {
72+
return typeof str === 'string' && str !== 'undefined'
73+
}

modules/channel-web/src/views/lite/main.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ import constants from './core/constants'
1313
import BpSocket from './core/socket'
1414
import ChatIcon from './icons/Chat'
1515
import { RootStore, StoreDef } from './store'
16-
import { Config, Message, uuid } from './typings'
16+
import { Config, Message, Overrides, uuid } from './typings'
1717
import { checkLocationOrigin, initializeAnalytics, isIE, trackMessage, trackWebchatState } from './utils'
1818

19-
const _values = obj => Object.keys(obj).map(x => obj[x])
19+
const _values = (obj: Overrides) => Object.keys(obj).map(x => obj[x])
2020

2121
class Web extends React.Component<MainProps> {
2222
private config: Config
@@ -62,8 +62,10 @@ class Web extends React.Component<MainProps> {
6262
}
6363

6464
componentDidUpdate() {
65-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
66-
this.initializeIfChatDisplayed()
65+
if (this.config) {
66+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
67+
this.initializeIfChatDisplayed()
68+
}
6769
}
6870

6971
async initializeIfChatDisplayed() {
@@ -110,7 +112,7 @@ class Web extends React.Component<MainProps> {
110112
window.parent?.postMessage({ type, value, chatId: this.config.chatId }, '*')
111113
}
112114

113-
extractConfig() {
115+
extractConfig(): Config {
114116
const decodeIfRequired = (options: string) => {
115117
try {
116118
return decodeURIComponent(options)
@@ -121,7 +123,7 @@ class Web extends React.Component<MainProps> {
121123
const { options, ref } = queryString.parse(location.search)
122124
const { config } = JSON.parse(decodeIfRequired(options || '{}'))
123125

124-
const userConfig = Object.assign({}, constants.DEFAULT_CONFIG, config)
126+
const userConfig: Config = Object.assign({}, constants.DEFAULT_CONFIG, config)
125127
userConfig.reference = config.ref || ref
126128

127129
this.props.updateConfig(userConfig, this.props.bp)
@@ -143,7 +145,7 @@ class Web extends React.Component<MainProps> {
143145
await this.socket.waitForUserId()
144146
}
145147

146-
loadOverrides(overrides) {
148+
loadOverrides(overrides: Overrides) {
147149
try {
148150
for (const override of _values(overrides)) {
149151
override.map(({ module }) => this.props.bp.loadModuleView(module, true))
@@ -159,8 +161,8 @@ class Web extends React.Component<MainProps> {
159161
return
160162
}
161163

162-
await this.socket.changeUserId(data.newValue)
163-
await this.socket.setup()
164+
this.socket.changeUserId(data.newValue)
165+
this.socket.setup()
164166
await this.socket.waitForUserId()
165167
await this.props.initializeChat()
166168
})
@@ -246,7 +248,7 @@ class Web extends React.Component<MainProps> {
246248

247249
if (!['session_reset'].includes(event.payload.type) && event.id !== this.lastMessageId) {
248250
this.lastMessageId = event.id
249-
this.props.store.loadEventInDebugger(event.id)
251+
await this.props.store.loadEventInDebugger(event.id)
250252
}
251253
}
252254

@@ -259,7 +261,7 @@ class Web extends React.Component<MainProps> {
259261
await this.props.updateTyping(event)
260262
}
261263

262-
handleDataMessage = event => {
264+
handleDataMessage = (event: Message) => {
263265
if (!event || !event.payload) {
264266
return
265267
}

modules/channel-web/src/views/lite/store/composer.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class ComposerStore {
3131
this.rootStore = rootStore
3232

3333
if (window.BP_STORAGE) {
34-
this._sentHistory = JSON.parse(window.BP_STORAGE.get(SENT_HISTORY_KEY) || '[]')
34+
this._sentHistory = window.BP_STORAGE.get<string[]>(SENT_HISTORY_KEY) || []
3535
}
3636
}
3737

@@ -52,10 +52,7 @@ class ComposerStore {
5252
this._sentHistoryIndex = 0
5353

5454
if (this.rootStore.config.enablePersistHistory) {
55-
window.BP_STORAGE?.set(
56-
SENT_HISTORY_KEY,
57-
JSON.stringify(takeRight(this._sentHistory, constants.SENT_HISTORY_SIZE))
58-
)
55+
window.BP_STORAGE?.set(SENT_HISTORY_KEY, takeRight(this._sentHistory, constants.SENT_HISTORY_SIZE))
5956
}
6057
}
6158
}

modules/channel-web/src/views/lite/store/index.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class RootStore {
3636
public composer: ComposerStore
3737
public view: ViewStore
3838

39-
private _typingInterval
39+
private _typingInterval: ReturnType<typeof setInterval> | undefined
4040
private api: WebchatApi
4141

4242
@observable
@@ -76,11 +76,10 @@ class RootStore {
7676
constructor({ fullscreen }) {
7777
this.composer = new ComposerStore(this)
7878
this.view = new ViewStore(this, fullscreen)
79-
this.updateBotUILanguage(chosenLocale)
8079
}
8180

8281
@action.bound
83-
setIntlProvider(provider) {
82+
setIntlProvider(provider: InjectedIntl) {
8483
this.intl = provider
8584
}
8685

@@ -140,7 +139,7 @@ class RootStore {
140139
}
141140

142141
@action.bound
143-
updateMessages(messages) {
142+
updateMessages(messages: Message[]) {
144143
this.currentConversation.messages = messages
145144
}
146145

@@ -427,20 +426,21 @@ class RootStore {
427426
this.view.disableAnimations = this.config.disableAnimations
428427
this.config.showPoweredBy ? this.view.showPoweredBy() : this.view.hidePoweredBy()
429428

430-
const locale = getUserLocale(this.config.locale)
431-
this.config.locale && this.updateBotUILanguage(locale)
432-
document.documentElement.setAttribute('lang', locale)
433-
434429
document.title = this.config.botName || 'Botpress Webchat'
435430

436-
try {
431+
this.api.updateAxiosConfig({ botId: this.config.botId, externalAuthToken: this.config.externalAuthToken })
432+
this.api.updateUserId(this.config.userId)
433+
434+
if (!this.isInitialized) {
437435
window.USE_SESSION_STORAGE = this.config.useSessionStorage
438-
} catch {
439-
console.error('Could not set USE_SESSION_STORAGE')
436+
} else if (window.USE_SESSION_STORAGE !== this.config.useSessionStorage) {
437+
console.warn('[WebChat] "useSessionStorage" value cannot be altered once the webchat is initialized')
440438
}
441439

442-
this.api.updateAxiosConfig({ botId: this.config.botId, externalAuthToken: this.config.externalAuthToken })
443-
this.api.updateUserId(this.config.userId)
440+
const locale = this.config.locale ? getUserLocale(this.config.locale) : chosenLocale
441+
this.updateBotUILanguage(locale)
442+
document.documentElement.setAttribute('lang', locale)
443+
444444
this.publishConfigChanged()
445445
}
446446

modules/channel-web/src/views/lite/translations/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const DEFAULT_LOCALE = 'en'
2525
const STORAGE_KEY = 'bp/channel-web/user-lang'
2626
const translations = { en, fr, pt, es, ar, ru, uk, de, it }
2727

28-
const cleanLanguageCode = str => str.split('-')[0]
28+
const cleanLanguageCode = (str: string) => str.split('-')[0]
2929
const getNavigatorLanguage = () => cleanLanguageCode(navigator.language || navigator['userLanguage'] || '')
3030
const getStorageLanguage = () => cleanLanguageCode(window.BP_STORAGE?.get(STORAGE_KEY) || '')
3131

modules/channel-web/src/views/lite/typings.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { BPStorage } from '../../../../../packages/ui-shared-lite/utils/storage'
12
import { RootStore } from './store'
23

34
declare global {
@@ -16,7 +17,7 @@ declare global {
1617
SEND_USAGE_STATS: boolean
1718
SHOW_POWERED_BY: boolean
1819
USE_SESSION_STORAGE: boolean
19-
BP_STORAGE: any
20+
BP_STORAGE: BPStorage
2021
botpress: {
2122
[moduleName: string]: any
2223
}

modules/hitlnext/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
"serialize-javascript": "^5.0.1",
3030
"yn": "^4.0.0"
3131
},
32+
"devDependencies": {
33+
"@types/serialize-javascript": "^5.0.1"
34+
},
3235
"resolutions": {
3336
"fstream": ">=1.0.12",
3437
"lodash": ">=4.17.21"

modules/hitlnext/src/types.d.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,6 @@ import * as sdk from 'botpress/sdk'
22
import { UserProfile } from 'common/typings'
33

44
// TODO fix this and use those from common/typings
5-
declare global {
6-
interface Window {
7-
botpressWebChat: {
8-
init: (config: any, containerSelector?: string) => void
9-
sendEvent: (payload: any, webchatId?: string) => void
10-
}
11-
BOT_ID: string
12-
BP_STORAGE: any
13-
ROOT_PATH: string
14-
}
15-
}
165
export interface AuthRule {
176
res: string
187
op: string

modules/hitlnext/src/views/full/app/storage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const get = (path: string, defaultValue = undefined) => {
1313
return data ? deserialize(data) : defaultValue
1414
}
1515

16-
const set = (path: string, data) => {
16+
const set = (path: string, data: any) => {
1717
window.BP_STORAGE.set(key(path), serialize(data))
1818
}
1919

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { BPStorage } from '../../../../packages/ui-shared-lite/utils/storage'
2+
3+
declare global {
4+
interface Window {
5+
botpressWebChat: {
6+
init: (config: any, containerSelector?: string) => void
7+
sendEvent: (payload: any, webchatId?: string) => void
8+
}
9+
BOT_ID: string
10+
BP_STORAGE: BPStorage
11+
ROOT_PATH: string
12+
}
13+
}

0 commit comments

Comments
 (0)