@aslaluroba/help-center-react 3.0.21 → 3.2.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/dist/components/ui/image-attachment.d.ts +9 -0
- package/dist/components/ui/image-preview-dialog.d.ts +10 -0
- package/dist/components/ui/index.d.ts +4 -0
- package/dist/core/api.d.ts +3 -1
- package/dist/index.css +1 -1
- package/dist/index.esm.js +5332 -843
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +5332 -843
- package/dist/index.js.map +1 -1
- package/dist/lib/types.d.ts +23 -0
- package/dist/services.esm.js +492 -361
- package/dist/services.esm.js.map +1 -1
- package/dist/services.js +492 -361
- package/dist/services.js.map +1 -1
- package/dist/ui/chatbot-popup/chat-window-screen/footer.d.ts +3 -2
- package/dist/ui/chatbot-popup/chat-window-screen/index.d.ts +3 -2
- package/dist/ui/help-center.d.ts +1 -1
- package/dist/ui/help-popup.d.ts +3 -2
- package/package.json +1 -1
- package/src/.DS_Store +0 -0
- package/src/assets/icons/paperclip.svg +3 -0
- package/src/assets/icons/x.svg +4 -0
- package/src/components/ui/image-attachment.tsx +107 -0
- package/src/components/ui/image-preview-dialog.tsx +354 -0
- package/src/components/ui/index.ts +4 -0
- package/src/core/AblyService.ts +6 -3
- package/src/core/ApiService.ts +0 -2
- package/src/core/api.ts +106 -58
- package/src/lib/types.ts +110 -84
- package/src/ui/chatbot-popup/chat-window-screen/footer.tsx +259 -22
- package/src/ui/chatbot-popup/chat-window-screen/index.tsx +206 -101
- package/src/ui/help-center.tsx +88 -92
- package/src/ui/help-popup.tsx +11 -9
- package/src/ui/powered-by.tsx +10 -9
package/src/core/api.ts
CHANGED
|
@@ -1,39 +1,30 @@
|
|
|
1
|
-
import { TokenResponse } from
|
|
1
|
+
import { TokenResponse, PresignUploadRequestDto, PresignUploadResponse, PresignDownloadResponse } from '../lib/types';
|
|
2
2
|
|
|
3
3
|
let getTokenFunction: (() => Promise<TokenResponse>) | undefined = undefined;
|
|
4
4
|
let baseUrl: string | null = null;
|
|
5
5
|
|
|
6
6
|
// Add request cache and connection optimization
|
|
7
|
-
const requestCache = new Map<
|
|
8
|
-
string,
|
|
9
|
-
{ data: any; timestamp: number; ttl: number }
|
|
10
|
-
>();
|
|
7
|
+
const requestCache = new Map<string, { data: any; timestamp: number; ttl: number }>();
|
|
11
8
|
const CACHE_TTL = 30000; // 30 seconds cache for non-critical requests
|
|
12
9
|
const pendingRequests = new Map<string, Promise<any>>();
|
|
13
10
|
|
|
14
|
-
export function initializeAPI(
|
|
15
|
-
url: string,
|
|
16
|
-
getToken: () => Promise<TokenResponse>,
|
|
17
|
-
) {
|
|
11
|
+
export function initializeAPI(url: string, getToken: () => Promise<TokenResponse>) {
|
|
18
12
|
getTokenFunction = getToken;
|
|
19
13
|
baseUrl = url;
|
|
20
14
|
}
|
|
21
15
|
|
|
22
16
|
export async function getValidToken(forceRefresh = false): Promise<string> {
|
|
23
17
|
if (!getTokenFunction) {
|
|
24
|
-
throw new Error(
|
|
25
|
-
"API module not initialized. Call initializeAPI(getToken) first.",
|
|
26
|
-
);
|
|
18
|
+
throw new Error('API module not initialized. Call initializeAPI(getToken) first.');
|
|
27
19
|
}
|
|
28
20
|
|
|
29
|
-
let storedToken = localStorage.getItem(
|
|
30
|
-
let storedExpiry = localStorage.getItem(
|
|
21
|
+
let storedToken = localStorage.getItem('chatbot-token');
|
|
22
|
+
let storedExpiry = localStorage.getItem('chatbot-token-expiry');
|
|
31
23
|
const currentTime = Math.floor(Date.now() / 1000);
|
|
32
24
|
|
|
33
25
|
// Add buffer time to prevent token expiry during request
|
|
34
26
|
const bufferTime = 60; // 1 minute buffer
|
|
35
|
-
const isTokenExpiring =
|
|
36
|
-
storedExpiry && currentTime >= Number(storedExpiry) - bufferTime;
|
|
27
|
+
const isTokenExpiring = storedExpiry && currentTime >= Number(storedExpiry) - bufferTime;
|
|
37
28
|
|
|
38
29
|
if (!storedToken || !storedExpiry || isTokenExpiring || forceRefresh) {
|
|
39
30
|
try {
|
|
@@ -41,10 +32,9 @@ export async function getValidToken(forceRefresh = false): Promise<string> {
|
|
|
41
32
|
storedToken = tokenResponse.token;
|
|
42
33
|
storedExpiry = String(currentTime + (tokenResponse.expiresIn ?? 900));
|
|
43
34
|
|
|
44
|
-
localStorage.setItem(
|
|
45
|
-
localStorage.setItem(
|
|
35
|
+
localStorage.setItem('chatbot-token', storedToken);
|
|
36
|
+
localStorage.setItem('chatbot-token-expiry', storedExpiry);
|
|
46
37
|
} catch (error) {
|
|
47
|
-
console.error("Failed to refresh token:", error);
|
|
48
38
|
throw error;
|
|
49
39
|
}
|
|
50
40
|
}
|
|
@@ -53,21 +43,17 @@ export async function getValidToken(forceRefresh = false): Promise<string> {
|
|
|
53
43
|
}
|
|
54
44
|
|
|
55
45
|
// Optimized fetch with retry logic and connection pooling
|
|
56
|
-
async function fetchWithAuth(
|
|
57
|
-
url: string,
|
|
58
|
-
options: RequestInit,
|
|
59
|
-
retry = true,
|
|
60
|
-
): Promise<Response> {
|
|
46
|
+
async function fetchWithAuth(url: string, options: RequestInit, retry = true): Promise<Response> {
|
|
61
47
|
const headers = new Headers(options.headers);
|
|
62
48
|
|
|
63
49
|
try {
|
|
64
50
|
const token = await getValidToken();
|
|
65
|
-
headers.set(
|
|
51
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
66
52
|
|
|
67
53
|
// Add performance optimizations
|
|
68
|
-
headers.set(
|
|
69
|
-
headers.set(
|
|
70
|
-
headers.set(
|
|
54
|
+
headers.set('Accept', 'application/json');
|
|
55
|
+
headers.set('Accept-Encoding', 'gzip, deflate, br');
|
|
56
|
+
headers.set('Connection', 'keep-alive');
|
|
71
57
|
|
|
72
58
|
options.headers = headers;
|
|
73
59
|
|
|
@@ -80,17 +66,16 @@ async function fetchWithAuth(
|
|
|
80
66
|
...options,
|
|
81
67
|
signal: controller.signal,
|
|
82
68
|
// Add HTTP/2 optimization hints
|
|
83
|
-
cache:
|
|
84
|
-
mode:
|
|
69
|
+
cache: 'no-cache',
|
|
70
|
+
mode: 'cors',
|
|
85
71
|
});
|
|
86
72
|
|
|
87
73
|
clearTimeout(timeoutId);
|
|
88
74
|
|
|
89
75
|
// Handle 401/403 with token refresh
|
|
90
76
|
if ((response.status === 401 || response.status === 403) && retry) {
|
|
91
|
-
console.warn("Token expired, refreshing...");
|
|
92
77
|
const newToken = await getValidToken(true);
|
|
93
|
-
headers.set(
|
|
78
|
+
headers.set('Authorization', `Bearer ${newToken}`);
|
|
94
79
|
options.headers = headers;
|
|
95
80
|
|
|
96
81
|
// Retry the request with new token
|
|
@@ -101,13 +86,12 @@ async function fetchWithAuth(
|
|
|
101
86
|
} catch (error) {
|
|
102
87
|
clearTimeout(timeoutId);
|
|
103
88
|
|
|
104
|
-
if (error instanceof Error && error.name ===
|
|
105
|
-
throw new Error(
|
|
89
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
90
|
+
throw new Error('Request timeout - please try again');
|
|
106
91
|
}
|
|
107
92
|
throw error;
|
|
108
93
|
}
|
|
109
94
|
} catch (error) {
|
|
110
|
-
console.error("Fetch error:", error);
|
|
111
95
|
throw error;
|
|
112
96
|
}
|
|
113
97
|
}
|
|
@@ -126,11 +110,7 @@ function getCachedResponse(cacheKey: string): any | null {
|
|
|
126
110
|
return null;
|
|
127
111
|
}
|
|
128
112
|
|
|
129
|
-
function setCachedResponse(
|
|
130
|
-
cacheKey: string,
|
|
131
|
-
data: any,
|
|
132
|
-
ttl: number = CACHE_TTL,
|
|
133
|
-
): void {
|
|
113
|
+
function setCachedResponse(cacheKey: string, data: any, ttl: number = CACHE_TTL): void {
|
|
134
114
|
requestCache.set(cacheKey, {
|
|
135
115
|
data,
|
|
136
116
|
timestamp: Date.now(),
|
|
@@ -154,11 +134,11 @@ function setPendingRequest(requestKey: string, promise: Promise<any>): void {
|
|
|
154
134
|
|
|
155
135
|
export async function apiRequest(
|
|
156
136
|
endpoint: string,
|
|
157
|
-
method =
|
|
137
|
+
method = 'GET',
|
|
158
138
|
body: any = null,
|
|
159
|
-
options: { cache?: boolean; timeout?: number; language: string }
|
|
139
|
+
options: { cache?: boolean; timeout?: number; language: string }
|
|
160
140
|
) {
|
|
161
|
-
if (!baseUrl) throw new Error(
|
|
141
|
+
if (!baseUrl) throw new Error('API not initialized');
|
|
162
142
|
|
|
163
143
|
const url = `${baseUrl}/${endpoint}`;
|
|
164
144
|
const requestKey = `${method}:${endpoint}:${JSON.stringify(body)}`;
|
|
@@ -170,11 +150,7 @@ export async function apiRequest(
|
|
|
170
150
|
}
|
|
171
151
|
|
|
172
152
|
// Check cache for GET requests (except real-time endpoints)
|
|
173
|
-
if (
|
|
174
|
-
method === "GET" &&
|
|
175
|
-
options.cache !== false &&
|
|
176
|
-
!endpoint.includes("/send-message")
|
|
177
|
-
) {
|
|
153
|
+
if (method === 'GET' && options.cache !== false && !endpoint.includes('/send-message')) {
|
|
178
154
|
const cached = getCachedResponse(requestKey);
|
|
179
155
|
if (cached) {
|
|
180
156
|
return Promise.resolve(cached);
|
|
@@ -184,9 +160,9 @@ export async function apiRequest(
|
|
|
184
160
|
const requestOptions: RequestInit = {
|
|
185
161
|
method,
|
|
186
162
|
headers: {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
163
|
+
'Content-Type': 'application/json',
|
|
164
|
+
'Cache-Control': method === 'GET' ? 'max-age=30' : 'no-cache',
|
|
165
|
+
'Accept-Language': options.language,
|
|
190
166
|
},
|
|
191
167
|
body: body ? JSON.stringify(body) : null,
|
|
192
168
|
};
|
|
@@ -196,28 +172,39 @@ export async function apiRequest(
|
|
|
196
172
|
const response = await fetchWithAuth(url, requestOptions);
|
|
197
173
|
|
|
198
174
|
if (!response.ok) {
|
|
199
|
-
let errorMessage =
|
|
175
|
+
let errorMessage = 'API request failed';
|
|
200
176
|
|
|
201
177
|
try {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
errorMessage =
|
|
178
|
+
// Clone response before reading to avoid consuming the body
|
|
179
|
+
const errorResponse = response.clone();
|
|
180
|
+
const errorData = await errorResponse.json();
|
|
181
|
+
errorMessage = errorData.message || errorData.error || errorMessage;
|
|
182
|
+
} catch (parseError) {
|
|
183
|
+
// If JSON parsing fails, try to get text
|
|
184
|
+
try {
|
|
185
|
+
const errorResponse = response.clone();
|
|
186
|
+
const errorText = await errorResponse.text();
|
|
187
|
+
errorMessage = errorText || `HTTP ${response.status}: ${response.statusText}`;
|
|
188
|
+
} catch {
|
|
189
|
+
errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
190
|
+
}
|
|
206
191
|
}
|
|
207
192
|
|
|
208
193
|
throw new Error(errorMessage);
|
|
209
194
|
}
|
|
210
195
|
|
|
211
196
|
// Cache successful GET responses
|
|
212
|
-
|
|
197
|
+
// Note: We clone before caching to avoid consuming the original response body
|
|
198
|
+
if (method === 'GET' && options.cache !== false) {
|
|
213
199
|
const responseData = response.clone();
|
|
214
200
|
const data = await responseData.json();
|
|
215
201
|
setCachedResponse(requestKey, { json: () => Promise.resolve(data) });
|
|
216
202
|
}
|
|
217
203
|
|
|
204
|
+
// Return the original response - it's body hasn't been consumed yet
|
|
205
|
+
// (we only cloned for caching, and the clone was consumed)
|
|
218
206
|
return response;
|
|
219
207
|
} catch (error) {
|
|
220
|
-
console.error(`API request failed for ${endpoint}:`, error);
|
|
221
208
|
throw error;
|
|
222
209
|
}
|
|
223
210
|
})();
|
|
@@ -227,3 +214,64 @@ export async function apiRequest(
|
|
|
227
214
|
|
|
228
215
|
return requestPromise;
|
|
229
216
|
}
|
|
217
|
+
|
|
218
|
+
export async function presignUpload(
|
|
219
|
+
chatSessionId: string,
|
|
220
|
+
file: File,
|
|
221
|
+
language: string
|
|
222
|
+
): Promise<PresignUploadResponse> {
|
|
223
|
+
const requestBody: PresignUploadRequestDto = {
|
|
224
|
+
name: file.name,
|
|
225
|
+
contentType: file.type,
|
|
226
|
+
sizeBytes: file.size,
|
|
227
|
+
pathData: {
|
|
228
|
+
type: 1,
|
|
229
|
+
chatSessionId: chatSessionId,
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const response = await apiRequest('NewFile/presign-upload', 'POST', requestBody, { language });
|
|
234
|
+
|
|
235
|
+
if (!response.ok) {
|
|
236
|
+
throw new Error('Failed to get presigned upload URL');
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return await response.json();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export async function presignDownload(fileId: string, language: string): Promise<PresignDownloadResponse> {
|
|
243
|
+
try {
|
|
244
|
+
const response = await apiRequest(`NewFile/${fileId}/presign-download`, 'GET', null, {
|
|
245
|
+
language,
|
|
246
|
+
cache: false, // Don't cache presigned URLs as they have expiration times
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// If response is not ok, apiRequest would have thrown an error already
|
|
250
|
+
// So we can safely read the JSON here
|
|
251
|
+
try {
|
|
252
|
+
return await response.json();
|
|
253
|
+
} catch (jsonError) {
|
|
254
|
+
// If JSON parsing fails, the response body might have been consumed
|
|
255
|
+
// or the response might not be valid JSON
|
|
256
|
+
if (jsonError instanceof Error) {
|
|
257
|
+
if (jsonError.message.includes('already read')) {
|
|
258
|
+
throw new Error(`Failed to parse response for file ${fileId}: Response body was already consumed`);
|
|
259
|
+
}
|
|
260
|
+
throw new Error(`Failed to parse response for file ${fileId}: ${jsonError.message}`);
|
|
261
|
+
}
|
|
262
|
+
throw new Error(`Failed to parse response for file ${fileId}`);
|
|
263
|
+
}
|
|
264
|
+
} catch (error) {
|
|
265
|
+
// Handle all types of errors
|
|
266
|
+
if (error instanceof Error) {
|
|
267
|
+
// If it's already a descriptive error from apiRequest, re-throw it
|
|
268
|
+
if (error.message.includes('API request failed') || error.message.includes('HTTP')) {
|
|
269
|
+
throw new Error(`Failed to get presigned download URL for file ${fileId}: ${error.message}`);
|
|
270
|
+
}
|
|
271
|
+
// Otherwise, re-throw with context
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
// Handle non-Error types
|
|
275
|
+
throw new Error(`Failed to get presigned download URL for file ${fileId}: ${String(error)}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
package/src/lib/types.ts
CHANGED
|
@@ -1,128 +1,154 @@
|
|
|
1
1
|
export interface HelpCenterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
2
|
-
helpScreenId: string
|
|
3
|
-
primaryColor?: string
|
|
4
|
-
secondaryColor?: string
|
|
5
|
-
logoUrl?: string
|
|
2
|
+
helpScreenId: string;
|
|
3
|
+
primaryColor?: string;
|
|
4
|
+
secondaryColor?: string;
|
|
5
|
+
logoUrl?: string;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export interface Theme {
|
|
9
|
-
primary: string
|
|
10
|
-
secondary: string
|
|
11
|
-
text: string
|
|
12
|
-
background: string
|
|
13
|
-
error: string
|
|
14
|
-
success: string
|
|
9
|
+
primary: string;
|
|
10
|
+
secondary: string;
|
|
11
|
+
text: string;
|
|
12
|
+
background: string;
|
|
13
|
+
error: string;
|
|
14
|
+
success: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export interface UserData {
|
|
18
|
-
id: string
|
|
19
|
-
name: string
|
|
20
|
-
email: string
|
|
21
|
-
avatar?: string
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
email: string;
|
|
21
|
+
avatar?: string;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export interface Message {
|
|
25
|
-
id: number
|
|
26
|
-
senderType: number // 1: Customer, 2: Agent, 3: AI
|
|
27
|
-
messageContent: string
|
|
28
|
-
sentAt: Date
|
|
29
|
-
isSeen: boolean
|
|
25
|
+
id: number;
|
|
26
|
+
senderType: number; // 1: Customer, 2: Agent, 3: AI
|
|
27
|
+
messageContent: string;
|
|
28
|
+
sentAt: Date;
|
|
29
|
+
isSeen: boolean;
|
|
30
|
+
attachmentIds?: string[];
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
export interface ChatSession {
|
|
33
|
-
id: string
|
|
34
|
-
messages: Message[]
|
|
35
|
-
participants: UserData[]
|
|
36
|
-
status: 'active' | 'closed'
|
|
37
|
-
createdAt: Date
|
|
38
|
-
updatedAt: Date
|
|
34
|
+
id: string;
|
|
35
|
+
messages: Message[];
|
|
36
|
+
participants: UserData[];
|
|
37
|
+
status: 'active' | 'closed';
|
|
38
|
+
createdAt: Date;
|
|
39
|
+
updatedAt: Date;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export interface ChatSessionData {
|
|
42
|
-
helpScreenId: string
|
|
43
|
-
user: UserData
|
|
44
|
-
initialMessage?: string
|
|
43
|
+
helpScreenId: string;
|
|
44
|
+
user: UserData;
|
|
45
|
+
initialMessage?: string;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
export interface HelpCenterConfig {
|
|
48
|
-
baseUrl: string
|
|
49
|
-
getToken: () => Promise<{ token: string; expiresIn: number }
|
|
50
|
-
helpScreenId: string
|
|
51
|
-
user?: UserData
|
|
52
|
-
theme?: Partial<Theme
|
|
53
|
-
onMessageReceived?: (message: Message) => void
|
|
54
|
-
onSessionClosed?: () => void
|
|
55
|
-
onError?: (error: Error) => void
|
|
49
|
+
baseUrl: string;
|
|
50
|
+
getToken: () => Promise<{ token: string; expiresIn: number }>;
|
|
51
|
+
helpScreenId: string;
|
|
52
|
+
user?: UserData;
|
|
53
|
+
theme?: Partial<Theme>;
|
|
54
|
+
onMessageReceived?: (message: Message) => void;
|
|
55
|
+
onSessionClosed?: () => void;
|
|
56
|
+
onError?: (error: Error) => void;
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
export interface HelpScreenOption {
|
|
59
|
-
id: string
|
|
60
|
-
title: string
|
|
61
|
-
paragraphs?: string[]
|
|
62
|
-
nestedOptions?: HelpScreenOption[]
|
|
63
|
-
chatWithUs?: boolean
|
|
60
|
+
id: string;
|
|
61
|
+
title: string;
|
|
62
|
+
paragraphs?: string[];
|
|
63
|
+
nestedOptions?: HelpScreenOption[];
|
|
64
|
+
chatWithUs?: boolean;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
export interface HelpScreen {
|
|
67
|
-
id: string
|
|
68
|
-
title: string
|
|
69
|
-
options: HelpScreenOption[]
|
|
68
|
+
id: string;
|
|
69
|
+
title: string;
|
|
70
|
+
options: HelpScreenOption[];
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
export interface ApiResponse<T> {
|
|
73
|
-
data: T
|
|
74
|
-
success: boolean
|
|
75
|
-
error?: string
|
|
74
|
+
data: T;
|
|
75
|
+
success: boolean;
|
|
76
|
+
error?: string;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
export interface TokenResponse {
|
|
79
|
-
token: string
|
|
80
|
-
expiresIn: number
|
|
80
|
+
token: string;
|
|
81
|
+
expiresIn: number;
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
export interface HelpScreenData {
|
|
84
|
-
id: string
|
|
85
|
-
tenantId: string
|
|
85
|
+
id: string;
|
|
86
|
+
tenantId: string;
|
|
86
87
|
tenant: {
|
|
87
|
-
id: string
|
|
88
|
-
name: string
|
|
89
|
-
key: string
|
|
90
|
-
}
|
|
91
|
-
title: string
|
|
92
|
-
description: string
|
|
93
|
-
options: Option[]
|
|
94
|
-
chatWithUs: boolean
|
|
88
|
+
id: string;
|
|
89
|
+
name: string;
|
|
90
|
+
key: string;
|
|
91
|
+
};
|
|
92
|
+
title: string;
|
|
93
|
+
description: string;
|
|
94
|
+
options: Option[];
|
|
95
|
+
chatWithUs: boolean;
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
export interface Option {
|
|
98
|
-
id: string
|
|
99
|
-
helpScreenId: string
|
|
100
|
-
parentOptionId: string | null
|
|
101
|
-
parentOption: Option | null
|
|
102
|
-
files: any[]
|
|
103
|
-
nestedOptions: Option[]
|
|
104
|
-
title: string
|
|
105
|
-
paragraphs: string[]
|
|
106
|
-
chatWithUs: boolean
|
|
107
|
-
assistantId?: string
|
|
99
|
+
id: string;
|
|
100
|
+
helpScreenId: string;
|
|
101
|
+
parentOptionId: string | null;
|
|
102
|
+
parentOption: Option | null;
|
|
103
|
+
files: any[];
|
|
104
|
+
nestedOptions: Option[];
|
|
105
|
+
title: string;
|
|
106
|
+
paragraphs: string[];
|
|
107
|
+
chatWithUs: boolean;
|
|
108
|
+
assistantId?: string;
|
|
108
109
|
assistant?: {
|
|
109
|
-
id: string
|
|
110
|
-
tenantId: string
|
|
110
|
+
id: string;
|
|
111
|
+
tenantId: string;
|
|
111
112
|
tenant: {
|
|
112
|
-
id: string
|
|
113
|
-
name: string
|
|
114
|
-
key: string
|
|
115
|
-
}
|
|
116
|
-
name: string
|
|
117
|
-
openAIAssistantId: string
|
|
118
|
-
greeting: string
|
|
119
|
-
closing: string
|
|
120
|
-
}
|
|
121
|
-
hasNestedOptions: boolean
|
|
122
|
-
order: number
|
|
113
|
+
id: string;
|
|
114
|
+
name: string;
|
|
115
|
+
key: string;
|
|
116
|
+
};
|
|
117
|
+
name: string;
|
|
118
|
+
openAIAssistantId: string;
|
|
119
|
+
greeting: string;
|
|
120
|
+
closing: string;
|
|
121
|
+
};
|
|
122
|
+
hasNestedOptions: boolean;
|
|
123
|
+
order: number;
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
export interface ReviewProps {
|
|
126
|
-
comment: string
|
|
127
|
-
rating: number
|
|
127
|
+
comment: string;
|
|
128
|
+
rating: number;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface PresignUploadRequestDto {
|
|
132
|
+
name: string;
|
|
133
|
+
contentType: string;
|
|
134
|
+
sizeBytes: number;
|
|
135
|
+
pathData: {
|
|
136
|
+
type: number;
|
|
137
|
+
chatSessionId: string;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface PresignUploadResponse {
|
|
142
|
+
id: string;
|
|
143
|
+
uploadUrl: string;
|
|
144
|
+
path: string;
|
|
145
|
+
expiresAt: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface PresignDownloadResponse {
|
|
149
|
+
id: string;
|
|
150
|
+
name: string;
|
|
151
|
+
downloadUrl: string;
|
|
152
|
+
contentType: string;
|
|
153
|
+
expiresAt: string;
|
|
128
154
|
}
|