@iblai/web-utils 0.2.1 → 1.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/README.md +504 -0
- package/dist/data-layer/src/features/chat-files/api-slice.d.ts +185 -0
- package/dist/data-layer/src/features/chat-files/types.d.ts +32 -0
- package/dist/data-layer/src/features/core/api-slice.d.ts +419 -61
- package/dist/data-layer/src/features/core/constants.d.ts +3 -0
- package/dist/data-layer/src/features/core/custom-api-slice.d.ts +50 -50
- package/dist/data-layer/src/features/core/custom-public-image-asset-api-slice.d.ts +333 -0
- package/dist/data-layer/src/features/core/types.d.ts +33 -0
- package/dist/data-layer/src/features/credentials/api-slice.d.ts +62 -39
- package/dist/data-layer/src/features/mentor/api-slice.d.ts +980 -188
- package/dist/data-layer/src/features/notifications/constants.d.ts +6 -0
- package/dist/data-layer/src/features/notifications/custom-api-slice.d.ts +43 -43
- package/dist/data-layer/src/features/notifications/types.d.ts +25 -2
- package/dist/data-layer/src/index.d.ts +3 -0
- package/dist/index.d.ts +425 -66
- package/dist/index.esm.js +999 -109
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1030 -107
- package/dist/index.js.map +1 -1
- package/dist/package.json +4 -2
- package/dist/web-utils/src/constants/chat.d.ts +8 -0
- package/dist/web-utils/src/features/files/filesSlice.d.ts +20 -0
- package/dist/web-utils/src/features/index.d.ts +1 -0
- package/dist/web-utils/src/hooks/chat/use-advanced-chat.d.ts +6 -4
- package/dist/web-utils/src/hooks/chat/use-chat-v2.d.ts +11 -1
- package/dist/web-utils/src/index.d.ts +2 -0
- package/dist/web-utils/src/index.web.d.ts +14 -12
- package/dist/web-utils/src/providers/auth-provider.d.ts +9 -1
- package/dist/web-utils/src/providers/tenant-provider.d.ts +2 -1
- package/dist/web-utils/src/services/__tests__/file-upload.test.d.ts +1 -0
- package/dist/web-utils/src/services/file-upload.d.ts +60 -0
- package/dist/web-utils/src/services/index.d.ts +1 -0
- package/dist/web-utils/src/types/file-upload.d.ts +62 -0
- package/dist/web-utils/src/types/index.d.ts +1 -0
- package/dist/web-utils/src/utils/auth.d.ts +180 -0
- package/dist/web-utils/src/utils/index.d.ts +1 -0
- package/dist/web-utils/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var React = require('react');
|
|
4
4
|
var iblaiApi = require('@iblai/iblai-api');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
var axios = require('axios');
|
|
6
7
|
|
|
7
8
|
function _interopNamespaceDefault(e) {
|
|
8
9
|
var n = Object.create(null);
|
|
@@ -3400,7 +3401,7 @@ function updateMutationSubstateIfExists(state, id, update) {
|
|
|
3400
3401
|
update(substate);
|
|
3401
3402
|
}
|
|
3402
3403
|
}
|
|
3403
|
-
var initialState$
|
|
3404
|
+
var initialState$2 = {};
|
|
3404
3405
|
function buildSlice({
|
|
3405
3406
|
reducerPath,
|
|
3406
3407
|
queryThunk,
|
|
@@ -3476,7 +3477,7 @@ function buildSlice({
|
|
|
3476
3477
|
}
|
|
3477
3478
|
const querySlice = createSlice$1({
|
|
3478
3479
|
name: `${reducerPath}/queries`,
|
|
3479
|
-
initialState: initialState$
|
|
3480
|
+
initialState: initialState$2,
|
|
3480
3481
|
reducers: {
|
|
3481
3482
|
removeQueryResult: {
|
|
3482
3483
|
reducer(draft, {
|
|
@@ -3610,7 +3611,7 @@ function buildSlice({
|
|
|
3610
3611
|
});
|
|
3611
3612
|
const mutationSlice = createSlice$1({
|
|
3612
3613
|
name: `${reducerPath}/mutations`,
|
|
3613
|
-
initialState: initialState$
|
|
3614
|
+
initialState: initialState$2,
|
|
3614
3615
|
reducers: {
|
|
3615
3616
|
removeMutationResult: {
|
|
3616
3617
|
reducer(draft, {
|
|
@@ -3779,7 +3780,7 @@ function buildSlice({
|
|
|
3779
3780
|
}
|
|
3780
3781
|
const subscriptionSlice = createSlice$1({
|
|
3781
3782
|
name: `${reducerPath}/subscriptions`,
|
|
3782
|
-
initialState: initialState$
|
|
3783
|
+
initialState: initialState$2,
|
|
3783
3784
|
reducers: {
|
|
3784
3785
|
updateSubscriptionOptions(d, a) {
|
|
3785
3786
|
},
|
|
@@ -3791,7 +3792,7 @@ function buildSlice({
|
|
|
3791
3792
|
});
|
|
3792
3793
|
const internalSubscriptionsSlice = createSlice$1({
|
|
3793
3794
|
name: `${reducerPath}/internalSubscriptions`,
|
|
3794
|
-
initialState: initialState$
|
|
3795
|
+
initialState: initialState$2,
|
|
3795
3796
|
reducers: {
|
|
3796
3797
|
subscriptionsUpdated: {
|
|
3797
3798
|
reducer(state, action) {
|
|
@@ -6461,6 +6462,25 @@ createApi({
|
|
|
6461
6462
|
}),
|
|
6462
6463
|
});
|
|
6463
6464
|
|
|
6465
|
+
createApi({
|
|
6466
|
+
reducerPath: 'chatFilesApiSlice',
|
|
6467
|
+
baseQuery: iblFetchBaseQuery,
|
|
6468
|
+
endpoints: (builder) => ({
|
|
6469
|
+
/**
|
|
6470
|
+
* Get presigned S3 URL for file upload
|
|
6471
|
+
* POST /api/ai-mentor/orgs/{org}/users/{userId}/chat/files/upload-url/
|
|
6472
|
+
*/
|
|
6473
|
+
getFileUploadUrl: builder.mutation({
|
|
6474
|
+
query: ({ org, userId, requestBody, }) => ({
|
|
6475
|
+
url: `/api/ai-mentor/orgs/${org}/users/${userId}/chat/files/upload-url/`,
|
|
6476
|
+
method: 'POST',
|
|
6477
|
+
body: requestBody,
|
|
6478
|
+
service: SERVICES.DM,
|
|
6479
|
+
}),
|
|
6480
|
+
}),
|
|
6481
|
+
}),
|
|
6482
|
+
});
|
|
6483
|
+
|
|
6464
6484
|
createApi({
|
|
6465
6485
|
reducerPath: 'llmsApiSlice',
|
|
6466
6486
|
baseQuery: iblFakeBaseQuery,
|
|
@@ -6481,6 +6501,7 @@ const mentorApiSlice = createApi({
|
|
|
6481
6501
|
'mentorPublicSettings',
|
|
6482
6502
|
'shareableLinks',
|
|
6483
6503
|
'publicMentors',
|
|
6504
|
+
'moderationLogs',
|
|
6484
6505
|
],
|
|
6485
6506
|
endpoints: (builder) => ({
|
|
6486
6507
|
createMentor: builder.mutation({
|
|
@@ -6546,7 +6567,7 @@ const mentorApiSlice = createApi({
|
|
|
6546
6567
|
}));
|
|
6547
6568
|
}
|
|
6548
6569
|
catch (error) {
|
|
6549
|
-
console.error(error);
|
|
6570
|
+
console.error(JSON.stringify(error));
|
|
6550
6571
|
}
|
|
6551
6572
|
},
|
|
6552
6573
|
}),
|
|
@@ -6602,9 +6623,17 @@ const mentorApiSlice = createApi({
|
|
|
6602
6623
|
...buildEndpointFromDmService(iblaiApi.AiMentorService.aiMentorOrgsUsersMentorsForkCreate),
|
|
6603
6624
|
invalidatesTags: ['mentors'],
|
|
6604
6625
|
}),
|
|
6626
|
+
getRecentlyAccessedMentors: builder.query({
|
|
6627
|
+
...buildEndpointFromDmService(iblaiApi.AiMentorService.aiMentorOrgsUsersRecentlyAccessedMentorsList),
|
|
6628
|
+
providesTags: ['mentors'],
|
|
6629
|
+
}),
|
|
6630
|
+
getModerationLogs: builder.query({
|
|
6631
|
+
...buildEndpointFromDmService(iblaiApi.AiMentorService.aiMentorOrgsUsersModerationLogsList),
|
|
6632
|
+
providesTags: ['moderationLogs'],
|
|
6633
|
+
}),
|
|
6605
6634
|
}),
|
|
6606
6635
|
});
|
|
6607
|
-
const { useLazyGetMentorsQuery, useLazySeedMentorsQuery, useGetMentorSettingsQuery, useGetMentorPublicSettingsQuery, useLazyGetMentorPublicSettingsQuery, useLazyGetFreeUsageCountQuery} = mentorApiSlice;
|
|
6636
|
+
const { useLazyGetMentorsQuery, useLazySeedMentorsQuery, useGetMentorSettingsQuery, useGetMentorPublicSettingsQuery, useLazyGetMentorPublicSettingsQuery, useLazyGetFreeUsageCountQuery, useLazyGetRecentlyAccessedMentorsQuery} = mentorApiSlice;
|
|
6608
6637
|
|
|
6609
6638
|
createApi({
|
|
6610
6639
|
reducerPath: 'mentorCategoriesApiSlice',
|
|
@@ -7071,7 +7100,20 @@ const coreApiSlice = createApi({
|
|
|
7071
7100
|
invalidatesTags: ['RbacGroups'],
|
|
7072
7101
|
}),
|
|
7073
7102
|
getRbacGroupDetails: builder.query({
|
|
7074
|
-
...
|
|
7103
|
+
...buildEndpointFromService(SERVICES.DM, async (args) => {
|
|
7104
|
+
const url = `${iblaiApi.OpenAPI.BASE}/api/core/rbac/groups/${args.id}/`;
|
|
7105
|
+
const response = await fetch(url, {
|
|
7106
|
+
method: 'GET',
|
|
7107
|
+
headers: iblaiApi.OpenAPI.HEADERS,
|
|
7108
|
+
});
|
|
7109
|
+
if (!response.ok) {
|
|
7110
|
+
const error = new Error('Failed to fetch RBAC group details');
|
|
7111
|
+
error.status = response.status;
|
|
7112
|
+
error.body = await response.text();
|
|
7113
|
+
throw error;
|
|
7114
|
+
}
|
|
7115
|
+
return response.json();
|
|
7116
|
+
}),
|
|
7075
7117
|
providesTags: ['RbacGroups'],
|
|
7076
7118
|
}),
|
|
7077
7119
|
//RBAC POLICIES
|
|
@@ -7092,7 +7134,22 @@ const coreApiSlice = createApi({
|
|
|
7092
7134
|
invalidatesTags: ['RbacPolicies'],
|
|
7093
7135
|
}),
|
|
7094
7136
|
getRbacPolicyDetails: builder.query({
|
|
7095
|
-
...
|
|
7137
|
+
...buildEndpointFromService(SERVICES.DM, async (args) => {
|
|
7138
|
+
const queryParams = new URLSearchParams({ platform_key: args.platform_key });
|
|
7139
|
+
const queryString = queryParams.toString();
|
|
7140
|
+
const url = `${iblaiApi.OpenAPI.BASE}/api/core/rbac/policies/${args.id}/?${queryString}`;
|
|
7141
|
+
const response = await fetch(url, {
|
|
7142
|
+
method: 'GET',
|
|
7143
|
+
headers: iblaiApi.OpenAPI.HEADERS,
|
|
7144
|
+
});
|
|
7145
|
+
if (!response.ok) {
|
|
7146
|
+
const error = new Error('Failed to fetch RBAC policy details');
|
|
7147
|
+
error.status = response.status;
|
|
7148
|
+
error.body = await response.text();
|
|
7149
|
+
throw error;
|
|
7150
|
+
}
|
|
7151
|
+
return response.json();
|
|
7152
|
+
}),
|
|
7096
7153
|
providesTags: ['RbacPolicies'],
|
|
7097
7154
|
}),
|
|
7098
7155
|
//RBAC ROLES
|
|
@@ -7117,14 +7174,36 @@ const coreApiSlice = createApi({
|
|
|
7117
7174
|
invalidatesTags: ['RbacRoles'],
|
|
7118
7175
|
}),
|
|
7119
7176
|
getRbacRoleDetails: builder.query({
|
|
7120
|
-
...
|
|
7177
|
+
...buildEndpointFromService(SERVICES.DM, async (args) => {
|
|
7178
|
+
const queryParams = new URLSearchParams({ platform_key: args.platform_key });
|
|
7179
|
+
const queryString = queryParams.toString();
|
|
7180
|
+
const url = `${iblaiApi.OpenAPI.BASE}/api/core/rbac/roles/${args.id}/?${queryString}`;
|
|
7181
|
+
const response = await fetch(url, {
|
|
7182
|
+
method: 'GET',
|
|
7183
|
+
headers: iblaiApi.OpenAPI.HEADERS,
|
|
7184
|
+
});
|
|
7185
|
+
if (!response.ok) {
|
|
7186
|
+
const error = new Error('Failed to fetch RBAC role details');
|
|
7187
|
+
error.status = response.status;
|
|
7188
|
+
error.body = await response.text();
|
|
7189
|
+
throw error;
|
|
7190
|
+
}
|
|
7191
|
+
return response.json();
|
|
7192
|
+
}),
|
|
7121
7193
|
providesTags: ['RbacRoles'],
|
|
7122
7194
|
}),
|
|
7195
|
+
getRbacMentorAccessList: builder.query({
|
|
7196
|
+
...buildEndpointFromDmService(iblaiApi.CoreService.coreRbacMentorAccessList),
|
|
7197
|
+
}),
|
|
7198
|
+
updateRbacMentorAccess: builder.mutation({
|
|
7199
|
+
...buildEndpointFromDmService(iblaiApi.CoreService.coreRbacMentorAccessCreate),
|
|
7200
|
+
}),
|
|
7123
7201
|
}),
|
|
7124
7202
|
});
|
|
7125
7203
|
const { useGetRbacPermissionsMutation} = coreApiSlice;
|
|
7126
7204
|
|
|
7127
7205
|
const CORE_CUSTOM_REDUCER_PATH = 'coreCustomApiSlice';
|
|
7206
|
+
const CORE_FAKE_CUSTOM_REDUCER_PATH = 'coreFakeCustomApiSlice';
|
|
7128
7207
|
const PLATFORM_MEMBERSHIP_TAG = 'PlatformMembership';
|
|
7129
7208
|
const CORE_CUSTOM_ENDPOINTS = {
|
|
7130
7209
|
GET_PLATFORM_MEMBERSHIP: {
|
|
@@ -7158,7 +7237,13 @@ const CORE_CUSTOM_ENDPOINTS = {
|
|
|
7158
7237
|
DELETE_PLATFORM_IMAGE_ASSET: {
|
|
7159
7238
|
path: (platform_key, asset_id) => `/api/core/platforms/${platform_key}/public-image-assets/${asset_id}/`,
|
|
7160
7239
|
service: SERVICES.DM,
|
|
7161
|
-
}
|
|
7240
|
+
},
|
|
7241
|
+
GET_PUBLIC_PLATFORM_IMAGE_ASSET_FILE_URL: {
|
|
7242
|
+
path: (platform_key, asset_id) => `/api/core/platforms/${platform_key}/public-image-assets/${asset_id}/file/`,
|
|
7243
|
+
baseUrl: getServiceUrl(SERVICES.DM),
|
|
7244
|
+
service: SERVICES.DM,
|
|
7245
|
+
},
|
|
7246
|
+
};
|
|
7162
7247
|
|
|
7163
7248
|
createApi({
|
|
7164
7249
|
// TODO: replace to catalogSlice
|
|
@@ -7230,7 +7315,13 @@ createApi({
|
|
|
7230
7315
|
...buildEndpointFromDmService(iblaiApi.AiAccountService.aiAccountOrgsIntegrationCredentialPartialUpdate),
|
|
7231
7316
|
}),
|
|
7232
7317
|
getConnectedServiceAuthUrl: builder.query({
|
|
7233
|
-
|
|
7318
|
+
queryFn: async (queryParams, api, extraOptions) => {
|
|
7319
|
+
const url = `/api/ai-account/connected-services/orgs/${queryParams.org}/users/${queryParams.userId}/${queryParams.provider}/${queryParams.service}/`;
|
|
7320
|
+
return iblFetchBaseQuery({
|
|
7321
|
+
url,
|
|
7322
|
+
service: SERVICES.DM,
|
|
7323
|
+
}, api, extraOptions);
|
|
7324
|
+
},
|
|
7234
7325
|
}),
|
|
7235
7326
|
connectedServicesCallback: builder.query({
|
|
7236
7327
|
queryFn: async (queryParams, api, extraOptions) => {
|
|
@@ -7362,7 +7453,7 @@ const sessionApiSlice = createApi({
|
|
|
7362
7453
|
}),
|
|
7363
7454
|
}),
|
|
7364
7455
|
});
|
|
7365
|
-
const { useCreateSessionIdMutation, useEditSessionMutation, } = sessionApiSlice;
|
|
7456
|
+
const { useCreateSessionIdMutation, useLazyGetSessionIdQuery, useEditSessionMutation, } = sessionApiSlice;
|
|
7366
7457
|
|
|
7367
7458
|
createApi({
|
|
7368
7459
|
reducerPath: 'datasetsApiSlice',
|
|
@@ -8299,6 +8390,12 @@ createApi({
|
|
|
8299
8390
|
});
|
|
8300
8391
|
|
|
8301
8392
|
const NOTIFICATIONS_CUSTOM_REDUCER_PATH = 'notificationsCustomApiSlice';
|
|
8393
|
+
const NOTIFICATIONS_CUSTOM_TAGS = {
|
|
8394
|
+
TEMPLATES: 'NOTIFICATIONS_CUSTOM_TEMPLATES',
|
|
8395
|
+
TEMPLATE_DETAILS: 'NOTIFICATIONS_CUSTOM_TEMPLATE_DETAILS',
|
|
8396
|
+
UPDATE_TEMPLATE: 'NOTIFICATIONS_CUSTOM_UPDATE_TEMPLATE',
|
|
8397
|
+
TOGGLE_TEMPLATE: 'NOTIFICATIONS_CUSTOM_TOGGLE_TEMPLATE',
|
|
8398
|
+
};
|
|
8302
8399
|
const NOTIFICATIONS_CUSTOM_ENDPOINTS = {
|
|
8303
8400
|
GET_TEMPLATES: {
|
|
8304
8401
|
service: SERVICES.DM,
|
|
@@ -8320,6 +8417,7 @@ const NOTIFICATIONS_CUSTOM_ENDPOINTS = {
|
|
|
8320
8417
|
|
|
8321
8418
|
createApi({
|
|
8322
8419
|
reducerPath: NOTIFICATIONS_CUSTOM_REDUCER_PATH,
|
|
8420
|
+
tagTypes: [...Object.values(NOTIFICATIONS_CUSTOM_TAGS)],
|
|
8323
8421
|
baseQuery: iblFetchBaseQuery,
|
|
8324
8422
|
endpoints: (builder) => ({
|
|
8325
8423
|
getTemplates: builder.query({
|
|
@@ -8329,6 +8427,7 @@ createApi({
|
|
|
8329
8427
|
service: NOTIFICATIONS_CUSTOM_ENDPOINTS.GET_TEMPLATES.service,
|
|
8330
8428
|
};
|
|
8331
8429
|
},
|
|
8430
|
+
providesTags: [NOTIFICATIONS_CUSTOM_TAGS.TEMPLATES],
|
|
8332
8431
|
}),
|
|
8333
8432
|
getTemplateDetails: builder.query({
|
|
8334
8433
|
query: (args) => {
|
|
@@ -8337,6 +8436,7 @@ createApi({
|
|
|
8337
8436
|
service: NOTIFICATIONS_CUSTOM_ENDPOINTS.GET_TEMPLATE_DETAILS.service,
|
|
8338
8437
|
};
|
|
8339
8438
|
},
|
|
8439
|
+
providesTags: [NOTIFICATIONS_CUSTOM_TAGS.TEMPLATE_DETAILS],
|
|
8340
8440
|
}),
|
|
8341
8441
|
updateTemplate: builder.mutation({
|
|
8342
8442
|
query: (args) => {
|
|
@@ -8347,6 +8447,7 @@ createApi({
|
|
|
8347
8447
|
body: args.template,
|
|
8348
8448
|
};
|
|
8349
8449
|
},
|
|
8450
|
+
invalidatesTags: [NOTIFICATIONS_CUSTOM_TAGS.TEMPLATE_DETAILS],
|
|
8350
8451
|
}),
|
|
8351
8452
|
toggleTemplate: builder.mutation({
|
|
8352
8453
|
query: (args) => {
|
|
@@ -8359,6 +8460,7 @@ createApi({
|
|
|
8359
8460
|
},
|
|
8360
8461
|
};
|
|
8361
8462
|
},
|
|
8463
|
+
invalidatesTags: [NOTIFICATIONS_CUSTOM_TAGS.TEMPLATES],
|
|
8362
8464
|
}),
|
|
8363
8465
|
}),
|
|
8364
8466
|
});
|
|
@@ -8639,7 +8741,7 @@ const CUSTOM_DOMAIN_QUERY_KEYS = {
|
|
|
8639
8741
|
CREATE_CUSTOM_DOMAIN: () => ['CREATE_CUSTOM_DOMAIN'],
|
|
8640
8742
|
};
|
|
8641
8743
|
|
|
8642
|
-
createApi({
|
|
8744
|
+
const customDomainApiSlice = createApi({
|
|
8643
8745
|
reducerPath: CUSTOM_DOMAIN_REDUCER_PATH,
|
|
8644
8746
|
baseQuery: iblFetchBaseQuery,
|
|
8645
8747
|
tagTypes: [...CUSTOM_DOMAIN_QUERY_KEYS.GET_CUSTOM_DOMAINS()],
|
|
@@ -8678,6 +8780,7 @@ createApi({
|
|
|
8678
8780
|
}),
|
|
8679
8781
|
}),
|
|
8680
8782
|
});
|
|
8783
|
+
const { useGetCustomDomainsQuery} = customDomainApiSlice;
|
|
8681
8784
|
|
|
8682
8785
|
const PLATFORM_CUSTOM_REDUCER_PATH = "platformCustomApiSlice";
|
|
8683
8786
|
const PLATFORM_CONFIGURATION_TAG = "PlatformConfiguration";
|
|
@@ -8740,7 +8843,7 @@ createApi({
|
|
|
8740
8843
|
const coreCustomApiSlice = createApi({
|
|
8741
8844
|
reducerPath: CORE_CUSTOM_REDUCER_PATH,
|
|
8742
8845
|
baseQuery: iblFetchBaseQuery,
|
|
8743
|
-
tagTypes: [PLATFORM_MEMBERSHIP_TAG],
|
|
8846
|
+
tagTypes: [PLATFORM_MEMBERSHIP_TAG, 'PlatformImageAssetFileUrl'],
|
|
8744
8847
|
endpoints: (builder) => ({
|
|
8745
8848
|
getPlatformMembership: builder.query({
|
|
8746
8849
|
query: ({ platform_key }) => ({
|
|
@@ -8813,6 +8916,19 @@ const coreCustomApiSlice = createApi({
|
|
|
8813
8916
|
});
|
|
8814
8917
|
const { useJoinTenantMutation} = coreCustomApiSlice;
|
|
8815
8918
|
|
|
8919
|
+
createApi({
|
|
8920
|
+
reducerPath: CORE_FAKE_CUSTOM_REDUCER_PATH,
|
|
8921
|
+
baseQuery: iblFakeBaseQuery,
|
|
8922
|
+
endpoints: (builder) => ({
|
|
8923
|
+
getPublicPlatformImageAssetFileUrl: builder.query({
|
|
8924
|
+
...buildEndpointFromService(SERVICES.DM, async (args) => {
|
|
8925
|
+
const url = `${iblaiApi.OpenAPI.BASE}${CORE_CUSTOM_ENDPOINTS.GET_PUBLIC_PLATFORM_IMAGE_ASSET_FILE_URL.path(args.platform_key, args.asset_id)}`;
|
|
8926
|
+
return url;
|
|
8927
|
+
}),
|
|
8928
|
+
}),
|
|
8929
|
+
}),
|
|
8930
|
+
});
|
|
8931
|
+
|
|
8816
8932
|
const EDX_PROCTORING_ENDPOINTS = {
|
|
8817
8933
|
GET_EXAM_INFO: {
|
|
8818
8934
|
service: SERVICES.LMS,
|
|
@@ -10325,6 +10441,299 @@ const formatRelativeTime = (timestamp) => {
|
|
|
10325
10441
|
return `${diffInYears} year${diffInYears === 1 ? "" : "s"} ago`;
|
|
10326
10442
|
};
|
|
10327
10443
|
|
|
10444
|
+
/**
|
|
10445
|
+
* Authentication and Authorization Utilities
|
|
10446
|
+
*
|
|
10447
|
+
* This module provides utility functions for handling authentication flows,
|
|
10448
|
+
* including redirects to auth SPA, cookie management, and session handling.
|
|
10449
|
+
*/
|
|
10450
|
+
/**
|
|
10451
|
+
* Check if the current window is inside an iframe
|
|
10452
|
+
* @returns {boolean} True if running in an iframe, false otherwise
|
|
10453
|
+
*/
|
|
10454
|
+
function isInIframe() {
|
|
10455
|
+
if (typeof window === "undefined") {
|
|
10456
|
+
return false;
|
|
10457
|
+
}
|
|
10458
|
+
return (window === null || window === void 0 ? void 0 : window.self) !== (window === null || window === void 0 ? void 0 : window.top);
|
|
10459
|
+
}
|
|
10460
|
+
/**
|
|
10461
|
+
* Send a message to the parent website (when in iframe)
|
|
10462
|
+
* @param payload - The data to send to parent window
|
|
10463
|
+
*/
|
|
10464
|
+
function sendMessageToParentWebsite(payload) {
|
|
10465
|
+
window.parent.postMessage(payload, "*");
|
|
10466
|
+
}
|
|
10467
|
+
/**
|
|
10468
|
+
* Delete a cookie with specific name, path, and domain
|
|
10469
|
+
* @param name - Cookie name
|
|
10470
|
+
* @param path - Cookie path
|
|
10471
|
+
* @param domain - Cookie domain
|
|
10472
|
+
*/
|
|
10473
|
+
function deleteCookie(name, path, domain) {
|
|
10474
|
+
const expires = "expires=Thu, 01 Jan 1970 00:00:00 UTC;";
|
|
10475
|
+
const cookieValue = `${name}=;`;
|
|
10476
|
+
const pathValue = path ? `path=${path};` : "";
|
|
10477
|
+
const domainValue = domain ? `domain=${domain};` : "";
|
|
10478
|
+
document.cookie = cookieValue + expires + pathValue + domainValue;
|
|
10479
|
+
}
|
|
10480
|
+
/**
|
|
10481
|
+
* Get all possible domain parts for cookie deletion
|
|
10482
|
+
* @param domain - The domain to split
|
|
10483
|
+
* @returns Array of domain parts
|
|
10484
|
+
* @example
|
|
10485
|
+
* getDomainParts('app.example.com') // returns ['app.example.com', 'example.com', 'com']
|
|
10486
|
+
*/
|
|
10487
|
+
function getDomainParts(domain) {
|
|
10488
|
+
const parts = domain.split(".");
|
|
10489
|
+
const domains = [];
|
|
10490
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
10491
|
+
domains.push(parts.slice(i).join("."));
|
|
10492
|
+
}
|
|
10493
|
+
return domains;
|
|
10494
|
+
}
|
|
10495
|
+
/**
|
|
10496
|
+
* Delete a cookie across all possible domain variations
|
|
10497
|
+
* @param name - Cookie name to delete
|
|
10498
|
+
* @param childDomain - The current domain
|
|
10499
|
+
*/
|
|
10500
|
+
function deleteCookieOnAllDomains(name, childDomain) {
|
|
10501
|
+
getDomainParts(childDomain).forEach((domainPart) => {
|
|
10502
|
+
deleteCookie(name, "/", domainPart);
|
|
10503
|
+
deleteCookie(name, "", domainPart);
|
|
10504
|
+
});
|
|
10505
|
+
}
|
|
10506
|
+
/**
|
|
10507
|
+
* Get the parent domain from a given domain
|
|
10508
|
+
* @param domain - The domain to process
|
|
10509
|
+
* @returns The parent domain (e.g., 'app.example.com' → '.example.com')
|
|
10510
|
+
*/
|
|
10511
|
+
function getParentDomain(domain) {
|
|
10512
|
+
if (!domain) {
|
|
10513
|
+
return "";
|
|
10514
|
+
}
|
|
10515
|
+
const parts = domain.split(".");
|
|
10516
|
+
return parts.length > 1 ? `.${parts.slice(-2).join(".")}` : domain;
|
|
10517
|
+
}
|
|
10518
|
+
/**
|
|
10519
|
+
* Set a cookie for authentication with cross-domain support
|
|
10520
|
+
* @param name - Cookie name
|
|
10521
|
+
* @param value - Cookie value
|
|
10522
|
+
* @param days - Number of days until expiration (default: 365)
|
|
10523
|
+
*/
|
|
10524
|
+
function setCookieForAuth(name, value, days = 365) {
|
|
10525
|
+
const expires = new Date();
|
|
10526
|
+
expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);
|
|
10527
|
+
const hostname = window.location.hostname;
|
|
10528
|
+
let baseDomain = hostname;
|
|
10529
|
+
// Calculate base domain (skip for localhost and IP addresses)
|
|
10530
|
+
if (hostname !== "localhost" && !/^\d+\.\d+\.\d+\.\d+$/.test(hostname)) {
|
|
10531
|
+
const parts = hostname.split(".");
|
|
10532
|
+
if (parts.length > 2) {
|
|
10533
|
+
baseDomain = `.${parts.slice(-2).join(".")}`;
|
|
10534
|
+
}
|
|
10535
|
+
}
|
|
10536
|
+
const domainAttr = baseDomain ? `;domain=${baseDomain}` : "";
|
|
10537
|
+
document.cookie = `${name}=${encodeURIComponent(value)};expires=${expires.toUTCString()};path=/;SameSite=None;Secure${domainAttr}`;
|
|
10538
|
+
}
|
|
10539
|
+
/**
|
|
10540
|
+
* Clear all cookies for the current domain
|
|
10541
|
+
*/
|
|
10542
|
+
function clearCookies() {
|
|
10543
|
+
const cookies = document.cookie.split(";");
|
|
10544
|
+
for (let i = 0; i < cookies.length; i++) {
|
|
10545
|
+
const cookie = cookies[i];
|
|
10546
|
+
const eqPos = cookie.indexOf("=");
|
|
10547
|
+
const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
|
|
10548
|
+
deleteCookieOnAllDomains(name, window.location.hostname);
|
|
10549
|
+
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;Domain=${getParentDomain(window.location.hostname)}`;
|
|
10550
|
+
}
|
|
10551
|
+
}
|
|
10552
|
+
/**
|
|
10553
|
+
* Check if user is currently logged in
|
|
10554
|
+
* @param tokenKey - The localStorage key for the auth token (default: 'axd_token')
|
|
10555
|
+
* @returns True if logged in, false otherwise
|
|
10556
|
+
*/
|
|
10557
|
+
function isLoggedIn(tokenKey = "axd_token") {
|
|
10558
|
+
return !!localStorage.getItem(tokenKey);
|
|
10559
|
+
}
|
|
10560
|
+
/**
|
|
10561
|
+
* Extract platform/tenant key from URL
|
|
10562
|
+
* @param url - The URL to parse
|
|
10563
|
+
* @param pattern - RegExp pattern to match platform key (default matches /platform/[key]/...)
|
|
10564
|
+
* @returns The platform key or null if not found
|
|
10565
|
+
*/
|
|
10566
|
+
function getPlatformKey(url, pattern = /\/platform\/([^/]+)/) {
|
|
10567
|
+
const match = url.match(pattern);
|
|
10568
|
+
return match ? match[1] : null;
|
|
10569
|
+
}
|
|
10570
|
+
/**
|
|
10571
|
+
* Redirect to authentication SPA for login/logout
|
|
10572
|
+
*
|
|
10573
|
+
* This function handles the complete authentication flow:
|
|
10574
|
+
* - Clears localStorage and cookies on logout
|
|
10575
|
+
* - Saves redirect path for post-auth return
|
|
10576
|
+
* - Handles iframe scenarios
|
|
10577
|
+
* - Syncs logout across multiple SPAs via cookies
|
|
10578
|
+
*
|
|
10579
|
+
* @param options - Configuration options for the redirect
|
|
10580
|
+
*
|
|
10581
|
+
* @example
|
|
10582
|
+
* ```tsx
|
|
10583
|
+
* // Basic usage
|
|
10584
|
+
* redirectToAuthSpa({
|
|
10585
|
+
* authUrl: 'https://auth.example.com',
|
|
10586
|
+
* appName: 'mentor',
|
|
10587
|
+
* });
|
|
10588
|
+
*
|
|
10589
|
+
* // With logout
|
|
10590
|
+
* redirectToAuthSpa({
|
|
10591
|
+
* authUrl: 'https://auth.example.com',
|
|
10592
|
+
* appName: 'mentor',
|
|
10593
|
+
* logout: true,
|
|
10594
|
+
* platformKey: 'my-tenant',
|
|
10595
|
+
* });
|
|
10596
|
+
*
|
|
10597
|
+
* // With custom redirect
|
|
10598
|
+
* redirectToAuthSpa({
|
|
10599
|
+
* authUrl: 'https://auth.example.com',
|
|
10600
|
+
* appName: 'mentor',
|
|
10601
|
+
* redirectTo: '/dashboard',
|
|
10602
|
+
* platformKey: 'my-tenant',
|
|
10603
|
+
* });
|
|
10604
|
+
* ```
|
|
10605
|
+
*/
|
|
10606
|
+
async function redirectToAuthSpa(options) {
|
|
10607
|
+
const { redirectTo, platformKey, logout = false, saveRedirect = true, authUrl, appName, queryParams = {
|
|
10608
|
+
app: "app",
|
|
10609
|
+
redirectTo: "redirect-to",
|
|
10610
|
+
tenant: "tenant",
|
|
10611
|
+
}, redirectPathStorageKey = "redirect_to", cookieNames = {
|
|
10612
|
+
currentTenant: "ibl_current_tenant",
|
|
10613
|
+
userData: "ibl_user_data",
|
|
10614
|
+
tenant: "ibl_tenant",
|
|
10615
|
+
logoutTimestamp: "ibl_logout_timestamp",
|
|
10616
|
+
}, } = options;
|
|
10617
|
+
// Clear localStorage
|
|
10618
|
+
localStorage.clear();
|
|
10619
|
+
if (logout) {
|
|
10620
|
+
// Delete authentication cookies for cross-SPA synchronization
|
|
10621
|
+
const currentDomain = window.location.hostname;
|
|
10622
|
+
if (cookieNames.currentTenant) {
|
|
10623
|
+
deleteCookieOnAllDomains(cookieNames.currentTenant, currentDomain);
|
|
10624
|
+
}
|
|
10625
|
+
if (cookieNames.userData) {
|
|
10626
|
+
deleteCookieOnAllDomains(cookieNames.userData, currentDomain);
|
|
10627
|
+
}
|
|
10628
|
+
if (cookieNames.tenant) {
|
|
10629
|
+
deleteCookieOnAllDomains(cookieNames.tenant, currentDomain);
|
|
10630
|
+
}
|
|
10631
|
+
// Set logout timestamp cookie to trigger logout on other SPAs
|
|
10632
|
+
if (cookieNames.logoutTimestamp) {
|
|
10633
|
+
setCookieForAuth(cookieNames.logoutTimestamp, Date.now().toString());
|
|
10634
|
+
}
|
|
10635
|
+
}
|
|
10636
|
+
// Handle iframe scenario
|
|
10637
|
+
if (isInIframe()) {
|
|
10638
|
+
console.log("[redirectToAuthSpa]: sending authExpired to parent");
|
|
10639
|
+
sendMessageToParentWebsite({ authExpired: true });
|
|
10640
|
+
return;
|
|
10641
|
+
}
|
|
10642
|
+
const redirectPath = redirectTo !== null && redirectTo !== void 0 ? redirectTo : `${window.location.pathname}${window.location.search}`;
|
|
10643
|
+
// Never save sso-login routes as redirect paths
|
|
10644
|
+
if (!redirectPath.startsWith("/sso-login") && saveRedirect) {
|
|
10645
|
+
window.localStorage.setItem(redirectPathStorageKey, redirectPath);
|
|
10646
|
+
}
|
|
10647
|
+
const platform = platformKey !== null && platformKey !== void 0 ? platformKey : getPlatformKey(redirectPath);
|
|
10648
|
+
const redirectToUrl = `${window.location.origin}`;
|
|
10649
|
+
let authRedirectUrl = `${authUrl}/login?${queryParams.app}=${appName}`;
|
|
10650
|
+
authRedirectUrl += `&${queryParams.redirectTo}=${redirectToUrl}`;
|
|
10651
|
+
if (platform) {
|
|
10652
|
+
authRedirectUrl += `&${queryParams.tenant}=${platform}`;
|
|
10653
|
+
}
|
|
10654
|
+
if (logout) {
|
|
10655
|
+
authRedirectUrl += "&logout=1";
|
|
10656
|
+
}
|
|
10657
|
+
// Small delay for any pending operations
|
|
10658
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
10659
|
+
// Redirect to auth SPA
|
|
10660
|
+
window.location.href = authRedirectUrl;
|
|
10661
|
+
}
|
|
10662
|
+
/**
|
|
10663
|
+
* Get the URL for joining a tenant (sign up flow)
|
|
10664
|
+
* @param authUrl - Auth SPA base URL
|
|
10665
|
+
* @param tenantKey - Tenant to join
|
|
10666
|
+
* @param redirectUrl - URL to redirect to after joining (defaults to current URL)
|
|
10667
|
+
* @returns The join URL
|
|
10668
|
+
*/
|
|
10669
|
+
function getAuthSpaJoinUrl(authUrl, tenantKey, redirectUrl) {
|
|
10670
|
+
const resolvedTenant = tenantKey || getPlatformKey(window.location.pathname) || "";
|
|
10671
|
+
if (!resolvedTenant) {
|
|
10672
|
+
return "";
|
|
10673
|
+
}
|
|
10674
|
+
const targetUrl = redirectUrl !== null && redirectUrl !== void 0 ? redirectUrl : window.location.href;
|
|
10675
|
+
const joinUrl = `${authUrl}/join?tenant=${encodeURIComponent(resolvedTenant)}&redirect-to=${encodeURIComponent(targetUrl)}`;
|
|
10676
|
+
return joinUrl;
|
|
10677
|
+
}
|
|
10678
|
+
/**
|
|
10679
|
+
* Redirect to auth SPA's join/signup page for a specific tenant
|
|
10680
|
+
* @param authUrl - Auth SPA base URL
|
|
10681
|
+
* @param tenantKey - Tenant to join
|
|
10682
|
+
* @param redirectUrl - URL to redirect to after joining (defaults to current URL)
|
|
10683
|
+
*/
|
|
10684
|
+
function redirectToAuthSpaJoinTenant(authUrl, tenantKey, redirectUrl) {
|
|
10685
|
+
const resolvedTenant = tenantKey || getPlatformKey(window.location.pathname) || "";
|
|
10686
|
+
if (!resolvedTenant) {
|
|
10687
|
+
console.log("[auth-redirect] Missing tenant key for join", {
|
|
10688
|
+
tenantKey,
|
|
10689
|
+
redirectUrl,
|
|
10690
|
+
});
|
|
10691
|
+
redirectToAuthSpa({
|
|
10692
|
+
authUrl,
|
|
10693
|
+
appName: "app", // Will need to be configured
|
|
10694
|
+
redirectTo: redirectUrl,
|
|
10695
|
+
});
|
|
10696
|
+
return;
|
|
10697
|
+
}
|
|
10698
|
+
const targetUrl = redirectUrl !== null && redirectUrl !== void 0 ? redirectUrl : window.location.href;
|
|
10699
|
+
const joinUrl = `${authUrl}/join?tenant=${encodeURIComponent(resolvedTenant)}&redirect-to=${encodeURIComponent(targetUrl)}`;
|
|
10700
|
+
window.location.href = joinUrl;
|
|
10701
|
+
}
|
|
10702
|
+
/**
|
|
10703
|
+
* Handle user logout
|
|
10704
|
+
*
|
|
10705
|
+
* This function:
|
|
10706
|
+
* - Clears localStorage (preserving tenant)
|
|
10707
|
+
* - Sets logout timestamp cookie for cross-SPA sync
|
|
10708
|
+
* - Clears all cookies
|
|
10709
|
+
* - Redirects to auth SPA logout endpoint
|
|
10710
|
+
*
|
|
10711
|
+
* @param options - Logout configuration options
|
|
10712
|
+
*
|
|
10713
|
+
* @example
|
|
10714
|
+
* ```tsx
|
|
10715
|
+
* handleLogout({
|
|
10716
|
+
* authUrl: 'https://auth.example.com',
|
|
10717
|
+
* redirectUrl: 'https://app.example.com',
|
|
10718
|
+
* });
|
|
10719
|
+
* ```
|
|
10720
|
+
*/
|
|
10721
|
+
function handleLogout(options) {
|
|
10722
|
+
const { redirectUrl = window.location.origin, authUrl, tenantStorageKey = "tenant", logoutTimestampCookie = "ibl_logout_timestamp", callback, } = options;
|
|
10723
|
+
const tenant = window.localStorage.getItem(tenantStorageKey);
|
|
10724
|
+
window.localStorage.clear();
|
|
10725
|
+
if (tenant) {
|
|
10726
|
+
window.localStorage.setItem(tenantStorageKey, tenant);
|
|
10727
|
+
}
|
|
10728
|
+
// Set logout timestamp cookie to trigger logout on other SPAs
|
|
10729
|
+
setCookieForAuth(logoutTimestampCookie, Date.now().toString());
|
|
10730
|
+
clearCookies();
|
|
10731
|
+
callback === null || callback === void 0 ? void 0 : callback();
|
|
10732
|
+
if (!isInIframe()) {
|
|
10733
|
+
window.location.href = `${authUrl}/logout?redirect-to=${redirectUrl}${tenant ? "&tenant=" + tenant : ""}`;
|
|
10734
|
+
}
|
|
10735
|
+
}
|
|
10736
|
+
|
|
10328
10737
|
const useExternalPricingPlan = ({ pricingModalData, userEmail, }) => {
|
|
10329
10738
|
const pricingBoxIframeRef = React.useRef(null);
|
|
10330
10739
|
const getIFrameReadyData = async () => {
|
|
@@ -10456,6 +10865,8 @@ function jwtDecode(token, options) {
|
|
|
10456
10865
|
* - Polls for cookie changes every 2 seconds
|
|
10457
10866
|
* - Refreshes the page when cross-SPA changes are detected
|
|
10458
10867
|
* - Listens for storage events to update cookies when localStorage changes
|
|
10868
|
+
* - Monitors logout timestamp cookie to trigger cross-SPA logout
|
|
10869
|
+
* - Automatically logs out when another SPA initiates logout
|
|
10459
10870
|
*
|
|
10460
10871
|
* For React Native:
|
|
10461
10872
|
* - Relies on AsyncStorage only (handled by StorageService)
|
|
@@ -10465,7 +10876,7 @@ function jwtDecode(token, options) {
|
|
|
10465
10876
|
/**
|
|
10466
10877
|
* Check if we're running in a web browser environment
|
|
10467
10878
|
*/
|
|
10468
|
-
const isWeb = () => {
|
|
10879
|
+
const isWeb$1 = () => {
|
|
10469
10880
|
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
10470
10881
|
};
|
|
10471
10882
|
/**
|
|
@@ -10475,6 +10886,7 @@ const COOKIE_KEYS = {
|
|
|
10475
10886
|
CURRENT_TENANT: "ibl_current_tenant",
|
|
10476
10887
|
USER_DATA: "ibl_user_data",
|
|
10477
10888
|
TENANT: "ibl_tenant",
|
|
10889
|
+
LOGOUT_TIMESTAMP: "ibl_logout_timestamp",
|
|
10478
10890
|
};
|
|
10479
10891
|
/**
|
|
10480
10892
|
* Get the base domain for cookie sharing
|
|
@@ -10485,7 +10897,7 @@ const COOKIE_KEYS = {
|
|
|
10485
10897
|
*/
|
|
10486
10898
|
const getBaseDomain = () => {
|
|
10487
10899
|
// Must check for window existence before accessing it
|
|
10488
|
-
if (!isWeb())
|
|
10900
|
+
if (!isWeb$1())
|
|
10489
10901
|
return "";
|
|
10490
10902
|
const hostname = window.location.hostname;
|
|
10491
10903
|
// For localhost or IP addresses, use as-is
|
|
@@ -10514,7 +10926,7 @@ const CookieUtils = {
|
|
|
10514
10926
|
* Uses SameSite=None for cross-subdomain sharing and base domain
|
|
10515
10927
|
*/
|
|
10516
10928
|
set(name, value, days = 365) {
|
|
10517
|
-
if (!isWeb())
|
|
10929
|
+
if (!isWeb$1())
|
|
10518
10930
|
return;
|
|
10519
10931
|
const expires = new Date();
|
|
10520
10932
|
expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);
|
|
@@ -10526,7 +10938,7 @@ const CookieUtils = {
|
|
|
10526
10938
|
* Get a cookie value by name
|
|
10527
10939
|
*/
|
|
10528
10940
|
get(name) {
|
|
10529
|
-
if (!isWeb())
|
|
10941
|
+
if (!isWeb$1())
|
|
10530
10942
|
return null;
|
|
10531
10943
|
const nameEQ = name + "=";
|
|
10532
10944
|
const cookies = document.cookie.split(";");
|
|
@@ -10545,7 +10957,7 @@ const CookieUtils = {
|
|
|
10545
10957
|
* Uses same domain logic as set() to ensure proper deletion
|
|
10546
10958
|
*/
|
|
10547
10959
|
delete(name) {
|
|
10548
|
-
if (!isWeb())
|
|
10960
|
+
if (!isWeb$1())
|
|
10549
10961
|
return;
|
|
10550
10962
|
const baseDomain = getBaseDomain();
|
|
10551
10963
|
const domainAttr = baseDomain ? `;domain=${baseDomain}` : "";
|
|
@@ -10558,8 +10970,7 @@ const CookieUtils = {
|
|
|
10558
10970
|
* On React Native, this is a no-op
|
|
10559
10971
|
*/
|
|
10560
10972
|
async function syncAuthToCookies(storageService) {
|
|
10561
|
-
|
|
10562
|
-
if (!isWeb())
|
|
10973
|
+
if (!isWeb$1())
|
|
10563
10974
|
return;
|
|
10564
10975
|
try {
|
|
10565
10976
|
const currentTenant = await storageService.getItem(LOCAL_STORAGE_KEYS.CURRENT_TENANT);
|
|
@@ -10588,13 +10999,23 @@ async function syncAuthToCookies(storageService) {
|
|
|
10588
10999
|
console.error("[syncAuthToCookies] Error syncing to cookies:", error);
|
|
10589
11000
|
}
|
|
10590
11001
|
}
|
|
11002
|
+
/**
|
|
11003
|
+
* Clear current tenant cookie only (web only)
|
|
11004
|
+
* Should be called before tenant switching
|
|
11005
|
+
* On React Native, this is a no-op
|
|
11006
|
+
*/
|
|
11007
|
+
function clearCurrentTenantCookie() {
|
|
11008
|
+
if (!isWeb$1())
|
|
11009
|
+
return;
|
|
11010
|
+
CookieUtils.delete(COOKIE_KEYS.CURRENT_TENANT);
|
|
11011
|
+
}
|
|
10591
11012
|
/**
|
|
10592
11013
|
* Clear all authentication cookies (web only)
|
|
10593
11014
|
* Should be called on logout
|
|
10594
11015
|
* On React Native, this is a no-op
|
|
10595
11016
|
*/
|
|
10596
11017
|
function clearAuthCookies() {
|
|
10597
|
-
if (!isWeb())
|
|
11018
|
+
if (!isWeb$1())
|
|
10598
11019
|
return;
|
|
10599
11020
|
CookieUtils.delete(COOKIE_KEYS.CURRENT_TENANT);
|
|
10600
11021
|
CookieUtils.delete(COOKIE_KEYS.USER_DATA);
|
|
@@ -10606,14 +11027,30 @@ function clearAuthCookies() {
|
|
|
10606
11027
|
* On React Native, always returns false (no-op)
|
|
10607
11028
|
*/
|
|
10608
11029
|
async function syncCookiesToLocalStorage(storageService) {
|
|
10609
|
-
if (!isWeb())
|
|
11030
|
+
if (!isWeb$1())
|
|
10610
11031
|
return false;
|
|
10611
11032
|
try {
|
|
10612
11033
|
let needsRefresh = false;
|
|
10613
11034
|
// Check current_tenant
|
|
10614
11035
|
const cookieCurrentTenant = CookieUtils.get(COOKIE_KEYS.CURRENT_TENANT);
|
|
11036
|
+
console.log("[syncCookiesToLocalStorage] cookieCurrentTenant", cookieCurrentTenant);
|
|
10615
11037
|
const localCurrentTenant = await storageService.getItem(LOCAL_STORAGE_KEYS.CURRENT_TENANT);
|
|
10616
|
-
|
|
11038
|
+
console.log("[syncCookiesToLocalStorage] localCurrentTenant", localCurrentTenant);
|
|
11039
|
+
// Compare current tenant objects by key field only to avoid false positives from extra fields
|
|
11040
|
+
let currentTenantIsDifferent = false;
|
|
11041
|
+
if (cookieCurrentTenant && localCurrentTenant) {
|
|
11042
|
+
try {
|
|
11043
|
+
const cookieTenant = JSON.parse(cookieCurrentTenant);
|
|
11044
|
+
const localTenant = JSON.parse(localCurrentTenant);
|
|
11045
|
+
// Compare by the tenant key only
|
|
11046
|
+
currentTenantIsDifferent = cookieTenant.key !== localTenant.key;
|
|
11047
|
+
}
|
|
11048
|
+
catch (e) {
|
|
11049
|
+
// If parsing fails, fall back to string comparison
|
|
11050
|
+
currentTenantIsDifferent = cookieCurrentTenant !== localCurrentTenant;
|
|
11051
|
+
}
|
|
11052
|
+
}
|
|
11053
|
+
if (currentTenantIsDifferent) {
|
|
10617
11054
|
if (cookieCurrentTenant) {
|
|
10618
11055
|
await storageService.setItem(LOCAL_STORAGE_KEYS.CURRENT_TENANT, cookieCurrentTenant);
|
|
10619
11056
|
}
|
|
@@ -10625,8 +11062,24 @@ async function syncCookiesToLocalStorage(storageService) {
|
|
|
10625
11062
|
}
|
|
10626
11063
|
// Check userData
|
|
10627
11064
|
const cookieUserData = CookieUtils.get(COOKIE_KEYS.USER_DATA);
|
|
11065
|
+
console.log("[syncCookiesToLocalStorage] cookieUserData", cookieUserData);
|
|
10628
11066
|
const localUserData = await storageService.getItem(LOCAL_STORAGE_KEYS.USER_DATA);
|
|
10629
|
-
|
|
11067
|
+
console.log("[syncCookiesToLocalStorage] localUserData", localUserData);
|
|
11068
|
+
// Compare userData objects by user_id to avoid false positives from extra fields
|
|
11069
|
+
let userDataIsDifferent = false;
|
|
11070
|
+
if (cookieUserData && localUserData) {
|
|
11071
|
+
try {
|
|
11072
|
+
const cookieUser = JSON.parse(cookieUserData);
|
|
11073
|
+
const localUser = JSON.parse(localUserData);
|
|
11074
|
+
// Compare by user_id - the primary identifier
|
|
11075
|
+
userDataIsDifferent = cookieUser.user_id !== localUser.user_id;
|
|
11076
|
+
}
|
|
11077
|
+
catch (e) {
|
|
11078
|
+
// If parsing fails, fall back to string comparison
|
|
11079
|
+
userDataIsDifferent = cookieUserData !== localUserData;
|
|
11080
|
+
}
|
|
11081
|
+
}
|
|
11082
|
+
if (userDataIsDifferent) {
|
|
10630
11083
|
if (cookieUserData) {
|
|
10631
11084
|
await storageService.setItem(LOCAL_STORAGE_KEYS.USER_DATA, cookieUserData);
|
|
10632
11085
|
}
|
|
@@ -10638,8 +11091,37 @@ async function syncCookiesToLocalStorage(storageService) {
|
|
|
10638
11091
|
}
|
|
10639
11092
|
// Check tenant
|
|
10640
11093
|
const cookieTenant = CookieUtils.get(COOKIE_KEYS.TENANT);
|
|
11094
|
+
console.log("[syncCookiesToLocalStorage] cookieTenant", cookieTenant);
|
|
10641
11095
|
const localTenant = await storageService.getItem(LOCAL_STORAGE_KEYS.TENANTS);
|
|
10642
|
-
|
|
11096
|
+
console.log("[syncCookiesToLocalStorage] localTenant", localTenant);
|
|
11097
|
+
// Compare tenant arrays by checking length and tenant keys
|
|
11098
|
+
let tenantsAreDifferent = false;
|
|
11099
|
+
if (cookieTenant &&
|
|
11100
|
+
localTenant &&
|
|
11101
|
+
cookieTenant !== "[]" &&
|
|
11102
|
+
localTenant !== "[]") {
|
|
11103
|
+
try {
|
|
11104
|
+
const cookieTenantsArray = JSON.parse(cookieTenant);
|
|
11105
|
+
const localTenantsArray = JSON.parse(localTenant);
|
|
11106
|
+
// Check if arrays have same length
|
|
11107
|
+
if (cookieTenantsArray.length !== localTenantsArray.length) {
|
|
11108
|
+
tenantsAreDifferent = true;
|
|
11109
|
+
}
|
|
11110
|
+
else {
|
|
11111
|
+
// Check if all tenant keys match
|
|
11112
|
+
const cookieKeys = new Set(cookieTenantsArray.map((t) => t.key));
|
|
11113
|
+
const localKeys = new Set(localTenantsArray.map((t) => t.key));
|
|
11114
|
+
tenantsAreDifferent =
|
|
11115
|
+
cookieKeys.size !== localKeys.size ||
|
|
11116
|
+
[...cookieKeys].some((key) => !localKeys.has(key));
|
|
11117
|
+
}
|
|
11118
|
+
}
|
|
11119
|
+
catch (e) {
|
|
11120
|
+
// If parsing fails, fall back to string comparison
|
|
11121
|
+
tenantsAreDifferent = cookieTenant !== localTenant;
|
|
11122
|
+
}
|
|
11123
|
+
}
|
|
11124
|
+
if (tenantsAreDifferent) {
|
|
10643
11125
|
if (cookieTenant) {
|
|
10644
11126
|
await storageService.setItem(LOCAL_STORAGE_KEYS.TENANTS, cookieTenant);
|
|
10645
11127
|
}
|
|
@@ -10694,6 +11176,7 @@ async function isJwtTokenExpired(storageService) {
|
|
|
10694
11176
|
async function validateJwtToken(storageService) {
|
|
10695
11177
|
try {
|
|
10696
11178
|
const edxJwtToken = await storageService.getItem(LOCAL_STORAGE_KEYS.EDX_TOKEN_KEY);
|
|
11179
|
+
console.log("[AuthProvider] JWT token ", edxJwtToken);
|
|
10697
11180
|
const userData = await storageService.getItem(LOCAL_STORAGE_KEYS.USER_DATA);
|
|
10698
11181
|
if (!edxJwtToken || !userData) {
|
|
10699
11182
|
return false;
|
|
@@ -10716,7 +11199,9 @@ async function validateJwtToken(storageService) {
|
|
|
10716
11199
|
function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure, redirectToAuthSpa, hasNonExpiredAuthToken, username, pathname, storageService, skipAuthCheck, token, }) {
|
|
10717
11200
|
const [isAuthenticating, setIsAuthenticating] = React.useState(true);
|
|
10718
11201
|
const [userIsAccessingPublicRoute, setUserIsAccessingPublicRoute] = React.useState(false);
|
|
11202
|
+
const [initialSyncComplete, setInitialSyncComplete] = React.useState(false);
|
|
10719
11203
|
const cookieCheckIntervalRef = React.useRef(null);
|
|
11204
|
+
const lastLogoutTimestampRef = React.useRef(null);
|
|
10720
11205
|
// RTK Query hook for refreshing JWT token
|
|
10721
11206
|
const [refreshJwtToken] = useLazyRefreshJwtTokenQuery();
|
|
10722
11207
|
/**
|
|
@@ -10725,24 +11210,65 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
10725
11210
|
* On React Native, this is a no-op
|
|
10726
11211
|
*/
|
|
10727
11212
|
React.useEffect(() => {
|
|
10728
|
-
|
|
10729
|
-
|
|
11213
|
+
if (!storageService || !isWeb$1()) {
|
|
11214
|
+
// If no storage service or not web, mark sync as complete immediately
|
|
11215
|
+
setInitialSyncComplete(true);
|
|
10730
11216
|
return;
|
|
11217
|
+
}
|
|
10731
11218
|
// Initial sync on mount
|
|
10732
11219
|
async function initialSync() {
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
|
|
10736
|
-
|
|
11220
|
+
try {
|
|
11221
|
+
// Initialize last known logout timestamp
|
|
11222
|
+
lastLogoutTimestampRef.current = CookieUtils.get(COOKIE_KEYS.LOGOUT_TIMESTAMP);
|
|
11223
|
+
const needsRefresh = await syncCookiesToLocalStorage(storageService);
|
|
11224
|
+
if (needsRefresh) {
|
|
11225
|
+
console.log("[auth-redirect] Cookie sync detected changes, refreshing page");
|
|
11226
|
+
redirectToAuthSpa(undefined, undefined, false, false);
|
|
11227
|
+
}
|
|
11228
|
+
else {
|
|
11229
|
+
await syncAuthToCookies(storageService);
|
|
11230
|
+
}
|
|
11231
|
+
}
|
|
11232
|
+
finally {
|
|
11233
|
+
// Mark initial sync as complete
|
|
11234
|
+
setInitialSyncComplete(true);
|
|
10737
11235
|
}
|
|
10738
11236
|
}
|
|
10739
11237
|
initialSync();
|
|
10740
11238
|
// Poll for cookie changes every 2 seconds to detect cross-SPA updates
|
|
10741
11239
|
cookieCheckIntervalRef.current = setInterval(async () => {
|
|
11240
|
+
// Skip cookie sync checks if user is completing SSO at /sso-login
|
|
11241
|
+
const completingSso = new RegExp("^\/sso-login").test(pathname);
|
|
11242
|
+
if (completingSso) {
|
|
11243
|
+
console.log("[AuthProvider] Skipping cookie sync check for public route");
|
|
11244
|
+
return;
|
|
11245
|
+
}
|
|
11246
|
+
// Check for logout timestamp changes (cross-SPA logout detection)
|
|
11247
|
+
const currentLogoutTimestamp = CookieUtils.get(COOKIE_KEYS.LOGOUT_TIMESTAMP);
|
|
11248
|
+
if (currentLogoutTimestamp &&
|
|
11249
|
+
lastLogoutTimestampRef.current &&
|
|
11250
|
+
currentLogoutTimestamp !== lastLogoutTimestampRef.current) {
|
|
11251
|
+
console.log("[auth-redirect] Logout detected from another SPA", {
|
|
11252
|
+
previousTimestamp: lastLogoutTimestampRef.current,
|
|
11253
|
+
newTimestamp: currentLogoutTimestamp,
|
|
11254
|
+
});
|
|
11255
|
+
lastLogoutTimestampRef.current = currentLogoutTimestamp;
|
|
11256
|
+
redirectToAuthSpa(undefined, undefined, true);
|
|
11257
|
+
return;
|
|
11258
|
+
}
|
|
10742
11259
|
const needsRefresh = await syncCookiesToLocalStorage(storageService);
|
|
10743
11260
|
if (needsRefresh) {
|
|
10744
|
-
console.log("[
|
|
10745
|
-
|
|
11261
|
+
console.log("[auth-redirect] Cookie sync detected changes from another SPA, refreshing page");
|
|
11262
|
+
let cookieTenantKey;
|
|
11263
|
+
try {
|
|
11264
|
+
const cookieCurrentTenant = JSON.parse(CookieUtils.get(COOKIE_KEYS.CURRENT_TENANT));
|
|
11265
|
+
cookieTenantKey = cookieCurrentTenant.key;
|
|
11266
|
+
}
|
|
11267
|
+
catch (_a) { }
|
|
11268
|
+
redirectToAuthSpa(undefined, cookieTenantKey, false, false);
|
|
11269
|
+
}
|
|
11270
|
+
else {
|
|
11271
|
+
await syncAuthToCookies(storageService);
|
|
10746
11272
|
}
|
|
10747
11273
|
}, 2000);
|
|
10748
11274
|
// Cleanup interval on unmount
|
|
@@ -10751,15 +11277,14 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
10751
11277
|
clearInterval(cookieCheckIntervalRef.current);
|
|
10752
11278
|
}
|
|
10753
11279
|
};
|
|
10754
|
-
}, [storageService]);
|
|
11280
|
+
}, [storageService, middleware, pathname]);
|
|
10755
11281
|
/**
|
|
10756
11282
|
* Listen for storage events from other tabs/windows (web only)
|
|
10757
11283
|
* This catches same-SPA changes in different tabs
|
|
10758
11284
|
* On React Native, this is a no-op
|
|
10759
11285
|
*/
|
|
10760
11286
|
React.useEffect(() => {
|
|
10761
|
-
|
|
10762
|
-
if (!storageService || !isWeb())
|
|
11287
|
+
if (!storageService || !isWeb$1())
|
|
10763
11288
|
return;
|
|
10764
11289
|
const handleStorageChange = async (event) => {
|
|
10765
11290
|
// Only handle changes to our auth-related keys
|
|
@@ -10790,14 +11315,15 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
10790
11315
|
if (!hasNonExpiredAuthToken()) {
|
|
10791
11316
|
const reason = "Auth token expired";
|
|
10792
11317
|
onAuthFailure === null || onAuthFailure === void 0 ? void 0 : onAuthFailure(reason);
|
|
10793
|
-
|
|
11318
|
+
console.log("[auth-redirect] Auth token expired");
|
|
11319
|
+
redirectToAuthSpa(undefined, undefined, true);
|
|
10794
11320
|
return;
|
|
10795
11321
|
}
|
|
10796
11322
|
// Check JWT token expiry and force logout for protected routes
|
|
10797
11323
|
if (isProtectedRoute && storageService) {
|
|
10798
11324
|
const jwtExpired = await isJwtTokenExpired(storageService);
|
|
10799
11325
|
if (jwtExpired) {
|
|
10800
|
-
console.log("[
|
|
11326
|
+
console.log("[auth-redirect] JWT token has expired, forcing logout");
|
|
10801
11327
|
// Clear all auth-related storage keys
|
|
10802
11328
|
clearAuthCookies();
|
|
10803
11329
|
const reason = "JWT token expired";
|
|
@@ -10819,11 +11345,18 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
10819
11345
|
console.log("[AuthProvider] JWT token refreshed successfully");
|
|
10820
11346
|
}
|
|
10821
11347
|
else if (result.error) {
|
|
10822
|
-
console.
|
|
11348
|
+
console.log("[auth-redirect] Failed to refresh JWT token", {
|
|
11349
|
+
error: result.error,
|
|
11350
|
+
});
|
|
11351
|
+
redirectToAuthSpa(undefined, undefined, true);
|
|
11352
|
+
return;
|
|
10823
11353
|
}
|
|
10824
11354
|
}
|
|
10825
11355
|
catch (refreshError) {
|
|
10826
|
-
console.
|
|
11356
|
+
console.log("[auth-redirect] JWT token refresh error", {
|
|
11357
|
+
error: refreshError,
|
|
11358
|
+
});
|
|
11359
|
+
redirectToAuthSpa(undefined, undefined, true);
|
|
10827
11360
|
// Continue with auth check even if JWT refresh fails
|
|
10828
11361
|
}
|
|
10829
11362
|
}
|
|
@@ -10835,12 +11368,18 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
10835
11368
|
setIsAuthenticating(false);
|
|
10836
11369
|
}
|
|
10837
11370
|
catch (error) {
|
|
11371
|
+
console.error("[AuthProvider] Error performing auth check:", error);
|
|
10838
11372
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
10839
11373
|
onAuthFailure === null || onAuthFailure === void 0 ? void 0 : onAuthFailure(`Unexpected error: ${errorMessage}`);
|
|
10840
11374
|
redirectToAuthSpa();
|
|
10841
11375
|
}
|
|
10842
11376
|
}
|
|
10843
11377
|
React.useEffect(() => {
|
|
11378
|
+
// Wait for initial sync to complete before performing auth check
|
|
11379
|
+
if (!initialSyncComplete) {
|
|
11380
|
+
console.log("[useAuthProvider] Waiting for initial sync to complete...");
|
|
11381
|
+
return;
|
|
11382
|
+
}
|
|
10844
11383
|
async function checkAuth() {
|
|
10845
11384
|
setIsAuthenticating(true);
|
|
10846
11385
|
const authRequired = (await determineAuthRequired(middleware, pathname)) && !token;
|
|
@@ -10861,7 +11400,7 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
10861
11400
|
}
|
|
10862
11401
|
console.log("[useAuthProvider] performing auth check for ", username);
|
|
10863
11402
|
checkAuth();
|
|
10864
|
-
}, [username]);
|
|
11403
|
+
}, [username, initialSyncComplete]);
|
|
10865
11404
|
return {
|
|
10866
11405
|
isAuthenticating,
|
|
10867
11406
|
userIsAccessingPublicRoute,
|
|
@@ -10929,7 +11468,7 @@ function AuthProvider({ children, fallback, middleware = new Map(), onAuthSucces
|
|
|
10929
11468
|
if (isAuthenticating) {
|
|
10930
11469
|
return fallback;
|
|
10931
11470
|
}
|
|
10932
|
-
return (jsxRuntime.jsx(AuthContextProvider, { value: { userIsAccessingPublicRoute, setUserIsAccessingPublicRoute }, children:
|
|
11471
|
+
return (jsxRuntime.jsx(AuthContextProvider, { value: { userIsAccessingPublicRoute, setUserIsAccessingPublicRoute }, children: children }));
|
|
10933
11472
|
}
|
|
10934
11473
|
|
|
10935
11474
|
/**
|
|
@@ -10942,6 +11481,12 @@ function AuthProvider({ children, fallback, middleware = new Map(), onAuthSucces
|
|
|
10942
11481
|
* - Tenant metadata retrieval
|
|
10943
11482
|
* - User-tenant relationship verification
|
|
10944
11483
|
*/
|
|
11484
|
+
/**
|
|
11485
|
+
* Check if we're running in a web browser environment
|
|
11486
|
+
*/
|
|
11487
|
+
const isWeb = () => {
|
|
11488
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
11489
|
+
};
|
|
10945
11490
|
const TenantContext = React.createContext(undefined);
|
|
10946
11491
|
/**
|
|
10947
11492
|
* Context Provider component that wraps children with tenant context
|
|
@@ -10962,7 +11507,7 @@ const useTenantContext = () => React.useContext(TenantContext);
|
|
|
10962
11507
|
* 4. Handles tenant-specific domain redirects
|
|
10963
11508
|
* 5. Maintains tenant access state
|
|
10964
11509
|
*/
|
|
10965
|
-
function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, currentTenant, requestedTenant, saveCurrentTenant, saveUserTenants, handleTenantSwitch, saveVisitingTenant, removeVisitingTenant, saveUserTokens, saveTenant, onAutoJoinUserToTenant, }) {
|
|
11510
|
+
function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, currentTenant, requestedTenant, saveCurrentTenant, saveUserTenants, handleTenantSwitch, saveVisitingTenant, removeVisitingTenant, saveUserTokens, saveTenant, onAutoJoinUserToTenant, redirectToAuthSpa, }) {
|
|
10966
11511
|
const { userIsAccessingPublicRoute, setUserIsAccessingPublicRoute } = useAuthContext();
|
|
10967
11512
|
const [determineUserPath, setDetermineUserPath] = React.useState(false);
|
|
10968
11513
|
const [isLoading, setIsLoading] = React.useState(true);
|
|
@@ -10973,6 +11518,26 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
|
|
|
10973
11518
|
const [getAppToken] = useGetAppTokensMutation();
|
|
10974
11519
|
const [tenantKey, setTenantKey] = React.useState(currentTenant);
|
|
10975
11520
|
const [metadata, setMetadata] = React.useState({});
|
|
11521
|
+
// Fetch custom domain to get platform_key
|
|
11522
|
+
const currentDomain = typeof window !== "undefined" ? window.location.hostname : "";
|
|
11523
|
+
const { data: customDomainData, isLoading: isLoadingCustomDomain, isError: isCustomDomainError, } = useGetCustomDomainsQuery({ params: { domain: currentDomain } }, { skip: !isWeb() || !currentDomain });
|
|
11524
|
+
// Extract platform_key from custom domain response to use as requestedTenant
|
|
11525
|
+
const customDomainPlatformKey = React.useMemo(() => {
|
|
11526
|
+
if (customDomainData &&
|
|
11527
|
+
typeof customDomainData === "object" &&
|
|
11528
|
+
"custom_domains" in customDomainData) {
|
|
11529
|
+
const domains = customDomainData.custom_domains;
|
|
11530
|
+
if (Array.isArray(domains) &&
|
|
11531
|
+
domains.length > 0 &&
|
|
11532
|
+
domains[0].platform_key) {
|
|
11533
|
+
console.log("[TenantProvider] Using platform_key from custom domain:", domains[0].platform_key);
|
|
11534
|
+
return domains[0].platform_key;
|
|
11535
|
+
}
|
|
11536
|
+
}
|
|
11537
|
+
return undefined;
|
|
11538
|
+
}, [customDomainData]);
|
|
11539
|
+
// Use custom domain platform_key as requested tenant if available, otherwise use provided requestedTenant
|
|
11540
|
+
const effectiveRequestedTenant = customDomainPlatformKey || requestedTenant;
|
|
10976
11541
|
/**
|
|
10977
11542
|
* Helper function to enhance tenants with platform metadata from user apps
|
|
10978
11543
|
*/
|
|
@@ -11032,24 +11597,32 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
|
|
|
11032
11597
|
const otherTenant = tenants.find((t) => t.key !== MAIN_TENANT_KEY);
|
|
11033
11598
|
if (mainTenant &&
|
|
11034
11599
|
otherTenant &&
|
|
11035
|
-
|
|
11036
|
-
|
|
11600
|
+
effectiveRequestedTenant &&
|
|
11601
|
+
effectiveRequestedTenant !== otherTenant.key) {
|
|
11037
11602
|
handleTenantSwitch(otherTenant.key, true);
|
|
11038
11603
|
console.log("TenantProvider: Triggering tenant switch to newly joined tenant:", otherTenant.key);
|
|
11039
11604
|
}
|
|
11040
11605
|
}
|
|
11041
|
-
// Enhance tenants with platform
|
|
11606
|
+
// Enhance tenants with platform metadatax
|
|
11042
11607
|
let enhancedTenants = await enhanceTenants(tenants);
|
|
11608
|
+
// if there is customDomainPlatformKey and user doesn't belong to that tenant, trigger logout
|
|
11609
|
+
if (customDomainPlatformKey) {
|
|
11610
|
+
if (!(enhancedTenants === null || enhancedTenants === void 0 ? void 0 : enhancedTenants.find((tenant) => tenant.key === customDomainPlatformKey))) {
|
|
11611
|
+
redirectToAuthSpa === null || redirectToAuthSpa === void 0 ? void 0 : redirectToAuthSpa(undefined, undefined, true);
|
|
11612
|
+
return;
|
|
11613
|
+
}
|
|
11614
|
+
}
|
|
11043
11615
|
saveUserTenants(enhancedTenants);
|
|
11044
11616
|
// Find requested tenant or fallback to current tenant
|
|
11045
|
-
console.log("checking requested tenant", {
|
|
11046
|
-
|
|
11047
|
-
|
|
11617
|
+
console.log("checking requested tenant", JSON.stringify({
|
|
11618
|
+
requestedTenant: effectiveRequestedTenant,
|
|
11619
|
+
customDomainPlatformKey,
|
|
11620
|
+
}));
|
|
11621
|
+
let tenant = enhancedTenants === null || enhancedTenants === void 0 ? void 0 : enhancedTenants.find((tenant) => tenant.key === effectiveRequestedTenant);
|
|
11622
|
+
console.log("requested tenant", tenant);
|
|
11048
11623
|
if (!tenant && !userIsAccessingPublicRoute) {
|
|
11049
11624
|
setDetermineUserPath(true);
|
|
11050
|
-
console.log("no requested tenant, checking current tenant",
|
|
11051
|
-
currentTenant,
|
|
11052
|
-
});
|
|
11625
|
+
console.log("no requested tenant, checking current tenant", currentTenant);
|
|
11053
11626
|
tenant = enhancedTenants === null || enhancedTenants === void 0 ? void 0 : enhancedTenants.find((tenant) => tenant.key === currentTenant);
|
|
11054
11627
|
console.log("current tenant", { tenant });
|
|
11055
11628
|
}
|
|
@@ -11061,7 +11634,7 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
|
|
|
11061
11634
|
tenant = enhancedTenants[0];
|
|
11062
11635
|
}
|
|
11063
11636
|
// Fetch and validate tenant metadata
|
|
11064
|
-
console.log("fetching tenant metadata",
|
|
11637
|
+
console.log("fetching tenant metadata", JSON.stringify(tenant));
|
|
11065
11638
|
const { data: tenantMetadata } = await fetchTenantMetadata([
|
|
11066
11639
|
{
|
|
11067
11640
|
org: (tenant === null || tenant === void 0 ? void 0 : tenant.key) || currentTenant,
|
|
@@ -11203,28 +11776,44 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
|
|
|
11203
11776
|
}
|
|
11204
11777
|
// Effect to handle tenant determination when auth state changes
|
|
11205
11778
|
React.useEffect(() => {
|
|
11779
|
+
// Wait for custom domain query to complete (unless skipped or error)
|
|
11780
|
+
const customDomainQuerySkipped = !isWeb() || !currentDomain;
|
|
11781
|
+
if (!customDomainQuerySkipped && isLoadingCustomDomain) {
|
|
11782
|
+
console.log("[TenantProvider] Waiting for custom domain query to complete...");
|
|
11783
|
+
return;
|
|
11784
|
+
}
|
|
11785
|
+
if (isCustomDomainError) {
|
|
11786
|
+
console.warn("[TenantProvider] Custom domain query failed, proceeding without custom domain platform_key");
|
|
11787
|
+
}
|
|
11206
11788
|
// NOTE: currentTenant comes from local storage.
|
|
11207
11789
|
// it's the tenant the user is currently signed into.
|
|
11208
11790
|
console.log("determineWhichTenantToUse", {
|
|
11209
11791
|
userIsAccessingPublicRoute,
|
|
11210
11792
|
currentTenant,
|
|
11211
11793
|
requestedTenant,
|
|
11794
|
+
effectiveRequestedTenant,
|
|
11795
|
+
customDomainPlatformKey,
|
|
11212
11796
|
});
|
|
11213
|
-
if (userIsAccessingPublicRoute &&
|
|
11797
|
+
if (userIsAccessingPublicRoute && effectiveRequestedTenant.length === 0) {
|
|
11214
11798
|
setIsLoading(false);
|
|
11215
11799
|
return;
|
|
11216
11800
|
}
|
|
11217
|
-
if (userIsAccessingPublicRoute &&
|
|
11801
|
+
if (userIsAccessingPublicRoute && effectiveRequestedTenant.length > 0) {
|
|
11218
11802
|
setIsLoading(true);
|
|
11219
|
-
setTenantKey(
|
|
11220
|
-
handleLoadTenantMetadata(
|
|
11803
|
+
setTenantKey(effectiveRequestedTenant);
|
|
11804
|
+
handleLoadTenantMetadata(effectiveRequestedTenant);
|
|
11221
11805
|
}
|
|
11222
11806
|
else {
|
|
11223
11807
|
setIsLoading(true);
|
|
11224
11808
|
removeVisitingTenant === null || removeVisitingTenant === void 0 ? void 0 : removeVisitingTenant();
|
|
11225
11809
|
determineWhichTenantToUse();
|
|
11226
11810
|
}
|
|
11227
|
-
}, [
|
|
11811
|
+
}, [
|
|
11812
|
+
userIsAccessingPublicRoute,
|
|
11813
|
+
effectiveRequestedTenant,
|
|
11814
|
+
isLoadingCustomDomain,
|
|
11815
|
+
isCustomDomainError,
|
|
11816
|
+
]);
|
|
11228
11817
|
// Show fallback component during tenant determination
|
|
11229
11818
|
if (isLoading) {
|
|
11230
11819
|
return fallback;
|
|
@@ -11260,21 +11849,14 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
|
|
|
11260
11849
|
function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redirectToAuthSpa, redirectToMentor, onLoadMentorsPermissions, redirectToNoMentorsPage, redirectToCreateMentor, username, isAdmin, mainTenantKey, requestedMentorId, handleMentorNotFound, forceDetermineMentor = false, }) {
|
|
11261
11850
|
const [isLoading, setIsLoading] = React.useState(true);
|
|
11262
11851
|
const { userIsAccessingPublicRoute } = useAuthContext();
|
|
11263
|
-
const { determineUserPath, tenantKey } = useTenantContext();
|
|
11852
|
+
const { determineUserPath, tenantKey, metadata } = useTenantContext();
|
|
11264
11853
|
const isMainTenant = tenantKey === mainTenantKey;
|
|
11265
|
-
console.log("MentorProvider initialized",
|
|
11266
|
-
username,
|
|
11267
|
-
isAdmin,
|
|
11268
|
-
tenantKey,
|
|
11269
|
-
mainTenantKey,
|
|
11270
|
-
isMainTenant,
|
|
11271
|
-
requestedMentorId,
|
|
11272
|
-
determineUserPath,
|
|
11273
|
-
});
|
|
11854
|
+
console.log("MentorProvider initialized", username, isAdmin, tenantKey, mainTenantKey, isMainTenant, requestedMentorId, determineUserPath);
|
|
11274
11855
|
const [fetchMentors] = useLazyGetMentorsQuery();
|
|
11275
11856
|
const [fetchSeedMentors] = useLazySeedMentorsQuery();
|
|
11276
11857
|
const [getMentorPublicSettings] = useLazyGetMentorPublicSettingsQuery();
|
|
11277
11858
|
const [getRbacPermissions] = useGetRbacPermissionsMutation();
|
|
11859
|
+
const [getRecentlyAccessedMentors] = useLazyGetRecentlyAccessedMentorsQuery();
|
|
11278
11860
|
const QUERY_LIMIT = 10;
|
|
11279
11861
|
const loadMentorsPermissions = async (mentorDbId) => {
|
|
11280
11862
|
try {
|
|
@@ -11301,21 +11883,69 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
|
|
|
11301
11883
|
*/
|
|
11302
11884
|
async function determineMentorToRedirectTo() {
|
|
11303
11885
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
11304
|
-
console.log("starting mentor determination process", {
|
|
11886
|
+
console.log("starting mentor determination process", JSON.stringify({
|
|
11305
11887
|
tenantKey,
|
|
11306
11888
|
username,
|
|
11307
11889
|
isAdmin,
|
|
11308
11890
|
isMainTenant,
|
|
11309
|
-
});
|
|
11891
|
+
}));
|
|
11892
|
+
console.log("###################### metadata is ", metadata, typeof metadata);
|
|
11310
11893
|
setIsLoading(true);
|
|
11311
11894
|
try {
|
|
11312
11895
|
// Get the user's recent mentors
|
|
11313
|
-
console.log("fetching recent mentors", {
|
|
11896
|
+
console.log("fetching recent mentors", JSON.stringify({
|
|
11314
11897
|
tenantKey,
|
|
11315
11898
|
username,
|
|
11316
11899
|
limit: QUERY_LIMIT,
|
|
11317
11900
|
orderBy: "recently_accessed_at",
|
|
11901
|
+
}));
|
|
11902
|
+
if (typeof metadata === "object" &&
|
|
11903
|
+
metadata.skills_embedded_mentor_name) {
|
|
11904
|
+
const defaultMentor = JSON.parse(metadata.skills_embedded_mentor_name);
|
|
11905
|
+
if (defaultMentor === null || defaultMentor === void 0 ? void 0 : defaultMentor.unique_id) {
|
|
11906
|
+
if (defaultMentor === null || defaultMentor === void 0 ? void 0 : defaultMentor.id) {
|
|
11907
|
+
const rbacPermissions = await loadMentorsPermissions(defaultMentor === null || defaultMentor === void 0 ? void 0 : defaultMentor.id);
|
|
11908
|
+
onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
|
|
11909
|
+
}
|
|
11910
|
+
redirectToMentor(tenantKey, defaultMentor.unique_id);
|
|
11911
|
+
onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
|
|
11912
|
+
return;
|
|
11913
|
+
}
|
|
11914
|
+
}
|
|
11915
|
+
// Check for recently accessed mentors (second choice)
|
|
11916
|
+
console.log("checking recently accessed mentors", JSON.stringify({
|
|
11917
|
+
tenantKey,
|
|
11918
|
+
username,
|
|
11919
|
+
}));
|
|
11920
|
+
const recentlyAccessedResult = await getRecentlyAccessedMentors({
|
|
11921
|
+
org: tenantKey,
|
|
11922
|
+
// @ts-ignore
|
|
11923
|
+
userId: username,
|
|
11318
11924
|
});
|
|
11925
|
+
// @ts-ignore
|
|
11926
|
+
const recentlyAccessedMentors = recentlyAccessedResult.data;
|
|
11927
|
+
const starredMentors = recentlyAccessedMentors === null || recentlyAccessedMentors === void 0 ? void 0 : recentlyAccessedMentors.starred_mentors;
|
|
11928
|
+
let recentMentors = recentlyAccessedMentors === null || recentlyAccessedMentors === void 0 ? void 0 : recentlyAccessedMentors.recent_mentors;
|
|
11929
|
+
if (starredMentors.length > 0) {
|
|
11930
|
+
const starredMentor = starredMentors[0];
|
|
11931
|
+
if (starredMentor === null || starredMentor === void 0 ? void 0 : starredMentor.unique_id) {
|
|
11932
|
+
const rbacPermissions = await loadMentorsPermissions(starredMentor === null || starredMentor === void 0 ? void 0 : starredMentor.id);
|
|
11933
|
+
onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
|
|
11934
|
+
redirectToMentor(tenantKey, starredMentor.unique_id);
|
|
11935
|
+
onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
|
|
11936
|
+
return;
|
|
11937
|
+
}
|
|
11938
|
+
}
|
|
11939
|
+
if (recentMentors.length > 0) {
|
|
11940
|
+
const recentMentor = recentMentors[0];
|
|
11941
|
+
if (recentMentor === null || recentMentor === void 0 ? void 0 : recentMentor.unique_id) {
|
|
11942
|
+
const rbacPermissions = await loadMentorsPermissions(recentMentor === null || recentMentor === void 0 ? void 0 : recentMentor.id);
|
|
11943
|
+
onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
|
|
11944
|
+
redirectToMentor(tenantKey, recentMentor.unique_id);
|
|
11945
|
+
onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
|
|
11946
|
+
return;
|
|
11947
|
+
}
|
|
11948
|
+
}
|
|
11319
11949
|
const recentMentorsResult = await fetchMentors({
|
|
11320
11950
|
// @ts-ignore
|
|
11321
11951
|
org: tenantKey,
|
|
@@ -11323,20 +11953,20 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
|
|
|
11323
11953
|
limit: QUERY_LIMIT,
|
|
11324
11954
|
orderBy: "recently_accessed_at",
|
|
11325
11955
|
});
|
|
11326
|
-
|
|
11327
|
-
console.log("recent mentors fetched", {
|
|
11956
|
+
recentMentors = ((_a = recentMentorsResult.data) === null || _a === void 0 ? void 0 : _a.results) || [];
|
|
11957
|
+
console.log("recent mentors fetched", JSON.stringify({
|
|
11328
11958
|
count: recentMentors.length,
|
|
11329
11959
|
mentorIds: recentMentors.map((m) => m === null || m === void 0 ? void 0 : m.unique_id),
|
|
11330
|
-
});
|
|
11960
|
+
}));
|
|
11331
11961
|
// Check if we found recent mentors for the tenant
|
|
11332
11962
|
if (recentMentors.length > 0) {
|
|
11333
11963
|
const selectedMentorId = ((_b = recentMentors[0]) === null || _b === void 0 ? void 0 : _b.unique_id) || "";
|
|
11334
11964
|
const selectedMentorDbId = ((_c = recentMentors[0]) === null || _c === void 0 ? void 0 : _c.id) || "";
|
|
11335
|
-
console.log("redirecting to recent mentor", {
|
|
11965
|
+
console.log("redirecting to recent mentor", JSON.stringify({
|
|
11336
11966
|
selectedMentorId,
|
|
11337
11967
|
mentorName: (_d = recentMentors[0]) === null || _d === void 0 ? void 0 : _d.name,
|
|
11338
11968
|
tenantKey,
|
|
11339
|
-
});
|
|
11969
|
+
}));
|
|
11340
11970
|
const rbacPermissions = await loadMentorsPermissions(selectedMentorDbId);
|
|
11341
11971
|
// Select the most recent mentor as current mentor
|
|
11342
11972
|
onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
|
|
@@ -11538,6 +12168,9 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
|
|
|
11538
12168
|
isAdmin,
|
|
11539
12169
|
});
|
|
11540
12170
|
onAuthFailure === null || onAuthFailure === void 0 ? void 0 : onAuthFailure(`Unexpected error: ${errorMessage}`);
|
|
12171
|
+
console.log("[auth-redirect] Unexpected error in mentor provider", {
|
|
12172
|
+
error: errorMessage,
|
|
12173
|
+
});
|
|
11541
12174
|
redirectToAuthSpa();
|
|
11542
12175
|
}
|
|
11543
12176
|
finally {
|
|
@@ -11545,11 +12178,7 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
|
|
|
11545
12178
|
}
|
|
11546
12179
|
}
|
|
11547
12180
|
async function mentorExistsInTenant(tenantKey, requestedMentorId) {
|
|
11548
|
-
console.log("checking if mentor exists in tenant",
|
|
11549
|
-
tenantKey,
|
|
11550
|
-
requestedMentorId,
|
|
11551
|
-
username,
|
|
11552
|
-
});
|
|
12181
|
+
console.log("checking if mentor exists in tenant", tenantKey, requestedMentorId, username);
|
|
11553
12182
|
try {
|
|
11554
12183
|
const response = await getMentorPublicSettings({
|
|
11555
12184
|
// @ts-ignore
|
|
@@ -11578,11 +12207,7 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
|
|
|
11578
12207
|
// Effect to handle mentor determination when tenant path is determined
|
|
11579
12208
|
React.useEffect(() => {
|
|
11580
12209
|
async function checkMentor() {
|
|
11581
|
-
console.log("starting mentor check process",
|
|
11582
|
-
determineUserPath,
|
|
11583
|
-
requestedMentorId,
|
|
11584
|
-
tenantKey,
|
|
11585
|
-
});
|
|
12210
|
+
console.log("starting mentor check process", determineUserPath, requestedMentorId, tenantKey);
|
|
11586
12211
|
if (userIsAccessingPublicRoute && !requestedMentorId) {
|
|
11587
12212
|
setIsLoading(false);
|
|
11588
12213
|
return;
|
|
@@ -11602,11 +12227,11 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
|
|
|
11602
12227
|
const [mentorExists, requestedMentorDbId] = await mentorExistsInTenant(tenantKey, requestedMentorId);
|
|
11603
12228
|
// If the mentor does not exist in the tenant, redirect the user to the correct mentor
|
|
11604
12229
|
if (!mentorExists) {
|
|
11605
|
-
console.log("requested mentor not found in tenant", {
|
|
12230
|
+
console.log("requested mentor not found in tenant", JSON.stringify({
|
|
11606
12231
|
requestedMentorId,
|
|
11607
12232
|
tenantKey,
|
|
11608
12233
|
hasCustomHandler: !!handleMentorNotFound,
|
|
11609
|
-
});
|
|
12234
|
+
}));
|
|
11610
12235
|
if (handleMentorNotFound) {
|
|
11611
12236
|
console.log("calling custom mentor not found handler");
|
|
11612
12237
|
await handleMentorNotFound();
|
|
@@ -11618,9 +12243,7 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
|
|
|
11618
12243
|
return;
|
|
11619
12244
|
}
|
|
11620
12245
|
else {
|
|
11621
|
-
console.log("requested mentor exists in tenant, proceeding",
|
|
11622
|
-
requestedMentorId,
|
|
11623
|
-
});
|
|
12246
|
+
console.log("requested mentor exists in tenant, proceeding", requestedMentorId);
|
|
11624
12247
|
if (requestedMentorDbId) {
|
|
11625
12248
|
const rbacPermissions = await loadMentorsPermissions(requestedMentorDbId);
|
|
11626
12249
|
onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
|
|
@@ -12092,7 +12715,7 @@ function formatProdErrorMessage(code) {
|
|
|
12092
12715
|
|
|
12093
12716
|
const defaultSessionIds = Object.fromEntries(Object.keys(advancedTabsProperties).map((key) => [key, ""]));
|
|
12094
12717
|
const defaultChatState = Object.fromEntries(Object.keys(advancedTabsProperties).map((key) => [key, []]));
|
|
12095
|
-
const initialState = {
|
|
12718
|
+
const initialState$1 = {
|
|
12096
12719
|
chats: defaultChatState,
|
|
12097
12720
|
isTyping: false,
|
|
12098
12721
|
streaming: false,
|
|
@@ -12120,7 +12743,7 @@ const initialState = {
|
|
|
12120
12743
|
};
|
|
12121
12744
|
const chatSlice = createSlice({
|
|
12122
12745
|
name: "chatSliceShared",
|
|
12123
|
-
initialState,
|
|
12746
|
+
initialState: initialState$1,
|
|
12124
12747
|
reducers: {
|
|
12125
12748
|
setChats: (state, action) => {
|
|
12126
12749
|
state.chats = action.payload;
|
|
@@ -12224,6 +12847,25 @@ const chatSlice = createSlice({
|
|
|
12224
12847
|
setShowingSharedChat: (state, action) => {
|
|
12225
12848
|
state.showingSharedChat = action.payload;
|
|
12226
12849
|
},
|
|
12850
|
+
updateFileUrlInMessage: (state, action) => {
|
|
12851
|
+
const { fileId, fileUrl } = action.payload;
|
|
12852
|
+
// Update all tabs' messages that have this file
|
|
12853
|
+
Object.keys(state.chats).forEach((tab) => {
|
|
12854
|
+
state.chats[tab] = state.chats[tab].map((message) => {
|
|
12855
|
+
if (message.fileAttachments && message.fileAttachments.length > 0) {
|
|
12856
|
+
const updatedAttachments = message.fileAttachments.map((attachment) => {
|
|
12857
|
+
// Match by fileId
|
|
12858
|
+
if (attachment.fileId === fileId) {
|
|
12859
|
+
return { ...attachment, uploadUrl: fileUrl };
|
|
12860
|
+
}
|
|
12861
|
+
return attachment;
|
|
12862
|
+
});
|
|
12863
|
+
return { ...message, fileAttachments: updatedAttachments };
|
|
12864
|
+
}
|
|
12865
|
+
return message;
|
|
12866
|
+
});
|
|
12867
|
+
});
|
|
12868
|
+
},
|
|
12227
12869
|
},
|
|
12228
12870
|
});
|
|
12229
12871
|
const chatActions = chatSlice.actions;
|
|
@@ -12507,6 +13149,61 @@ function useTimeTrackerNative(config) {
|
|
|
12507
13149
|
};
|
|
12508
13150
|
}
|
|
12509
13151
|
|
|
13152
|
+
const initialState = {
|
|
13153
|
+
attachedFiles: [],
|
|
13154
|
+
};
|
|
13155
|
+
const filesSlice = createSlice({
|
|
13156
|
+
name: "files",
|
|
13157
|
+
initialState,
|
|
13158
|
+
reducers: {
|
|
13159
|
+
addFiles: (state, action) => {
|
|
13160
|
+
state.attachedFiles = [...state.attachedFiles, ...action.payload];
|
|
13161
|
+
},
|
|
13162
|
+
updateFileProgress: (state, action) => {
|
|
13163
|
+
state.attachedFiles = state.attachedFiles.map((file) => file.id === action.payload.id
|
|
13164
|
+
? { ...file, uploadProgress: action.payload.progress }
|
|
13165
|
+
: file);
|
|
13166
|
+
},
|
|
13167
|
+
updateFileStatus: (state, action) => {
|
|
13168
|
+
state.attachedFiles = state.attachedFiles.map((file) => file.id === action.payload.id
|
|
13169
|
+
? { ...file, uploadStatus: action.payload.status }
|
|
13170
|
+
: file);
|
|
13171
|
+
},
|
|
13172
|
+
updateFileUrl: (state, action) => {
|
|
13173
|
+
state.attachedFiles = state.attachedFiles.map((file) => file.id === action.payload.id
|
|
13174
|
+
? { ...file, uploadUrl: action.payload.uploadUrl }
|
|
13175
|
+
: file);
|
|
13176
|
+
},
|
|
13177
|
+
updateFileMetadata: (state, action) => {
|
|
13178
|
+
state.attachedFiles = state.attachedFiles.map((file) => file.id === action.payload.id
|
|
13179
|
+
? {
|
|
13180
|
+
...file,
|
|
13181
|
+
fileKey: action.payload.fileKey,
|
|
13182
|
+
fileId: action.payload.fileId,
|
|
13183
|
+
}
|
|
13184
|
+
: file);
|
|
13185
|
+
},
|
|
13186
|
+
updateFileRetryCount: (state, action) => {
|
|
13187
|
+
state.attachedFiles = state.attachedFiles.map((file) => file.id === action.payload.id
|
|
13188
|
+
? { ...file, retryCount: action.payload.retryCount }
|
|
13189
|
+
: file);
|
|
13190
|
+
},
|
|
13191
|
+
updateFileUrlFromWebSocket: (state, action) => {
|
|
13192
|
+
state.attachedFiles = state.attachedFiles.map((file) => file.fileId === action.payload.fileId
|
|
13193
|
+
? { ...file, fileUrl: action.payload.fileUrl }
|
|
13194
|
+
: file);
|
|
13195
|
+
},
|
|
13196
|
+
removeFile: (state, action) => {
|
|
13197
|
+
state.attachedFiles = state.attachedFiles.filter((file) => file.id !== action.payload);
|
|
13198
|
+
},
|
|
13199
|
+
clearFiles: (state) => {
|
|
13200
|
+
state.attachedFiles = [];
|
|
13201
|
+
},
|
|
13202
|
+
},
|
|
13203
|
+
});
|
|
13204
|
+
const { addFiles, removeFile, clearFiles, updateFileProgress, updateFileStatus, updateFileUrl, updateFileMetadata, updateFileRetryCount, updateFileUrlFromWebSocket, } = filesSlice.actions;
|
|
13205
|
+
const filesReducer = filesSlice.reducer;
|
|
13206
|
+
|
|
12510
13207
|
const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, enableHaptics = false, hapticFeedback, store, errorHandler, onStatusChange, onStreamingChange, onStreamingMessageUpdate, WebSocketImpl = WebSocket, redirectToAuthSpa, sendMessageToParentWebsite, on402Error, }) => {
|
|
12511
13208
|
const dispatch = useDispatch();
|
|
12512
13209
|
const isWebSocketPaused = React.useRef(false);
|
|
@@ -12542,8 +13239,8 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12542
13239
|
}
|
|
12543
13240
|
if (!wsToken) {
|
|
12544
13241
|
if (!userIsAccessingPublicRoute) {
|
|
12545
|
-
console.
|
|
12546
|
-
redirectToAuthSpa();
|
|
13242
|
+
console.log("[auth-redirect] WebSocket token is missing for non-anonymous user");
|
|
13243
|
+
redirectToAuthSpa(undefined, undefined, true);
|
|
12547
13244
|
return;
|
|
12548
13245
|
}
|
|
12549
13246
|
}
|
|
@@ -12598,6 +13295,16 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12598
13295
|
onStreamingChange(!!messageData.isTyping);
|
|
12599
13296
|
return;
|
|
12600
13297
|
}
|
|
13298
|
+
// Handle file processing success
|
|
13299
|
+
if (messageData.type === "file_processing_success") {
|
|
13300
|
+
console.log("🟣 File processing success:", messageData);
|
|
13301
|
+
dispatch(chatActions.updateFileUrlInMessage({
|
|
13302
|
+
fileId: messageData.file_id,
|
|
13303
|
+
fileName: messageData.file_name,
|
|
13304
|
+
fileUrl: messageData.file_url,
|
|
13305
|
+
}));
|
|
13306
|
+
return;
|
|
13307
|
+
}
|
|
12601
13308
|
// Handle start of new streaming session
|
|
12602
13309
|
if (messageData.generation_id &&
|
|
12603
13310
|
!messageData.data &&
|
|
@@ -12693,19 +13400,31 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12693
13400
|
};
|
|
12694
13401
|
};
|
|
12695
13402
|
const sendMessage = React.useCallback(async (tab, text, options) => {
|
|
12696
|
-
var _a;
|
|
13403
|
+
var _a, _b;
|
|
12697
13404
|
dispatch(chatActions.setShowingSharedChat(false));
|
|
12698
|
-
if
|
|
13405
|
+
// Allow sending if there's text OR file references
|
|
13406
|
+
if (!text.trim() &&
|
|
13407
|
+
(!(options === null || options === void 0 ? void 0 : options.fileReferences) || options.fileReferences.length === 0)) {
|
|
12699
13408
|
return;
|
|
13409
|
+
}
|
|
12700
13410
|
onStatusChange("pending");
|
|
12701
13411
|
isWebSocketPaused.current = false;
|
|
12702
13412
|
await triggerHapticFeedback();
|
|
13413
|
+
// Create file attachments array from file references if present
|
|
13414
|
+
const fileAttachments = (_a = options === null || options === void 0 ? void 0 : options.fileReferences) === null || _a === void 0 ? void 0 : _a.map((ref) => ({
|
|
13415
|
+
fileName: ref.file_name,
|
|
13416
|
+
fileType: ref.content_type,
|
|
13417
|
+
fileSize: ref.file_size,
|
|
13418
|
+
uploadUrl: ref.upload_url, // Include URL for display
|
|
13419
|
+
fileId: ref.file_id, // Include fileId for matching WebSocket updates
|
|
13420
|
+
}));
|
|
12703
13421
|
const userMessage = {
|
|
12704
13422
|
id: `user-${Date.now()}`,
|
|
12705
13423
|
role: "user",
|
|
12706
13424
|
content: text,
|
|
12707
13425
|
timestamp: new Date().toISOString(),
|
|
12708
|
-
visible: (
|
|
13426
|
+
visible: (_b = options === null || options === void 0 ? void 0 : options.visible) !== null && _b !== void 0 ? _b : true,
|
|
13427
|
+
fileAttachments,
|
|
12709
13428
|
};
|
|
12710
13429
|
// Notify parent to add user message
|
|
12711
13430
|
// onAddUserMessage?.(tab, userMessage);
|
|
@@ -12717,8 +13436,14 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
|
|
|
12717
13436
|
flow: flowConfig,
|
|
12718
13437
|
session_id: sessionId,
|
|
12719
13438
|
token: wsToken,
|
|
12720
|
-
prompt: text,
|
|
13439
|
+
prompt: text || "", // Allow empty prompt when sending files
|
|
12721
13440
|
};
|
|
13441
|
+
if ((options === null || options === void 0 ? void 0 : options.fileReferences) && options.fileReferences.length > 0) {
|
|
13442
|
+
messageData = {
|
|
13443
|
+
...messageData,
|
|
13444
|
+
file_references: options.fileReferences,
|
|
13445
|
+
};
|
|
13446
|
+
}
|
|
12722
13447
|
if (iframeContext.pageContent) {
|
|
12723
13448
|
messageData = {
|
|
12724
13449
|
...messageData,
|
|
@@ -12903,7 +13628,7 @@ function useMentorSettings({ mentorId, tenantKey, username }) {
|
|
|
12903
13628
|
};
|
|
12904
13629
|
}
|
|
12905
13630
|
|
|
12906
|
-
function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, token, wsUrl, stopGenerationWsUrl, redirectToAuthSpa, errorHandler, sendMessageToParentWebsite, isPreviewMode, mentorShareableToken, on402Error, }) {
|
|
13631
|
+
function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, token, wsUrl, stopGenerationWsUrl, redirectToAuthSpa, errorHandler, sendMessageToParentWebsite, isPreviewMode, mentorShareableToken, on402Error, cachedSessionId, onStartNewChat, }) {
|
|
12907
13632
|
var _a, _b, _c, _d;
|
|
12908
13633
|
const dispatch = useDispatch();
|
|
12909
13634
|
const [createSessionId, { isLoading: isLoadingSessionIds }] = useCreateSessionIdMutation();
|
|
@@ -12942,7 +13667,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
12942
13667
|
username,
|
|
12943
13668
|
pathway: mentorId,
|
|
12944
13669
|
},
|
|
12945
|
-
sessionId: sessionIds[activeTab],
|
|
13670
|
+
sessionId: cachedSessionId !== null && cachedSessionId !== void 0 ? cachedSessionId : sessionIds[activeTab],
|
|
12946
13671
|
activeTab,
|
|
12947
13672
|
wsToken: token,
|
|
12948
13673
|
errorHandler,
|
|
@@ -12953,6 +13678,49 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
12953
13678
|
onStatusChange,
|
|
12954
13679
|
on402Error,
|
|
12955
13680
|
});
|
|
13681
|
+
const [getSessionChats, { isError: isErrorGettingSessionChats }] = useLazyGetSessionIdQuery();
|
|
13682
|
+
React.useEffect(() => {
|
|
13683
|
+
const getChats = async () => {
|
|
13684
|
+
var _a;
|
|
13685
|
+
try {
|
|
13686
|
+
const { data } = await getSessionChats({
|
|
13687
|
+
sessionId: cachedSessionId !== null && cachedSessionId !== void 0 ? cachedSessionId : "",
|
|
13688
|
+
org: tenantKey,
|
|
13689
|
+
share: true,
|
|
13690
|
+
});
|
|
13691
|
+
let previousChats = [];
|
|
13692
|
+
try {
|
|
13693
|
+
previousChats =
|
|
13694
|
+
((_a = data === null || data === void 0 ? void 0 : data.results) === null || _a === void 0 ? void 0 : _a.map((result) => {
|
|
13695
|
+
return {
|
|
13696
|
+
...result,
|
|
13697
|
+
role: result.type === "human" ? "user" : "assistant",
|
|
13698
|
+
visible: true,
|
|
13699
|
+
id: new Date().getTime(),
|
|
13700
|
+
content: typeof result.content === "object" &&
|
|
13701
|
+
result.content.length > 0
|
|
13702
|
+
? result.content[0].text
|
|
13703
|
+
: result.content,
|
|
13704
|
+
};
|
|
13705
|
+
}).reverse()) || [];
|
|
13706
|
+
}
|
|
13707
|
+
catch (error) {
|
|
13708
|
+
console.error(JSON.stringify(error));
|
|
13709
|
+
}
|
|
13710
|
+
dispatch(chatActions.setNewMessages(previousChats));
|
|
13711
|
+
}
|
|
13712
|
+
catch (error) {
|
|
13713
|
+
console.error(JSON.stringify(error));
|
|
13714
|
+
}
|
|
13715
|
+
};
|
|
13716
|
+
if (cachedSessionId) {
|
|
13717
|
+
dispatch(chatActions.updateSessionIds(cachedSessionId));
|
|
13718
|
+
getChats();
|
|
13719
|
+
}
|
|
13720
|
+
}, [cachedSessionId]);
|
|
13721
|
+
React.useEffect(() => {
|
|
13722
|
+
}, [isErrorGettingSessionChats]);
|
|
13723
|
+
React.useEffect(() => { }, []);
|
|
12956
13724
|
const startNewChat = React.useCallback(async () => {
|
|
12957
13725
|
// Reset all chat state
|
|
12958
13726
|
if (!showingSharedChat) {
|
|
@@ -12962,6 +13730,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
12962
13730
|
dispatch(chatActions.setStreaming(false));
|
|
12963
13731
|
dispatch(chatActions.resetCurrentStreamingMessage(undefined));
|
|
12964
13732
|
dispatch(chatActions.setTools([]));
|
|
13733
|
+
dispatch(clearFiles(undefined));
|
|
12965
13734
|
if (isPreviewMode) {
|
|
12966
13735
|
return;
|
|
12967
13736
|
}
|
|
@@ -12972,6 +13741,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
12972
13741
|
// @ts-ignore
|
|
12973
13742
|
requestBody["shareable_link_token"] = mentorShareableToken;
|
|
12974
13743
|
}
|
|
13744
|
+
console.log("[startNewChat] requestBody", tenantKey, username, JSON.stringify(requestBody));
|
|
12975
13745
|
const response = await createSessionId({
|
|
12976
13746
|
org: tenantKey,
|
|
12977
13747
|
// @ts-ignore
|
|
@@ -12979,10 +13749,12 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
12979
13749
|
requestBody,
|
|
12980
13750
|
}).unwrap();
|
|
12981
13751
|
dispatch(chatActions.updateSessionIds(response.session_id));
|
|
12982
|
-
|
|
13752
|
+
onStartNewChat === null || onStartNewChat === void 0 ? void 0 : onStartNewChat(response.session_id);
|
|
12983
13753
|
}
|
|
12984
13754
|
catch (error) {
|
|
12985
|
-
errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler(
|
|
13755
|
+
errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler(`Failed to start new chat: ${JSON.stringify(error)}`);
|
|
13756
|
+
console.log("[auth-redirect] Failed to start new chat", JSON.stringify({ error }));
|
|
13757
|
+
redirectToAuthSpa(undefined, undefined, true);
|
|
12986
13758
|
}
|
|
12987
13759
|
}, [
|
|
12988
13760
|
isPreviewMode,
|
|
@@ -12996,7 +13768,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
12996
13768
|
]);
|
|
12997
13769
|
React.useEffect(() => {
|
|
12998
13770
|
if (!showingSharedChat || mentorSettings.allowAnonymous) {
|
|
12999
|
-
if (mentorSettings.allowAnonymous !== undefined) {
|
|
13771
|
+
if (mentorSettings.allowAnonymous !== undefined && !cachedSessionId) {
|
|
13000
13772
|
startNewChat();
|
|
13001
13773
|
}
|
|
13002
13774
|
}
|
|
@@ -13048,7 +13820,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
|
|
|
13048
13820
|
}
|
|
13049
13821
|
}
|
|
13050
13822
|
catch (error) {
|
|
13051
|
-
errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler(
|
|
13823
|
+
errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler(`Failed to start new chat: ${error}`);
|
|
13052
13824
|
return;
|
|
13053
13825
|
}
|
|
13054
13826
|
}
|
|
@@ -17938,11 +18710,130 @@ const tenantSchema = z.object({
|
|
|
17938
18710
|
});
|
|
17939
18711
|
const tenantKeySchema = z.string().min(1);
|
|
17940
18712
|
|
|
18713
|
+
/**
|
|
18714
|
+
* Chat area size constants
|
|
18715
|
+
*/
|
|
18716
|
+
const CHAT_AREA_SIZE = {
|
|
18717
|
+
DEFAULT: 672,
|
|
18718
|
+
MIN: 672,
|
|
18719
|
+
MAX: 1024,
|
|
18720
|
+
};
|
|
18721
|
+
|
|
18722
|
+
/**
|
|
18723
|
+
* Extract file information from File object
|
|
18724
|
+
*/
|
|
18725
|
+
function getFileInfo(file) {
|
|
18726
|
+
const fileName = file.name;
|
|
18727
|
+
const contentType = file.type || "application/octet-stream";
|
|
18728
|
+
const fileSize = file.size;
|
|
18729
|
+
return {
|
|
18730
|
+
fileName,
|
|
18731
|
+
contentType,
|
|
18732
|
+
fileSize,
|
|
18733
|
+
};
|
|
18734
|
+
}
|
|
18735
|
+
/**
|
|
18736
|
+
* Request presigned S3 URL from backend
|
|
18737
|
+
* Note: This function should be called via the RTK Query mutation hook
|
|
18738
|
+
* This is a helper to show the data flow
|
|
18739
|
+
*/
|
|
18740
|
+
async function requestPresignedUrl(sessionId, file, getUploadUrlFn, org, userId) {
|
|
18741
|
+
const { fileName, contentType, fileSize } = getFileInfo(file);
|
|
18742
|
+
return await getUploadUrlFn({
|
|
18743
|
+
org,
|
|
18744
|
+
userId,
|
|
18745
|
+
requestBody: {
|
|
18746
|
+
session_id: sessionId,
|
|
18747
|
+
file_name: fileName,
|
|
18748
|
+
content_type: contentType,
|
|
18749
|
+
file_size: fileSize,
|
|
18750
|
+
},
|
|
18751
|
+
});
|
|
18752
|
+
}
|
|
18753
|
+
/**
|
|
18754
|
+
* Upload file directly to S3 using presigned URL
|
|
18755
|
+
* Uses axios for cross-platform support (web + React Native)
|
|
18756
|
+
*/
|
|
18757
|
+
async function uploadToS3(presignedUrl, file, contentType, onProgress) {
|
|
18758
|
+
await axios.put(presignedUrl, file, {
|
|
18759
|
+
headers: {
|
|
18760
|
+
"Content-Type": contentType,
|
|
18761
|
+
},
|
|
18762
|
+
onUploadProgress: (progressEvent) => {
|
|
18763
|
+
if (onProgress && progressEvent.total) {
|
|
18764
|
+
const progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);
|
|
18765
|
+
onProgress(progress);
|
|
18766
|
+
}
|
|
18767
|
+
},
|
|
18768
|
+
});
|
|
18769
|
+
}
|
|
18770
|
+
/**
|
|
18771
|
+
* Complete file upload flow:
|
|
18772
|
+
* 1. Request presigned URL
|
|
18773
|
+
* 2. Upload to S3
|
|
18774
|
+
* 3. Return file reference
|
|
18775
|
+
*/
|
|
18776
|
+
async function createFileReference(file, sessionId, getUploadUrlFn, org, userId, onProgress) {
|
|
18777
|
+
// Step 1: Get presigned URL
|
|
18778
|
+
const presignedResponse = await requestPresignedUrl(sessionId, file, getUploadUrlFn, org, userId);
|
|
18779
|
+
// Step 2: Upload to S3
|
|
18780
|
+
const { fileName, contentType, fileSize } = getFileInfo(file);
|
|
18781
|
+
await uploadToS3(presignedResponse.upload_url, file, contentType, onProgress);
|
|
18782
|
+
// Step 3: Return file reference
|
|
18783
|
+
return {
|
|
18784
|
+
file_id: presignedResponse.file_id,
|
|
18785
|
+
file_key: presignedResponse.file_key,
|
|
18786
|
+
file_name: fileName,
|
|
18787
|
+
content_type: contentType,
|
|
18788
|
+
file_size: fileSize,
|
|
18789
|
+
};
|
|
18790
|
+
}
|
|
18791
|
+
/**
|
|
18792
|
+
* Upload multiple files and return their references
|
|
18793
|
+
*/
|
|
18794
|
+
async function createMultipleFileReferences(files, sessionId, getUploadUrlFn, org, userId, onFileProgress) {
|
|
18795
|
+
const fileReferences = [];
|
|
18796
|
+
for (let i = 0; i < files.length; i++) {
|
|
18797
|
+
const file = files[i];
|
|
18798
|
+
const onProgress = onFileProgress
|
|
18799
|
+
? (progress) => onFileProgress(i, progress)
|
|
18800
|
+
: undefined;
|
|
18801
|
+
const fileReference = await createFileReference(file, sessionId, getUploadUrlFn, org, userId, onProgress);
|
|
18802
|
+
fileReferences.push(fileReference);
|
|
18803
|
+
}
|
|
18804
|
+
return fileReferences;
|
|
18805
|
+
}
|
|
18806
|
+
/**
|
|
18807
|
+
* Validate file before upload
|
|
18808
|
+
* Returns error message if invalid, null if valid
|
|
18809
|
+
*/
|
|
18810
|
+
function validateFile(file, maxSizeBytes, allowedTypes) {
|
|
18811
|
+
var _a;
|
|
18812
|
+
// Check file size
|
|
18813
|
+
if (maxSizeBytes && file.size > maxSizeBytes) {
|
|
18814
|
+
const maxSizeMB = (maxSizeBytes / (1024 * 1024)).toFixed(2);
|
|
18815
|
+
const fileSizeMB = (file.size / (1024 * 1024)).toFixed(2);
|
|
18816
|
+
return `File size (${fileSizeMB}MB) exceeds maximum allowed size (${maxSizeMB}MB)`;
|
|
18817
|
+
}
|
|
18818
|
+
// Check file type
|
|
18819
|
+
if (allowedTypes && allowedTypes.length > 0) {
|
|
18820
|
+
const fileExtension = (_a = file.name.split(".").pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
18821
|
+
const fileType = file.type.toLowerCase();
|
|
18822
|
+
const isTypeAllowed = allowedTypes.some((allowed) => fileType.includes(allowed.toLowerCase()) ||
|
|
18823
|
+
fileExtension === allowed.toLowerCase().replace(".", ""));
|
|
18824
|
+
if (!isTypeAllowed) {
|
|
18825
|
+
return `File type not allowed. Allowed types: ${allowedTypes.join(", ")}`;
|
|
18826
|
+
}
|
|
18827
|
+
}
|
|
18828
|
+
return null;
|
|
18829
|
+
}
|
|
18830
|
+
|
|
17941
18831
|
exports.ALPHANUMERIC_32_REGEX = ALPHANUMERIC_32_REGEX;
|
|
17942
18832
|
exports.ANONYMOUS_USERNAME = ANONYMOUS_USERNAME;
|
|
17943
18833
|
exports.AuthContext = AuthContext;
|
|
17944
18834
|
exports.AuthContextProvider = AuthContextProvider;
|
|
17945
18835
|
exports.AuthProvider = AuthProvider;
|
|
18836
|
+
exports.CHAT_AREA_SIZE = CHAT_AREA_SIZE;
|
|
17946
18837
|
exports.LOCAL_STORAGE_KEYS = LOCAL_STORAGE_KEYS;
|
|
17947
18838
|
exports.MAX_INITIAL_WEBSOCKET_CONNECTION_ATTEMPTS = MAX_INITIAL_WEBSOCKET_CONNECTION_ATTEMPTS;
|
|
17948
18839
|
exports.MENTOR_CHAT_DOCUMENTS_EXTENSIONS = MENTOR_CHAT_DOCUMENTS_EXTENSIONS;
|
|
@@ -17959,20 +18850,42 @@ exports.TenantContext = TenantContext;
|
|
|
17959
18850
|
exports.TenantContextProvider = TenantContextProvider;
|
|
17960
18851
|
exports.TenantProvider = TenantProvider;
|
|
17961
18852
|
exports.TimeTracker = TimeTracker;
|
|
18853
|
+
exports.addFiles = addFiles;
|
|
17962
18854
|
exports.addProtocolToUrl = addProtocolToUrl;
|
|
17963
18855
|
exports.advancedTabs = advancedTabs;
|
|
17964
18856
|
exports.advancedTabsProperties = advancedTabsProperties;
|
|
17965
18857
|
exports.chatActions = chatActions;
|
|
17966
18858
|
exports.chatSliceReducerShared = chatSliceReducerShared;
|
|
17967
18859
|
exports.clearAuthCookies = clearAuthCookies;
|
|
18860
|
+
exports.clearCookies = clearCookies;
|
|
18861
|
+
exports.clearCurrentTenantCookie = clearCurrentTenantCookie;
|
|
18862
|
+
exports.clearFiles = clearFiles;
|
|
18863
|
+
exports.createFileReference = createFileReference;
|
|
18864
|
+
exports.createMultipleFileReferences = createMultipleFileReferences;
|
|
17968
18865
|
exports.defaultSessionIds = defaultSessionIds;
|
|
18866
|
+
exports.deleteCookie = deleteCookie;
|
|
18867
|
+
exports.deleteCookieOnAllDomains = deleteCookieOnAllDomains;
|
|
18868
|
+
exports.filesReducer = filesReducer;
|
|
18869
|
+
exports.filesSlice = filesSlice;
|
|
17969
18870
|
exports.formatRelativeTime = formatRelativeTime;
|
|
18871
|
+
exports.getAuthSpaJoinUrl = getAuthSpaJoinUrl;
|
|
18872
|
+
exports.getDomainParts = getDomainParts;
|
|
18873
|
+
exports.getFileInfo = getFileInfo;
|
|
17970
18874
|
exports.getInitials = getInitials;
|
|
18875
|
+
exports.getParentDomain = getParentDomain;
|
|
18876
|
+
exports.getPlatformKey = getPlatformKey;
|
|
17971
18877
|
exports.getTimeAgo = getTimeAgo;
|
|
17972
18878
|
exports.getUserName = getUserName;
|
|
18879
|
+
exports.handleLogout = handleLogout;
|
|
17973
18880
|
exports.isAlphaNumeric32 = isAlphaNumeric32;
|
|
18881
|
+
exports.isInIframe = isInIframe;
|
|
17974
18882
|
exports.isJSON = isJSON;
|
|
18883
|
+
exports.isLoggedIn = isLoggedIn;
|
|
17975
18884
|
exports.loadMetadataConfig = loadMetadataConfig;
|
|
18885
|
+
exports.redirectToAuthSpa = redirectToAuthSpa;
|
|
18886
|
+
exports.redirectToAuthSpaJoinTenant = redirectToAuthSpaJoinTenant;
|
|
18887
|
+
exports.removeFile = removeFile;
|
|
18888
|
+
exports.requestPresignedUrl = requestPresignedUrl;
|
|
17976
18889
|
exports.selectActiveChatMessages = selectActiveChatMessages;
|
|
17977
18890
|
exports.selectActiveTab = selectActiveTab;
|
|
17978
18891
|
exports.selectChats = selectChats;
|
|
@@ -17993,10 +18906,19 @@ exports.selectStreaming = selectStreaming;
|
|
|
17993
18906
|
exports.selectToken = selectToken;
|
|
17994
18907
|
exports.selectTokenEnabled = selectTokenEnabled;
|
|
17995
18908
|
exports.selectTools = selectTools;
|
|
18909
|
+
exports.sendMessageToParentWebsite = sendMessageToParentWebsite;
|
|
18910
|
+
exports.setCookieForAuth = setCookieForAuth;
|
|
17996
18911
|
exports.syncAuthToCookies = syncAuthToCookies;
|
|
17997
18912
|
exports.tenantKeySchema = tenantKeySchema;
|
|
17998
18913
|
exports.tenantSchema = tenantSchema;
|
|
17999
18914
|
exports.translatePrompt = translatePrompt;
|
|
18915
|
+
exports.updateFileMetadata = updateFileMetadata;
|
|
18916
|
+
exports.updateFileProgress = updateFileProgress;
|
|
18917
|
+
exports.updateFileRetryCount = updateFileRetryCount;
|
|
18918
|
+
exports.updateFileStatus = updateFileStatus;
|
|
18919
|
+
exports.updateFileUrl = updateFileUrl;
|
|
18920
|
+
exports.updateFileUrlFromWebSocket = updateFileUrlFromWebSocket;
|
|
18921
|
+
exports.uploadToS3 = uploadToS3;
|
|
18000
18922
|
exports.useAdvancedChat = useAdvancedChat;
|
|
18001
18923
|
exports.useAuthContext = useAuthContext;
|
|
18002
18924
|
exports.useAuthProvider = useAuthProvider;
|
|
@@ -18014,4 +18936,5 @@ exports.useTimeTracker = useTimeTracker;
|
|
|
18014
18936
|
exports.useTimeTrackerNative = useTimeTrackerNative;
|
|
18015
18937
|
exports.useUserProfileUpdate = useUserProfileUpdate;
|
|
18016
18938
|
exports.userDataSchema = userDataSchema;
|
|
18939
|
+
exports.validateFile = validateFile;
|
|
18017
18940
|
//# sourceMappingURL=index.js.map
|