From e7e4480a92b7fb7a1f7771a3813d198395da41d0 Mon Sep 17 00:00:00 2001 From: Fabilin Date: Wed, 29 Jul 2026 11:45:35 +0200 Subject: [PATCH] resolve #208: add nullable userId setting --- .eslintrc.js => .eslintrc.cjs | 0 .prettierrc.js => .prettierrc.cjs | 0 README.md | 17 +++++++----- src/TockContext.tsx | 5 +++- src/TockState.tsx | 2 +- src/components/Carousel/Carousel.tsx | 2 +- src/components/Conversation/Conversation.tsx | 2 +- src/model/buttons.ts | 28 ++++++++++---------- src/network/TockEventSource.ts | 4 +-- src/settings/TockSettings.tsx | 1 + 10 files changed, 35 insertions(+), 26 deletions(-) rename .eslintrc.js => .eslintrc.cjs (100%) rename .prettierrc.js => .prettierrc.cjs (100%) diff --git a/.eslintrc.js b/.eslintrc.cjs similarity index 100% rename from .eslintrc.js rename to .eslintrc.cjs diff --git a/.prettierrc.js b/.prettierrc.cjs similarity index 100% rename from .prettierrc.js rename to .prettierrc.cjs diff --git a/README.md b/README.md index 1a38a66..a544155 100644 --- a/README.md +++ b/README.md @@ -355,12 +355,17 @@ A `TockTheme` can be used as a value of a `ThemeProvider` of [`emotion-theming`] The main source of configuration for the chatbot interface. Objects implementing this interface can be passed to `renderChat` or to `TockContext`. -| Property name | Type | Description | -|----------------|-------------------------|------------------------------------------------------| -| `locale` | `string?` | Optional user language, as an *RFC 5646* code | -| `localStorage` | `LocalStorageSettings?` | Configuration for use of localStorage by the library | -| `network` | `NetworkSettings?` | If `true`, disables any SSE connection attempt | -| `renderers` | `RendererSettings?` | Configuration for custom image and text renderers | +| Property name | Type | Description | +|----------------|-------------------------|-----------------------------------------------------------------------------------------------------------------------| +| `endpoint` | `string` | The URL of the web connector endpoint | +| `userId` | `(string\|null)?` | Unique user ID. `null` means no clientside ID. `undefined` (default) generates and stores a UUID in the localStorage. | +| `locale` | `string?` | Optional user language, as an *RFC 5646* code | +| `localStorage` | `LocalStorageSettings?` | Configuration for use of localStorage by the library | +| `network` | `NetworkSettings?` | If `true`, disables any SSE connection attempt | +| `renderers` | `RendererSettings?` | Configuration for custom image and text renderers | + +> Note: disabling clientside ID is more secure, but requires setting a different [Web Security Mode](https://github.com/theopenconversationkit/tock/tree/master/bot/connector-web#web-security-modes) +> in TOCK Studio. #### `LocalStorageSettings` diff --git a/src/TockContext.tsx b/src/TockContext.tsx index d2e67f8..830b7a8 100644 --- a/src/TockContext.tsx +++ b/src/TockContext.tsx @@ -29,7 +29,10 @@ const TockContext: (props: { const [state, dispatch] = useReducer(tockReducer, { quickReplies: [], messages: [], - userId: retrieveUserId(mergedSettings.localStorage.prefix), + userId: + mergedSettings.userId === undefined + ? retrieveUserId(mergedSettings.localStorage.prefix) + : mergedSettings.userId, loading: false, sseInitializing: false, metadata: {}, diff --git a/src/TockState.tsx b/src/TockState.tsx index c909bee..d2e17c0 100644 --- a/src/TockState.tsx +++ b/src/TockState.tsx @@ -28,7 +28,7 @@ export const useTockDispatch: () => Dispatch = () => { export interface TockState { quickReplies: QuickReply[]; messages: Message[]; - userId: string; + userId: string | null; loading: boolean; sseInitializing: boolean; metadata: Record; diff --git a/src/components/Carousel/Carousel.tsx b/src/components/Carousel/Carousel.tsx index f34f14c..add28e7 100644 --- a/src/components/Carousel/Carousel.tsx +++ b/src/components/Carousel/Carousel.tsx @@ -177,7 +177,7 @@ const Carousel: (props: { aria-roledescription={ cardRef === undefined ? undefined - : accessibility?.carousel?.slideRoleDescription ?? 'Slide' + : (accessibility?.carousel?.slideRoleDescription ?? 'Slide') } > {cloneElement( diff --git a/src/components/Conversation/Conversation.tsx b/src/components/Conversation/Conversation.tsx index 1091c64..3fb80e2 100644 --- a/src/components/Conversation/Conversation.tsx +++ b/src/components/Conversation/Conversation.tsx @@ -44,7 +44,7 @@ const ConversationInnerContainer = styled.ul` ::-webkit-scrollbar { display: none; } -`; +`; const ConversationItemLi = styled.li` width: 100%; diff --git a/src/model/buttons.ts b/src/model/buttons.ts index ac58ff3..38a4087 100644 --- a/src/model/buttons.ts +++ b/src/model/buttons.ts @@ -5,10 +5,10 @@ export class QuickReply { imageUrl?: string; constructor( - label: string, - payload: string, - nlpText?: string, - imageUrl?: string, + label: string, + payload: string, + nlpText?: string, + imageUrl?: string, ) { this.label = label; this.payload = payload; @@ -24,10 +24,10 @@ export class PostBackButton { style?: string; constructor( - label: string, - payload: string, - imageUrl?: string, - style?: string, + label: string, + payload: string, + imageUrl?: string, + style?: string, ) { this.label = label; this.payload = payload; @@ -45,12 +45,12 @@ export class UrlButton { style?: string; constructor( - label: string, - url: string, - imageUrl?: string, - target?: string, - windowFeatures?: string, - style?: string, + label: string, + url: string, + imageUrl?: string, + target?: string, + windowFeatures?: string, + style?: string, ) { this.label = label; this.url = url; diff --git a/src/network/TockEventSource.ts b/src/network/TockEventSource.ts index bd85f3d..dac4bbc 100644 --- a/src/network/TockEventSource.ts +++ b/src/network/TockEventSource.ts @@ -67,8 +67,8 @@ export class TockEventSource { * @returns a promise that gets resolved when the connection is open * and gets rejected if the connection fails or this event source is closed */ - open(endpoint: string, userId: string): Promise { - const url = `${endpoint}/sse?userid=${userId}`; + open(endpoint: string, userId: string | null): Promise { + const url = `${endpoint}/sse${userId == null ? '' : `?userid=${userId}`}`; this.onStateChange(EventSource.CONNECTING); this.currentUrl = url; return new Promise((resolve, reject): void => { diff --git a/src/settings/TockSettings.tsx b/src/settings/TockSettings.tsx index 6b7303f..c33877e 100644 --- a/src/settings/TockSettings.tsx +++ b/src/settings/TockSettings.tsx @@ -17,6 +17,7 @@ export interface NetworkSettings { export default interface TockSettings { endpoint?: string; // will be required in a future release + userId?: string | null; locale?: string; localStorage: LocalStorageSettings; network: NetworkSettings;