@iblai/iblai-js 2.3.4 → 2.3.6

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.
@@ -1,9 +1,9 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { useRef, useEffect, useState, useCallback, useLayoutEffect, forwardRef, createElement as createElement$1, createContext, useContext, useMemo, useReducer, useImperativeHandle, isValidElement, Children, PureComponent, cloneElement, Component, useId as useId$2, useDebugValue, lazy, Suspense } from 'react';
3
3
  import { useDispatch, useSelector } from 'react-redux';
4
- import { selectSessionId, selectActiveChatMessages, useCachedSessionId, chatActions, LOCAL_STORAGE_KEYS, TimeTracker, getInitials, useTenantMetadata, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, getTimeAgo, REQUIRED_ACTIONS_FOR_GROUPS, formatRelativeTime as formatRelativeTime$2, ANONYMOUS_USERNAME, combineCSVData, redirectToAuthSpaJoinTenant, redirectToAuthSpa, getAuthSpaJoinUrl, useOS, selectNumberOfActiveChatMessages, useUsername, selectStreaming, isLoggedIn, TOOLS, hasRemoteAiConfig, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, selectRbacPermissions, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, chatInputSliceActions, removeFile, WithFormPermissions, MENTOR_VISIBILITY } from '@iblai/web-utils';
4
+ import { selectSessionId, selectActiveChatMessages, useCachedSessionId, chatActions, LOCAL_STORAGE_KEYS, TimeTracker, getInitials, useTenantMetadata, useCurrentTenant, selectRbacPermissions, isPureWatcher, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, getTimeAgo, REQUIRED_ACTIONS_FOR_GROUPS, getVisibleAnalyticsTabs, formatRelativeTime as formatRelativeTime$2, ANONYMOUS_USERNAME, combineCSVData, WATCHER_HIDDEN_REPORTS, redirectToAuthSpaJoinTenant, redirectToAuthSpa, getAuthSpaJoinUrl, useOS, selectNumberOfActiveChatMessages, useUsername, selectStreaming, isLoggedIn, TOOLS, hasRemoteAiConfig, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, chatInputSliceActions, removeFile, WithFormPermissions, MENTOR_VISIBILITY } from '@iblai/web-utils';
5
5
  import * as dataLayer from '@iblai/data-layer';
6
- import { useCreateSessionIdMutation, useTimeTrackingMutation, useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useDeleteGlobalMemoryMutation, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useUpdateTenantMetadataMutation, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useGetAiSearchMentorsQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetNotificationsCountQuery, useLazyGetNotificationsQuery, useMarkAllAsReadMutation, useCreateNotificationPreviewMutation, useSendNotificationMutation, useGetMentorsQuery, useUpdateTemplateMutation, useGetTemplateDetailsQuery, useGetTemplatesQuery, useLazyGetTemplateDetailsQuery, useToggleTemplateMutation, useGetTopicsStatsQuery, useGetUsersStatsQuery, useGetSessionStatsQuery, useGetTopicsDetailsStatsQuery, useGetAccessTimeHeatmapQuery, useGetUserDetailsStatsQuery, useGetTranscriptsConversationHeadlineQuery, useGetAverageRatingQuery, useGetFinancialStatsQuery, useGetDetailedFinancialStatsQuery, useGetTranscriptsMessagesDetailsQuery, useGetTranscriptsMessagesQuery, useGetReportDetailQuery, useLazyGetDownloadReportFromURLQuery, useGetMentorPublicSettingsQuery, useGetReportsQuery, useCreateReportMutation, useGetContentAnalyticsQuery, useGetContentAnalyticsDetailsQuery, useGetRevenueQuery, useListSubscribersQuery, useGetAuditLogsQuery, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetUserEnrolledCoursesQuery, useLazyGetUserAssignedCoursesQuery, useLazyGetUserCredentialsQuery, useLazyGetOverTimeActivityQuery, useLazyGetCatalogSearchQuery, useCreateOrUpdateUserReportedSkillMutation, useCreateOrUpdateUserDesiredSkillMutation, useLazyGetPathwayListQuery, useLazyGetUserAssignedPathwaysQuery, useLazyGetUserEnrolledPathwaysQuery, useLazyGetPathwayCompletionQuery, useLazyGetProgramListQuery, useLazyGetProgramCompletionQuery, useLazyGetUserEnrolledProgramsQuery, useLazyGetAssignedProgramsQuery, useLazyGetUserSkillsPointsQuery, useLazyGetUserReportedSkillsQuery, useLazyGetUserDesiredSkillsQuery, useLazyGetUserCatalogPathwaysQuery, useLazyGetPerLearnerInfoQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useLazyGetPersonnalizedSearchQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetClawMentorConfigQuery, useGetClawInstancesQuery, useGetAgentConfigQuery, useUpdateClawMentorConfigMutation, useCreateClawMentorConfigMutation, useDeleteClawMentorConfigMutation, usePushClawConfigMutation, useCreateClawInstanceMutation, useDeleteClawInstanceMutation, useUpdateAgentConfigMutation, useHealthCheckClawInstanceMutation, useTestConnectivityClawInstanceMutation, useUpdateClawInstanceMutation, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetAgentSkillsQuery, useGetMentorSkillAssignmentsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, resolveEffectiveAgentSkills, filterSlashSkills, useCreateCheckoutMutation, useGetUserProjectsQuery, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useDeleteMentorMemoryMutation, useUpdateMentorMemoryMutation, useCreateMentorMemoryMutation, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useGetMentorCategoriesQuery, useCreateMentorMutation, useUpdateUserPlatformMetadataMutation, useGetApplicationStatusQuery, useListOwnApplicationsQuery, useGetApplicationFormQuery, useWithdrawApplicationMutation, useRenewApplicationMutation, useCreateApplicationDraftMutation, useSubmitApplicationMutation, useUpdateApplicationMutation, useUploadApplicationAttachmentMutation, useDeleteApplicationAttachmentMutation, useGetPromptCategoriesQuery, useCreatePromptMutation, useDeletePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation } from '@iblai/data-layer';
6
+ import { useCreateSessionIdMutation, useTimeTrackingMutation, useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, useGetAccessibleUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useUpdateTenantMetadataMutation, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useGetAiSearchMentorsQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetNotificationsCountQuery, useLazyGetNotificationsQuery, useMarkAllAsReadMutation, useCreateNotificationPreviewMutation, useSendNotificationMutation, useGetMentorsQuery, useUpdateTemplateMutation, useGetTemplateDetailsQuery, useGetTemplatesQuery, useLazyGetTemplateDetailsQuery, useToggleTemplateMutation, useGetTopicsStatsQuery, useGetUsersStatsQuery, useGetSessionStatsQuery, useGetTopicsDetailsStatsQuery, useGetAccessTimeHeatmapQuery, useGetUserDetailsStatsQuery, useGetTranscriptsConversationHeadlineQuery, useGetAverageRatingQuery, useGetFinancialStatsQuery, useGetDetailedFinancialStatsQuery, useGetTranscriptsMessagesDetailsQuery, useGetTranscriptsMessagesQuery, useGetReportDetailQuery, useLazyGetDownloadReportFromURLQuery, useGetMentorPublicSettingsQuery, useGetReportsQuery, useCreateReportMutation, useGetContentAnalyticsQuery, useGetContentAnalyticsDetailsQuery, useGetRevenueQuery, useListSubscribersQuery, useGetAuditLogsQuery, useGetMentorMemoriesListQuery, useGetMentorMemoriesQuery, useGetMemoryCategoriesAdminQuery, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetUserEnrolledCoursesQuery, useLazyGetUserAssignedCoursesQuery, useLazyGetUserCredentialsQuery, useLazyGetOverTimeActivityQuery, useLazyGetCatalogSearchQuery, useCreateOrUpdateUserReportedSkillMutation, useCreateOrUpdateUserDesiredSkillMutation, useLazyGetPathwayListQuery, useLazyGetUserAssignedPathwaysQuery, useLazyGetUserEnrolledPathwaysQuery, useLazyGetPathwayCompletionQuery, useLazyGetProgramListQuery, useLazyGetProgramCompletionQuery, useLazyGetUserEnrolledProgramsQuery, useLazyGetAssignedProgramsQuery, useLazyGetUserSkillsPointsQuery, useLazyGetUserReportedSkillsQuery, useLazyGetUserDesiredSkillsQuery, useLazyGetUserCatalogPathwaysQuery, useLazyGetPerLearnerInfoQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useLazyGetPersonnalizedSearchQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetClawMentorConfigQuery, useGetClawInstancesQuery, useGetAgentConfigQuery, useUpdateClawMentorConfigMutation, useCreateClawMentorConfigMutation, useDeleteClawMentorConfigMutation, usePushClawConfigMutation, useCreateClawInstanceMutation, useDeleteClawInstanceMutation, useUpdateAgentConfigMutation, useHealthCheckClawInstanceMutation, useTestConnectivityClawInstanceMutation, useUpdateClawInstanceMutation, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetAgentSkillsQuery, useGetMentorSkillAssignmentsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, resolveEffectiveAgentSkills, filterSlashSkills, useCreateCheckoutMutation, useGetUserProjectsQuery, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useDeleteMentorMemoryMutation, useUpdateMentorMemoryMutation, useCreateMentorMemoryMutation, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useGetMentorCategoriesQuery, useCreateMentorMutation, useUpdateUserPlatformMetadataMutation, useGetApplicationStatusQuery, useListOwnApplicationsQuery, useGetApplicationFormQuery, useWithdrawApplicationMutation, useRenewApplicationMutation, useCreateApplicationDraftMutation, useSubmitApplicationMutation, useUpdateApplicationMutation, useUploadApplicationAttachmentMutation, useDeleteApplicationAttachmentMutation, useGetPromptCategoriesQuery, useCreatePromptMutation, useDeletePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation } from '@iblai/data-layer';
7
7
  import { toast } from 'sonner';
8
8
  import { jsx, Fragment as Fragment$1, jsxs } from 'react/jsx-runtime';
9
9
  import * as ReactDOM from 'react-dom';
@@ -54884,7 +54884,7 @@ const createLucideIcon = (iconName, iconNode) => {
54884
54884
  */
54885
54885
 
54886
54886
 
54887
- const __iconNode$2l = [
54887
+ const __iconNode$2m = [
54888
54888
  [
54889
54889
  "path",
54890
54890
  {
@@ -54893,7 +54893,7 @@ const __iconNode$2l = [
54893
54893
  }
54894
54894
  ]
54895
54895
  ];
54896
- const Activity = createLucideIcon("activity", __iconNode$2l);
54896
+ const Activity = createLucideIcon("activity", __iconNode$2m);
54897
54897
 
54898
54898
  /**
54899
54899
  * @license lucide-react v0.528.0 - ISC
@@ -54903,12 +54903,12 @@ const Activity = createLucideIcon("activity", __iconNode$2l);
54903
54903
  */
54904
54904
 
54905
54905
 
54906
- const __iconNode$2k = [
54906
+ const __iconNode$2l = [
54907
54907
  ["path", { d: "M17 12H7", key: "16if0g" }],
54908
54908
  ["path", { d: "M19 18H5", key: "18s9l3" }],
54909
54909
  ["path", { d: "M21 6H3", key: "1jwq7v" }]
54910
54910
  ];
54911
- const AlignCenter = createLucideIcon("align-center", __iconNode$2k);
54911
+ const AlignCenter = createLucideIcon("align-center", __iconNode$2l);
54912
54912
 
54913
54913
  /**
54914
54914
  * @license lucide-react v0.528.0 - ISC
@@ -54918,12 +54918,12 @@ const AlignCenter = createLucideIcon("align-center", __iconNode$2k);
54918
54918
  */
54919
54919
 
54920
54920
 
54921
- const __iconNode$2j = [
54921
+ const __iconNode$2k = [
54922
54922
  ["path", { d: "M15 12H3", key: "6jk70r" }],
54923
54923
  ["path", { d: "M17 18H3", key: "1amg6g" }],
54924
54924
  ["path", { d: "M21 6H3", key: "1jwq7v" }]
54925
54925
  ];
54926
- const AlignLeft = createLucideIcon("align-left", __iconNode$2j);
54926
+ const AlignLeft = createLucideIcon("align-left", __iconNode$2k);
54927
54927
 
54928
54928
  /**
54929
54929
  * @license lucide-react v0.528.0 - ISC
@@ -54933,12 +54933,12 @@ const AlignLeft = createLucideIcon("align-left", __iconNode$2j);
54933
54933
  */
54934
54934
 
54935
54935
 
54936
- const __iconNode$2i = [
54936
+ const __iconNode$2j = [
54937
54937
  ["path", { d: "M21 12H9", key: "dn1m92" }],
54938
54938
  ["path", { d: "M21 18H7", key: "1ygte8" }],
54939
54939
  ["path", { d: "M21 6H3", key: "1jwq7v" }]
54940
54940
  ];
54941
- const AlignRight = createLucideIcon("align-right", __iconNode$2i);
54941
+ const AlignRight = createLucideIcon("align-right", __iconNode$2j);
54942
54942
 
54943
54943
  /**
54944
54944
  * @license lucide-react v0.528.0 - ISC
@@ -54948,12 +54948,12 @@ const AlignRight = createLucideIcon("align-right", __iconNode$2i);
54948
54948
  */
54949
54949
 
54950
54950
 
54951
- const __iconNode$2h = [
54951
+ const __iconNode$2i = [
54952
54952
  ["rect", { width: "20", height: "5", x: "2", y: "3", rx: "1", key: "1wp1u1" }],
54953
54953
  ["path", { d: "M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8", key: "1s80jp" }],
54954
54954
  ["path", { d: "M10 12h4", key: "a56b0p" }]
54955
54955
  ];
54956
- const Archive = createLucideIcon("archive", __iconNode$2h);
54956
+ const Archive = createLucideIcon("archive", __iconNode$2i);
54957
54957
 
54958
54958
  /**
54959
54959
  * @license lucide-react v0.528.0 - ISC
@@ -54963,11 +54963,11 @@ const Archive = createLucideIcon("archive", __iconNode$2h);
54963
54963
  */
54964
54964
 
54965
54965
 
54966
- const __iconNode$2g = [
54966
+ const __iconNode$2h = [
54967
54967
  ["path", { d: "M12 5v14", key: "s699le" }],
54968
54968
  ["path", { d: "m19 12-7 7-7-7", key: "1idqje" }]
54969
54969
  ];
54970
- const ArrowDown = createLucideIcon("arrow-down", __iconNode$2g);
54970
+ const ArrowDown = createLucideIcon("arrow-down", __iconNode$2h);
54971
54971
 
54972
54972
  /**
54973
54973
  * @license lucide-react v0.528.0 - ISC
@@ -54977,11 +54977,11 @@ const ArrowDown = createLucideIcon("arrow-down", __iconNode$2g);
54977
54977
  */
54978
54978
 
54979
54979
 
54980
- const __iconNode$2f = [
54980
+ const __iconNode$2g = [
54981
54981
  ["path", { d: "m12 19-7-7 7-7", key: "1l729n" }],
54982
54982
  ["path", { d: "M19 12H5", key: "x3x0zl" }]
54983
54983
  ];
54984
- const ArrowLeft = createLucideIcon("arrow-left", __iconNode$2f);
54984
+ const ArrowLeft = createLucideIcon("arrow-left", __iconNode$2g);
54985
54985
 
54986
54986
  /**
54987
54987
  * @license lucide-react v0.528.0 - ISC
@@ -54991,11 +54991,11 @@ const ArrowLeft = createLucideIcon("arrow-left", __iconNode$2f);
54991
54991
  */
54992
54992
 
54993
54993
 
54994
- const __iconNode$2e = [
54994
+ const __iconNode$2f = [
54995
54995
  ["path", { d: "M5 12h14", key: "1ays0h" }],
54996
54996
  ["path", { d: "m12 5 7 7-7 7", key: "xquz4c" }]
54997
54997
  ];
54998
- const ArrowRight = createLucideIcon("arrow-right", __iconNode$2e);
54998
+ const ArrowRight = createLucideIcon("arrow-right", __iconNode$2f);
54999
54999
 
55000
55000
  /**
55001
55001
  * @license lucide-react v0.528.0 - ISC
@@ -55005,11 +55005,11 @@ const ArrowRight = createLucideIcon("arrow-right", __iconNode$2e);
55005
55005
  */
55006
55006
 
55007
55007
 
55008
- const __iconNode$2d = [
55008
+ const __iconNode$2e = [
55009
55009
  ["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
55010
55010
  ["path", { d: "M12 19V5", key: "x0mq9r" }]
55011
55011
  ];
55012
- const ArrowUp = createLucideIcon("arrow-up", __iconNode$2d);
55012
+ const ArrowUp = createLucideIcon("arrow-up", __iconNode$2e);
55013
55013
 
55014
55014
  /**
55015
55015
  * @license lucide-react v0.528.0 - ISC
@@ -55019,7 +55019,7 @@ const ArrowUp = createLucideIcon("arrow-up", __iconNode$2d);
55019
55019
  */
55020
55020
 
55021
55021
 
55022
- const __iconNode$2c = [
55022
+ const __iconNode$2d = [
55023
55023
  [
55024
55024
  "path",
55025
55025
  {
@@ -55029,7 +55029,7 @@ const __iconNode$2c = [
55029
55029
  ],
55030
55030
  ["circle", { cx: "12", cy: "8", r: "6", key: "1vp47v" }]
55031
55031
  ];
55032
- const Award = createLucideIcon("award", __iconNode$2c);
55032
+ const Award = createLucideIcon("award", __iconNode$2d);
55033
55033
 
55034
55034
  /**
55035
55035
  * @license lucide-react v0.528.0 - ISC
@@ -55039,11 +55039,11 @@ const Award = createLucideIcon("award", __iconNode$2c);
55039
55039
  */
55040
55040
 
55041
55041
 
55042
- const __iconNode$2b = [
55042
+ const __iconNode$2c = [
55043
55043
  ["path", { d: "M4.929 4.929 19.07 19.071", key: "196cmz" }],
55044
55044
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]
55045
55045
  ];
55046
- const Ban = createLucideIcon("ban", __iconNode$2b);
55046
+ const Ban = createLucideIcon("ban", __iconNode$2c);
55047
55047
 
55048
55048
  /**
55049
55049
  * @license lucide-react v0.528.0 - ISC
@@ -55053,12 +55053,12 @@ const Ban = createLucideIcon("ban", __iconNode$2b);
55053
55053
  */
55054
55054
 
55055
55055
 
55056
- const __iconNode$2a = [
55056
+ const __iconNode$2b = [
55057
55057
  ["rect", { width: "20", height: "12", x: "2", y: "6", rx: "2", key: "9lu3g6" }],
55058
55058
  ["circle", { cx: "12", cy: "12", r: "2", key: "1c9p78" }],
55059
55059
  ["path", { d: "M6 12h.01M18 12h.01", key: "113zkx" }]
55060
55060
  ];
55061
- const Banknote = createLucideIcon("banknote", __iconNode$2a);
55061
+ const Banknote = createLucideIcon("banknote", __iconNode$2b);
55062
55062
 
55063
55063
  /**
55064
55064
  * @license lucide-react v0.528.0 - ISC
@@ -55068,7 +55068,7 @@ const Banknote = createLucideIcon("banknote", __iconNode$2a);
55068
55068
  */
55069
55069
 
55070
55070
 
55071
- const __iconNode$29 = [
55071
+ const __iconNode$2a = [
55072
55072
  ["path", { d: "M10.268 21a2 2 0 0 0 3.464 0", key: "vwvbt9" }],
55073
55073
  ["path", { d: "M22 8c0-2.3-.8-4.3-2-6", key: "5bb3ad" }],
55074
55074
  [
@@ -55080,7 +55080,7 @@ const __iconNode$29 = [
55080
55080
  ],
55081
55081
  ["path", { d: "M4 2C2.8 3.7 2 5.7 2 8", key: "tap9e0" }]
55082
55082
  ];
55083
- const BellRing = createLucideIcon("bell-ring", __iconNode$29);
55083
+ const BellRing = createLucideIcon("bell-ring", __iconNode$2a);
55084
55084
 
55085
55085
  /**
55086
55086
  * @license lucide-react v0.528.0 - ISC
@@ -55090,7 +55090,7 @@ const BellRing = createLucideIcon("bell-ring", __iconNode$29);
55090
55090
  */
55091
55091
 
55092
55092
 
55093
- const __iconNode$28 = [
55093
+ const __iconNode$29 = [
55094
55094
  ["path", { d: "M10.268 21a2 2 0 0 0 3.464 0", key: "vwvbt9" }],
55095
55095
  [
55096
55096
  "path",
@@ -55100,7 +55100,7 @@ const __iconNode$28 = [
55100
55100
  }
55101
55101
  ]
55102
55102
  ];
55103
- const Bell = createLucideIcon("bell", __iconNode$28);
55103
+ const Bell = createLucideIcon("bell", __iconNode$29);
55104
55104
 
55105
55105
  /**
55106
55106
  * @license lucide-react v0.528.0 - ISC
@@ -55110,13 +55110,13 @@ const Bell = createLucideIcon("bell", __iconNode$28);
55110
55110
  */
55111
55111
 
55112
55112
 
55113
- const __iconNode$27 = [
55113
+ const __iconNode$28 = [
55114
55114
  [
55115
55115
  "path",
55116
55116
  { d: "M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8", key: "mg9rjx" }
55117
55117
  ]
55118
55118
  ];
55119
- const Bold$1 = createLucideIcon("bold", __iconNode$27);
55119
+ const Bold$1 = createLucideIcon("bold", __iconNode$28);
55120
55120
 
55121
55121
  /**
55122
55122
  * @license lucide-react v0.528.0 - ISC
@@ -55126,7 +55126,7 @@ const Bold$1 = createLucideIcon("bold", __iconNode$27);
55126
55126
  */
55127
55127
 
55128
55128
 
55129
- const __iconNode$26 = [
55129
+ const __iconNode$27 = [
55130
55130
  ["path", { d: "M12 7v14", key: "1akyts" }],
55131
55131
  [
55132
55132
  "path",
@@ -55136,7 +55136,7 @@ const __iconNode$26 = [
55136
55136
  }
55137
55137
  ]
55138
55138
  ];
55139
- const BookOpen = createLucideIcon("book-open", __iconNode$26);
55139
+ const BookOpen = createLucideIcon("book-open", __iconNode$27);
55140
55140
 
55141
55141
  /**
55142
55142
  * @license lucide-react v0.528.0 - ISC
@@ -55146,7 +55146,7 @@ const BookOpen = createLucideIcon("book-open", __iconNode$26);
55146
55146
  */
55147
55147
 
55148
55148
 
55149
- const __iconNode$25 = [
55149
+ const __iconNode$26 = [
55150
55150
  ["path", { d: "M12 8V4H8", key: "hb8ula" }],
55151
55151
  ["rect", { width: "16", height: "12", x: "4", y: "8", rx: "2", key: "enze0r" }],
55152
55152
  ["path", { d: "M2 14h2", key: "vft8re" }],
@@ -55154,7 +55154,27 @@ const __iconNode$25 = [
55154
55154
  ["path", { d: "M15 13v2", key: "1xurst" }],
55155
55155
  ["path", { d: "M9 13v2", key: "rq6x2g" }]
55156
55156
  ];
55157
- const Bot = createLucideIcon("bot", __iconNode$25);
55157
+ const Bot = createLucideIcon("bot", __iconNode$26);
55158
+
55159
+ /**
55160
+ * @license lucide-react v0.528.0 - ISC
55161
+ *
55162
+ * This source code is licensed under the ISC license.
55163
+ * See the LICENSE file in the root directory of this source tree.
55164
+ */
55165
+
55166
+
55167
+ const __iconNode$25 = [
55168
+ ["path", { d: "M12 18V5", key: "adv99a" }],
55169
+ ["path", { d: "M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4", key: "1e3is1" }],
55170
+ ["path", { d: "M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5", key: "1gqd8o" }],
55171
+ ["path", { d: "M17.997 5.125a4 4 0 0 1 2.526 5.77", key: "iwvgf7" }],
55172
+ ["path", { d: "M18 18a4 4 0 0 0 2-7.464", key: "efp6ie" }],
55173
+ ["path", { d: "M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517", key: "1gq6am" }],
55174
+ ["path", { d: "M6 18a4 4 0 0 1-2-7.464", key: "k1g0md" }],
55175
+ ["path", { d: "M6.003 5.125a4 4 0 0 0-2.526 5.77", key: "q97ue3" }]
55176
+ ];
55177
+ const Brain = createLucideIcon("brain", __iconNode$25);
55158
55178
 
55159
55179
  /**
55160
55180
  * @license lucide-react v0.528.0 - ISC
@@ -60619,6 +60639,37 @@ var analyticsAnalyticsFinancialStats$3 = {
60619
60639
  goToLastPage: "Go to last page",
60620
60640
  paginationShowing: "Showing {from} to {to} of {total} results"
60621
60641
  };
60642
+ var analyticsAnalyticsMemoryStats$3 = {
60643
+ noPermission: "You do not have permission to view user memories.",
60644
+ scopeLabel: "Memory scope",
60645
+ scopeMentor: "This Agent",
60646
+ scopeAllMentors: "All Agents",
60647
+ scopeGlobal: "Global",
60648
+ searchAgents: "Search Agents…",
60649
+ searchAgentsTitle: "Search Agents",
60650
+ clearAgentSearch: "Clear Agent Search",
60651
+ contentPlaceholder: "Search memory content",
60652
+ pickDateRange: "Pick a Date Range",
60653
+ allCategories: "All Categories",
60654
+ byCategory: "Memories by Category",
60655
+ categoryCount: "{count} ({percent}%)",
60656
+ loadError: "An error occurred while loading memories.",
60657
+ noMemories: "No memories have been captured yet.",
60658
+ detailTitle: "Memory Detail",
60659
+ detailUser: "User",
60660
+ detailAgent: "Agent",
60661
+ detailCategory: "Category",
60662
+ detailSource: "Source",
60663
+ detailCaptured: "Captured",
60664
+ detailSession: "Session",
60665
+ sourceAuto: "Auto-captured",
60666
+ sourceManual: "Added manually",
60667
+ colUser: "USER",
60668
+ colMemory: "MEMORY",
60669
+ colAgent: "AGENT",
60670
+ colCategory: "CATEGORY",
60671
+ colCaptured: "CAPTURED"
60672
+ };
60622
60673
  var analyticsAnalyticsMonetizationStats$3 = {
60623
60674
  totalRevenue: "Total Revenue",
60624
60675
  totalSales: "Total Sales",
@@ -60864,6 +60915,13 @@ var analyticsStatCard$3 = {
60864
60915
  ariaLabel: "{title} mini card",
60865
60916
  ariaLabelValue: "{title} mini card value"
60866
60917
  };
60918
+ var analyticsUserFilterSelect$3 = {
60919
+ filterByUser: "Filter by user",
60920
+ you: "You",
60921
+ searchPlaceholder: "Search users…",
60922
+ noUsersFound: "No users found.",
60923
+ loadingUsers: "Loading users…"
60924
+ };
60867
60925
  var apiTabApiKeyModal$3 = {
60868
60926
  title: "API Key",
60869
60927
  dialogDescription: "Copy and paste the API key.",
@@ -62567,12 +62625,14 @@ var memoryMemoryTab$3 = {
62567
62625
  useMemoryLabelDesc: "When enabled, the AI will use what it knows about you to personalize responses.",
62568
62626
  useMemoryAriaLabel: "Use memory in responses {state}",
62569
62627
  sectionMyMemories: "My Memories",
62628
+ sectionMyMemoriesPreview: "Memories",
62570
62629
  addMemoryButton: "Add Memory",
62571
62630
  autoGeneratedMemoryAriaLabel: "Auto-generated memory",
62572
62631
  manuallyAddedMemoryAriaLabel: "Manually added memory",
62573
62632
  autoBadge: "auto",
62574
62633
  deleteMemoryAriaLabel: "Delete memory: {excerpt}",
62575
62634
  noMemoriesYet: "No memories yet. The AI will start remembering information from your conversations, or you can add memories manually.",
62635
+ noMemoriesYetPreview: "No memories yet. The AI has not recorded any information from this user's conversations.",
62576
62636
  stateEnabled: "enabled",
62577
62637
  stateDisabled: "disabled"
62578
62638
  };
@@ -64778,6 +64838,10 @@ var analyticsTabLabels$3 = {
64778
64838
  label: "Transcripts",
64779
64839
  description: "Read full conversation transcripts message by message."
64780
64840
  },
64841
+ memory: {
64842
+ label: "Memory",
64843
+ description: "What this agent remembers about each user it talks to."
64844
+ },
64781
64845
  financial: {
64782
64846
  label: "Costs",
64783
64847
  description: "Track token usage and what this agent is costing you."
@@ -65897,6 +65961,7 @@ var en = {
65897
65961
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail$3,
65898
65962
  analyticsAnalyticsCourses: analyticsAnalyticsCourses$3,
65899
65963
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats$3,
65964
+ analyticsAnalyticsMemoryStats: analyticsAnalyticsMemoryStats$3,
65900
65965
  analyticsAnalyticsMonetizationStats: analyticsAnalyticsMonetizationStats$3,
65901
65966
  analyticsAnalyticsOverview: analyticsAnalyticsOverview$3,
65902
65967
  analyticsAnalyticsProgramDetail: analyticsAnalyticsProgramDetail$3,
@@ -65907,6 +65972,7 @@ var en = {
65907
65972
  analyticsAnalyticsUsersStats: analyticsAnalyticsUsersStats$3,
65908
65973
  analyticsGroupsFilterDropdown: analyticsGroupsFilterDropdown$3,
65909
65974
  analyticsStatCard: analyticsStatCard$3,
65975
+ analyticsUserFilterSelect: analyticsUserFilterSelect$3,
65910
65976
  apiTabApiKeyModal: apiTabApiKeyModal$3,
65911
65977
  apiTabCreateApiModal2: apiTabCreateApiModal2$3,
65912
65978
  apiTabDeleteApiModal2: apiTabDeleteApiModal2$3,
@@ -66839,6 +66905,37 @@ var analyticsAnalyticsFinancialStats$2 = {
66839
66905
  goToLastPage: "Aller à la dernière page",
66840
66906
  paginationShowing: "Affichage de {from} à {to} sur {total} résultats"
66841
66907
  };
66908
+ var analyticsAnalyticsMemoryStats$2 = {
66909
+ noPermission: "Vous n'avez pas l'autorisation de consulter les mémoires des utilisateurs.",
66910
+ scopeLabel: "Portée de la mémoire",
66911
+ scopeMentor: "Cet agent",
66912
+ scopeAllMentors: "Tous les agents",
66913
+ scopeGlobal: "Global",
66914
+ searchAgents: "Rechercher des agents…",
66915
+ searchAgentsTitle: "Rechercher des agents",
66916
+ clearAgentSearch: "Effacer la recherche d'agent",
66917
+ contentPlaceholder: "Rechercher dans le contenu des mémoires",
66918
+ pickDateRange: "Choisir une plage de dates",
66919
+ allCategories: "Toutes les catégories",
66920
+ byCategory: "Mémoires par catégorie",
66921
+ categoryCount: "{count} ({percent}%)",
66922
+ loadError: "Une erreur s'est produite lors du chargement des mémoires.",
66923
+ noMemories: "Aucune mémoire n'a encore été capturée.",
66924
+ detailTitle: "Détail de la mémoire",
66925
+ detailUser: "Utilisateur",
66926
+ detailAgent: "Agent",
66927
+ detailCategory: "Catégorie",
66928
+ detailSource: "Source",
66929
+ detailCaptured: "Capturée",
66930
+ detailSession: "Session",
66931
+ sourceAuto: "Capturée automatiquement",
66932
+ sourceManual: "Ajoutée manuellement",
66933
+ colUser: "UTILISATEUR",
66934
+ colMemory: "MÉMOIRE",
66935
+ colAgent: "AGENT",
66936
+ colCategory: "CATÉGORIE",
66937
+ colCaptured: "CAPTURÉE"
66938
+ };
66842
66939
  var analyticsAnalyticsMonetizationStats$2 = {
66843
66940
  totalRevenue: "Revenu total",
66844
66941
  totalSales: "Ventes totales",
@@ -67084,6 +67181,13 @@ var analyticsStatCard$2 = {
67084
67181
  ariaLabel: "mini carte {title}",
67085
67182
  ariaLabelValue: "valeur de la mini carte {title}"
67086
67183
  };
67184
+ var analyticsUserFilterSelect$2 = {
67185
+ filterByUser: "Filtrer par utilisateur",
67186
+ you: "Vous",
67187
+ searchPlaceholder: "Rechercher des utilisateurs…",
67188
+ noUsersFound: "Aucun utilisateur trouvé.",
67189
+ loadingUsers: "Chargement des utilisateurs…"
67190
+ };
67087
67191
  var apiTabApiKeyModal$2 = {
67088
67192
  title: "Clé API",
67089
67193
  dialogDescription: "Copiez et collez la clé API.",
@@ -68899,12 +69003,14 @@ var memoryMemoryTab$2 = {
68899
69003
  useMemoryLabelDesc: "Lorsque cette option est activée, l'IA utilisera ce qu'elle sait de vous pour personnaliser ses réponses.",
68900
69004
  useMemoryAriaLabel: "Utilisation de la mémoire dans les réponses {state}",
68901
69005
  sectionMyMemories: "Mes souvenirs",
69006
+ sectionMyMemoriesPreview: "Souvenirs",
68902
69007
  addMemoryButton: "Ajouter un souvenir",
68903
69008
  autoGeneratedMemoryAriaLabel: "Souvenir généré automatiquement",
68904
69009
  manuallyAddedMemoryAriaLabel: "Souvenir ajouté manuellement",
68905
69010
  autoBadge: "auto",
68906
69011
  deleteMemoryAriaLabel: "Supprimer le souvenir : {excerpt}",
68907
69012
  noMemoriesYet: "Aucun souvenir pour l'instant. L'IA commencera à mémoriser des informations de vos conversations, ou vous pouvez ajouter des souvenirs manuellement.",
69013
+ noMemoriesYetPreview: "Aucun souvenir pour l'instant. L'IA n'a enregistré aucune information des conversations de cet utilisateur.",
68908
69014
  stateEnabled: "activée",
68909
69015
  stateDisabled: "désactivée"
68910
69016
  };
@@ -71110,6 +71216,10 @@ var analyticsTabLabels$2 = {
71110
71216
  label: "Transcriptions",
71111
71217
  description: "Lisez les transcriptions complètes des conversations, message par message."
71112
71218
  },
71219
+ memory: {
71220
+ label: "Mémoire",
71221
+ description: "Ce que cet agent retient de chaque utilisateur avec qui il échange."
71222
+ },
71113
71223
  financial: {
71114
71224
  label: "Coûts",
71115
71225
  description: "Suivez l'utilisation des jetons et ce que cet agent vous coûte."
@@ -72117,6 +72227,7 @@ var fr = {
72117
72227
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail$2,
72118
72228
  analyticsAnalyticsCourses: analyticsAnalyticsCourses$2,
72119
72229
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats$2,
72230
+ analyticsAnalyticsMemoryStats: analyticsAnalyticsMemoryStats$2,
72120
72231
  analyticsAnalyticsMonetizationStats: analyticsAnalyticsMonetizationStats$2,
72121
72232
  analyticsAnalyticsOverview: analyticsAnalyticsOverview$2,
72122
72233
  analyticsAnalyticsProgramDetail: analyticsAnalyticsProgramDetail$2,
@@ -72127,6 +72238,7 @@ var fr = {
72127
72238
  analyticsAnalyticsUsersStats: analyticsAnalyticsUsersStats$2,
72128
72239
  analyticsGroupsFilterDropdown: analyticsGroupsFilterDropdown$2,
72129
72240
  analyticsStatCard: analyticsStatCard$2,
72241
+ analyticsUserFilterSelect: analyticsUserFilterSelect$2,
72130
72242
  apiTabApiKeyModal: apiTabApiKeyModal$2,
72131
72243
  apiTabCreateApiModal2: apiTabCreateApiModal2$2,
72132
72244
  apiTabDeleteApiModal2: apiTabDeleteApiModal2$2,
@@ -73059,6 +73171,37 @@ var analyticsAnalyticsFinancialStats$1 = {
73059
73171
  goToLastPage: "Ir a la última página",
73060
73172
  paginationShowing: "Mostrando {from} a {to} de {total} resultados"
73061
73173
  };
73174
+ var analyticsAnalyticsMemoryStats$1 = {
73175
+ noPermission: "No tienes permiso para ver los recuerdos de los usuarios.",
73176
+ scopeLabel: "Alcance de la memoria",
73177
+ scopeMentor: "Este agente",
73178
+ scopeAllMentors: "Todos los agentes",
73179
+ scopeGlobal: "Global",
73180
+ searchAgents: "Buscar agentes…",
73181
+ searchAgentsTitle: "Buscar agentes",
73182
+ clearAgentSearch: "Borrar la búsqueda de agentes",
73183
+ contentPlaceholder: "Buscar en el contenido de los recuerdos",
73184
+ pickDateRange: "Elige un rango de fechas",
73185
+ allCategories: "Todas las categorías",
73186
+ byCategory: "Recuerdos por categoría",
73187
+ categoryCount: "{count} ({percent}%)",
73188
+ loadError: "Se produjo un error al cargar los recuerdos.",
73189
+ noMemories: "Todavía no se ha capturado ningún recuerdo.",
73190
+ detailTitle: "Detalle del recuerdo",
73191
+ detailUser: "Usuario",
73192
+ detailAgent: "Agente",
73193
+ detailCategory: "Categoría",
73194
+ detailSource: "Origen",
73195
+ detailCaptured: "Capturado",
73196
+ detailSession: "Sesión",
73197
+ sourceAuto: "Capturado automáticamente",
73198
+ sourceManual: "Añadido manualmente",
73199
+ colUser: "USUARIO",
73200
+ colMemory: "RECUERDO",
73201
+ colAgent: "AGENTE",
73202
+ colCategory: "CATEGORÍA",
73203
+ colCaptured: "CAPTURADO"
73204
+ };
73062
73205
  var analyticsAnalyticsMonetizationStats$1 = {
73063
73206
  totalRevenue: "Ingresos totales",
73064
73207
  totalSales: "Ventas totales",
@@ -73304,6 +73447,13 @@ var analyticsStatCard$1 = {
73304
73447
  ariaLabel: "mini tarjeta {title}",
73305
73448
  ariaLabelValue: "valor de la mini tarjeta {title}"
73306
73449
  };
73450
+ var analyticsUserFilterSelect$1 = {
73451
+ filterByUser: "Filtrar por usuario",
73452
+ you: "Tú",
73453
+ searchPlaceholder: "Buscar usuarios…",
73454
+ noUsersFound: "No se encontraron usuarios.",
73455
+ loadingUsers: "Cargando usuarios…"
73456
+ };
73307
73457
  var apiTabApiKeyModal$1 = {
73308
73458
  title: "Clave API",
73309
73459
  dialogDescription: "Copie y pegue la clave API.",
@@ -75119,12 +75269,14 @@ var memoryMemoryTab$1 = {
75119
75269
  useMemoryLabelDesc: "Cuando está habilitado, la IA usará lo que sabe sobre usted para personalizar las respuestas.",
75120
75270
  useMemoryAriaLabel: "Uso de memoria en las respuestas {state}",
75121
75271
  sectionMyMemories: "Mis memorias",
75272
+ sectionMyMemoriesPreview: "Memorias",
75122
75273
  addMemoryButton: "Añadir memoria",
75123
75274
  autoGeneratedMemoryAriaLabel: "Memoria generada automáticamente",
75124
75275
  manuallyAddedMemoryAriaLabel: "Memoria añadida manualmente",
75125
75276
  autoBadge: "auto",
75126
75277
  deleteMemoryAriaLabel: "Eliminar memoria: {excerpt}",
75127
75278
  noMemoriesYet: "Aún no hay memorias. La IA comenzará a recordar información de sus conversaciones, o puede añadir memorias manualmente.",
75279
+ noMemoriesYetPreview: "Aún no hay memorias. La IA no ha registrado información de las conversaciones de este usuario.",
75128
75280
  stateEnabled: "habilitada",
75129
75281
  stateDisabled: "deshabilitada"
75130
75282
  };
@@ -77330,6 +77482,10 @@ var analyticsTabLabels$1 = {
77330
77482
  label: "Transcripciones",
77331
77483
  description: "Lee las transcripciones completas de las conversaciones, mensaje a mensaje."
77332
77484
  },
77485
+ memory: {
77486
+ label: "Memoria",
77487
+ description: "Lo que este agente recuerda de cada usuario con el que habla."
77488
+ },
77333
77489
  financial: {
77334
77490
  label: "Costos",
77335
77491
  description: "Controla el uso de tokens y lo que te cuesta este agente."
@@ -78337,6 +78493,7 @@ var es = {
78337
78493
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail$1,
78338
78494
  analyticsAnalyticsCourses: analyticsAnalyticsCourses$1,
78339
78495
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats$1,
78496
+ analyticsAnalyticsMemoryStats: analyticsAnalyticsMemoryStats$1,
78340
78497
  analyticsAnalyticsMonetizationStats: analyticsAnalyticsMonetizationStats$1,
78341
78498
  analyticsAnalyticsOverview: analyticsAnalyticsOverview$1,
78342
78499
  analyticsAnalyticsProgramDetail: analyticsAnalyticsProgramDetail$1,
@@ -78347,6 +78504,7 @@ var es = {
78347
78504
  analyticsAnalyticsUsersStats: analyticsAnalyticsUsersStats$1,
78348
78505
  analyticsGroupsFilterDropdown: analyticsGroupsFilterDropdown$1,
78349
78506
  analyticsStatCard: analyticsStatCard$1,
78507
+ analyticsUserFilterSelect: analyticsUserFilterSelect$1,
78350
78508
  apiTabApiKeyModal: apiTabApiKeyModal$1,
78351
78509
  apiTabCreateApiModal2: apiTabCreateApiModal2$1,
78352
78510
  apiTabDeleteApiModal2: apiTabDeleteApiModal2$1,
@@ -79279,6 +79437,37 @@ var analyticsAnalyticsFinancialStats = {
79279
79437
  goToLastPage: "转到最后一页",
79280
79438
  paginationShowing: "显示第 {from} 至 {to} 条,共 {total} 条结果"
79281
79439
  };
79440
+ var analyticsAnalyticsMemoryStats = {
79441
+ noPermission: "您没有查看用户记忆的权限。",
79442
+ scopeLabel: "记忆范围",
79443
+ scopeMentor: "当前智能体",
79444
+ scopeAllMentors: "所有智能体",
79445
+ scopeGlobal: "全局",
79446
+ searchAgents: "搜索智能体…",
79447
+ searchAgentsTitle: "搜索智能体",
79448
+ clearAgentSearch: "清除智能体搜索",
79449
+ contentPlaceholder: "搜索记忆内容",
79450
+ pickDateRange: "选择日期范围",
79451
+ allCategories: "所有类别",
79452
+ byCategory: "按类别统计记忆",
79453
+ categoryCount: "{count} ({percent}%)",
79454
+ loadError: "加载记忆时发生错误。",
79455
+ noMemories: "尚未捕获任何记忆。",
79456
+ detailTitle: "记忆详情",
79457
+ detailUser: "用户",
79458
+ detailAgent: "智能体",
79459
+ detailCategory: "类别",
79460
+ detailSource: "来源",
79461
+ detailCaptured: "捕获时间",
79462
+ detailSession: "会话",
79463
+ sourceAuto: "自动捕获",
79464
+ sourceManual: "手动添加",
79465
+ colUser: "用户",
79466
+ colMemory: "记忆",
79467
+ colAgent: "智能体",
79468
+ colCategory: "类别",
79469
+ colCaptured: "捕获时间"
79470
+ };
79282
79471
  var analyticsAnalyticsMonetizationStats = {
79283
79472
  totalRevenue: "总收入",
79284
79473
  totalSales: "总销售额",
@@ -79524,6 +79713,13 @@ var analyticsStatCard = {
79524
79713
  ariaLabel: "{title} 迷你卡片",
79525
79714
  ariaLabelValue: "{title} 迷你卡片值"
79526
79715
  };
79716
+ var analyticsUserFilterSelect = {
79717
+ filterByUser: "按用户筛选",
79718
+ you: "我",
79719
+ searchPlaceholder: "搜索用户…",
79720
+ noUsersFound: "未找到用户。",
79721
+ loadingUsers: "正在加载用户…"
79722
+ };
79527
79723
  var apiTabApiKeyModal = {
79528
79724
  title: "API 密钥",
79529
79725
  dialogDescription: "复制并粘贴 API 密钥。",
@@ -81339,12 +81535,14 @@ var memoryMemoryTab = {
81339
81535
  useMemoryLabelDesc: "启用后,AI 将利用它对您的了解来个性化回复。",
81340
81536
  useMemoryAriaLabel: "在回复中使用记忆{state}",
81341
81537
  sectionMyMemories: "我的记忆",
81538
+ sectionMyMemoriesPreview: "记忆",
81342
81539
  addMemoryButton: "添加记忆",
81343
81540
  autoGeneratedMemoryAriaLabel: "自动生成的记忆",
81344
81541
  manuallyAddedMemoryAriaLabel: "手动添加的记忆",
81345
81542
  autoBadge: "自动",
81346
81543
  deleteMemoryAriaLabel: "删除记忆:{excerpt}",
81347
81544
  noMemoriesYet: "暂无记忆。AI 将开始记住您对话中的信息,或者您也可以手动添加记忆。",
81545
+ noMemoriesYetPreview: "暂无记忆。AI 尚未记录该用户对话中的任何信息。",
81348
81546
  stateEnabled: "已启用",
81349
81547
  stateDisabled: "已禁用"
81350
81548
  };
@@ -83550,6 +83748,10 @@ var analyticsTabLabels = {
83550
83748
  label: "对话记录",
83551
83749
  description: "逐条阅读完整的对话记录。"
83552
83750
  },
83751
+ memory: {
83752
+ label: "记忆",
83753
+ description: "该智能体记住的与其对话的每位用户的相关信息。"
83754
+ },
83553
83755
  financial: {
83554
83756
  label: "费用",
83555
83757
  description: "跟踪令牌用量以及该智能体的花费。"
@@ -84557,6 +84759,7 @@ var zh = {
84557
84759
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail,
84558
84760
  analyticsAnalyticsCourses: analyticsAnalyticsCourses,
84559
84761
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats,
84762
+ analyticsAnalyticsMemoryStats: analyticsAnalyticsMemoryStats,
84560
84763
  analyticsAnalyticsMonetizationStats: analyticsAnalyticsMonetizationStats,
84561
84764
  analyticsAnalyticsOverview: analyticsAnalyticsOverview,
84562
84765
  analyticsAnalyticsProgramDetail: analyticsAnalyticsProgramDetail,
@@ -84567,6 +84770,7 @@ var zh = {
84567
84770
  analyticsAnalyticsUsersStats: analyticsAnalyticsUsersStats,
84568
84771
  analyticsGroupsFilterDropdown: analyticsGroupsFilterDropdown,
84569
84772
  analyticsStatCard: analyticsStatCard,
84773
+ analyticsUserFilterSelect: analyticsUserFilterSelect,
84570
84774
  apiTabApiKeyModal: apiTabApiKeyModal,
84571
84775
  apiTabCreateApiModal2: apiTabCreateApiModal2,
84572
84776
  apiTabDeleteApiModal2: apiTabDeleteApiModal2,
@@ -87544,11 +87748,10 @@ const getUserName$1 = () => {
87544
87748
  };
87545
87749
 
87546
87750
  /**
87547
- * True when the logged-in user is viewing someone else's profile (preview
87548
- * mode), so editing affordances can be hidden. Reads the current username from
87549
- * localStorage after mount to stay SSR-safe.
87751
+ * The signed-in user's username, or an empty string before it is known. Read
87752
+ * from localStorage after mount to stay SSR-safe.
87550
87753
  */
87551
- function useIsProfilePreview(username) {
87754
+ function useCurrentUsername() {
87552
87755
  const [currentUsername, setCurrentUsername] = useState('');
87553
87756
  useEffect(() => {
87554
87757
  try {
@@ -87558,6 +87761,14 @@ function useIsProfilePreview(username) {
87558
87761
  setCurrentUsername('');
87559
87762
  }
87560
87763
  }, []);
87764
+ return currentUsername;
87765
+ }
87766
+ /**
87767
+ * True when the logged-in user is viewing someone else's profile (preview
87768
+ * mode), so editing affordances can be hidden.
87769
+ */
87770
+ function useIsProfilePreview(username) {
87771
+ const currentUsername = useCurrentUsername();
87561
87772
  return !!currentUsername && currentUsername !== username;
87562
87773
  }
87563
87774
 
@@ -141243,7 +141454,7 @@ const EmptyStats = ({ title = 'No data available' }) => {
141243
141454
 
141244
141455
  const COMPLETED_COLOR = '#ED8936';
141245
141456
  const REMAINING_COLOR = '#E5E7EB';
141246
- const formatDate$1 = (value) => {
141457
+ const formatDate$2 = (value) => {
141247
141458
  if (!value)
141248
141459
  return '—';
141249
141460
  const date = new Date(value);
@@ -141347,13 +141558,13 @@ function EnrolledUserProgressModal({ open, onOpenChange, username, userName, ema
141347
141558
  const passingPct = getPassingPct((_h = (_g = item === null || item === void 0 ? void 0 : item.edx_progress) === null || _g === void 0 ? void 0 : _g.grading_policy) === null || _h === void 0 ? void 0 : _h.grade_range);
141348
141559
  return (jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: jsxs(DialogContent, { className: "max-w-2xl max-h-[85vh] overflow-y-auto", "aria-label": "Enrolled user progress", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { children: userName || username || 'Learner progress' }), jsxs(DialogDescription, { children: [email ? `${email} · ` : '', resolvedName || (isProgram ? 'Program progress' : 'Course progress')] })] }), loading ? (jsx("div", { className: "flex items-center justify-center py-12", children: jsx("div", { className: "text-sm text-gray-500", children: "Loading..." }) })) : !item ? (jsx(EmptyStats, { title: "No progress data available" })) : (jsxs("div", { className: "space-y-6", children: [jsxs("div", { className: "relative mx-auto", style: { width: 220, height: 220 }, children: [jsx(ResponsiveContainer, { width: "100%", height: "100%", children: jsx(PieChart, { children: jsxs(Pie, { data: pieData, dataKey: "value", cx: "50%", cy: "50%", innerRadius: 75, outerRadius: 100, startAngle: 90, endAngle: -270, stroke: "none", isAnimationActive: false, children: [jsx(Cell, { fill: COMPLETED_COLOR }), jsx(Cell, { fill: REMAINING_COLOR })] }) }) }), jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center pointer-events-none", children: [jsxs("span", { className: "text-3xl font-bold text-gray-700", children: [percentage, "%"] }), jsx("span", { className: "text-sm text-gray-500", children: "completed" })] })] }), jsxs("div", { className: "divide-y divide-[oklch(0.922_0_0)]", children: [jsx(DetailRow, { label: "Status", children: jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${((_j = item.completion) === null || _j === void 0 ? void 0 : _j.passed)
141349
141560
  ? 'bg-green-50 text-green-700'
141350
- : 'bg-gray-100 text-gray-600'}`, children: ((_k = item.completion) === null || _k === void 0 ? void 0 : _k.passed) ? 'Passed' : 'Not passed' }) }), jsx(DetailRow, { label: "Passed on", children: formatDate$1((_l = item.completion) === null || _l === void 0 ? void 0 : _l.passed_date) }), jsx(DetailRow, { label: "Time spent", children: item.time_spent || '—' }), jsx(DetailRow, { label: "Enrollment date", children: formatDate$1((_o = (_m = item.enrollment) === null || _m === void 0 ? void 0 : _m.started) !== null && _o !== void 0 ? _o : (_p = item.enrollment) === null || _p === void 0 ? void 0 : _p.created) })] }), ((_s = (_r = (_q = item.edx_progress) === null || _q === void 0 ? void 0 : _q.grading_policy) === null || _r === void 0 ? void 0 : _r.assignment_policies) === null || _s === void 0 ? void 0 : _s.length) ? (jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "rounded-lg border p-4", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("h4", { className: "text-sm font-semibold text-gray-900", children: "Grades" }), jsx("p", { className: "text-xs text-gray-500", children: "This represents the weighted grade against the grade needed to pass this course." }), jsx(GradeBar, { currentPct: currentGradePct, passingPct: passingPct })] }), jsxs("div", { className: "flex items-start gap-2 rounded-md border border-amber-200 bg-amber-50 px-4 py-3", children: [jsx(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-600" }), jsxs("span", { className: "text-sm font-medium text-gray-800", children: ["A weighted grade of ", passingPct, "% is required to pass in this course"] })] }), jsxs("div", { className: "rounded-lg border p-4 space-y-3", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("h4", { className: "text-sm font-semibold text-gray-900", children: "Grade summary" }), jsx("div", { className: "overflow-x-auto", children: jsxs("table", { className: "w-full border-collapse text-sm", children: [jsx("thead", { children: jsxs("tr", { className: "bg-amber-50 text-[11px] uppercase tracking-wide text-gray-600", children: [jsx("th", { className: "px-3 py-2 text-left font-medium", children: "Assignment type" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Weight" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Grade" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Weighted grade" })] }) }), jsxs("tbody", { children: [gradeSummary === null || gradeSummary === void 0 ? void 0 : gradeSummary.rows.map((row, index) => (jsxs("tr", { className: index % 2 === 0 ? '' : 'bg-gray-50', children: [jsxs("td", { className: "px-3 py-2 text-gray-800", children: [row.type, row.footnote ? (jsx("sup", { className: "ml-0.5 text-amber-500", children: row.footnote })) : null] }), jsxs("td", { className: "px-3 py-2 text-right text-gray-700", children: [row.weightPct, "%"] }), jsxs("td", { className: "px-3 py-2 text-right text-gray-700", children: [row.gradePct, "%"] }), jsxs("td", { className: "px-3 py-2 text-right font-semibold text-amber-600", children: [row.weightedGradePct, "%"] })] }, row.type))), jsxs("tr", { className: "border-l-2 border-amber-400 bg-amber-50", children: [jsx("td", { className: "px-3 py-2 font-medium text-gray-800", colSpan: 3, children: "Current weighted grade summary" }), jsxs("td", { className: "px-3 py-2 text-right font-bold text-amber-600", children: [currentGradePct, "%"] })] })] })] }) }), gradeSummary && gradeSummary.footnotes.length > 0 ? (jsx("div", { className: "space-y-1", children: gradeSummary.footnotes.map((note, index) => (jsxs("p", { className: "text-xs text-gray-500", children: [jsx("sup", { className: "text-amber-500", children: index + 1 }), " ", note] }, note))) })) : null] })] })) : null] }))] }) }));
141561
+ : 'bg-gray-100 text-gray-600'}`, children: ((_k = item.completion) === null || _k === void 0 ? void 0 : _k.passed) ? 'Passed' : 'Not passed' }) }), jsx(DetailRow, { label: "Passed on", children: formatDate$2((_l = item.completion) === null || _l === void 0 ? void 0 : _l.passed_date) }), jsx(DetailRow, { label: "Time spent", children: item.time_spent || '—' }), jsx(DetailRow, { label: "Enrollment date", children: formatDate$2((_o = (_m = item.enrollment) === null || _m === void 0 ? void 0 : _m.started) !== null && _o !== void 0 ? _o : (_p = item.enrollment) === null || _p === void 0 ? void 0 : _p.created) })] }), ((_s = (_r = (_q = item.edx_progress) === null || _q === void 0 ? void 0 : _q.grading_policy) === null || _r === void 0 ? void 0 : _r.assignment_policies) === null || _s === void 0 ? void 0 : _s.length) ? (jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "rounded-lg border p-4", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("h4", { className: "text-sm font-semibold text-gray-900", children: "Grades" }), jsx("p", { className: "text-xs text-gray-500", children: "This represents the weighted grade against the grade needed to pass this course." }), jsx(GradeBar, { currentPct: currentGradePct, passingPct: passingPct })] }), jsxs("div", { className: "flex items-start gap-2 rounded-md border border-amber-200 bg-amber-50 px-4 py-3", children: [jsx(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-600" }), jsxs("span", { className: "text-sm font-medium text-gray-800", children: ["A weighted grade of ", passingPct, "% is required to pass in this course"] })] }), jsxs("div", { className: "rounded-lg border p-4 space-y-3", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("h4", { className: "text-sm font-semibold text-gray-900", children: "Grade summary" }), jsx("div", { className: "overflow-x-auto", children: jsxs("table", { className: "w-full border-collapse text-sm", children: [jsx("thead", { children: jsxs("tr", { className: "bg-amber-50 text-[11px] uppercase tracking-wide text-gray-600", children: [jsx("th", { className: "px-3 py-2 text-left font-medium", children: "Assignment type" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Weight" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Grade" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Weighted grade" })] }) }), jsxs("tbody", { children: [gradeSummary === null || gradeSummary === void 0 ? void 0 : gradeSummary.rows.map((row, index) => (jsxs("tr", { className: index % 2 === 0 ? '' : 'bg-gray-50', children: [jsxs("td", { className: "px-3 py-2 text-gray-800", children: [row.type, row.footnote ? (jsx("sup", { className: "ml-0.5 text-amber-500", children: row.footnote })) : null] }), jsxs("td", { className: "px-3 py-2 text-right text-gray-700", children: [row.weightPct, "%"] }), jsxs("td", { className: "px-3 py-2 text-right text-gray-700", children: [row.gradePct, "%"] }), jsxs("td", { className: "px-3 py-2 text-right font-semibold text-amber-600", children: [row.weightedGradePct, "%"] })] }, row.type))), jsxs("tr", { className: "border-l-2 border-amber-400 bg-amber-50", children: [jsx("td", { className: "px-3 py-2 font-medium text-gray-800", colSpan: 3, children: "Current weighted grade summary" }), jsxs("td", { className: "px-3 py-2 text-right font-bold text-amber-600", children: [currentGradePct, "%"] })] })] })] }) }), gradeSummary && gradeSummary.footnotes.length > 0 ? (jsx("div", { className: "space-y-1", children: gradeSummary.footnotes.map((note, index) => (jsxs("p", { className: "text-xs text-gray-500", children: [jsx("sup", { className: "text-amber-500", children: index + 1 }), " ", note] }, note))) })) : null] })] })) : null] }))] }) }));
141351
141562
  }
141352
141563
  function DetailRow({ label, children }) {
141353
141564
  return (jsxs("div", { className: "flex items-center justify-between gap-4 py-2", children: [jsx("span", { className: "text-sm text-gray-500", children: label }), jsx("span", { className: "text-sm font-medium text-gray-900 text-right", children: children })] }));
141354
141565
  }
141355
141566
 
141356
- const PAGE_SIZE$5 = 8;
141567
+ const PAGE_SIZE$6 = 8;
141357
141568
  const CONTENT_TYPES = [
141358
141569
  { value: 'courses', labelKey: 'gradebookGradebookTab.typeCourses', icon: GraduationCap },
141359
141570
  { value: 'programs', labelKey: 'gradebookGradebookTab.typePrograms', icon: Layers },
@@ -141370,7 +141581,7 @@ function useDebounce$1(value, delay) {
141370
141581
  }, [value, delay]);
141371
141582
  return debouncedValue;
141372
141583
  }
141373
- const formatDate = (value) => {
141584
+ const formatDate$1 = (value) => {
141374
141585
  if (!value)
141375
141586
  return '—';
141376
141587
  const date = new Date(value);
@@ -141384,29 +141595,29 @@ function useGradebookData(type, org, username, page, search) {
141384
141595
  username,
141385
141596
  query: {
141386
141597
  page,
141387
- page_size: PAGE_SIZE$5,
141598
+ page_size: PAGE_SIZE$6,
141388
141599
  platform_key: org,
141389
141600
  ...(trimmed ? { search: trimmed } : {}),
141390
141601
  },
141391
141602
  }, { skip: type !== 'courses', refetchOnMountOrArgChange: true });
141392
141603
  const programsQ = useGetUserEnrolledProgramsQuery([{ username, platformKey: org }], { skip: type !== 'programs' });
141393
141604
  const pathwaysQ = useGetUserCatalogPathwaysQuery({ username, platform_key: org }, { skip: type !== 'pathways' });
141394
- const credentialsQ = useGetUsersAsAssertionsQuery({ platformKey: org, userId: username, page, pageSize: PAGE_SIZE$5 }, { skip: type !== 'credentials', refetchOnMountOrArgChange: true });
141605
+ const credentialsQ = useGetUsersAsAssertionsQuery({ platformKey: org, userId: username, page, pageSize: PAGE_SIZE$6 }, { skip: type !== 'credentials', refetchOnMountOrArgChange: true });
141395
141606
  const earnedQ = useGetUserEarnedSkillsQuery([{ org, userId: username }], { skip: type !== 'skills' });
141396
141607
  const reportedQ = useGetUserReportedSkillsQuery([{ username }], { skip: type !== 'skills' });
141397
141608
  const desiredQ = useGetUserDesiredSkillsQuery([{ username }], { skip: type !== 'skills' });
141398
141609
  const statusLabel = (active) => active ? t('gradebookGradebookTab.statusActive') : t('gradebookGradebookTab.statusInactive');
141399
- const enrolledSubtitle = (created) => `${t('gradebookGradebookTab.enrolledOn')}: ${formatDate(created)}`;
141610
+ const enrolledSubtitle = (created) => `${t('gradebookGradebookTab.enrolledOn')}: ${formatDate$1(created)}`;
141400
141611
  const paginateClient = (rows) => {
141401
141612
  const filtered = trimmed
141402
141613
  ? rows.filter((row) => row.name.toLowerCase().includes(trimmed.toLowerCase()))
141403
141614
  : rows;
141404
- const start = (page - 1) * PAGE_SIZE$5;
141615
+ const start = (page - 1) * PAGE_SIZE$6;
141405
141616
  return {
141406
- rows: filtered.slice(start, start + PAGE_SIZE$5),
141617
+ rows: filtered.slice(start, start + PAGE_SIZE$6),
141407
141618
  total: filtered.length,
141408
141619
  hasPrev: page > 1,
141409
- hasNext: start + PAGE_SIZE$5 < filtered.length,
141620
+ hasNext: start + PAGE_SIZE$6 < filtered.length,
141410
141621
  };
141411
141622
  };
141412
141623
  switch (type) {
@@ -141463,7 +141674,7 @@ function useGradebookData(type, org, username, page, search) {
141463
141674
  rows,
141464
141675
  total,
141465
141676
  hasPrev: page > 1,
141466
- hasNext: page * PAGE_SIZE$5 < total,
141677
+ hasNext: page * PAGE_SIZE$6 < total,
141467
141678
  isLoading: credentialsQ.isLoading,
141468
141679
  isFetching: credentialsQ.isFetching,
141469
141680
  isError: credentialsQ.isError,
@@ -141702,29 +141913,58 @@ const IblPagination = ({ currentPage, totalPages, onPageChange, disabled = false
141702
141913
 
141703
141914
  const MEMORIES_PAGE_SIZE = 25;
141704
141915
  function MemoryTab({ org, username }) {
141705
- var _a, _b, _c;
141916
+ var _a, _b;
141706
141917
  const t = useT();
141707
141918
  const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
141708
141919
  const [deletingId, setDeletingId] = useState(null);
141709
141920
  const [currentPage, setCurrentPage] = useState(1);
141921
+ // Viewing someone else's profile, which lists both of that user's memory
141922
+ // collections — global and per-agent — instead of just your own global feed.
141923
+ const isPreview = useIsProfilePreview(username);
141924
+ const currentUsername = useCurrentUsername();
141710
141925
  // Platform memsearch status (available to students and admins)
141711
141926
  const { data: memsearchStatus, isLoading: isLoadingConfig, isError: isConfigError, } = useGetMemsearchStatusQuery({
141712
141927
  org,
141713
141928
  userId: username,
141714
- });
141929
+ }, { skip: isPreview });
141715
141930
  // User memory settings
141716
141931
  const { data: settings, isLoading: isLoadingSettings } = useGetUserMemorySettingsQuery({
141717
141932
  org,
141718
141933
  userId: username,
141719
- });
141934
+ }, { skip: isPreview });
141720
141935
  const [updateSettings, { isLoading: isUpdatingSettings }] = useUpdateUserMemorySettingsMutation();
141721
- // Global memories
141722
- const { data: memoriesData, isLoading: isLoadingMemories } = useGetGlobalMemoriesQuery({
141936
+ const memoriesParams = { page: currentPage, page_size: MEMORIES_PAGE_SIZE };
141937
+ // Global memories. On your own profile this is the plain call — your username
141938
+ // in the path. Previewing someone else addresses it the way the analytics
141939
+ // memory tab does: the caller in the `{user_id}` path segment, and the user
141940
+ // being looked at in the `user_id` param.
141941
+ const { data: globalMemoriesData, isLoading: isLoadingGlobalMemories } = useGetGlobalMemoriesQuery(isPreview
141942
+ ? { org, userId: currentUsername, params: { ...memoriesParams, user_id: username } }
141943
+ : { org, userId: username, params: memoriesParams }, { skip: isPreview && !currentUsername });
141944
+ // Agent memories across every mentor, addressed the same way. Only fetched in
141945
+ // preview, where the tab shows both of the profile owner's collections.
141946
+ const { data: mentorMemoriesData, isLoading: isLoadingMentorMemories } = useGetAllMentorMemoriesQuery({
141723
141947
  org,
141724
- userId: username,
141725
- params: { page: currentPage, page_size: MEMORIES_PAGE_SIZE },
141726
- });
141727
- const totalPages = (memoriesData === null || memoriesData === void 0 ? void 0 : memoriesData.count) ? Math.ceil(memoriesData.count / MEMORIES_PAGE_SIZE) : 0;
141948
+ userId: currentUsername,
141949
+ params: { ...memoriesParams, user_id: username },
141950
+ }, { skip: !isPreview || !currentUsername });
141951
+ const memories = useMemo(() => {
141952
+ var _a, _b;
141953
+ const globalMemories = (_a = globalMemoriesData === null || globalMemoriesData === void 0 ? void 0 : globalMemoriesData.results) !== null && _a !== void 0 ? _a : [];
141954
+ if (!isPreview)
141955
+ return globalMemories;
141956
+ // Both collections are newest-first on their own; interleave them so the
141957
+ // combined list still reads chronologically.
141958
+ return [...((_b = mentorMemoriesData === null || mentorMemoriesData === void 0 ? void 0 : mentorMemoriesData.results) !== null && _b !== void 0 ? _b : []), ...globalMemories].sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
141959
+ }, [isPreview, globalMemoriesData, mentorMemoriesData]);
141960
+ const isLoadingMemories = isLoadingGlobalMemories || (isPreview && isLoadingMentorMemories);
141961
+ // The two collections page independently at the same size, so a page shows
141962
+ // that page of each and the pager spans whichever collection is longer.
141963
+ const totalPages = useMemo(() => {
141964
+ const pageCount = (count) => (count ? Math.ceil(count / MEMORIES_PAGE_SIZE) : 0);
141965
+ const globalPages = pageCount(globalMemoriesData === null || globalMemoriesData === void 0 ? void 0 : globalMemoriesData.count);
141966
+ return isPreview ? Math.max(globalPages, pageCount(mentorMemoriesData === null || mentorMemoriesData === void 0 ? void 0 : mentorMemoriesData.count)) : globalPages;
141967
+ }, [isPreview, globalMemoriesData, mentorMemoriesData]);
141728
141968
  const [deleteMemory] = useDeleteGlobalMemoryMutation();
141729
141969
  const handleToggleSetting = async (key, checked) => {
141730
141970
  try {
@@ -141763,7 +142003,7 @@ function MemoryTab({ org, username }) {
141763
142003
  if (!isConfigError && memsearchStatus && !memsearchStatus.enable_memsearch) {
141764
142004
  return (jsx("div", { className: "max-w-2xl", children: jsx("div", { className: "rounded-lg border px-6 py-8 text-center", style: { borderColor: 'oklch(.922 0 0)' }, children: jsx("p", { className: "text-sm text-gray-500", children: t('memoryMemoryTab.memoryFeatureDisabled') }) }) }));
141765
142005
  }
141766
- return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "space-y-4", children: [jsx("h4", { className: "text-sm font-semibold text-gray-700 dark:text-gray-300 tracking-wide", children: t('memoryMemoryTab.sectionMemoryPersonalization') }), jsxs("div", { className: "flex items-center justify-between rounded-lg border px-6 py-5", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex-1 mr-4", children: [jsx("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: t('memoryMemoryTab.autoCaptureLabelTitle') }), jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: t('memoryMemoryTab.autoCaptureLabelDesc') })] }), jsx(Switch, { checked: (_a = settings === null || settings === void 0 ? void 0 : settings.auto_capture_enabled) !== null && _a !== void 0 ? _a : false, onCheckedChange: (checked) => handleToggleSetting('auto_capture_enabled', checked), disabled: isUpdatingSettings, "aria-label": t('memoryMemoryTab.autoCaptureAriaLabel', {
142006
+ return (jsxs("div", { className: "space-y-8", children: [!isPreview && (jsxs("div", { className: "space-y-4", children: [!isPreview && (jsx("h4", { className: "text-sm font-semibold text-gray-700 dark:text-gray-300 tracking-wide", children: t('memoryMemoryTab.sectionMemoryPersonalization') })), jsxs("div", { className: "flex items-center justify-between rounded-lg border px-6 py-5", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex-1 mr-4", children: [jsx("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: t('memoryMemoryTab.autoCaptureLabelTitle') }), jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: t('memoryMemoryTab.autoCaptureLabelDesc') })] }), jsx(Switch, { checked: (_a = settings === null || settings === void 0 ? void 0 : settings.auto_capture_enabled) !== null && _a !== void 0 ? _a : false, onCheckedChange: (checked) => handleToggleSetting('auto_capture_enabled', checked), disabled: isUpdatingSettings, "aria-label": t('memoryMemoryTab.autoCaptureAriaLabel', {
141767
142007
  state: (settings === null || settings === void 0 ? void 0 : settings.auto_capture_enabled)
141768
142008
  ? t('memoryMemoryTab.stateEnabled')
141769
142009
  : t('memoryMemoryTab.stateDisabled'),
@@ -141771,9 +142011,13 @@ function MemoryTab({ org, username }) {
141771
142011
  state: (settings === null || settings === void 0 ? void 0 : settings.use_memory_in_responses)
141772
142012
  ? t('memoryMemoryTab.stateEnabled')
141773
142013
  : t('memoryMemoryTab.stateDisabled'),
141774
- }), className: "cursor-pointer data-[state=checked]:bg-blue-500 flex-shrink-0" })] })] }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between", children: [jsx("h4", { className: "text-sm font-semibold text-gray-700 dark:text-gray-300 tracking-wide", children: t('memoryMemoryTab.sectionMyMemories') }), jsxs(Button$1, { variant: "outline", size: "sm", onClick: () => setIsAddDialogOpen(true), className: "text-xs", children: [jsx(Plus, { className: "h-3 w-3 mr-1" }), t('memoryMemoryTab.addMemoryButton')] })] }), isLoadingMemories ? (jsx("div", { className: "space-y-3", children: [1, 2, 3].map((i) => (jsx(Skeleton, { className: "h-16 w-full rounded-lg" }, i))) })) : ((_c = memoriesData === null || memoriesData === void 0 ? void 0 : memoriesData.results) === null || _c === void 0 ? void 0 : _c.length) ? (jsx("div", { className: "space-y-3", children: memoriesData.results.map((memory) => (jsxs("div", { className: "group flex items-start gap-3 rounded-lg border px-4 py-3", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("div", { className: "flex-shrink-0 mt-0.5", children: memory.is_auto_generated ? (jsx(Bot, { className: "h-4 w-4 text-blue-500", "aria-label": t('memoryMemoryTab.autoGeneratedMemoryAriaLabel') })) : (jsx(User, { className: "h-4 w-4 text-gray-400", "aria-label": t('memoryMemoryTab.manuallyAddedMemoryAriaLabel') })) }), jsxs("div", { className: "flex-1 min-w-0", children: [jsx("p", { className: "text-sm text-gray-800 dark:text-gray-200", children: memory.content }), jsxs("p", { className: "text-xs text-gray-400 mt-1", children: [new Date(memory.created_at).toLocaleDateString(), memory.is_auto_generated && (jsx("span", { className: "ml-2 inline-flex items-center rounded-full bg-blue-50 px-1.5 py-0.5 text-[10px] font-medium text-blue-600", children: t('memoryMemoryTab.autoBadge') }))] })] }), jsx("button", { type: "button", onClick: () => handleDeleteMemory(memory.id), disabled: deletingId === memory.id, className: "flex-shrink-0 opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded hover:bg-gray-100 text-gray-400 hover:text-gray-600 focus:opacity-100 focus:outline-none focus:ring-2 focus:ring-gray-300", "aria-label": t('memoryMemoryTab.deleteMemoryAriaLabel', {
142014
+ }), className: "cursor-pointer data-[state=checked]:bg-blue-500 flex-shrink-0" })] })] })), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between", children: [jsx("h4", { className: "text-sm font-semibold text-gray-700 dark:text-gray-300 tracking-wide", children: isPreview
142015
+ ? t('memoryMemoryTab.sectionMyMemoriesPreview')
142016
+ : t('memoryMemoryTab.sectionMyMemories') }), !isPreview && (jsxs(Button$1, { variant: "outline", size: "sm", onClick: () => setIsAddDialogOpen(true), className: "text-xs", children: [jsx(Plus, { className: "h-3 w-3 mr-1" }), t('memoryMemoryTab.addMemoryButton')] }))] }), isLoadingMemories ? (jsx("div", { className: "space-y-3", children: [1, 2, 3].map((i) => (jsx(Skeleton, { className: "h-16 w-full rounded-lg" }, i))) })) : memories.length ? (jsx("div", { className: "space-y-3", children: memories.map((memory) => (jsxs("div", { className: "group flex items-start gap-3 rounded-lg border px-4 py-3", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("div", { className: "flex-shrink-0 mt-0.5", children: memory.is_auto_generated ? (jsx(Bot, { className: "h-4 w-4 text-blue-500", "aria-label": t('memoryMemoryTab.autoGeneratedMemoryAriaLabel') })) : (jsx(User, { className: "h-4 w-4 text-gray-400", "aria-label": t('memoryMemoryTab.manuallyAddedMemoryAriaLabel') })) }), jsxs("div", { className: "flex-1 min-w-0", children: [jsx("p", { className: "text-sm text-gray-800 dark:text-gray-200", children: memory.content }), jsxs("p", { className: "text-xs text-gray-400 mt-1", children: [new Date(memory.created_at).toLocaleDateString(), memory.is_auto_generated && (jsx("span", { className: "ml-2 inline-flex items-center rounded-full bg-blue-50 px-1.5 py-0.5 text-[10px] font-medium text-blue-600", children: t('memoryMemoryTab.autoBadge') }))] })] }), !isPreview && (jsx("button", { type: "button", onClick: () => handleDeleteMemory(memory.id), disabled: deletingId === memory.id, className: "flex-shrink-0 opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded hover:bg-gray-100 text-gray-400 hover:text-gray-600 focus:opacity-100 focus:outline-none focus:ring-2 focus:ring-gray-300", "aria-label": t('memoryMemoryTab.deleteMemoryAriaLabel', {
141775
142017
  excerpt: memory.content.substring(0, 30),
141776
- }), children: deletingId === memory.id ? (jsx("div", { className: "w-4 h-4 border-2 border-gray-500 border-t-transparent rounded-full animate-spin" })) : (jsx(Trash2, { className: "h-4 w-4" })) })] }, memory.id))) })) : (jsx("div", { className: "rounded-lg border px-6 py-8 text-center", style: { borderColor: 'oklch(.922 0 0)' }, children: jsx("p", { className: "text-sm text-gray-500", children: t('memoryMemoryTab.noMemoriesYet') }) })), totalPages > 1 && (jsx(IblPagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: setCurrentPage, disabled: isLoadingMemories }))] }), jsx(AddMemoryDialog, { open: isAddDialogOpen, onOpenChange: setIsAddDialogOpen, org: org, username: username })] }));
142018
+ }), children: deletingId === memory.id ? (jsx("div", { className: "w-4 h-4 border-2 border-gray-500 border-t-transparent rounded-full animate-spin" })) : (jsx(Trash2, { className: "h-4 w-4" })) }))] }, `${'mentor_id' in memory ? memory.mentor_id : 'global'}-${memory.id}`))) })) : (jsx("div", { className: "rounded-lg border px-6 py-8 text-center", style: { borderColor: 'oklch(.922 0 0)' }, children: jsx("p", { className: "text-sm text-gray-500", children: isPreview
142019
+ ? t('memoryMemoryTab.noMemoriesYetPreview')
142020
+ : t('memoryMemoryTab.noMemoriesYet') }) })), totalPages > 1 && (jsx(IblPagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: setCurrentPage, disabled: isLoadingMemories }))] }), jsx(AddMemoryDialog, { open: isAddDialogOpen, onOpenChange: setIsAddDialogOpen, org: org, username: username })] }));
141777
142021
  }
141778
142022
 
141779
142023
  // One entry per chat-privacy mode. `description` is read inline on each
@@ -143872,7 +144116,9 @@ const PopoverContent = React.forwardRef(({ className, align = 'center', sideOffs
143872
144116
  });
143873
144117
  PopoverContent.displayName = Content2$3.displayName;
143874
144118
 
144119
+ const PAGE_SIZE$5 = 10;
143875
144120
  function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false, }) {
144121
+ var _a, _b;
143876
144122
  const t = useT();
143877
144123
  const dispatch = useDispatch();
143878
144124
  const [page, setPage] = useState(1);
@@ -143884,14 +144130,35 @@ function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false,
143884
144130
  const [updatingUserIds, setUpdatingUserIds] = useState(new Set());
143885
144131
  const [openPolicyPopover, setOpenPolicyPopover] = useState(null);
143886
144132
  const [selectedUser, setSelectedUser] = useState(null);
143887
- const { data: users, refetch: refetchPlatformUsers, isLoading, } = usePlatformUsersQuery({
144133
+ const { currentTenant } = useCurrentTenant();
144134
+ const rbacPermissions = useSelector(selectRbacPermissions);
144135
+ // A pure watcher administers nothing: the platform users endpoint 403s for
144136
+ // them, so they get the RBAC-scoped list of users they may read instead —
144137
+ // name and email only, with no invite, role, policy or status controls.
144138
+ const isWatcher = isPureWatcher(rbacPermissions, currentTenant);
144139
+ const { data: users, refetch: refetchPlatformUsers, isLoading: isLoadingPlatformUsers, } = usePlatformUsersQuery({
143888
144140
  page,
143889
- page_size: 10,
144141
+ page_size: PAGE_SIZE$5,
143890
144142
  platform_key: tenant,
143891
144143
  platform_org: tenant,
143892
144144
  query: debouncedSearchQuery,
143893
144145
  return_policies: 'true',
143894
- });
144146
+ }, { skip: isWatcher });
144147
+ // The accessible endpoint scopes itself to the caller's platform from their
144148
+ // token, so it takes no tenant param. It also filters per field instead of
144149
+ // with one search param, hence the "@" routing the term to `email` and
144150
+ // anything else to `username`.
144151
+ const { data: accessibleUsers, isLoading: isLoadingAccessibleUsers } = useGetAccessibleUsersQuery({
144152
+ // TODO to use required_action: 'Ibl.Core/Users/read',
144153
+ required_action: 'Ibl.Mentor/Memory/list',
144154
+ page,
144155
+ page_size: PAGE_SIZE$5,
144156
+ sort: 'name',
144157
+ ...(debouncedSearchQuery.includes('@')
144158
+ ? { email: debouncedSearchQuery }
144159
+ : { username: debouncedSearchQuery }),
144160
+ }, { skip: !isWatcher });
144161
+ const isLoading = isWatcher ? isLoadingAccessibleUsers : isLoadingPlatformUsers;
143895
144162
  useEffect(() => {
143896
144163
  const handler = setTimeout(() => {
143897
144164
  if (searchQuery.length > 2) {
@@ -143908,7 +144175,10 @@ function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false,
143908
144175
  }, [searchQuery]);
143909
144176
  const handlePageChange = async (newPage) => {
143910
144177
  setPage(newPage);
143911
- await refetchPlatformUsers();
144178
+ // The watcher list is served by the other (skipped) query — changing `page`
144179
+ // is enough to refetch it.
144180
+ if (!isWatcher)
144181
+ await refetchPlatformUsers();
143912
144182
  };
143913
144183
  const handleUserRoleChange = async (user) => {
143914
144184
  const userId = user === null || user === void 0 ? void 0 : user.user_id;
@@ -144026,8 +144296,6 @@ function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false,
144026
144296
  });
144027
144297
  }
144028
144298
  };
144029
- // Calculate total pages
144030
- const totalPages = users ? Math.ceil(users.count / 10) : 0; // Assuming 10 users per page
144031
144299
  // Extract allowed policies and user data
144032
144300
  const isResultsWithPolicies = (users === null || users === void 0 ? void 0 : users.results) ? isPoliciesResponse(users.results) : false;
144033
144301
  const allowedPolicies = isResultsWithPolicies
@@ -144036,31 +144304,55 @@ function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false,
144036
144304
  const userData = isResultsWithPolicies
144037
144305
  ? (users === null || users === void 0 ? void 0 : users.results).data
144038
144306
  : [];
144039
- return (jsxs("div", { className: "mt-4", children: [jsxs("div", { className: "flex justify-between items-center gap-1", children: [jsxs("div", { className: "relative mb-6 max-w-sm", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { type: "text", value: searchQuery, onChange: (event) => setQuerySearch(event.target.value), placeholder: t('tabsUserstab.searchPlaceholder'), className: "pl-10 pr-10 focus:ring-blue-500 focus:border-blue-500 h-[35px]", "aria-label": t('tabsUserstab.searchAriaLabel') }), searchQuery.length > 0 && (searchQuery !== debouncedSearchQuery || isLoading) && (jsx(LoaderCircle, { "data-testid": "search-spinner", className: "absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400 animate-spin", "aria-hidden": "true" }))] }), jsx("div", { className: "mb-6", children: jsx(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white h-[35px]", onClick: onInviteClick, children: t('tabsUserstab.inviteButton') }) })] }), isLoading ? (jsx("div", { className: "flex justify-center items-center h-64", children: jsx(Spinner, {}) })) : (jsxs(Fragment$1, { children: [jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[16%]", children: t('tabsUserstab.columnName') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[25%]", children: t('tabsUserstab.columnEmail') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[16%]", children: t('tabsUserstab.columnRole') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[25%]", children: t('tabsUserstab.columnPolicies') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[18%]", children: t('tabsUserstab.columnStatus') })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [userData.map((user, index) => (jsxs("tr", { onClick: () => setSelectedUser(user), className: "cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors", children: [jsx("td", { "aria-label": 'user-management-name-column', className: "px-6 py-4 text-gray-900 dark:text-gray-100 text-sm whitespace-nowrap overflow-hidden text-ellipsis max-w-0", children: jsx("button", { type: "button", onClick: (e) => {
144040
- e.stopPropagation();
144041
- setSelectedUser(user);
144042
- }, className: "block max-w-full truncate text-left hover:text-blue-600 hover:underline focus:outline-none focus:text-blue-600", "aria-label": t('tabsUserstab.viewProfileAriaLabel', { name: user.name }), children: user.name }) }), jsx("td", { "aria-label": 'user-management-email-column', className: "px-6 py-4 text-gray-600 dark:text-gray-300 text-sm max-w-0", children: jsx("div", { className: "truncate", children: user.email }) }), jsx("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: jsxs(Select$1, { value: user.is_admin ? 'admin' : 'student', onValueChange: () => handleUserRoleChange(user), children: [jsx(SelectTrigger, { className: "w-full text-sm", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { className: "text-sm", children: [jsx(SelectItem, { value: "admin", children: t('tabsUserstab.roleAdmin') }), jsx(SelectItem, { value: "student", children: t('tabsUserstab.roleUser') })] })] }) }), jsx("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: jsxs(Popover, { modal: true, open: openPolicyPopover === user.user_id, onOpenChange: (open) => setOpenPolicyPopover(open ? user.user_id : null), children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", role: "combobox", "aria-expanded": openPolicyPopover === user.user_id, "aria-label": t('tabsUserstab.selectPoliciesAriaLabel', {
144307
+ const rows = isWatcher
144308
+ ? ((_a = accessibleUsers === null || accessibleUsers === void 0 ? void 0 : accessibleUsers.results) !== null && _a !== void 0 ? _a : []).map((user) => ({
144309
+ key: user.id,
144310
+ name: user.name,
144311
+ email: user.email,
144312
+ username: user.username,
144313
+ isAdmin: false,
144314
+ }))
144315
+ : userData.map((user) => ({
144316
+ key: user.user_id,
144317
+ name: user.name,
144318
+ email: user.email,
144319
+ username: user.username,
144320
+ isAdmin: user.is_admin,
144321
+ managed: user,
144322
+ }));
144323
+ const totalCount = (_b = (isWatcher ? accessibleUsers === null || accessibleUsers === void 0 ? void 0 : accessibleUsers.count : users === null || users === void 0 ? void 0 : users.count)) !== null && _b !== void 0 ? _b : 0;
144324
+ const totalPages = Math.ceil(totalCount / PAGE_SIZE$5);
144325
+ return (jsxs("div", { className: "mt-4", children: [jsxs("div", { className: "flex justify-between items-center gap-1", children: [jsxs("div", { className: "relative mb-6 max-w-sm", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { type: "text", value: searchQuery, onChange: (event) => setQuerySearch(event.target.value), placeholder: t('tabsUserstab.searchPlaceholder'), className: "pl-10 pr-10 focus:ring-blue-500 focus:border-blue-500 h-[35px]", "aria-label": t('tabsUserstab.searchAriaLabel') }), searchQuery.length > 0 && (searchQuery !== debouncedSearchQuery || isLoading) && (jsx(LoaderCircle, { "data-testid": "search-spinner", className: "absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400 animate-spin", "aria-hidden": "true" }))] }), !isWatcher && (jsx("div", { className: "mb-6", children: jsx(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white h-[35px]", onClick: onInviteClick, children: t('tabsUserstab.inviteButton') }) }))] }), isLoading ? (jsx("div", { className: "flex justify-center items-center h-64", children: jsx(Spinner, {}) })) : (jsxs(Fragment$1, { children: [jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: `px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 ${isWatcher ? 'w-[40%]' : 'w-[16%]'}`, children: t('tabsUserstab.columnName') }), jsx("th", { className: `px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 ${isWatcher ? 'w-[60%]' : 'w-[25%]'}`, children: t('tabsUserstab.columnEmail') }), !isWatcher && (jsxs(Fragment$1, { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[16%]", children: t('tabsUserstab.columnRole') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[25%]", children: t('tabsUserstab.columnPolicies') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[18%]", children: t('tabsUserstab.columnStatus') })] }))] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [rows.map((row) => {
144326
+ // Only set on the admin path — see {@link UserRow}.
144327
+ const user = row.managed;
144328
+ return (jsxs("tr", { onClick: () => setSelectedUser(row), className: "cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors", children: [jsx("td", { "aria-label": 'user-management-name-column', className: "px-6 py-4 text-gray-900 dark:text-gray-100 text-sm whitespace-nowrap overflow-hidden text-ellipsis max-w-0", children: jsx("button", { type: "button", onClick: (e) => {
144329
+ e.stopPropagation();
144330
+ setSelectedUser(row);
144331
+ }, className: "block max-w-full truncate text-left hover:text-blue-600 hover:underline focus:outline-none focus:text-blue-600", "aria-label": t('tabsUserstab.viewProfileAriaLabel', { name: row.name }), children: row.name }) }), jsx("td", { "aria-label": 'user-management-email-column', className: "px-6 py-4 text-gray-600 dark:text-gray-300 text-sm max-w-0", children: jsx("div", { className: "truncate", children: row.email }) }), user && (jsxs(Fragment$1, { children: [jsx("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: jsxs(Select$1, { value: user.is_admin ? 'admin' : 'student', onValueChange: () => handleUserRoleChange(user), children: [jsx(SelectTrigger, { className: "w-full text-sm", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { className: "text-sm", children: [jsx(SelectItem, { value: "admin", children: t('tabsUserstab.roleAdmin') }), jsx(SelectItem, { value: "student", children: t('tabsUserstab.roleUser') })] })] }) }), jsx("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: jsxs(Popover, { modal: true, open: openPolicyPopover === user.user_id, onOpenChange: (open) => setOpenPolicyPopover(open ? user.user_id : null), children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", role: "combobox", "aria-expanded": openPolicyPopover === user.user_id, "aria-label": t('tabsUserstab.selectPoliciesAriaLabel', {
144332
+ name: user.name,
144333
+ }), className: "w-full justify-between text-sm h-9 font-normal", disabled: updatingUserIds.has(user === null || user === void 0 ? void 0 : user.user_id), children: [jsx("span", { className: "truncate", children: user.is_admin
144334
+ ? t('tabsUserstab.allPoliciesSelected', {
144335
+ count: allowedPolicies.length,
144336
+ })
144337
+ : user.policies && user.policies.length > 0
144338
+ ? t('tabsUserstab.nPoliciesSelected', {
144339
+ count: user.policies.length,
144340
+ })
144341
+ : t('tabsUserstab.noPolicies') }), openPolicyPopover === user.user_id ? (jsx(ChevronUp, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })) : (jsx(ChevronDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" }))] }) }), jsx(PopoverContent, { className: "w-64 p-3", align: "start", children: jsxs("div", { className: "space-y-2", children: [jsx("div", { className: "text-sm font-medium mb-2", children: t('tabsUserstab.selectPoliciesHeading') }), allowedPolicies.map((policy) => {
144342
+ var _a;
144343
+ return (jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: `${user.user_id}-${policy}`, checked: user.is_admin || ((_a = user.policies) === null || _a === void 0 ? void 0 : _a.includes(policy)), onCheckedChange: (checked) => handlePolicyChange(user, policy, checked), disabled: user.is_admin || updatingUserIds.has(user === null || user === void 0 ? void 0 : user.user_id), "aria-label": t('tabsUserstab.togglePolicyAriaLabel', {
144344
+ policy,
144345
+ name: user.name,
144346
+ }) }), jsx("label", { htmlFor: `${user.user_id}-${policy}`, className: `text-sm font-normal ${user.is_admin ? 'cursor-default' : 'cursor-pointer'}`, children: policy })] }, policy));
144347
+ })] }) })] }) }), jsx("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: jsx(Switch, { checked: user.active, onCheckedChange: (checked) => handleUserStatusChange(user, checked), disabled: updatingUserIds.has(user === null || user === void 0 ? void 0 : user.user_id), "aria-label": t('tabsUserstab.toggleStatusAriaLabel', {
144043
144348
  name: user.name,
144044
- }), className: "w-full justify-between text-sm h-9 font-normal", disabled: updatingUserIds.has(user === null || user === void 0 ? void 0 : user.user_id), children: [jsx("span", { className: "truncate", children: user.is_admin
144045
- ? t('tabsUserstab.allPoliciesSelected', {
144046
- count: allowedPolicies.length,
144047
- })
144048
- : user.policies && user.policies.length > 0
144049
- ? t('tabsUserstab.nPoliciesSelected', {
144050
- count: user.policies.length,
144051
- })
144052
- : t('tabsUserstab.noPolicies') }), openPolicyPopover === user.user_id ? (jsx(ChevronUp, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })) : (jsx(ChevronDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" }))] }) }), jsx(PopoverContent, { className: "w-64 p-3", align: "start", children: jsxs("div", { className: "space-y-2", children: [jsx("div", { className: "text-sm font-medium mb-2", children: t('tabsUserstab.selectPoliciesHeading') }), allowedPolicies.map((policy) => {
144053
- var _a;
144054
- return (jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: `${user.user_id}-${policy}`, checked: user.is_admin || ((_a = user.policies) === null || _a === void 0 ? void 0 : _a.includes(policy)), onCheckedChange: (checked) => handlePolicyChange(user, policy, checked), disabled: user.is_admin || updatingUserIds.has(user === null || user === void 0 ? void 0 : user.user_id), "aria-label": t('tabsUserstab.togglePolicyAriaLabel', {
144055
- policy,
144056
- name: user.name,
144057
- }) }), jsx("label", { htmlFor: `${user.user_id}-${policy}`, className: `text-sm font-normal ${user.is_admin ? 'cursor-default' : 'cursor-pointer'}`, children: policy })] }, policy));
144058
- })] }) })] }) }), jsx("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: jsx(Switch, { checked: user.active, onCheckedChange: (checked) => handleUserStatusChange(user, checked), disabled: updatingUserIds.has(user === null || user === void 0 ? void 0 : user.user_id), "aria-label": t('tabsUserstab.toggleStatusAriaLabel', { name: user.name }), className: "cursor-pointer data-[state=checked]:bg-blue-500 disabled:cursor-not-allowed disabled:opacity-50" }) })] }, index))), (!userData || userData.length === 0) && (jsx("tr", { children: jsx("td", { colSpan: 5, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: t('tabsUserstab.noUsersFound') }) }))] })] }) }), jsx(AdvancedPagination, { variant: "footer", className: "-mx-6 -mb-6 mt-4 rounded-b-lg", totalPages: totalPages, currentPage: page, onPageChange: (_page) => handlePageChange(_page), totalCount: users === null || users === void 0 ? void 0 : users.count, itemsPerPage: 10, itemLabel: "users" })] })), selectedUser && (jsx(Dialog, { open: !!selectedUser, onOpenChange: (open) => {
144349
+ }), className: "cursor-pointer data-[state=checked]:bg-blue-500 disabled:cursor-not-allowed disabled:opacity-50" }) })] }))] }, row.key));
144350
+ }), rows.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: isWatcher ? 2 : 5, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: t('tabsUserstab.noUsersFound') }) }))] })] }) }), jsx(AdvancedPagination, { variant: "footer", className: "-mx-6 -mb-6 mt-4 rounded-b-lg", totalPages: totalPages, currentPage: page, onPageChange: (_page) => handlePageChange(_page), totalCount: totalCount, itemsPerPage: PAGE_SIZE$5, itemLabel: "users" })] })), selectedUser && (jsx(Dialog, { open: !!selectedUser, onOpenChange: (open) => {
144059
144351
  if (!open)
144060
144352
  setSelectedUser(null);
144061
- }, children: jsxs(DialogContent, { autoFocus: false, className: "max-w-7xl w-[85vw] p-0 gap-0 overflow-hidden bg-white profile-component-dialog", style: { height: '85vh', display: 'flex', flexDirection: 'column' }, children: [jsx(DialogTitle, { className: "sr-only", children: t('tabsUserstab.profileDialogTitle') }), jsx(DialogDescription, { className: "sr-only", children: t('tabsUserstab.profileDialogDescription') }), jsx(Profile, { tenant: tenant, tenants: [], username: selectedUser.username, isAdmin: selectedUser.is_admin, currentSPA: currentSpa, onClose: () => setSelectedUser(null), customization: {
144353
+ }, children: jsxs(DialogContent, { autoFocus: false, className: "max-w-7xl w-[85vw] p-0 gap-0 overflow-hidden bg-white profile-component-dialog", style: { height: '85vh', display: 'flex', flexDirection: 'column' }, children: [jsx(DialogTitle, { className: "sr-only", children: t('tabsUserstab.profileDialogTitle') }), jsx(DialogDescription, { className: "sr-only", children: t('tabsUserstab.profileDialogDescription') }), jsx(Profile, { tenant: tenant, tenants: [], username: selectedUser.username, isAdmin: selectedUser.isAdmin, currentSPA: currentSpa, onClose: () => setSelectedUser(null), customization: {
144062
144354
  showGradebookTab: showGradebookTab,
144063
- } })] }) }))] }));
144355
+ }, enableMemoryTab: true })] }) }))] }));
144064
144356
  }
144065
144357
 
144066
144358
  // Permission options for teams access
@@ -146968,7 +147260,7 @@ function BlocksView({ platformKey, onBack, }) {
146968
147260
 
146969
147261
  const FILTER_ORDER = ['all', ...APPLICATION_STATUSES];
146970
147262
  const PAGE_SIZE$3 = 20;
146971
- const SEARCH_DEBOUNCE_MS = 300;
147263
+ const SEARCH_DEBOUNCE_MS$1 = 300;
146972
147264
  /**
146973
147265
  * The public application URL on the auth SPA for one form of a platform
146974
147266
  * (`<auth-url>/applications/<platform-key>/<form-id>?app=<spa>`), or null when
@@ -147077,7 +147369,7 @@ function SubmissionsPipeline({ platformKey, form, onBack, onOpen, }) {
147077
147369
  const timer = setTimeout(() => {
147078
147370
  setDebouncedSearch(search.trim());
147079
147371
  setDebouncedCandidateFilter(candidateFilter.trim());
147080
- }, SEARCH_DEBOUNCE_MS);
147372
+ }, SEARCH_DEBOUNCE_MS$1);
147081
147373
  return () => clearTimeout(timer);
147082
147374
  }, [search, candidateFilter]);
147083
147375
  // New filters restart paging.
@@ -151814,7 +152106,7 @@ function SearchableMultiSelect({ items, selectedItems, onSelectionChange, search
151814
152106
  }) }))] }));
151815
152107
  }
151816
152108
 
151817
- function useDebouncedValue$3(value, delay) {
152109
+ function useDebouncedValue$4(value, delay) {
151818
152110
  const [debouncedValue, setDebouncedValue] = React__default.useState(value);
151819
152111
  React__default.useEffect(() => {
151820
152112
  const timer = window.setTimeout(() => setDebouncedValue(value), delay);
@@ -151859,8 +152151,8 @@ function TokenPolicyFields({ tenantKey, mode, onModeChange, policies, onPolicies
151859
152151
  const t = useT();
151860
152152
  const [policySearch, setPolicySearch] = React__default.useState('');
151861
152153
  const [groupSearch, setGroupSearch] = React__default.useState('');
151862
- const debouncedPolicySearch = useDebouncedValue$3(policySearch, RBAC_SEARCH_DEBOUNCE_MS);
151863
- const debouncedGroupSearch = useDebouncedValue$3(groupSearch, RBAC_SEARCH_DEBOUNCE_MS);
152154
+ const debouncedPolicySearch = useDebouncedValue$4(policySearch, RBAC_SEARCH_DEBOUNCE_MS);
152155
+ const debouncedGroupSearch = useDebouncedValue$4(groupSearch, RBAC_SEARCH_DEBOUNCE_MS);
151864
152156
  const canWriteMode = canWriteField(fieldPermissions, 'mode');
151865
152157
  const canWritePolicies = canWriteField(fieldPermissions, 'policies_to_add') ||
151866
152158
  canWriteField(fieldPermissions, 'policies_to_remove');
@@ -184641,7 +184933,7 @@ function PolicyConfigDialog({ open, onOpenChange, config, onSave, }) {
184641
184933
  return (jsx(Dialog, { open: open, onOpenChange: handleOpenChange, children: jsxs(DialogContent, { className: "sm:max-w-md", "aria-describedby": "policy-config-description", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { children: t('componentsPolicyConfigDialog.title') }), jsx(DialogDescription, { id: "policy-config-description", children: t('componentsPolicyConfigDialog.description') })] }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { children: [jsx(Label$2, { htmlFor: "policy-config-role-name", className: "text-sm font-medium text-gray-700", children: t('componentsPolicyConfigDialog.roleName') }), jsx(Input, { id: "policy-config-role-name", value: (_a = draft === null || draft === void 0 ? void 0 : draft.role_name) !== null && _a !== void 0 ? _a : '', disabled: true, className: "bg-gray-50" })] }), jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: "policy-config-enabled", checked: (_b = draft === null || draft === void 0 ? void 0 : draft.enabled) !== null && _b !== void 0 ? _b : true, onCheckedChange: (checked) => updateDraft({ enabled: checked === true }) }), jsx(Label$2, { htmlFor: "policy-config-enabled", className: "text-sm font-medium text-gray-700 cursor-pointer", children: t('componentsPolicyConfigDialog.enabled') })] }), jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: "policy-config-notify-assignment", checked: (_c = draft === null || draft === void 0 ? void 0 : draft.notify_on_assignment) !== null && _c !== void 0 ? _c : true, onCheckedChange: (checked) => updateDraft({ notify_on_assignment: checked === true }) }), jsx(Label$2, { htmlFor: "policy-config-notify-assignment", className: "text-sm font-medium text-gray-700 cursor-pointer", children: t('componentsPolicyConfigDialog.notifyOnAssignment') })] }), jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: "policy-config-notify-removal", checked: (_d = draft === null || draft === void 0 ? void 0 : draft.notify_on_removal) !== null && _d !== void 0 ? _d : true, onCheckedChange: (checked) => updateDraft({ notify_on_removal: checked === true }) }), jsx(Label$2, { htmlFor: "policy-config-notify-removal", className: "text-sm font-medium text-gray-700 cursor-pointer", children: t('componentsPolicyConfigDialog.notifyOnRemoval') })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "policy-config-subject", className: "text-sm font-medium text-gray-700", children: t('componentsPolicyConfigDialog.subject') }), jsx(Textarea, { id: "policy-config-subject", value: (_e = draft === null || draft === void 0 ? void 0 : draft.subject) !== null && _e !== void 0 ? _e : '', onChange: (event) => updateDraft({ subject: event.target.value }), placeholder: t('componentsPolicyConfigDialog.subjectPlaceholder'), rows: 3 }), jsx("p", { className: "text-xs text-gray-500", children: t('componentsPolicyConfigDialog.subjectHint') })] })] }), jsxs(DialogFooter, { className: "pt-2", children: [jsx(Button$1, { variant: "outline", onClick: () => onOpenChange(false), children: t('componentsPolicyConfigDialog.cancel') }), jsx(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white", onClick: handleSave, disabled: !config, children: t('componentsPolicyConfigDialog.saveConfiguration') })] })] }) }));
184642
184934
  }
184643
184935
 
184644
- function useDebouncedValue$2(value, delay) {
184936
+ function useDebouncedValue$3(value, delay) {
184645
184937
  const [debouncedValue, setDebouncedValue] = useState(value);
184646
184938
  useEffect(() => {
184647
184939
  const timer = window.setTimeout(() => setDebouncedValue(value), delay);
@@ -184670,7 +184962,7 @@ function ProactiveSettingsSection({ platformKey, username, isSaving, userLocalTi
184670
184962
  const [isPromptDialogOpen, setIsPromptDialogOpen] = useState(false);
184671
184963
  const customIntervalErrorId = 'proactive-custom-interval-error';
184672
184964
  const executionTimeErrorId = 'proactive-execution-time-error';
184673
- const debouncedMentorSearch = useDebouncedValue$2(mentorSearch, 300);
184965
+ const debouncedMentorSearch = useDebouncedValue$3(mentorSearch, 300);
184674
184966
  const showUseLocalTimezone = periodicTimezone !== userLocalTimezone;
184675
184967
  const shouldFetchMentors = Boolean(platformKey) && Boolean(username);
184676
184968
  const { data: mentorsResponse, isLoading: isMentorsLoading } = useGetMentorsQuery({
@@ -184767,7 +185059,7 @@ function ProactiveSettingsSection({ platformKey, username, isSaving, userLocalTi
184767
185059
  }) })] })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "periodic-execution-time", className: "text-sm font-medium text-gray-700", children: t('componentsProactiveSettingsSection.executionTimeLabel') }), jsx(Input, { id: "periodic-execution-time", type: "time", value: periodicExecutionTime, onChange: (event) => onExecutionTimeChange(event.target.value), disabled: isSaving, "aria-invalid": isExecutionTimeMissing, "aria-describedby": isExecutionTimeMissing ? executionTimeErrorId : undefined }), renderTimezoneNotice(t('componentsProactiveSettingsSection.chooseWhenNotice'))] })] })), periodicFrequency !== 'CUSTOM' && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "periodic-execution-time", className: "text-sm font-medium text-gray-700", children: t('componentsProactiveSettingsSection.executionTimeLabel') }), jsx(Input, { id: "periodic-execution-time", type: "time", value: periodicExecutionTime, onChange: (event) => onExecutionTimeChange(event.target.value), disabled: isSaving }), renderTimezoneNotice(t('componentsProactiveSettingsSection.optionalChooseWhenNotice'))] })), isProactiveInvalid && (jsxs("div", { className: "space-y-1", "aria-live": "polite", children: [isCustomIntervalMissing && (jsx("p", { id: customIntervalErrorId, className: "text-sm text-red-600", role: "alert", children: t('componentsProactiveSettingsSection.customIntervalError') })), isExecutionTimeMissing && (jsx("p", { id: executionTimeErrorId, className: "text-sm text-red-600", role: "alert", children: t('componentsProactiveSettingsSection.executionTimeError') }))] })), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", htmlFor: "periodic-mentors", children: t('componentsProactiveSettingsSection.periodicAgentsLabel') }), jsx(SearchableMultiSelect, { items: mentorOptions, selectedItems: selectedMentors, onSelectionChange: handleMentorSelectionChange, searchQuery: mentorSearch, onSearchChange: setMentorSearch, isLoading: isMentorsLoading, placeholder: t('componentsProactiveSettingsSection.searchAgentsPlaceholder'), getItemValue: (mentor) => mentor.unique_id, getItemLabel: (mentor) => mentor.name ? `${mentor.name} (${mentor.unique_id})` : mentor.unique_id, onSelectedItemAction: handleEditMentorPrompt, selectedItemActionIcon: jsx(SquarePen, { className: "h-3 w-3", "aria-hidden": "true" }), selectedItemActionAriaLabel: t('componentsProactiveSettingsSection.editAgentPromptAriaLabel'), inputId: "periodic-mentors", ariaDescribedBy: "periodic-mentors-help", className: "max-w-full" }), jsx("p", { id: "periodic-mentors-help", className: "text-xs text-gray-500", children: t('componentsProactiveSettingsSection.periodicAgentsHelp') })] })] }), jsx(MentorPromptDialog, { open: isPromptDialogOpen, onOpenChange: setIsPromptDialogOpen, mentor: activePromptMentor, initialPrompt: activePromptMentor ? ((_b = mentorPrompts[activePromptMentor.id]) !== null && _b !== void 0 ? _b : '') : '', onSave: handlePromptSave })] }));
184768
185060
  }
184769
185061
 
184770
- function useDebouncedValue$1(value, delay) {
185062
+ function useDebouncedValue$2(value, delay) {
184771
185063
  const [debouncedValue, setDebouncedValue] = useState(value);
184772
185064
  useEffect(() => {
184773
185065
  const timer = window.setTimeout(() => setDebouncedValue(value), delay);
@@ -184799,7 +185091,7 @@ function PolicyAssignmentSection({ platformKey, isSaving, notifyOnAssignment, on
184799
185091
  const [isPolicyConfigDialogOpen, setIsPolicyConfigDialogOpen] = useState(false);
184800
185092
  // Track the last initialized data to detect when new data arrives
184801
185093
  const lastInitializedRef = useRef('');
184802
- const debouncedPolicySearch = useDebouncedValue$1(policySearch, 300);
185094
+ const debouncedPolicySearch = useDebouncedValue$2(policySearch, 300);
184803
185095
  const shouldFetchPolicies = Boolean(platformKey);
184804
185096
  const { data: policiesResponse, isLoading: isPoliciesLoading } = useGetRbacPoliciesQuery({ platformKey }, { skip: !shouldFetchPolicies });
184805
185097
  const policyOptions = useMemo(() => {
@@ -184894,7 +185186,7 @@ function PolicyAssignmentSection({ platformKey, isSaving, notifyOnAssignment, on
184894
185186
  return (jsxs(Fragment$1, { children: [jsxs("div", { className: "space-y-4 border-t border-gray-200 pt-4", children: [jsxs("div", { className: "space-y-1", children: [jsx("h3", { className: "text-sm font-semibold text-gray-900", children: t('componentsPolicyAssignmentSection.sectionTitle') }), jsx("p", { className: "text-xs text-gray-500", children: t('componentsPolicyAssignmentSection.sectionDescription') })] }), jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: "policy-notify-assignment", checked: notifyOnAssignment, onCheckedChange: (checked) => onNotifyOnAssignmentChange(checked === true), disabled: isSaving }), jsx(Label$2, { htmlFor: "policy-notify-assignment", className: "text-sm font-medium text-gray-700 cursor-pointer", children: t('componentsPolicyAssignmentSection.notifyOnAssignment') })] }), jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: "policy-notify-removal", checked: notifyOnRemoval, onCheckedChange: (checked) => onNotifyOnRemovalChange(checked === true), disabled: isSaving }), jsx(Label$2, { htmlFor: "policy-notify-removal", className: "text-sm font-medium text-gray-700 cursor-pointer", children: t('componentsPolicyAssignmentSection.notifyOnRemoval') })] })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", htmlFor: "enabled-policies", children: t('componentsPolicyAssignmentSection.enabledPoliciesLabel') }), jsx(SearchableMultiSelect, { items: policyOptions, selectedItems: selectedPolicies, onSelectionChange: handlePolicySelectionChange, searchQuery: policySearch, onSearchChange: setPolicySearch, isLoading: isPoliciesLoading, placeholder: t('componentsPolicyAssignmentSection.searchPlaceholder'), getItemValue: (policy) => String(policy.id), getItemLabel: (policy) => { var _a; return (((_a = policy.role) === null || _a === void 0 ? void 0 : _a.name) ? `${policy.name}` : policy.name); }, onSelectedItemAction: handleEditPolicyConfig, selectedItemActionIcon: jsx(SquarePen, { className: "h-3 w-3", "aria-hidden": "true" }), selectedItemActionAriaLabel: t('componentsPolicyAssignmentSection.editPolicyAriaLabel'), inputId: "enabled-policies", ariaDescribedBy: "enabled-policies-help", className: "max-w-full" }), jsx("p", { id: "enabled-policies-help", className: "text-xs text-gray-500", children: t('componentsPolicyAssignmentSection.enabledPoliciesHelp') })] })] }), jsx(PolicyConfigDialog, { open: isPolicyConfigDialogOpen, onOpenChange: setIsPolicyConfigDialogOpen, config: activePolicyConfig, onSave: handlePolicyConfigSave })] }));
184895
185187
  }
184896
185188
 
184897
- function useDebouncedValue(value, delay) {
185189
+ function useDebouncedValue$1(value, delay) {
184898
185190
  const [debouncedValue, setDebouncedValue] = useState(value);
184899
185191
  useEffect(() => {
184900
185192
  const timer = window.setTimeout(() => setDebouncedValue(value), delay);
@@ -184963,9 +185255,9 @@ function HumanSupportSection({ platformKey, isSaving, recipientMode, onRecipient
184963
185255
  // Track the last initialized data to detect when new data arrives
184964
185256
  const lastInitializedRef = useRef('');
184965
185257
  // Debounced search values
184966
- const debouncedUserSearch = useDebouncedValue(userSearch, 300);
184967
- const debouncedGroupSearch = useDebouncedValue(groupSearch, 300);
184968
- const debouncedPolicySearch = useDebouncedValue(policySearch, 300);
185258
+ const debouncedUserSearch = useDebouncedValue$1(userSearch, 300);
185259
+ const debouncedGroupSearch = useDebouncedValue$1(groupSearch, 300);
185260
+ const debouncedPolicySearch = useDebouncedValue$1(policySearch, 300);
184969
185261
  const shouldFetch = Boolean(platformKey);
184970
185262
  // Fetch users
184971
185263
  const { data: usersResponse, isLoading: isUsersLoading } = usePlatformUsersQuery({
@@ -186655,6 +186947,10 @@ const defaultTabs = [
186655
186947
  label: 'Transcripts',
186656
186948
  value: 'transcripts',
186657
186949
  },
186950
+ {
186951
+ label: 'Memory',
186952
+ value: 'memory',
186953
+ },
186658
186954
  {
186659
186955
  label: 'Costs',
186660
186956
  value: 'financial',
@@ -186670,6 +186966,16 @@ const defaultTabs = [
186670
186966
  ];
186671
186967
  const className = 'inline-flex items-center justify-center whitespace-nowrap rounded-[5px] px-2 sm:px-2.5 pt-1 pb-0.5 sm:text-sm text-gray-500 ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-blue-600 data-[state=active]:font-semibold text-sm font-medium data-[state=active]:bg-[#f5f7fb] data-[state=active]:shadow-none cursor-pointer';
186672
186968
  function AnalyticsLayout({ children, currentPath, basePath, onTabChange, tabs = defaultTabs, activeTabClassName = '', beforeDataReports, excludeTabs = [], }) {
186969
+ const { currentTenant } = useCurrentTenant();
186970
+ const rbacPermissions = useSelector(selectRbacPermissions);
186971
+ // Only a pure watcher narrows the tab strip — everyone else keeps whatever
186972
+ // the caller passed, custom tabs included.
186973
+ const isRestricted = isPureWatcher(rbacPermissions, currentTenant);
186974
+ const allowedTabs = useMemo(() => getVisibleAnalyticsTabs(rbacPermissions, currentTenant), [rbacPermissions, currentTenant]);
186975
+ const canAccessTab = useCallback(
186976
+ // Callers may pass custom tab values, so compare as plain strings: anything
186977
+ // outside the watcher allow-list stays hidden from a restricted user.
186978
+ (tabValue) => !isRestricted || allowedTabs.includes(tabValue), [isRestricted, allowedTabs]);
186673
186979
  useEffect(() => {
186674
186980
  const mainContentContainer = document.getElementById('main-content-container');
186675
186981
  if (mainContentContainer) {
@@ -186689,6 +186995,8 @@ function AnalyticsLayout({ children, currentPath, basePath, onTabChange, tabs =
186689
186995
  return 'topics';
186690
186996
  if (path === `${basePath}/transcripts`)
186691
186997
  return 'transcripts';
186998
+ if (path === `${basePath}/memory`)
186999
+ return 'memory';
186692
187000
  if (path === `${basePath}/financial`)
186693
187001
  return 'financial';
186694
187002
  if (path === `${basePath}/audit`)
@@ -186703,15 +187011,38 @@ function AnalyticsLayout({ children, currentPath, basePath, onTabChange, tabs =
186703
187011
  return 'programs';
186704
187012
  return '';
186705
187013
  };
187014
+ const activeTab = getTabValue(currentPath);
187015
+ const isActiveTabAllowed = canAccessTab(activeTab);
187016
+ // Kept in refs so the guard below only re-runs when the tab or the allowed
187017
+ // set changes — callers pass these inline, so their identity churns.
187018
+ const latestPropsRef = useRef({ onTabChange, excludeTabs });
187019
+ useEffect(() => {
187020
+ latestPropsRef.current = { onTabChange, excludeTabs };
187021
+ });
187022
+ // A watcher who deep-links into a restricted tab (e.g. /analytics/users, or
187023
+ // the Overview landing page) gets sent to the first tab they may open. It has
187024
+ // to skip `excludeTabs`: a host that drops a tab has no route behind it, so
187025
+ // redirecting there would 404 (mentorai excludes courses/programs).
187026
+ useEffect(() => {
187027
+ if (isActiveTabAllowed)
187028
+ return;
187029
+ const { onTabChange: notify, excludeTabs: excluded } = latestPropsRef.current;
187030
+ const fallbackTab = allowedTabs.find((tab) => !excluded.includes(tab));
187031
+ if (fallbackTab === undefined)
187032
+ return;
187033
+ notify(fallbackTab);
187034
+ }, [isActiveTabAllowed, allowedTabs]);
186706
187035
  const handleTabClick = (tabValue) => {
187036
+ if (!canAccessTab(tabValue))
187037
+ return;
186707
187038
  onTabChange(tabValue);
186708
187039
  };
186709
- return (jsxs("div", { className: "flex flex-col flex-1 min-h-0 h-full overflow-hidden overscroll-none bg-[#f5f7fb]", children: [jsx("div", { className: "p-6 pb-0", children: jsx("div", { className: "flex items-center justify-between mb-6", children: jsxs("div", { className: "flex items-center justify-between w-full overflow-x-auto", children: [jsx(Tabs, { className: "mb-6 bg-[#f5f7fb]", value: getTabValue(currentPath), children: jsx(TabsList, { className: "bg-[#f5f7fb]", children: tabs
186710
- .filter((tab) => !excludeTabs.includes(tab.value))
187040
+ return (jsxs("div", { className: "flex flex-col flex-1 min-h-0 h-full overflow-hidden overscroll-none bg-[#f5f7fb]", children: [jsx("div", { className: "p-6 pb-0", children: jsx("div", { className: "flex items-center justify-between mb-6", children: jsxs("div", { className: "flex items-center justify-between w-full overflow-x-auto", children: [jsx(Tabs, { className: "mb-6 bg-[#f5f7fb]", value: activeTab, children: jsx(TabsList, { className: "bg-[#f5f7fb]", children: tabs
187041
+ .filter((tab) => !excludeTabs.includes(tab.value) && canAccessTab(tab.value))
186711
187042
  .map((tab) => {
186712
- const isActive = getTabValue(currentPath) === tab.value;
187043
+ const isActive = activeTab === tab.value;
186713
187044
  return (jsx(TabsTrigger, { value: tab.value, className: cn(className, isActive && activeTabClassName), onClick: () => handleTabClick(tab.value), children: tab.label }, tab.value));
186714
- }) }) }), jsxs("div", { className: "flex items-center gap-4", children: [beforeDataReports, jsx(Tabs, { className: "mb-6 bg-[#f5f7fb]", value: getTabValue(currentPath), children: jsx(TabsList, { className: "bg-[#f5f7fb]", children: jsx(TabsTrigger, { value: "reports", className: cn(className, getTabValue(currentPath) === 'reports' && activeTabClassName), onClick: () => handleTabClick('reports'), children: "Data Reports" }) }) })] })] }) }) }), jsx("div", { className: "flex-1 overflow-auto overscroll-contain scrollbar-none px-6 pb-6 pt-0", children: children })] }));
187045
+ }) }) }), jsxs("div", { className: "flex items-center gap-4", children: [beforeDataReports, canAccessTab('reports') && (jsx(Tabs, { className: "mb-6 bg-[#f5f7fb]", value: activeTab, children: jsx(TabsList, { className: "bg-[#f5f7fb]", children: jsx(TabsTrigger, { value: "reports", className: cn(className, activeTab === 'reports' && activeTabClassName), onClick: () => handleTabClick('reports'), children: "Data Reports" }) }) }))] })] }) }) }), jsx("div", { className: "flex-1 overflow-auto overscroll-contain scrollbar-none px-6 pb-6 pt-0", children: isActiveTabAllowed ? children : null })] }));
186715
187046
  }
186716
187047
 
186717
187048
  const accessTimeData = [
@@ -222565,6 +222896,8 @@ const toTitleCase = (value) => {
222565
222896
  };
222566
222897
  function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], usergroupIds, selectedMentorDbId, }) {
222567
222898
  const t = useT();
222899
+ const { currentTenant } = useCurrentTenant();
222900
+ const rbacPermissions = useSelector(selectRbacPermissions);
222568
222901
  const { metadata } = useTenantMetadata({ org: tenantKey });
222569
222902
  //we using metadata to get the combined recommendation reports
222570
222903
  //"combined_recommendation_reports": "Recommendation History Report,Course Grade Report,User Group Member List Report",
@@ -222925,14 +223258,18 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
222925
223258
  timeZone: 'UTC',
222926
223259
  });
222927
223260
  }, []);
222928
- // Filter out disabled reports and sort alphabetically by display name
223261
+ // Reports the tenant disabled, plus the ones a pure watcher may not see.
223262
+ const hiddenReports = useMemo(() => isPureWatcher(rbacPermissions, currentTenant)
223263
+ ? [...disabledReports, ...WATCHER_HIDDEN_REPORTS]
223264
+ : disabledReports, [disabledReports, rbacPermissions, currentTenant]);
223265
+ // Filter out hidden reports and sort alphabetically by display name
222929
223266
  const filteredReports = useMemo(() => {
222930
- const filtered = disabledReports.length
223267
+ const filtered = hiddenReports.length
222931
223268
  ? reports.filter((report) => {
222932
223269
  const displayName = (report.display_name ||
222933
223270
  toTitleCase(report.report_name) ||
222934
223271
  '').toLowerCase();
222935
- return !disabledReports.some((disabledReport) => displayName.includes(disabledReport.toLowerCase()));
223272
+ return !hiddenReports.some((hiddenReport) => displayName.includes(hiddenReport.toLowerCase()));
222936
223273
  })
222937
223274
  : [...reports];
222938
223275
  return filtered.sort((a, b) => {
@@ -222940,7 +223277,7 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
222940
223277
  const nameB = (b.display_name || toTitleCase(b.report_name) || '').toLowerCase();
222941
223278
  return nameA.localeCompare(nameB);
222942
223279
  });
222943
- }, [reports, disabledReports]);
223280
+ }, [reports, hiddenReports]);
222944
223281
  const content = useMemo(() => {
222945
223282
  if (isLoading) {
222946
223283
  return (jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8 items-stretch", children: Array.from({ length: 12 }).map((_, key) => (jsx(Card, { className: "bg-white border-gray-200 h-full flex flex-col", children: jsx(CardContent, { className: "p-6 flex-1 flex flex-col", children: jsxs("div", { className: "flex-1", children: [jsxs("div", { className: "flex justify-between items-start mb-2", children: [jsx(Skeleton, { className: "h-5 w-32 flex-1 mr-2" }), jsx(Skeleton, { className: "h-8 w-8 flex-shrink-0" })] }), jsx(Skeleton, { className: "h-4 w-full" })] }) }) }, key))) }));
@@ -223317,7 +223654,7 @@ const formatSecondsToHours$1 = (seconds) => {
223317
223654
  return Math.round((seconds / 3600) * 10) / 10;
223318
223655
  };
223319
223656
  function AnalyticsCourses({ tenantKey, mentorId, selectedMentorId, basePath = '', }) {
223320
- var _a, _b, _c, _d, _e;
223657
+ var _a, _b, _c, _d;
223321
223658
  const t = useT();
223322
223659
  const router = useRouter();
223323
223660
  const currentMentorId = selectedMentorId || mentorId;
@@ -223325,11 +223662,12 @@ function AnalyticsCourses({ tenantKey, mentorId, selectedMentorId, basePath = ''
223325
223662
  const handleCourseClick = (courseId) => {
223326
223663
  router.push(`${basePath}/courses/${courseId}`);
223327
223664
  };
223328
- return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6", children: [jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourses.activeCourses'), value: courseStats.active_courses, percentage: courseStats.active_courses_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourses.totalCourses'), value: courseStats.total_courses, percentage: courseStats.total_courses_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourses.enrollments'), value: courseStats.enrollments, percentage: courseStats.enrollments_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourses.totalLearners'), value: courseStats.total_learners })] }), jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(ChartCardWrapper, { title: t('analyticsAnalyticsCourses.courseOvertime'), label: t('analyticsAnalyticsCourses.timeSpent'), filters: enrollmentStatsDateFilter, setOutsideFilters: setEnrollmentStatsDateFilter, children: isLoading ? (jsx(ChartLoading, {})) : ((_a = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _a === void 0 ? void 0 : _a.length) && ((_b = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _b === void 0 ? void 0 : _b.length) > 0 ? (jsxs(LineChart, { data: ((_c = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _c === void 0 ? void 0 : _c.map((point) => ({
223665
+ const hasEnrollmentStatsPoints = Number((_a = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _a === void 0 ? void 0 : _a.length) > 0;
223666
+ return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6", children: [jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourses.activeCourses'), value: courseStats.active_courses, percentage: courseStats.active_courses_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourses.totalCourses'), value: courseStats.total_courses, percentage: courseStats.total_courses_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourses.enrollments'), value: courseStats.enrollments, percentage: courseStats.enrollments_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourses.totalLearners'), value: courseStats.total_learners })] }), (isLoading || hasEnrollmentStatsPoints) && (jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(ChartCardWrapper, { title: t('analyticsAnalyticsCourses.courseOvertime'), label: t('analyticsAnalyticsCourses.timeSpent'), filters: enrollmentStatsDateFilter, setOutsideFilters: setEnrollmentStatsDateFilter, children: isLoading ? (jsx(ChartLoading, {})) : (jsxs(LineChart, { data: ((_b = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _b === void 0 ? void 0 : _b.map((point) => ({
223329
223667
  date: formatDateToShortFormat$1(point.date, enrollmentStatsDateFilter.activeFilter === 'today'),
223330
223668
  value: formatSecondsToHours$1(point.value),
223331
223669
  rawSeconds: point.value,
223332
- }))) || [], margin: { top: 5, right: 5, left: 0, bottom: 5 }, children: [jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: "#f0f0f0", vertical: false }), jsx(XAxis, { dataKey: "date", tick: { fontSize: 8, textAnchor: 'end' }, angle: -45, interval: Math.floor(Number((_d = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _d === void 0 ? void 0 : _d.length) / 31) || 0 }), jsx(YAxis, { tick: { fontSize: 10 }, width: 40, allowDecimals: false, tickFormatter: (value) => `${value}h` }), jsx(Tooltip, { content: ({ active, payload, label }) => {
223670
+ }))) || [], margin: { top: 5, right: 5, left: 0, bottom: 5 }, children: [jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: "#f0f0f0", vertical: false }), jsx(XAxis, { dataKey: "date", tick: { fontSize: 8, textAnchor: 'end' }, angle: -45, interval: Math.floor(Number((_c = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _c === void 0 ? void 0 : _c.length) / 31) || 0 }), jsx(YAxis, { tick: { fontSize: 10 }, width: 40, allowDecimals: false, tickFormatter: (value) => `${value}h` }), jsx(Tooltip, { content: ({ active, payload, label }) => {
223333
223671
  var _a;
223334
223672
  if (!active || !(payload === null || payload === void 0 ? void 0 : payload.length))
223335
223673
  return null;
@@ -223340,7 +223678,7 @@ function AnalyticsCourses({ tenantKey, mentorId, selectedMentorId, basePath = ''
223340
223678
  stroke: '#38A1E5',
223341
223679
  strokeWidth: 2,
223342
223680
  fill: 'white',
223343
- } })] })) : (jsx(EmptyStats, {})) }) }), jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(Card, { className: "w-full bg-white shadow-xs", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs(CardContent, { className: "p-4", "aria-label": t('analyticsAnalyticsCourses.coursesTableAriaLabel'), children: [jsx("h3", { className: "text-base font-medium text-gray-700 mb-4", children: t('analyticsAnalyticsCourses.coursesHeading') }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "search-course", type: "text", placeholder: t('analyticsAnalyticsCourses.searchPlaceholder'), value: coursesListSearch, onChange: handleSearchInputChange, className: "pl-9 border-gray-300 focus:bg-transparent focus:color-transparent h-11", "aria-label": t('analyticsAnalyticsCourses.searchAriaLabel') })] }), isLoading ? (jsx("div", { className: "flex items-center justify-center py-8", children: jsx("div", { className: "text-sm text-gray-500", children: t('analyticsAnalyticsCourses.loading') }) })) : ((_e = coursesList === null || coursesList === void 0 ? void 0 : coursesList.courses) === null || _e === void 0 ? void 0 : _e.length) && coursesList.courses.length > 0 ? (jsxs(Fragment$1, { children: [jsx("div", { className: "rounded-md overflow-x-auto", style: { borderColor: 'oklch(.922 0 0)', borderWidth: '1px' }, children: jsxs(Table, { children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "h-[48px]", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "text-left", children: t('analyticsAnalyticsCourses.colCourseName') }), jsx(TableHead, { className: "text-left", children: t('analyticsAnalyticsCourses.colCourseId') }), jsx(TableHead, { className: "text-right", children: t('analyticsAnalyticsCourses.colEnrollments') })] }) }), jsx(TableBody, { children: coursesList.courses.map((course, index) => (jsxs(TableRow, { className: `cursor-pointer hover:bg-muted/50 h-[48px] ${index % 2 === 0 ? 'bg-gray-50' : ''}`, onClick: () => handleCourseClick(course.id), role: "button", tabIndex: 0, onKeyDown: (e) => {
223681
+ } })] })) }) })), jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(Card, { className: "w-full bg-white shadow-xs", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs(CardContent, { className: "p-4", "aria-label": t('analyticsAnalyticsCourses.coursesTableAriaLabel'), children: [jsx("h3", { className: "text-base font-medium text-gray-700 mb-4", children: t('analyticsAnalyticsCourses.coursesHeading') }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "search-course", type: "text", placeholder: t('analyticsAnalyticsCourses.searchPlaceholder'), value: coursesListSearch, onChange: handleSearchInputChange, className: "pl-9 border-gray-300 focus:bg-transparent focus:color-transparent h-11", "aria-label": t('analyticsAnalyticsCourses.searchAriaLabel') })] }), isLoading ? (jsx("div", { className: "flex items-center justify-center py-8", children: jsx("div", { className: "text-sm text-gray-500", children: t('analyticsAnalyticsCourses.loading') }) })) : ((_d = coursesList === null || coursesList === void 0 ? void 0 : coursesList.courses) === null || _d === void 0 ? void 0 : _d.length) && coursesList.courses.length > 0 ? (jsxs(Fragment$1, { children: [jsx("div", { className: "rounded-md overflow-x-auto", style: { borderColor: 'oklch(.922 0 0)', borderWidth: '1px' }, children: jsxs(Table, { children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "h-[48px]", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "text-left", children: t('analyticsAnalyticsCourses.colCourseName') }), jsx(TableHead, { className: "text-left", children: t('analyticsAnalyticsCourses.colCourseId') }), jsx(TableHead, { className: "text-right", children: t('analyticsAnalyticsCourses.colEnrollments') })] }) }), jsx(TableBody, { children: coursesList.courses.map((course, index) => (jsxs(TableRow, { className: `cursor-pointer hover:bg-muted/50 h-[48px] ${index % 2 === 0 ? 'bg-gray-50' : ''}`, onClick: () => handleCourseClick(course.id), role: "button", tabIndex: 0, onKeyDown: (e) => {
223344
223682
  if (e.key === 'Enter' || e.key === ' ') {
223345
223683
  e.preventDefault();
223346
223684
  handleCourseClick(course.id);
@@ -223366,15 +223704,6 @@ function AnalyticsCourses({ tenantKey, mentorId, selectedMentorId, basePath = ''
223366
223704
  }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-2 !w-auto !inline-flex bg-transparent", onClick: () => setCoursesListPage(coursesPagination.current_page + 1), disabled: coursesPagination.current_page === coursesPagination.total_pages, "aria-label": t('analyticsAnalyticsCourses.goToNextPage'), children: [jsx("span", { className: "sr-only", children: t('analyticsAnalyticsCourses.goToNextPage') }), jsx(ChevronRight, { className: "h-4 w-4" })] }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-2 !w-auto !inline-flex bg-transparent", onClick: () => setCoursesListPage(coursesPagination.total_pages), disabled: coursesPagination.current_page === coursesPagination.total_pages, "aria-label": t('analyticsAnalyticsCourses.goToLastPage'), children: [jsx("span", { className: "sr-only", children: t('analyticsAnalyticsCourses.goToLastPage') }), jsx(ChevronsRight, { className: "h-4 w-4" })] })] }))] })) : (jsx(EmptyStats, { title: t('analyticsAnalyticsCourses.noCoursesAvailable') }))] })] }) }) })] }));
223367
223705
  }
223368
223706
 
223369
- // Utility function to format time spent (in minutes) to readable format
223370
- const formatTimeSpent = (minutes) => {
223371
- if (minutes < 60) {
223372
- return `${minutes}m`;
223373
- }
223374
- const hours = Math.floor(minutes / 60);
223375
- const mins = minutes % 60;
223376
- return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
223377
- };
223378
223707
  function AnalyticsCourseDetail({ tenantKey, mentorId, selectedMentorId, courseId, courseName, showCourseTitle = true, onBack, }) {
223379
223708
  var _a, _b;
223380
223709
  const t = useT();
@@ -223387,7 +223716,7 @@ function AnalyticsCourseDetail({ tenantKey, mentorId, selectedMentorId, courseId
223387
223716
  const [selectedEnrollment, setSelectedEnrollment] = useState(null);
223388
223717
  const resolvedCourseName = courseName || (courseInfo === null || courseInfo === void 0 ? void 0 : courseInfo.name);
223389
223718
  const showTitle = showCourseTitle && !!resolvedCourseName;
223390
- return (jsxs("div", { className: "space-y-8", children: [(onBack || showTitle) && (jsxs("div", { className: "mb-4 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4", children: [jsx("div", { className: "flex flex-1 justify-start", children: onBack && (jsxs(Button$1, { variant: "ghost", onClick: onBack, "aria-label": t('analyticsAnalyticsCourseDetail.goBackAriaLabel'), children: [jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), t('analyticsAnalyticsCourseDetail.backToCourses')] })) }), showTitle && (jsx("h2", { className: "flex-1 text-left text-2xl font-medium text-gray-700 sm:text-center", children: resolvedCourseName })), jsx("div", { className: "hidden flex-1 sm:block" })] })), jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-3 gap-4 mb-6", children: [jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourseDetail.activeEnrollments'), value: courseDetailStats.active_enrollments, percentage: courseDetailStats.active_enrollments_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourseDetail.completedEnrollments'), value: courseDetailStats.completed_enrollments, percentage: courseDetailStats.completed_enrollments_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourseDetail.timeSpent'), value: formatTimeSpent(courseDetailStats.time_spent), percentage: courseDetailStats.time_spent_percentage })] }), jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(Card, { className: "w-full bg-white shadow-xs", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs(CardContent, { className: "p-4", "aria-label": t('analyticsAnalyticsCourseDetail.courseEnrollmentsTableAriaLabel'), children: [jsx("h3", { className: "text-base font-medium text-gray-700 mb-4", children: t('analyticsAnalyticsCourseDetail.enrolledUsers') }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "search-enrolled-user", type: "text", placeholder: t('analyticsAnalyticsCourseDetail.searchPlaceholder'), value: courseEnrollmentsSearch, onChange: handleCourseEnrollmentsSearchInputChange, className: "pl-9 border-gray-300 focus:bg-transparent focus:color-transparent h-11", "aria-label": t('analyticsAnalyticsCourseDetail.searchAriaLabel') })] }), isLoading ? (jsx("div", { className: "flex items-center justify-center py-8", children: jsx("div", { className: "text-sm text-gray-500", children: t('analyticsAnalyticsCourseDetail.loadingLabel') }) })) : ((_a = courseEnrollments === null || courseEnrollments === void 0 ? void 0 : courseEnrollments.enrollments) === null || _a === void 0 ? void 0 : _a.length) &&
223719
+ return (jsxs("div", { className: "space-y-8", children: [(onBack || showTitle) && (jsxs("div", { className: "mb-4 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4", children: [jsx("div", { className: "flex flex-1 justify-start", children: onBack && (jsxs(Button$1, { variant: "ghost", onClick: onBack, "aria-label": t('analyticsAnalyticsCourseDetail.goBackAriaLabel'), children: [jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), t('analyticsAnalyticsCourseDetail.backToCourses')] })) }), showTitle && (jsx("h2", { className: "flex-1 text-left text-2xl font-medium text-gray-700 sm:text-center", children: resolvedCourseName })), jsx("div", { className: "hidden flex-1 sm:block" })] })), jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4 mb-6", children: [jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourseDetail.activeEnrollments'), value: courseDetailStats.active_enrollments, percentage: courseDetailStats.active_enrollments_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsCourseDetail.completedEnrollments'), value: courseDetailStats.completed_enrollments, percentage: courseDetailStats.completed_enrollments_percentage })] }), jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(Card, { className: "w-full bg-white shadow-xs", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs(CardContent, { className: "p-4", "aria-label": t('analyticsAnalyticsCourseDetail.courseEnrollmentsTableAriaLabel'), children: [jsx("h3", { className: "text-base font-medium text-gray-700 mb-4", children: t('analyticsAnalyticsCourseDetail.enrolledUsers') }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "search-enrolled-user", type: "text", placeholder: t('analyticsAnalyticsCourseDetail.searchPlaceholder'), value: courseEnrollmentsSearch, onChange: handleCourseEnrollmentsSearchInputChange, className: "pl-9 border-gray-300 focus:bg-transparent focus:color-transparent h-11", "aria-label": t('analyticsAnalyticsCourseDetail.searchAriaLabel') })] }), isLoading ? (jsx("div", { className: "flex items-center justify-center py-8", children: jsx("div", { className: "text-sm text-gray-500", children: t('analyticsAnalyticsCourseDetail.loadingLabel') }) })) : ((_a = courseEnrollments === null || courseEnrollments === void 0 ? void 0 : courseEnrollments.enrollments) === null || _a === void 0 ? void 0 : _a.length) &&
223391
223720
  courseEnrollments.enrollments.length > 0 ? (jsxs(Fragment$1, { children: [jsx("div", { className: "rounded-md overflow-x-auto", style: { borderColor: 'oklch(.922 0 0)', borderWidth: '1px' }, children: jsxs(Table, { children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "h-[48px]", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "text-left", children: t('analyticsAnalyticsCourseDetail.columnName') }), jsx(TableHead, { className: "text-left", children: t('analyticsAnalyticsCourseDetail.columnEmail') }), jsx(TableHead, { className: "text-right", children: t('analyticsAnalyticsCourseDetail.columnEnrollmentDate') }), jsx(TableHead, { className: "text-right", children: t('analyticsAnalyticsCourseDetail.columnLastActiveOn') })] }) }), jsx(TableBody, { children: courseEnrollments.enrollments.map((enrollment, index) => (jsxs(TableRow, { className: `cursor-pointer hover:bg-muted/50 h-[48px] ${index % 2 === 0 ? 'bg-gray-50' : ''}`, onClick: () => setSelectedEnrollment(enrollment), role: "button", tabIndex: 0, onKeyDown: (e) => {
223392
223721
  if (e.key === 'Enter' || e.key === ' ') {
223393
223722
  e.preventDefault();
@@ -223682,7 +224011,7 @@ const formatSecondsToHours = (seconds) => {
223682
224011
  return Math.round((seconds / 3600) * 10) / 10;
223683
224012
  };
223684
224013
  function AnalyticsPrograms({ tenantKey, mentorId, selectedMentorId, basePath = '', }) {
223685
- var _a, _b, _c, _d, _e;
224014
+ var _a, _b, _c, _d;
223686
224015
  const t = useT();
223687
224016
  const router = useRouter();
223688
224017
  const currentMentorId = selectedMentorId || mentorId;
@@ -223690,11 +224019,12 @@ function AnalyticsPrograms({ tenantKey, mentorId, selectedMentorId, basePath = '
223690
224019
  const handleProgramClick = (programId) => {
223691
224020
  router.push(`${basePath}/programs/${programId}`);
223692
224021
  };
223693
- return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6", children: [jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsPrograms.activePrograms'), value: programStats.active_programs, percentage: programStats.active_programs_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsPrograms.totalPrograms'), value: programStats.total_programs, percentage: programStats.total_programs_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsPrograms.enrollments'), value: programStats.enrollments, percentage: programStats.enrollments_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsPrograms.totalLearners'), value: programStats.total_learners })] }), jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(ChartCardWrapper, { title: t('analyticsAnalyticsPrograms.programOvertime'), label: t('analyticsAnalyticsPrograms.timeSpent'), filters: enrollmentStatsDateFilter, setOutsideFilters: setEnrollmentStatsDateFilter, children: isLoading ? (jsx(ChartLoading, {})) : ((_a = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _a === void 0 ? void 0 : _a.length) && ((_b = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _b === void 0 ? void 0 : _b.length) > 0 ? (jsxs(LineChart, { data: ((_c = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _c === void 0 ? void 0 : _c.map((point) => ({
224022
+ const hasEnrollmentStatsPoints = Number((_a = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _a === void 0 ? void 0 : _a.length) > 0;
224023
+ return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6", children: [jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsPrograms.activePrograms'), value: programStats.active_programs, percentage: programStats.active_programs_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsPrograms.totalPrograms'), value: programStats.total_programs, percentage: programStats.total_programs_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsPrograms.enrollments'), value: programStats.enrollments, percentage: programStats.enrollments_percentage }), jsx(StatCard, { loading: isLoading, title: t('analyticsAnalyticsPrograms.totalLearners'), value: programStats.total_learners })] }), (isLoading || hasEnrollmentStatsPoints) && (jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(ChartCardWrapper, { title: t('analyticsAnalyticsPrograms.programOvertime'), label: t('analyticsAnalyticsPrograms.timeSpent'), filters: enrollmentStatsDateFilter, setOutsideFilters: setEnrollmentStatsDateFilter, children: isLoading ? (jsx(ChartLoading, {})) : (jsxs(LineChart, { data: ((_b = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _b === void 0 ? void 0 : _b.map((point) => ({
223694
224024
  date: formatDateToShortFormat(point.date, enrollmentStatsDateFilter.activeFilter === 'today'),
223695
224025
  value: formatSecondsToHours(point.value),
223696
224026
  rawSeconds: point.value,
223697
- }))) || [], margin: { top: 5, right: 5, left: 0, bottom: 5 }, children: [jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: "#f0f0f0", vertical: false }), jsx(XAxis, { dataKey: "date", tick: { fontSize: 8, textAnchor: 'end' }, angle: -45, interval: Math.floor(Number((_d = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _d === void 0 ? void 0 : _d.length) / 31) || 0 }), jsx(YAxis, { tick: { fontSize: 10 }, width: 40, allowDecimals: false, tickFormatter: (value) => `${value}h` }), jsx(Tooltip, { content: ({ active, payload, label }) => {
224027
+ }))) || [], margin: { top: 5, right: 5, left: 0, bottom: 5 }, children: [jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: "#f0f0f0", vertical: false }), jsx(XAxis, { dataKey: "date", tick: { fontSize: 8, textAnchor: 'end' }, angle: -45, interval: Math.floor(Number((_c = enrollmentStats === null || enrollmentStats === void 0 ? void 0 : enrollmentStats.points) === null || _c === void 0 ? void 0 : _c.length) / 31) || 0 }), jsx(YAxis, { tick: { fontSize: 10 }, width: 40, allowDecimals: false, tickFormatter: (value) => `${value}h` }), jsx(Tooltip, { content: ({ active, payload, label }) => {
223698
224028
  var _a;
223699
224029
  if (!active || !(payload === null || payload === void 0 ? void 0 : payload.length))
223700
224030
  return null;
@@ -223705,7 +224035,7 @@ function AnalyticsPrograms({ tenantKey, mentorId, selectedMentorId, basePath = '
223705
224035
  stroke: '#38A1E5',
223706
224036
  strokeWidth: 2,
223707
224037
  fill: 'white',
223708
- } })] })) : (jsx(EmptyStats, {})) }) }), jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(Card, { className: "w-full bg-white shadow-xs", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs(CardContent, { className: "p-4", "aria-label": t('analyticsAnalyticsPrograms.programsTableAriaLabel'), children: [jsx("h3", { className: "text-base font-medium text-gray-700 mb-4", children: t('analyticsAnalyticsPrograms.programs') }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "search-program", type: "text", placeholder: t('analyticsAnalyticsPrograms.searchPlaceholder'), value: programsListSearch, onChange: handleSearchInputChange, className: "pl-9 border-gray-300 focus:bg-transparent focus:color-transparent h-11", "aria-label": t('analyticsAnalyticsPrograms.searchAriaLabel') })] }), isLoading ? (jsx("div", { className: "flex items-center justify-center py-8", children: jsx("div", { className: "text-sm text-gray-500", children: t('analyticsAnalyticsPrograms.loading') }) })) : ((_e = programsList === null || programsList === void 0 ? void 0 : programsList.programs) === null || _e === void 0 ? void 0 : _e.length) && programsList.programs.length > 0 ? (jsxs(Fragment$1, { children: [jsx("div", { className: "rounded-md overflow-x-auto", style: { borderColor: 'oklch(.922 0 0)', borderWidth: '1px' }, children: jsxs(Table, { children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "h-[48px]", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "text-left", children: t('analyticsAnalyticsPrograms.programName') }), jsx(TableHead, { className: "text-left", children: t('analyticsAnalyticsPrograms.programId') }), jsx(TableHead, { className: "text-right", children: t('analyticsAnalyticsPrograms.enrollments') })] }) }), jsx(TableBody, { children: programsList.programs.map((program, index) => (jsxs(TableRow, { className: `cursor-pointer hover:bg-muted/50 h-[48px] ${index % 2 === 0 ? 'bg-gray-50' : ''}`, onClick: () => handleProgramClick(program.id), role: "button", tabIndex: 0, onKeyDown: (e) => {
224038
+ } })] })) }) })), jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(Card, { className: "w-full bg-white shadow-xs", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs(CardContent, { className: "p-4", "aria-label": t('analyticsAnalyticsPrograms.programsTableAriaLabel'), children: [jsx("h3", { className: "text-base font-medium text-gray-700 mb-4", children: t('analyticsAnalyticsPrograms.programs') }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "search-program", type: "text", placeholder: t('analyticsAnalyticsPrograms.searchPlaceholder'), value: programsListSearch, onChange: handleSearchInputChange, className: "pl-9 border-gray-300 focus:bg-transparent focus:color-transparent h-11", "aria-label": t('analyticsAnalyticsPrograms.searchAriaLabel') })] }), isLoading ? (jsx("div", { className: "flex items-center justify-center py-8", children: jsx("div", { className: "text-sm text-gray-500", children: t('analyticsAnalyticsPrograms.loading') }) })) : ((_d = programsList === null || programsList === void 0 ? void 0 : programsList.programs) === null || _d === void 0 ? void 0 : _d.length) && programsList.programs.length > 0 ? (jsxs(Fragment$1, { children: [jsx("div", { className: "rounded-md overflow-x-auto", style: { borderColor: 'oklch(.922 0 0)', borderWidth: '1px' }, children: jsxs(Table, { children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "h-[48px]", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "text-left", children: t('analyticsAnalyticsPrograms.programName') }), jsx(TableHead, { className: "text-left", children: t('analyticsAnalyticsPrograms.programId') }), jsx(TableHead, { className: "text-right", children: t('analyticsAnalyticsPrograms.enrollments') })] }) }), jsx(TableBody, { children: programsList.programs.map((program, index) => (jsxs(TableRow, { className: `cursor-pointer hover:bg-muted/50 h-[48px] ${index % 2 === 0 ? 'bg-gray-50' : ''}`, onClick: () => handleProgramClick(program.id), role: "button", tabIndex: 0, onKeyDown: (e) => {
223709
224039
  if (e.key === 'Enter' || e.key === ' ') {
223710
224040
  e.preventDefault();
223711
224041
  handleProgramClick(program.id);
@@ -224246,6 +224576,542 @@ function AnalyticsAuditLogStats({ tenantKey, mentorId, userId, selectedMentorId,
224246
224576
  }, children: [jsx(SelectTrigger, { className: "w-full font-normal bg-white h-9", children: jsx(SelectValue, { placeholder: t('analyticsAnalyticsAuditLogStats.allActions') }) }), jsx(SelectContent, { children: ACTION_FILTER_OPTIONS.map((opt) => (jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value))) })] }) })] }) }), jsx("div", { className: "overflow-hidden rounded-md border border-[oklch(0.922_0_0)] bg-white", children: jsx("div", { className: "overflow-x-auto", children: jsx("div", { className: "inline-block min-w-full align-middle", children: isLoading ? (jsx("div", { className: "flex items-center justify-center w-full py-10", children: jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-blue-600 border-t-transparent" }) })) : error && !is403 ? (jsx("div", { className: "py-8 text-center text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.loadError') })) : !((_a = data === null || data === void 0 ? void 0 : data.results) === null || _a === void 0 ? void 0 : _a.length) ? (jsx("div", { className: "h-[120px]", children: jsx(EmptyStats, { title: t('analyticsAnalyticsAuditLogStats.noEntries') }) })) : (jsxs(Table, { className: "min-w-full", children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "bg-muted/50 border-b border-[oklch(0.922_0_0)]", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.colUser') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.colAction') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.colTime') })] }) }), jsx(TableBody, { children: data.results.map((entry) => (jsxs(TableRow, { className: "border-b border-[oklch(0.922_0_0)] last:border-0", children: [jsx(TableCell, { className: "p-3 font-medium whitespace-nowrap text-[#646464]", children: entry.actor_email }), jsx(TableCell, { className: "min-w-[250px] p-3 text-[#646464]", children: summarizeChanges(entry) }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: formatDistanceToNow(new Date(entry.timestamp), { addSuffix: true }) })] }, entry.id))) })] })) }) }) }), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: isLoading })] }));
224247
224577
  }
224248
224578
 
224579
+ /**
224580
+ * Core agent search hook — thin wrapper around `useGetAiSearchMentorsQuery`.
224581
+ *
224582
+ * This is the low-level building block. For a higher-level hook that manages
224583
+ * search state, debounce, and pagination controls, use
224584
+ * `useAgentSearchWithPagination`.
224585
+ */
224586
+ function useAgentSearch({ tenantKey, query, limit = 6, offset, starred, featured, category, subjects, llm, types, includeMainPublicMentors, orderDirection, skip = false, }) {
224587
+ var _a, _b, _c;
224588
+ const { data, isLoading, isFetching, refetch } = useGetAiSearchMentorsQuery({
224589
+ platform_key: tenantKey,
224590
+ query: query || undefined,
224591
+ limit,
224592
+ ...(offset !== undefined && { offset }),
224593
+ ...(starred !== undefined && { starred }),
224594
+ ...(featured !== undefined && { featured }),
224595
+ ...(category && { category }),
224596
+ ...(subjects && { subjects }),
224597
+ ...(llm && { llm }),
224598
+ ...(types && { types }),
224599
+ ...(includeMainPublicMentors !== undefined && {
224600
+ include_main_public_mentors: includeMainPublicMentors,
224601
+ }),
224602
+ ...(orderDirection && { order_direction: orderDirection }),
224603
+ }, { skip: skip || !tenantKey });
224604
+ return {
224605
+ agents: ((_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : []),
224606
+ facets: data === null || data === void 0 ? void 0 : data.facets,
224607
+ hasMore: !!(data === null || data === void 0 ? void 0 : data.next),
224608
+ totalCount: (_b = data === null || data === void 0 ? void 0 : data.count) !== null && _b !== void 0 ? _b : 0,
224609
+ totalPages: (_c = data === null || data === void 0 ? void 0 : data.total_pages) !== null && _c !== void 0 ? _c : 0,
224610
+ isLoading,
224611
+ isFetching,
224612
+ refetch,
224613
+ };
224614
+ }
224615
+
224616
+ function c(e,u,c){var i=this,a=useRef(null),o=useRef(0),f=useRef(null),l=useRef([]),v=useRef(),m=useRef(),d=useRef(e),g=useRef(true);d.current=e;var p="undefined"!=typeof window,w=!u&&0!==u&&p;if("function"!=typeof e)throw new TypeError("Expected a function");u=+u||0;var s=!!(c=c||{}).leading,x=!("trailing"in c)||!!c.trailing,h="maxWait"in c,y="debounceOnServer"in c&&!!c.debounceOnServer,F=h?Math.max(+c.maxWait||0,u):null;useEffect(function(){return g.current=true,function(){g.current=false;}},[]);var A=useMemo(function(){var r=function(r){var n=l.current,t=v.current;return l.current=v.current=null,o.current=r,m.current=d.current.apply(t,n)},n=function(r,n){w&&cancelAnimationFrame(f.current),f.current=w?requestAnimationFrame(r):setTimeout(r,n);},t=function(r){if(!g.current)return false;var n=r-a.current;return !a.current||n>=u||n<0||h&&r-o.current>=F},e=function(n){return f.current=null,x&&l.current?r(n):(l.current=v.current=null,m.current)},c=function r(){var c=Date.now();if(t(c))return e(c);if(g.current){var i=u-(c-a.current),f=h?Math.min(i,F-(c-o.current)):i;n(r,f);}},A=function(){if(p||y){var e=Date.now(),d=t(e);if(l.current=[].slice.call(arguments),v.current=i,a.current=e,d){if(!f.current&&g.current)return o.current=a.current,n(c,u),s?r(a.current):m.current;if(h)return n(c,u),r(a.current)}return f.current||n(c,u),m.current}};return A.cancel=function(){f.current&&(w?cancelAnimationFrame(f.current):clearTimeout(f.current)),o.current=0,l.current=a.current=v.current=f.current=null;},A.isPending=function(){return !!f.current},A.flush=function(){return f.current?e(Date.now()):m.current},A},[s,h,u,F,x,w,p,y]);return A}function i(r,n){return r===n}function a(n,t,a){var o=i,f=useRef(n),l=useState({})[1],v=c(useCallback(function(r){f.current=r,l({});},[l]),t,a),m=useRef(n);return o(m.current,n)||(v(n),m.current=n),[f.current,v]}
224617
+
224618
+ /**
224619
+ * Higher-level agent search hook that manages search state, debounce, and
224620
+ * pagination controls on top of `useAgentSearch`.
224621
+ *
224622
+ * Use this for simple list/table views (MyMentorsModal, SettingsModal).
224623
+ * For the full explore page with sections, use `useAgentSearch` directly.
224624
+ */
224625
+ function useAgentSearchWithPagination({ itemsPerPage = 6, paginationMode = 'paginated', debounceMs = 500, ...queryConfig }) {
224626
+ const [searchQuery, setSearchQuery] = React__default.useState('');
224627
+ const [debouncedQuery] = a(searchQuery, debounceMs);
224628
+ const [currentPage, setCurrentPage] = React__default.useState(1);
224629
+ const [infiniteLimit, setInfiniteLimit] = React__default.useState(itemsPerPage);
224630
+ // Reset pagination when search changes
224631
+ React__default.useEffect(() => {
224632
+ setCurrentPage(1);
224633
+ setInfiniteLimit(itemsPerPage);
224634
+ }, [debouncedQuery, itemsPerPage]);
224635
+ const isPaginated = paginationMode === 'paginated';
224636
+ const result = useAgentSearch({
224637
+ ...queryConfig,
224638
+ query: debouncedQuery,
224639
+ limit: isPaginated ? itemsPerPage : infiniteLimit,
224640
+ offset: isPaginated ? (currentPage - 1) * itemsPerPage : undefined,
224641
+ });
224642
+ const totalPages = Math.ceil(result.totalCount / itemsPerPage);
224643
+ const handlePageChange = React__default.useCallback((page) => {
224644
+ setCurrentPage(page);
224645
+ }, []);
224646
+ const loadMore = React__default.useCallback(() => {
224647
+ setInfiniteLimit((prev) => prev + itemsPerPage);
224648
+ }, [itemsPerPage]);
224649
+ return {
224650
+ ...result,
224651
+ searchQuery,
224652
+ setSearchQuery,
224653
+ debouncedQuery,
224654
+ currentPage,
224655
+ totalPages,
224656
+ handlePageChange,
224657
+ loadMore,
224658
+ };
224659
+ }
224660
+
224661
+ function MentorSelectionGrid({ selectedMentorIds, onMentorSelect, searchQuery, onSearchChange, tenantKey, itemsPerPage = 8, showSearch = true, minHeight = '400px', }) {
224662
+ const t = useT();
224663
+ const { agents: mentors, isLoading: isMentorsLoading, isFetching: isMentorsFetching, currentPage, totalPages, setSearchQuery: setMentorSearch, handlePageChange, } = useAgentSearchWithPagination({ tenantKey, itemsPerPage });
224664
+ // Update search query with debounce effect handled by the hook
224665
+ React__default.useEffect(() => {
224666
+ setMentorSearch(searchQuery);
224667
+ }, [searchQuery]);
224668
+ const isMentorSelected = (mentorId) => {
224669
+ return selectedMentorIds.includes(mentorId);
224670
+ };
224671
+ return (jsxs("div", { className: "space-y-4", children: [showSearch && (jsxs("div", { className: "relative", children: [isMentorsFetching ? (jsx(Spinner, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 transform text-gray-400" })) : (jsx(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 transform text-gray-400" })), jsx(Input, { placeholder: t('mentorsMentorSelectionGrid.searchAgentsPlaceholder'), value: searchQuery, onChange: (e) => onSearchChange(e.target.value), className: "h-10 border-gray-200 pl-10 focus:border-blue-500 focus:ring-0" })] })), jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "grid max-h-96 auto-rows-min grid-cols-1 items-start gap-3 overflow-y-auto rounded-lg border border-gray-200 p-4 md:max-h-none md:grid-cols-2", style: { minHeight }, children: isMentorsLoading ? (jsx("div", { className: "col-span-full py-8 text-center text-gray-500", children: t('mentorsMentorSelectionGrid.loadingAgents') })) : mentors.length === 0 ? (jsx("div", { className: "col-span-full py-8 text-center text-gray-500", children: t('mentorsMentorSelectionGrid.noAgentsFound') })) : (mentors.map((mentor) => {
224672
+ const isSelected = isMentorSelected(mentor.unique_id || '');
224673
+ const isAlreadyAdded = selectedMentorIds.includes(mentor.unique_id || '');
224674
+ return (jsxs("button", { onClick: () => onMentorSelect(mentor), className: `flex cursor-pointer items-center gap-3 rounded-lg border-2 p-3 transition-all ${isSelected
224675
+ ? 'border-blue-500 bg-blue-50'
224676
+ : isAlreadyAdded
224677
+ ? 'bg-blue-25 border-blue-300'
224678
+ : 'border-gray-200 hover:border-gray-300 hover:bg-gray-50'}`, children: [jsxs(Avatar, { className: "h-12 w-12 flex-shrink-0", children: [jsx(AvatarImage, { src: mentor.profile_image || '/placeholder.svg', alt: mentor.name }), jsx(AvatarFallback, { children: mentor.name.substring(0, 2) })] }), jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-start text-left", children: [jsx("h4", { className: "truncate text-sm font-medium text-gray-900", children: mentor.name }), jsx("p", { className: "line-clamp-2 text-xs text-gray-600", children: mentor.description })] }), isSelected && (jsx("div", { className: "flex-shrink-0", children: jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-blue-600", children: jsx(Check, { className: "h-4 w-4 text-white" }) }) })), isAlreadyAdded && !isSelected && (jsx("div", { className: "flex-shrink-0", children: jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-blue-400", children: jsx(Check, { className: "h-4 w-4 text-white" }) }) }))] }, mentor.unique_id));
224679
+ })) }), jsx(IblPagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: handlePageChange, disabled: isMentorsFetching || isMentorsLoading })] })] }));
224680
+ }
224681
+
224682
+ const USERS_PAGE_SIZE = 50;
224683
+ const SEARCH_DEBOUNCE_MS = 300;
224684
+ /** cmdk needs a non-empty value; the handler treats this one as "clear". */
224685
+ const SELF_VALUE = '__self__';
224686
+ /**
224687
+ * RBAC action a watcher must hold on a user for their memories to be listable —
224688
+ * the same one the memory endpoints check, so the dropdown can't offer a user
224689
+ * whose memories would then come back 403.
224690
+ */
224691
+ const MEMORY_LIST_ACTION = 'Ibl.Mentor/Memory/list';
224692
+ function useDebouncedValue(value, delay) {
224693
+ const [debounced, setDebounced] = useState(value);
224694
+ useEffect(() => {
224695
+ const timer = setTimeout(() => setDebounced(value), delay);
224696
+ return () => clearTimeout(timer);
224697
+ }, [value, delay]);
224698
+ return debounced;
224699
+ }
224700
+ /**
224701
+ * Tenant user picker for the analytics memory filters. Both endpoints behind it
224702
+ * do the searching, so the dropdown only pages in the first
224703
+ * {@link USERS_PAGE_SIZE} matches for whatever is typed rather than filtering
224704
+ * client-side.
224705
+ *
224706
+ * Which endpoint serves the list depends on the caller:
224707
+ * - Admins get `GET /api/core/platform/users/` — every user on the tenant.
224708
+ * - Pure watchers get `GET /api/core/users/accessible/`, which the platform
224709
+ * endpoint would 403 for. It returns only the users they hold
224710
+ * {@link MEMORY_LIST_ACTION} on, i.e. the members of the groups they watch.
224711
+ */
224712
+ function UserFilterSelect({ tenantKey, currentUsername, value, onChange, }) {
224713
+ const t = useT();
224714
+ const [open, setOpen] = useState(false);
224715
+ const [search, setSearch] = useState('');
224716
+ const debouncedSearch = useDebouncedValue(search, SEARCH_DEBOUNCE_MS);
224717
+ const { currentTenant } = useCurrentTenant();
224718
+ const rbacPermissions = useSelector(selectRbacPermissions);
224719
+ const isWatcher = isPureWatcher(rbacPermissions, currentTenant);
224720
+ // Only fetched once the dropdown is open — the trigger shows the selected
224721
+ // username, which is the filter value itself, so nothing needs looking up
224722
+ // first.
224723
+ const { data, isFetching: isFetchingPlatformUsers } = usePlatformUsersQuery({
224724
+ platform_key: tenantKey,
224725
+ platform_org: tenantKey,
224726
+ page: 1,
224727
+ page_size: USERS_PAGE_SIZE,
224728
+ query: debouncedSearch,
224729
+ return_policies: 'false',
224730
+ }, { skip: !open || !tenantKey || isWatcher });
224731
+ // The accessible endpoint scopes itself to the caller's platform from their
224732
+ // token, so it takes no tenant param. It also filters per field instead of
224733
+ // with one search param, hence the "@" routing the term to `email` and
224734
+ // anything else to `username`.
224735
+ const { data: accessibleUsers, isFetching: isFetchingAccessibleUsers } = useGetAccessibleUsersQuery({
224736
+ required_action: MEMORY_LIST_ACTION,
224737
+ page: 1,
224738
+ page_size: USERS_PAGE_SIZE,
224739
+ sort: 'name',
224740
+ ...(debouncedSearch.includes('@')
224741
+ ? { email: debouncedSearch }
224742
+ : { username: debouncedSearch }),
224743
+ }, { skip: !open || !isWatcher });
224744
+ const isFetching = isWatcher ? isFetchingAccessibleUsers : isFetchingPlatformUsers;
224745
+ const users = useMemo(() => {
224746
+ var _a, _b;
224747
+ let list;
224748
+ if (isWatcher) {
224749
+ list = ((_a = accessibleUsers === null || accessibleUsers === void 0 ? void 0 : accessibleUsers.results) !== null && _a !== void 0 ? _a : []).map((user) => ({
224750
+ key: String(user.id),
224751
+ username: user.username,
224752
+ name: user.name,
224753
+ email: user.email,
224754
+ }));
224755
+ }
224756
+ else {
224757
+ // `results` is a bare array unless policies were requested, in which case
224758
+ // the users sit under `results.data`.
224759
+ const results = data === null || data === void 0 ? void 0 : data.results;
224760
+ const platformUsers = Array.isArray(results)
224761
+ ? results
224762
+ : ((_b = results === null || results === void 0 ? void 0 : results.data) !== null && _b !== void 0 ? _b : []);
224763
+ list = platformUsers.map((user) => {
224764
+ var _a;
224765
+ return ({
224766
+ key: String((_a = user.user_id) !== null && _a !== void 0 ? _a : user.username),
224767
+ username: user.username,
224768
+ name: user.name,
224769
+ email: user.email,
224770
+ });
224771
+ });
224772
+ }
224773
+ return list.filter(
224774
+ // Usernames are the filter values, so a user without one is unselectable,
224775
+ // and the caller already has their own entry at the top of the list.
224776
+ (user) => !!user.username && user.username !== currentUsername);
224777
+ }, [isWatcher, accessibleUsers, data, currentUsername]);
224778
+ const handleSelect = (username) => {
224779
+ onChange(username);
224780
+ setOpen(false);
224781
+ };
224782
+ return (jsxs(Popover, { open: open, onOpenChange: setOpen, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", role: "combobox", "aria-expanded": open, "aria-label": t('analyticsUserFilterSelect.filterByUser'), className: "h-9 w-full justify-between bg-white font-normal", children: [jsx("span", { className: "truncate", children: value || t('analyticsUserFilterSelect.you') }), jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })] }) }), jsx(PopoverContent, { "data-iblai-dialog-interaction-layer": true, className: "z-[60] w-[280px] p-0", align: "start", children: jsxs(Command, { shouldFilter: false, children: [jsx(CommandInput, { value: search, onValueChange: setSearch, placeholder: t('analyticsUserFilterSelect.searchPlaceholder') }), jsxs(CommandList, { children: [jsxs(CommandGroup, { children: [jsxs(CommandItem, { value: SELF_VALUE, onSelect: () => handleSelect(''), children: [jsx(Check, { className: cn('mr-2 h-4 w-4', value ? 'opacity-0' : 'opacity-100') }), t('analyticsUserFilterSelect.you')] }), users.map((user) => (jsxs(CommandItem, {
224783
+ // cmdk keys items by value; the search itself is server-side.
224784
+ value: user.username, onSelect: () => handleSelect(user.username), children: [jsx(Check, { className: cn('mr-2 h-4 w-4', value === user.username ? 'opacity-100' : 'opacity-0') }), jsxs("div", { className: "flex min-w-0 flex-col", children: [jsx("span", { className: "truncate font-medium", children: user.name || user.username }), jsx("span", { className: "truncate text-xs text-gray-500", children: user.email || user.username })] })] }, user.key)))] }), isFetching && (jsx("div", { className: "px-3 py-4 text-center text-sm text-gray-500", children: t('analyticsUserFilterSelect.loadingUsers') })), !isFetching && users.length === 0 && (jsx("div", { className: "px-3 py-4 text-center text-sm text-gray-500", children: t('analyticsUserFilterSelect.noUsersFound') }))] })] }) })] }));
224785
+ }
224786
+
224787
+ /**
224788
+ * The global and cross-mentor endpoints both cap `page_size` at 25 server-side,
224789
+ * so we ask for a size every scope can honor rather than paginating
224790
+ * inconsistently between them.
224791
+ */
224792
+ const MEMORY_PAGE_SIZE = 20;
224793
+ /** Sentinel for "don't filter by category" — categories are keyed by slug. */
224794
+ const ALL_CATEGORIES = 'all';
224795
+ const formatDate = (date) => date ? date.toISOString().split('T')[0] : undefined;
224796
+ function isForbiddenError(error) {
224797
+ return !!error && 'status' in error && error.status === 403;
224798
+ }
224799
+ function toRowFromMentorMemory(memory) {
224800
+ var _a, _b, _c, _d, _e, _f;
224801
+ return {
224802
+ id: memory.id,
224803
+ content: memory.content,
224804
+ categoryName: (_b = (_a = memory.category) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : null,
224805
+ categorySlug: (_d = (_c = memory.category) === null || _c === void 0 ? void 0 : _c.slug) !== null && _d !== void 0 ? _d : null,
224806
+ learner: memory.email || memory.username,
224807
+ email: memory.email || null,
224808
+ mentorId: (_e = memory.mentor_id) !== null && _e !== void 0 ? _e : null,
224809
+ mentorName: 'mentor_name' in memory ? ((_f = memory.mentor_name) !== null && _f !== void 0 ? _f : null) : null,
224810
+ isAutoGenerated: memory.is_auto_generated,
224811
+ sourceSessionId: memory.source_session_id,
224812
+ createdAt: memory.created_at,
224813
+ };
224814
+ }
224815
+ function toRowFromGlobalMemory(memory) {
224816
+ return {
224817
+ id: memory.id,
224818
+ content: memory.content,
224819
+ categoryName: null,
224820
+ categorySlug: null,
224821
+ learner: memory.username,
224822
+ email: null,
224823
+ mentorId: null,
224824
+ mentorName: null,
224825
+ isAutoGenerated: memory.is_auto_generated,
224826
+ sourceSessionId: memory.source_session_id,
224827
+ createdAt: memory.created_at,
224828
+ };
224829
+ }
224830
+ /**
224831
+ * Backs the analytics Memory tab. Owns scope selection (including an agent
224832
+ * picked through the dropdown's search), the shared filter state, and
224833
+ * pagination, and normalizes the three differently-shaped memory endpoints
224834
+ * into a single row type.
224835
+ *
224836
+ * All three list queries are always mounted (RTK Query hooks can't be called
224837
+ * conditionally); `skip` keeps only the active scope's request in flight.
224838
+ */
224839
+ const useMemory = ({ tenantKey, userId, mentorId, myMemory = false, }) => {
224840
+ const [searchedMentor, setSearchedMentor] = useState(null);
224841
+ // An agent picked from the scope dropdown's search stands in for the route
224842
+ // agent, so admins can inspect any agent's memories without leaving the tab.
224843
+ const activeMentorId = (searchedMentor === null || searchedMentor === void 0 ? void 0 : searchedMentor.id) || mentorId;
224844
+ const hasMentor = !!activeMentorId;
224845
+ // Global (agent-independent) memories lead: they are the ones that hold for
224846
+ // the user everywhere, so the tab opens on them and the dropdown lists them
224847
+ // first.
224848
+ const availableScopes = useMemo(() => (hasMentor ? ['global', 'mentor', 'all-mentors'] : ['global', 'all-mentors']), [hasMentor]);
224849
+ const [scope, setScope] = useState('global');
224850
+ const [page, setPage] = useState(1);
224851
+ const [learnerFilter, setLearnerFilter] = useState('');
224852
+ const [categoryFilter, setCategoryFilter] = useState(ALL_CATEGORIES);
224853
+ const [contentFilter, setContentFilter] = useState('');
224854
+ const [dateRange, setDateRange] = useState(undefined);
224855
+ const selectSearchedMentor = useCallback((mentor) => {
224856
+ setSearchedMentor(mentor);
224857
+ // Categories belong to a single agent, so a slug carried over from the
224858
+ // previous one would filter the new agent's memories down to nothing.
224859
+ setCategoryFilter(ALL_CATEGORIES);
224860
+ if (mentor)
224861
+ setScope('mentor');
224862
+ }, []);
224863
+ // Picking an agent in the analytics switcher is the more explicit choice, so
224864
+ // it drops whatever the tab's own search had pinned.
224865
+ useEffect(() => {
224866
+ setSearchedMentor(null);
224867
+ setCategoryFilter(ALL_CATEGORIES);
224868
+ }, [mentorId]);
224869
+ // The agent scope disappears when the analytics page has no agent selected;
224870
+ // fall back rather than leaving the tab stuck on an unqueryable scope.
224871
+ useEffect(() => {
224872
+ if (!hasMentor && scope === 'mentor') {
224873
+ setScope('all-mentors');
224874
+ }
224875
+ }, [hasMentor, scope]);
224876
+ // Only the agent-scoped endpoint takes a `category`, and the category list is
224877
+ // that agent's. Drop the selection anywhere else so a filter the UI no longer
224878
+ // shows can't silently narrow the results.
224879
+ useEffect(() => {
224880
+ if (scope !== 'mentor')
224881
+ setCategoryFilter(ALL_CATEGORIES);
224882
+ }, [scope]);
224883
+ // Any filter or scope change invalidates the current page index — the new
224884
+ // result set may well be shorter than the page we're sitting on.
224885
+ useEffect(() => {
224886
+ setPage(1);
224887
+ }, [scope, learnerFilter, categoryFilter, contentFilter, dateRange]);
224888
+ const startDate = formatDate(dateRange === null || dateRange === void 0 ? void 0 : dateRange.from);
224889
+ const endDate = formatDate(dateRange === null || dateRange === void 0 ? void 0 : dateRange.to);
224890
+ const isMentorScope = scope === 'mentor' && hasMentor;
224891
+ const isAllMentorsScope = scope === 'all-mentors';
224892
+ const isGlobalScope = scope === 'global';
224893
+ const hasIdentity = !!tenantKey && !!userId;
224894
+ const mentorListParams = useMemo(() => ({
224895
+ page,
224896
+ page_size: MEMORY_PAGE_SIZE,
224897
+ ...(categoryFilter !== ALL_CATEGORIES ? { category: categoryFilter } : {}),
224898
+ ...(learnerFilter ? { user_id: learnerFilter } : {}),
224899
+ ...(startDate ? { start_date: startDate } : {}),
224900
+ ...(endDate ? { end_date: endDate } : {}),
224901
+ ...(myMemory ? { my_memory: true } : {}),
224902
+ }), [page, categoryFilter, learnerFilter, startDate, endDate, myMemory]);
224903
+ const { data: mentorList, isLoading: isLoadingMentorList, isFetching: isFetchingMentorList, error: mentorListError, } = useGetMentorMemoriesListQuery({ org: tenantKey, userId, mentorId: activeMentorId !== null && activeMentorId !== void 0 ? activeMentorId : '', params: mentorListParams }, { skip: !hasIdentity || !isMentorScope });
224904
+ // Unpaginated, grouped-by-category companion to the list above. It honors the
224905
+ // same filters, so it's the only place we can source aggregates that describe
224906
+ // the whole filtered set instead of just the visible page.
224907
+ const mentorSnapshotParams = useMemo(() => ({
224908
+ ...(learnerFilter ? { user_id: learnerFilter } : {}),
224909
+ ...(startDate ? { start_date: startDate } : {}),
224910
+ ...(endDate ? { end_date: endDate } : {}),
224911
+ ...(myMemory ? { my_memory: true } : {}),
224912
+ }), [learnerFilter, startDate, endDate, myMemory]);
224913
+ const { data: mentorGrouped, isLoading: isLoadingMentorGrouped } = useGetMentorMemoriesQuery({ org: tenantKey, userId, mentorId: activeMentorId !== null && activeMentorId !== void 0 ? activeMentorId : '', params: mentorSnapshotParams }, { skip: !hasIdentity || !isMentorScope });
224914
+ // Deliberately unfiltered by mentor — the point of this scope is to span
224915
+ // every agent. Per-agent numbers come from the `mentor` scope instead.
224916
+ const allMentorsParams = useMemo(() => ({
224917
+ page,
224918
+ page_size: MEMORY_PAGE_SIZE,
224919
+ ...(learnerFilter ? { user_id: learnerFilter } : {}),
224920
+ ...(startDate ? { start_date: startDate } : {}),
224921
+ ...(endDate ? { end_date: endDate } : {}),
224922
+ }), [page, learnerFilter, startDate, endDate]);
224923
+ const { data: allMentors, isLoading: isLoadingAllMentors, isFetching: isFetchingAllMentors, error: allMentorsError, } = useGetAllMentorMemoriesQuery({ org: tenantKey, userId, params: allMentorsParams }, { skip: !hasIdentity || !isAllMentorsScope });
224924
+ const globalParams = useMemo(() => ({
224925
+ page,
224926
+ page_size: MEMORY_PAGE_SIZE,
224927
+ ...(learnerFilter ? { user_id: learnerFilter } : {}),
224928
+ ...(contentFilter ? { content: contentFilter } : {}),
224929
+ ...(startDate ? { start_date: startDate } : {}),
224930
+ ...(endDate ? { end_date: endDate } : {}),
224931
+ }), [page, learnerFilter, contentFilter, startDate, endDate]);
224932
+ const { data: globalMemories, isLoading: isLoadingGlobal, isFetching: isFetchingGlobal, error: globalError, } = useGetGlobalMemoriesQuery({ org: tenantKey, userId, params: globalParams }, { skip: !hasIdentity || !isGlobalScope });
224933
+ const { data: adminCategories } = useGetMemoryCategoriesAdminQuery({ org: tenantKey, mentorId: activeMentorId !== null && activeMentorId !== void 0 ? activeMentorId : '' }, { skip: !tenantKey || !hasMentor });
224934
+ const rows = useMemo(() => {
224935
+ var _a, _b, _c;
224936
+ if (isMentorScope)
224937
+ return ((_a = mentorList === null || mentorList === void 0 ? void 0 : mentorList.results) !== null && _a !== void 0 ? _a : []).map(toRowFromMentorMemory);
224938
+ if (isAllMentorsScope)
224939
+ return ((_b = allMentors === null || allMentors === void 0 ? void 0 : allMentors.results) !== null && _b !== void 0 ? _b : []).map(toRowFromMentorMemory);
224940
+ return ((_c = globalMemories === null || globalMemories === void 0 ? void 0 : globalMemories.results) !== null && _c !== void 0 ? _c : []).map(toRowFromGlobalMemory);
224941
+ }, [isMentorScope, isAllMentorsScope, mentorList, allMentors, globalMemories]);
224942
+ const totalCount = useMemo(() => {
224943
+ var _a, _b, _c;
224944
+ if (isMentorScope)
224945
+ return (_a = mentorList === null || mentorList === void 0 ? void 0 : mentorList.count) !== null && _a !== void 0 ? _a : 0;
224946
+ if (isAllMentorsScope)
224947
+ return (_b = allMentors === null || allMentors === void 0 ? void 0 : allMentors.count) !== null && _b !== void 0 ? _b : 0;
224948
+ return (_c = globalMemories === null || globalMemories === void 0 ? void 0 : globalMemories.count) !== null && _c !== void 0 ? _c : 0;
224949
+ }, [isMentorScope, isAllMentorsScope, mentorList, allMentors, globalMemories]);
224950
+ // Only the agent scope has an unpaginated source to aggregate over. The
224951
+ // category filter is applied client-side here because the grouped endpoint
224952
+ // returns every category regardless.
224953
+ const aggregates = useMemo(() => {
224954
+ if (!isMentorScope || !mentorGrouped)
224955
+ return null;
224956
+ const groups = categoryFilter === ALL_CATEGORIES
224957
+ ? mentorGrouped
224958
+ : mentorGrouped.filter((group) => group.category.slug === categoryFilter);
224959
+ const learners = new Set();
224960
+ let autoCaptured = 0;
224961
+ let totalMemories = 0;
224962
+ const categories = groups.map((group) => {
224963
+ group.memories.forEach((memory) => {
224964
+ learners.add(memory.email || memory.username);
224965
+ if (memory.is_auto_generated)
224966
+ autoCaptured += 1;
224967
+ });
224968
+ totalMemories += group.memories.length;
224969
+ return {
224970
+ slug: group.category.slug,
224971
+ name: group.category.name,
224972
+ count: group.memories.length,
224973
+ };
224974
+ });
224975
+ return {
224976
+ totalMemories,
224977
+ autoCaptured,
224978
+ learners: learners.size,
224979
+ categories: categories.sort((a, b) => b.count - a.count),
224980
+ };
224981
+ }, [isMentorScope, mentorGrouped, categoryFilter]);
224982
+ const error = isMentorScope ? mentorListError : isAllMentorsScope ? allMentorsError : globalError;
224983
+ const isLoading = isMentorScope
224984
+ ? isLoadingMentorList || isLoadingMentorGrouped
224985
+ : isAllMentorsScope
224986
+ ? isLoadingAllMentors
224987
+ : isLoadingGlobal;
224988
+ const isFetching = isMentorScope
224989
+ ? isFetchingMentorList
224990
+ : isAllMentorsScope
224991
+ ? isFetchingAllMentors
224992
+ : isFetchingGlobal;
224993
+ return {
224994
+ scope,
224995
+ setScope,
224996
+ availableScopes,
224997
+ searchedMentor,
224998
+ selectSearchedMentor,
224999
+ rows,
225000
+ aggregates,
225001
+ totalCount,
225002
+ categories: adminCategories !== null && adminCategories !== void 0 ? adminCategories : [],
225003
+ isLoading,
225004
+ isFetching,
225005
+ error,
225006
+ isForbidden: isForbiddenError(error),
225007
+ page,
225008
+ setPage,
225009
+ totalPages: Math.ceil(totalCount / MEMORY_PAGE_SIZE),
225010
+ pageSize: MEMORY_PAGE_SIZE,
225011
+ learnerFilter,
225012
+ setLearnerFilter,
225013
+ categoryFilter,
225014
+ setCategoryFilter,
225015
+ contentFilter,
225016
+ setContentFilter,
225017
+ dateRange,
225018
+ setDateRange,
225019
+ };
225020
+ };
225021
+
225022
+ const CELL = 'p-3 text-[#646464]';
225023
+ const HEAD = 'p-3 text-left text-sm whitespace-nowrap text-[#646464]';
225024
+ /**
225025
+ * Action items that share the scope dropdown. Radix rejects empty values and
225026
+ * matches the trigger label by value, so these are sentinels the change handler
225027
+ * intercepts rather than selectable scopes.
225028
+ */
225029
+ const SEARCH_AGENTS_ACTION = '__search-agents__';
225030
+ const CLEAR_AGENT_ACTION = '__clear-agent__';
225031
+ function MemoryDetailDialog({ memory, onClose, scope, }) {
225032
+ const t = useT();
225033
+ return (jsx(Dialog, { open: !!memory, onOpenChange: (open) => !open && onClose(), children: jsxs(DialogContent, { className: "max-w-lg", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { children: t('analyticsAnalyticsMemoryStats.detailTitle') }) }), memory && (jsxs("div", { className: "space-y-4", children: [jsx("p", { className: "text-sm whitespace-pre-wrap text-gray-700", children: memory.content }), jsxs("dl", { className: "grid grid-cols-2 gap-3 border-t border-gray-100 pt-3 text-xs", children: [jsxs("div", { children: [jsx("dt", { className: "text-gray-500", children: t('analyticsAnalyticsMemoryStats.detailUser') }), jsx("dd", { className: "mt-0.5 font-medium break-all text-gray-800", children: memory.learner })] }), memory.categoryName && (jsxs("div", { children: [jsx("dt", { className: "text-gray-500", children: t('analyticsAnalyticsMemoryStats.detailCategory') }), jsx("dd", { className: "mt-0.5 font-medium text-gray-800", children: memory.categoryName })] })), scope === 'all-mentors' && (jsxs("div", { children: [jsx("dt", { className: "text-gray-500", children: t('analyticsAnalyticsMemoryStats.detailAgent') }), jsx("dd", { className: "mt-0.5 font-medium break-all text-gray-800", children: memory.mentorName || memory.mentorId || '—' })] })), jsxs("div", { children: [jsx("dt", { className: "text-gray-500", children: t('analyticsAnalyticsMemoryStats.detailSource') }), jsx("dd", { className: "mt-0.5 font-medium text-gray-800", children: memory.isAutoGenerated
225034
+ ? t('analyticsAnalyticsMemoryStats.sourceAuto')
225035
+ : t('analyticsAnalyticsMemoryStats.sourceManual') })] }), jsxs("div", { children: [jsx("dt", { className: "text-gray-500", children: t('analyticsAnalyticsMemoryStats.detailCaptured') }), jsx("dd", { className: "mt-0.5 font-medium text-gray-800", children: format$1(new Date(memory.createdAt), "MMM dd, yyyy 'at' h:mm a") })] }), memory.sourceSessionId && (jsxs("div", { className: "col-span-2", children: [jsx("dt", { className: "text-gray-500", children: t('analyticsAnalyticsMemoryStats.detailSession') }), jsx("dd", { className: "mt-0.5 font-mono text-[11px] break-all text-gray-800", children: memory.sourceSessionId })] }))] })] }))] }) }));
225036
+ }
225037
+ function AgentSearchDialog({ tenantKey, open, onClose, selectedMentorId, onSelect, }) {
225038
+ const t = useT();
225039
+ const [query, setQuery] = useState('');
225040
+ return (jsx(Dialog, { open: open, onOpenChange: (next) => !next && onClose(), children: jsxs(DialogContent, { className: "max-w-2xl", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { children: t('analyticsAnalyticsMemoryStats.searchAgentsTitle') }) }), jsx(MentorSelectionGrid, { tenantKey: tenantKey, searchQuery: query, onSearchChange: setQuery, selectedMentorIds: selectedMentorId ? [selectedMentorId] : [], itemsPerPage: 6, minHeight: "240px", onMentorSelect: (mentor) => {
225041
+ if (!(mentor === null || mentor === void 0 ? void 0 : mentor.unique_id))
225042
+ return;
225043
+ onSelect({ id: mentor.unique_id, name: mentor.name });
225044
+ onClose();
225045
+ } })] }) }));
225046
+ }
225047
+ /**
225048
+ * Analytics "Memory" tab. Surfaces the memories memsearch captures while users
225049
+ * chat with agents, across three scopes: the selected agent, every agent in the
225050
+ * tenant, and global (agent-independent) memories. The scope dropdown also
225051
+ * offers an agent search, so any agent's memories can be pulled up without
225052
+ * leaving the tab.
225053
+ *
225054
+ * Hosts are expected to gate this behind `GET .../memsearch-status/`; the
225055
+ * component itself only handles the per-request permission failure (403).
225056
+ */
225057
+ function AnalyticsMemoryStats({ tenantKey, mentorId, userId, selectedMentorId, myMemory = false, }) {
225058
+ const t = useT();
225059
+ const [selectedMemory, setSelectedMemory] = useState(null);
225060
+ const [agentSearchOpen, setAgentSearchOpen] = useState(false);
225061
+ // The content search is committed on Enter/blur rather than per-keystroke so
225062
+ // we don't fire a request (and reset pagination) on every character typed.
225063
+ const [contentInput, setContentInput] = useState('');
225064
+ const { scope, setScope, availableScopes, searchedMentor, selectSearchedMentor, rows, aggregates, categories, isLoading, error, isForbidden, page, setPage, totalPages, learnerFilter, setLearnerFilter, categoryFilter, setCategoryFilter, setContentFilter, dateRange, setDateRange, } = useMemory({
225065
+ tenantKey,
225066
+ userId,
225067
+ mentorId: selectedMentorId || mentorId,
225068
+ myMemory,
225069
+ });
225070
+ const scopeLabels = {
225071
+ // A searched agent takes over the agent scope, so name it in the trigger.
225072
+ mentor: (searchedMentor === null || searchedMentor === void 0 ? void 0 : searchedMentor.name) || t('analyticsAnalyticsMemoryStats.scopeMentor'),
225073
+ 'all-mentors': t('analyticsAnalyticsMemoryStats.scopeAllMentors'),
225074
+ global: t('analyticsAnalyticsMemoryStats.scopeGlobal'),
225075
+ };
225076
+ const showCategoryColumn = scope !== 'global';
225077
+ const showAgentColumn = scope === 'all-mentors';
225078
+ // Only the agent-scoped endpoint filters by category, and the categories
225079
+ // themselves are that agent's — see `useMemory`.
225080
+ const showCategoryFilter = scope === 'mentor' && categories.length > 0;
225081
+ if (isForbidden) {
225082
+ return (jsx(Card, { className: "rounded-lg border border-gray-100 bg-white shadow-sm", children: jsx(CardContent, { className: "p-8 text-center", children: jsx("p", { className: "text-gray-500", children: t('analyticsAnalyticsMemoryStats.noPermission') }) }) }));
225083
+ }
225084
+ return (jsxs("div", { className: "space-y-6", children: [jsx("div", { className: "rounded-lg border border-[oklch(0.922_0_0)] bg-white p-4", children: jsxs("div", { className: "flex flex-col gap-3 lg:flex-row", children: [jsx("div", { className: "min-w-[160px]", children: jsxs(Select$1, { value: scope, onValueChange: (value) => {
225085
+ // The trailing items are actions, not scopes — the Select stays
225086
+ // on whatever scope is currently active.
225087
+ if (value === SEARCH_AGENTS_ACTION) {
225088
+ setAgentSearchOpen(true);
225089
+ return;
225090
+ }
225091
+ if (value === CLEAR_AGENT_ACTION) {
225092
+ selectSearchedMentor(null);
225093
+ return;
225094
+ }
225095
+ setScope(value);
225096
+ }, children: [jsx(SelectTrigger, { className: "h-9 w-full bg-white font-normal", "aria-label": t('analyticsAnalyticsMemoryStats.scopeLabel'), children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [availableScopes.map((value) => (jsx(SelectItem, { value: value, children: scopeLabels[value] }, value))), jsx(SelectSeparator, {}), jsx(SelectItem, { value: SEARCH_AGENTS_ACTION, children: jsxs("span", { className: "flex items-center gap-2", children: [jsx(Search, { className: "h-3.5 w-3.5" }), t('analyticsAnalyticsMemoryStats.searchAgents')] }) }), searchedMentor && (jsx(SelectItem, { value: CLEAR_AGENT_ACTION, children: jsxs("span", { className: "flex items-center gap-2", children: [jsx(X$1, { className: "h-3.5 w-3.5" }), t('analyticsAnalyticsMemoryStats.clearAgentSearch')] }) }))] })] }) }), jsx("div", { className: "min-w-[200px] flex-1", children: jsx(UserFilterSelect, { tenantKey: tenantKey, currentUsername: userId, value: learnerFilter, onChange: setLearnerFilter }) }), scope === 'global' && (jsx("form", { className: "min-w-[180px] flex-1", onSubmit: (event) => {
225097
+ event.preventDefault();
225098
+ setContentFilter(contentInput.trim());
225099
+ }, children: jsx(Input, { value: contentInput, onChange: (event) => setContentInput(event.target.value), onBlur: () => setContentFilter(contentInput.trim()), placeholder: t('analyticsAnalyticsMemoryStats.contentPlaceholder'), "aria-label": t('analyticsAnalyticsMemoryStats.contentPlaceholder'), className: "h-9 bg-white" }) })), jsxs(Popover, { modal: true, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", className: "flex h-9 w-full items-center gap-2 bg-white font-normal whitespace-nowrap lg:w-auto", children: [jsx(Calendar$1, { className: "h-4 w-4" }), (dateRange === null || dateRange === void 0 ? void 0 : dateRange.from) && (dateRange === null || dateRange === void 0 ? void 0 : dateRange.to)
225100
+ ? `${format$1(dateRange.from, 'MMM dd')} - ${format$1(dateRange.to, 'MMM dd')}`
225101
+ : t('analyticsAnalyticsMemoryStats.pickDateRange')] }) }), jsx(PopoverContent, { "data-iblai-dialog-interaction-layer": true, className: "z-[60] w-auto p-0", align: "start", children: jsx(Calendar, { mode: "range", selected: dateRange, onSelect: (range) => setDateRange(range ? { from: range.from, to: range.to } : undefined), numberOfMonths: 2 }) })] }), showCategoryFilter && (jsx("div", { className: "min-w-[160px]", children: jsxs(Select$1, { value: categoryFilter, onValueChange: setCategoryFilter, children: [jsx(SelectTrigger, { className: "h-9 w-full bg-white font-normal", "aria-label": t('analyticsAnalyticsMemoryStats.allCategories'), children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: ALL_CATEGORIES, children: t('analyticsAnalyticsMemoryStats.allCategories') }), categories.map((category) => (jsx(SelectItem, { value: category.slug, children: category.name }, category.slug)))] })] }) }))] }) }), aggregates && aggregates.categories.length > 0 && (jsxs("div", { className: "rounded-lg border border-[oklch(0.922_0_0)] bg-white p-4", children: [jsxs("h3", { className: "mb-4 flex items-center gap-2 text-sm font-medium text-[#484848]", children: [jsx(Brain, { className: "h-4 w-4 text-blue-600" }), t('analyticsAnalyticsMemoryStats.byCategory')] }), jsx("ul", { className: "space-y-3", children: aggregates.categories.map((category) => {
225102
+ const percent = aggregates.totalMemories
225103
+ ? Math.round((category.count / aggregates.totalMemories) * 100)
225104
+ : 0;
225105
+ return (jsxs("li", { children: [jsxs("div", { className: "mb-1 flex items-center justify-between text-sm text-[#646464]", children: [jsx("span", { children: category.name }), jsx("span", { className: "tabular-nums", children: t('analyticsAnalyticsMemoryStats.categoryCount', {
225106
+ count: category.count,
225107
+ percent,
225108
+ }) })] }), jsx("div", { className: "h-2 w-full overflow-hidden rounded-full bg-gray-100", children: jsx("div", { className: "h-full rounded-full bg-blue-600", style: { width: `${percent}%` } }) })] }, category.slug));
225109
+ }) })] })), jsx("div", { className: "overflow-hidden rounded-md border border-[oklch(0.922_0_0)] bg-white", children: jsx("div", { className: "overflow-x-auto", children: jsx("div", { className: "inline-block min-w-full align-middle", children: isLoading ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-blue-600 border-t-transparent" }) })) : error ? (jsx("div", { className: "py-8 text-center text-[#646464]", children: t('analyticsAnalyticsMemoryStats.loadError') })) : rows.length === 0 ? (jsx("div", { className: "h-[120px]", children: jsx(EmptyStats, { title: t('analyticsAnalyticsMemoryStats.noMemories') }) })) : (jsxs(Table, { className: "min-w-full", children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "bg-muted/50 border-b border-[oklch(0.922_0_0)]", children: [jsx(TableHead, { className: HEAD, children: t('analyticsAnalyticsMemoryStats.colUser') }), jsx(TableHead, { className: HEAD, children: t('analyticsAnalyticsMemoryStats.colMemory') }), showAgentColumn && (jsx(TableHead, { className: HEAD, children: t('analyticsAnalyticsMemoryStats.colAgent') })), showCategoryColumn && (jsx(TableHead, { className: HEAD, children: t('analyticsAnalyticsMemoryStats.colCategory') })), jsx(TableHead, { className: HEAD, children: t('analyticsAnalyticsMemoryStats.colCaptured') })] }) }), jsx(TableBody, { children: rows.map((row) => {
225110
+ var _a;
225111
+ return (jsxs(TableRow, { onClick: () => setSelectedMemory(row), className: "cursor-pointer border-b border-[oklch(0.922_0_0)] last:border-0 hover:bg-gray-50", children: [jsx(TableCell, { className: cn(CELL, 'font-medium whitespace-nowrap'), children: row.learner }), jsx(TableCell, { className: cn(CELL, 'min-w-[280px]'), children: jsx("span", { className: "line-clamp-2", children: row.content }) }), showAgentColumn && (jsx(TableCell, { className: cn(CELL, 'whitespace-nowrap'), children: row.mentorName || row.mentorId || '—' })), showCategoryColumn && (jsx(TableCell, { className: cn(CELL, 'whitespace-nowrap'), children: row.categoryName ? (jsx("span", { className: "rounded-md bg-blue-100 px-2 py-1 text-xs text-blue-700", children: row.categoryName })) : ('—') })), jsx(TableCell, { className: cn(CELL, 'whitespace-nowrap'), children: formatDistanceToNow(new Date(row.createdAt), { addSuffix: true }) })] }, `${(_a = row.mentorId) !== null && _a !== void 0 ? _a : 'global'}-${row.id}`));
225112
+ }) })] })) }) }) }), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: isLoading }), jsx(MemoryDetailDialog, { memory: selectedMemory, scope: scope, onClose: () => setSelectedMemory(null) }), agentSearchOpen && (jsx(AgentSearchDialog, { open: true, tenantKey: tenantKey, selectedMentorId: searchedMentor === null || searchedMentor === void 0 ? void 0 : searchedMentor.id, onSelect: selectSearchedMentor, onClose: () => setAgentSearchOpen(false) }))] }));
225113
+ }
225114
+
224249
225115
  const SkeletonMultiplier = ({ Skeleton, multiplier }) => {
224250
225116
  return (jsx(Fragment$1, { children: Array.from({ length: multiplier }).map((_, index) => (jsx(Skeleton, {}, index))) }));
224251
225117
  };
@@ -229123,8 +229989,6 @@ function CreditBalance({ tenant, username, mainPlatformKey, currentUserEmail, re
229123
229989
  : t('creditBalance.manageBilling')] })) }))] }), jsx(AutoRechargeModal, { tenant: tenant, isOpen: isAutoRechargeModalOpen, onClose: () => setIsAutoRechargeModalOpen(false) }), jsx(AddCreditsModal, { tenant: tenant, isOpen: isAddCreditsModalOpen, onClose: () => setIsAddCreditsModalOpen(false) }), jsx(AppleRestrictionModal, { isOpen: isAppleRestrictionModalOpen, onClose: () => setIsAppleRestrictionModalOpen(false) })] }));
229124
229990
  }
229125
229991
 
229126
- function c(e,u,c){var i=this,a=useRef(null),o=useRef(0),f=useRef(null),l=useRef([]),v=useRef(),m=useRef(),d=useRef(e),g=useRef(true);d.current=e;var p="undefined"!=typeof window,w=!u&&0!==u&&p;if("function"!=typeof e)throw new TypeError("Expected a function");u=+u||0;var s=!!(c=c||{}).leading,x=!("trailing"in c)||!!c.trailing,h="maxWait"in c,y="debounceOnServer"in c&&!!c.debounceOnServer,F=h?Math.max(+c.maxWait||0,u):null;useEffect(function(){return g.current=true,function(){g.current=false;}},[]);var A=useMemo(function(){var r=function(r){var n=l.current,t=v.current;return l.current=v.current=null,o.current=r,m.current=d.current.apply(t,n)},n=function(r,n){w&&cancelAnimationFrame(f.current),f.current=w?requestAnimationFrame(r):setTimeout(r,n);},t=function(r){if(!g.current)return false;var n=r-a.current;return !a.current||n>=u||n<0||h&&r-o.current>=F},e=function(n){return f.current=null,x&&l.current?r(n):(l.current=v.current=null,m.current)},c=function r(){var c=Date.now();if(t(c))return e(c);if(g.current){var i=u-(c-a.current),f=h?Math.min(i,F-(c-o.current)):i;n(r,f);}},A=function(){if(p||y){var e=Date.now(),d=t(e);if(l.current=[].slice.call(arguments),v.current=i,a.current=e,d){if(!f.current&&g.current)return o.current=a.current,n(c,u),s?r(a.current):m.current;if(h)return n(c,u),r(a.current)}return f.current||n(c,u),m.current}};return A.cancel=function(){f.current&&(w?cancelAnimationFrame(f.current):clearTimeout(f.current)),o.current=0,l.current=a.current=v.current=f.current=null;},A.isPending=function(){return !!f.current},A.flush=function(){return f.current?e(Date.now()):m.current},A},[s,h,u,F,x,w,p,y]);return A}function i(r,n){return r===n}function a(n,t,a){var o=i,f=useRef(n),l=useState({})[1],v=c(useCallback(function(r){f.current=r,l({});},[l]),t,a),m=useRef(n);return o(m.current,n)||(v(n),m.current=n),[f.current,v]}
229127
-
229128
229992
  const DEFAULT_ITEMS_PER_PAGE = 10;
229129
229993
  const DEFAULT_DEBOUNCE_MS = 500;
229130
229994
  /** Manages the projects list: debounced search, pagination, and the paged query. */
@@ -231024,107 +231888,6 @@ var minimumMentorAlert = /*#__PURE__*/Object.freeze({
231024
231888
  MinimumMentorAlert: MinimumMentorAlert
231025
231889
  });
231026
231890
 
231027
- /**
231028
- * Core agent search hook — thin wrapper around `useGetAiSearchMentorsQuery`.
231029
- *
231030
- * This is the low-level building block. For a higher-level hook that manages
231031
- * search state, debounce, and pagination controls, use
231032
- * `useAgentSearchWithPagination`.
231033
- */
231034
- function useAgentSearch({ tenantKey, query, limit = 6, offset, starred, featured, category, subjects, llm, types, includeMainPublicMentors, orderDirection, skip = false, }) {
231035
- var _a, _b, _c;
231036
- const { data, isLoading, isFetching, refetch } = useGetAiSearchMentorsQuery({
231037
- platform_key: tenantKey,
231038
- query: query || undefined,
231039
- limit,
231040
- ...(offset !== undefined && { offset }),
231041
- ...(starred !== undefined && { starred }),
231042
- ...(featured !== undefined && { featured }),
231043
- ...(category && { category }),
231044
- ...(subjects && { subjects }),
231045
- ...(llm && { llm }),
231046
- ...(types && { types }),
231047
- ...(includeMainPublicMentors !== undefined && {
231048
- include_main_public_mentors: includeMainPublicMentors,
231049
- }),
231050
- ...(orderDirection && { order_direction: orderDirection }),
231051
- }, { skip: skip || !tenantKey });
231052
- return {
231053
- agents: ((_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : []),
231054
- facets: data === null || data === void 0 ? void 0 : data.facets,
231055
- hasMore: !!(data === null || data === void 0 ? void 0 : data.next),
231056
- totalCount: (_b = data === null || data === void 0 ? void 0 : data.count) !== null && _b !== void 0 ? _b : 0,
231057
- totalPages: (_c = data === null || data === void 0 ? void 0 : data.total_pages) !== null && _c !== void 0 ? _c : 0,
231058
- isLoading,
231059
- isFetching,
231060
- refetch,
231061
- };
231062
- }
231063
-
231064
- /**
231065
- * Higher-level agent search hook that manages search state, debounce, and
231066
- * pagination controls on top of `useAgentSearch`.
231067
- *
231068
- * Use this for simple list/table views (MyMentorsModal, SettingsModal).
231069
- * For the full explore page with sections, use `useAgentSearch` directly.
231070
- */
231071
- function useAgentSearchWithPagination({ itemsPerPage = 6, paginationMode = 'paginated', debounceMs = 500, ...queryConfig }) {
231072
- const [searchQuery, setSearchQuery] = React__default.useState('');
231073
- const [debouncedQuery] = a(searchQuery, debounceMs);
231074
- const [currentPage, setCurrentPage] = React__default.useState(1);
231075
- const [infiniteLimit, setInfiniteLimit] = React__default.useState(itemsPerPage);
231076
- // Reset pagination when search changes
231077
- React__default.useEffect(() => {
231078
- setCurrentPage(1);
231079
- setInfiniteLimit(itemsPerPage);
231080
- }, [debouncedQuery, itemsPerPage]);
231081
- const isPaginated = paginationMode === 'paginated';
231082
- const result = useAgentSearch({
231083
- ...queryConfig,
231084
- query: debouncedQuery,
231085
- limit: isPaginated ? itemsPerPage : infiniteLimit,
231086
- offset: isPaginated ? (currentPage - 1) * itemsPerPage : undefined,
231087
- });
231088
- const totalPages = Math.ceil(result.totalCount / itemsPerPage);
231089
- const handlePageChange = React__default.useCallback((page) => {
231090
- setCurrentPage(page);
231091
- }, []);
231092
- const loadMore = React__default.useCallback(() => {
231093
- setInfiniteLimit((prev) => prev + itemsPerPage);
231094
- }, [itemsPerPage]);
231095
- return {
231096
- ...result,
231097
- searchQuery,
231098
- setSearchQuery,
231099
- debouncedQuery,
231100
- currentPage,
231101
- totalPages,
231102
- handlePageChange,
231103
- loadMore,
231104
- };
231105
- }
231106
-
231107
- function MentorSelectionGrid({ selectedMentorIds, onMentorSelect, searchQuery, onSearchChange, tenantKey, itemsPerPage = 8, showSearch = true, minHeight = '400px', }) {
231108
- const t = useT();
231109
- const { agents: mentors, isLoading: isMentorsLoading, isFetching: isMentorsFetching, currentPage, totalPages, setSearchQuery: setMentorSearch, handlePageChange, } = useAgentSearchWithPagination({ tenantKey, itemsPerPage });
231110
- // Update search query with debounce effect handled by the hook
231111
- React__default.useEffect(() => {
231112
- setMentorSearch(searchQuery);
231113
- }, [searchQuery]);
231114
- const isMentorSelected = (mentorId) => {
231115
- return selectedMentorIds.includes(mentorId);
231116
- };
231117
- return (jsxs("div", { className: "space-y-4", children: [showSearch && (jsxs("div", { className: "relative", children: [isMentorsFetching ? (jsx(Spinner, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 transform text-gray-400" })) : (jsx(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 transform text-gray-400" })), jsx(Input, { placeholder: t('mentorsMentorSelectionGrid.searchAgentsPlaceholder'), value: searchQuery, onChange: (e) => onSearchChange(e.target.value), className: "h-10 border-gray-200 pl-10 focus:border-blue-500 focus:ring-0" })] })), jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "grid max-h-96 auto-rows-min grid-cols-1 items-start gap-3 overflow-y-auto rounded-lg border border-gray-200 p-4 md:max-h-none md:grid-cols-2", style: { minHeight }, children: isMentorsLoading ? (jsx("div", { className: "col-span-full py-8 text-center text-gray-500", children: t('mentorsMentorSelectionGrid.loadingAgents') })) : mentors.length === 0 ? (jsx("div", { className: "col-span-full py-8 text-center text-gray-500", children: t('mentorsMentorSelectionGrid.noAgentsFound') })) : (mentors.map((mentor) => {
231118
- const isSelected = isMentorSelected(mentor.unique_id || '');
231119
- const isAlreadyAdded = selectedMentorIds.includes(mentor.unique_id || '');
231120
- return (jsxs("button", { onClick: () => onMentorSelect(mentor), className: `flex cursor-pointer items-center gap-3 rounded-lg border-2 p-3 transition-all ${isSelected
231121
- ? 'border-blue-500 bg-blue-50'
231122
- : isAlreadyAdded
231123
- ? 'bg-blue-25 border-blue-300'
231124
- : 'border-gray-200 hover:border-gray-300 hover:bg-gray-50'}`, children: [jsxs(Avatar, { className: "h-12 w-12 flex-shrink-0", children: [jsx(AvatarImage, { src: mentor.profile_image || '/placeholder.svg', alt: mentor.name }), jsx(AvatarFallback, { children: mentor.name.substring(0, 2) })] }), jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-start text-left", children: [jsx("h4", { className: "truncate text-sm font-medium text-gray-900", children: mentor.name }), jsx("p", { className: "line-clamp-2 text-xs text-gray-600", children: mentor.description })] }), isSelected && (jsx("div", { className: "flex-shrink-0", children: jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-blue-600", children: jsx(Check, { className: "h-4 w-4 text-white" }) }) })), isAlreadyAdded && !isSelected && (jsx("div", { className: "flex-shrink-0", children: jsx("div", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-blue-400", children: jsx(Check, { className: "h-4 w-4 text-white" }) }) }))] }, mentor.unique_id));
231125
- })) }), jsx(IblPagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: handlePageChange, disabled: isMentorsFetching || isMentorsLoading })] })] }));
231126
- }
231127
-
231128
231891
  function CreateProjectModal({ isOpen, onClose, tenantKey, username, navigateToMentorInProject, }) {
231129
231892
  const t = useT();
231130
231893
  const dispatch = useDispatch();
@@ -235121,5 +235884,5 @@ var trainOrDeleteModal = /*#__PURE__*/Object.freeze({
235121
235884
  TrainOrDeleteModal: TrainOrDeleteModal
235122
235885
  });
235123
235886
 
235124
- export { ACCESS_COURSE_LABEL, AccessTimeHeatmap, AccessiblePaginate, AddMentorToProjectModal, AddSkillDialog, Admin, AdvancedTab, AgentConfigPrompts, AgentSkills, AlertsTab, AnalyticsAuditLogStats, AnalyticsCourseDetail, AnalyticsCourses, AnalyticsFinancialStats, AnalyticsLayout, AnalyticsMonetizationStats, AnalyticsOverview, AnalyticsProgramDetail, AnalyticsPrograms, AnalyticsReportDownload, AnalyticsReports, AnalyticsSettingsProvider, AnalyticsTopicsStats, AnalyticsTranscriptsStats, AnalyticsUsersStats, AppleRestrictionModal, ApplyWizard, BUY_NOW_LABEL, BillingTab, CATALOGS, CREATE_AGENT_LABELS, CUA_DRIVER_REPO_URL, CUA_DRIVER_TAURI_COMMANDS, CUA_DRIVER_TAURI_EVENTS, CategorizedDropdownMenu, ChartCardWrapper, ChartFiltersProvider, ChartLoading, ChatContext, ChatPrivacyToggle, ChatProvider, CompanyDialog, ConnectorManagementDialog, CopyButtonIcon, CourseAccessGuard, CourseCardSkeleton, CourseContentLoading, CourseOutline, CourseOutlineContext, CourseOutlineDrawer, CreateAgentForm, CreateAgentModal, CreateProjectModal, CreateWorkflowModal, CredentialBox, CredentialMiniBoxSkeleton, CredentialsList, CreditBalance, CustomDateRangePicker, CustomTooltip, DEFAULT_COWORK_REQUIRED_SIZE_GB, DEFAULT_LOCALE, DefaultEmptyBox, DeleteProjectModal, DeleteWorkflowModal, DiscoverContentCard, DiscoverFacetsFilter, DiscoverFilterDrawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, ENROLL_NOW_COURSE_STARTING_SOON_LABEL, ENROLL_NOW_LABEL, EditAlertDialog, EducationBox, EducationDialog, EducationTab, EdxIframeContext, EmptyStats, ExperienceBox, ExperienceDialog, ExperienceTab, FacetFilterContext, Footer, GradebookTab, GroupsFilterDropdown, INVITATION_ONLY_LABEL, InstitutionDialog, IntegrationsTab, InviteUserContent, InviteUserDialog, InvitedUsersDialog, LOCAL_MODELS, Loader, LocalLLMTab, LocalModelsContent, LoginButton, MACOS_PERMISSIONS_COMMANDS, Markdown, MinimumMentorAlert, MonetizationTab, NotificationDisplay, NotificationDropdown, ONBOARDING_SECTORS, OnboardingShell, OnboardingWizard, PaywallModal, PlacementExam, PlacementExamsDropdown, PlatformNavbar, PlatformNavbarSearch, Profile, ProfileTimeChart, ProgressDots, ProjectActionButtons, ProjectFilesModal, ProjectInstructionsModal, ProjectLandingPage, ProjectMentorsList, ProjectsPage, REQUEST_ACCESS_COURSE_STARTING_SOON_LABEL, REQUEST_ACCESS_LABEL, RenameProjectModal, ResumeBox, ResumeTab, RichTextEditor, SUPPORTED_LOCALES, SandboxConfig, SearchableMultiSelect, SendNotificationDialog, SignupButton, SkeletonActivityStatBox, SkeletonAddSkillsLoading, SkeletonCreatePathwaySearchList, SkeletonDiscoverFilterBox, SkeletonEducationBox, SkeletonMultiplier, SkeletonPathwayBox, SkeletonProfileInfoCard, SkeletonSkillBox, SkillBox, SkillDetailModal, SkillLeaderboardChart, SkillsBox, SkillsList, SlashSkillPicker, Spinner, StatCard, StepHeader, TAURI_COMMANDS, TAURI_EVENTS, TenantSwitcher, TimeFilter, TimeTrackingProvider, TimedExam, ToolDialogs, TopBanner, UpgradePackageModal, UserAvatar, Version, WebContainersI18nProvider, WorkflowSidebar, addBookmarksTab, availablePlacementExams, findLastResumeBlock, findSequentialParent, flattenVerticalBlocks, getCatalog, getFirstAvailableUnit, getLocalLLMModel, getLocalLLMToolSupport, getNextUnitIframe, getOrg, getParentBlockById, getParentsInfosFromSublessonId, getPreviousUnitIframe, getRandomCourseImage, getSectorById, getTenant, getUnitToIframe, getUserId, getUserName, inBrowserPrint, inIframe, initialCuaDriverInstallState, initialModelDownloadState, isCoworkEnabled, isLocalLLMEnabled, isPlatformNavbarCreditBalanceVisible, isSlashCommandToken, isTauriApp, isValidLocale, components as markdownComponents, modelSupportsCowork, onboardingPrimaryButtonClass, onboardingSecondaryButtonClass, resolveCreateAgentLabels, sanitizeCss, setCoworkEnabled, setLocalLLMEnabled, setLocalLLMModel, setLocalLLMToolSupport, smallestCoworkModel, useAnalyticsSettings, useAuditLog, useCatalogSearch, useChartFilters, useChatPrivacy, useChatState, useCourseDetail, useCourseMetadata, useCourses, useCuaDriver, useDiscover, useEdxIframe, useFinancial, useIframeMessageHandler, useLocalStorage, useModelDownload, useMonetization, useOverview, useProfileActivityStats, useProfileCredentials, useProfilePathways, useProfilePrograms, useProfileSkills, useProfileTimeSpent, usePrograms, useReports, useSlashSkillPicker, useT, useTauri, useTimeTracking, useTopics, useTranscripts, useUserCourses, useUserMetadata, useUsers, useWebContainersI18n, useWebContainersLocale };
235887
+ export { ACCESS_COURSE_LABEL, ALL_CATEGORIES, AccessTimeHeatmap, AccessiblePaginate, AddMentorToProjectModal, AddSkillDialog, Admin, AdvancedTab, AgentConfigPrompts, AgentSkills, AlertsTab, AnalyticsAuditLogStats, AnalyticsCourseDetail, AnalyticsCourses, AnalyticsFinancialStats, AnalyticsLayout, AnalyticsMemoryStats, AnalyticsMonetizationStats, AnalyticsOverview, AnalyticsProgramDetail, AnalyticsPrograms, AnalyticsReportDownload, AnalyticsReports, AnalyticsSettingsProvider, AnalyticsTopicsStats, AnalyticsTranscriptsStats, AnalyticsUsersStats, AppleRestrictionModal, ApplyWizard, BUY_NOW_LABEL, BillingTab, CATALOGS, CREATE_AGENT_LABELS, CUA_DRIVER_REPO_URL, CUA_DRIVER_TAURI_COMMANDS, CUA_DRIVER_TAURI_EVENTS, CategorizedDropdownMenu, ChartCardWrapper, ChartFiltersProvider, ChartLoading, ChatContext, ChatPrivacyToggle, ChatProvider, CompanyDialog, ConnectorManagementDialog, CopyButtonIcon, CourseAccessGuard, CourseCardSkeleton, CourseContentLoading, CourseOutline, CourseOutlineContext, CourseOutlineDrawer, CreateAgentForm, CreateAgentModal, CreateProjectModal, CreateWorkflowModal, CredentialBox, CredentialMiniBoxSkeleton, CredentialsList, CreditBalance, CustomDateRangePicker, CustomTooltip, DEFAULT_COWORK_REQUIRED_SIZE_GB, DEFAULT_LOCALE, DefaultEmptyBox, DeleteProjectModal, DeleteWorkflowModal, DiscoverContentCard, DiscoverFacetsFilter, DiscoverFilterDrawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, ENROLL_NOW_COURSE_STARTING_SOON_LABEL, ENROLL_NOW_LABEL, EditAlertDialog, EducationBox, EducationDialog, EducationTab, EdxIframeContext, EmptyStats, ExperienceBox, ExperienceDialog, ExperienceTab, FacetFilterContext, Footer, GradebookTab, GroupsFilterDropdown, INVITATION_ONLY_LABEL, InstitutionDialog, IntegrationsTab, InviteUserContent, InviteUserDialog, InvitedUsersDialog, LOCAL_MODELS, Loader, LocalLLMTab, LocalModelsContent, LoginButton, MACOS_PERMISSIONS_COMMANDS, MEMORY_PAGE_SIZE, Markdown, MinimumMentorAlert, MonetizationTab, NotificationDisplay, NotificationDropdown, ONBOARDING_SECTORS, OnboardingShell, OnboardingWizard, PaywallModal, PlacementExam, PlacementExamsDropdown, PlatformNavbar, PlatformNavbarSearch, Profile, ProfileTimeChart, ProgressDots, ProjectActionButtons, ProjectFilesModal, ProjectInstructionsModal, ProjectLandingPage, ProjectMentorsList, ProjectsPage, REQUEST_ACCESS_COURSE_STARTING_SOON_LABEL, REQUEST_ACCESS_LABEL, RenameProjectModal, ResumeBox, ResumeTab, RichTextEditor, SUPPORTED_LOCALES, SandboxConfig, SearchableMultiSelect, SendNotificationDialog, SignupButton, SkeletonActivityStatBox, SkeletonAddSkillsLoading, SkeletonCreatePathwaySearchList, SkeletonDiscoverFilterBox, SkeletonEducationBox, SkeletonMultiplier, SkeletonPathwayBox, SkeletonProfileInfoCard, SkeletonSkillBox, SkillBox, SkillDetailModal, SkillLeaderboardChart, SkillsBox, SkillsList, SlashSkillPicker, Spinner, StatCard, StepHeader, TAURI_COMMANDS, TAURI_EVENTS, TenantSwitcher, TimeFilter, TimeTrackingProvider, TimedExam, ToolDialogs, TopBanner, UpgradePackageModal, UserAvatar, Version, WebContainersI18nProvider, WorkflowSidebar, addBookmarksTab, availablePlacementExams, findLastResumeBlock, findSequentialParent, flattenVerticalBlocks, getCatalog, getFirstAvailableUnit, getLocalLLMModel, getLocalLLMToolSupport, getNextUnitIframe, getOrg, getParentBlockById, getParentsInfosFromSublessonId, getPreviousUnitIframe, getRandomCourseImage, getSectorById, getTenant, getUnitToIframe, getUserId, getUserName, inBrowserPrint, inIframe, initialCuaDriverInstallState, initialModelDownloadState, isCoworkEnabled, isLocalLLMEnabled, isPlatformNavbarCreditBalanceVisible, isSlashCommandToken, isTauriApp, isValidLocale, components as markdownComponents, modelSupportsCowork, onboardingPrimaryButtonClass, onboardingSecondaryButtonClass, resolveCreateAgentLabels, sanitizeCss, setCoworkEnabled, setLocalLLMEnabled, setLocalLLMModel, setLocalLLMToolSupport, smallestCoworkModel, useAnalyticsSettings, useAuditLog, useCatalogSearch, useChartFilters, useChatPrivacy, useChatState, useCourseDetail, useCourseMetadata, useCourses, useCuaDriver, useDiscover, useEdxIframe, useFinancial, useIframeMessageHandler, useLocalStorage, useMemory, useModelDownload, useMonetization, useOverview, useProfileActivityStats, useProfileCredentials, useProfilePathways, useProfilePrograms, useProfileSkills, useProfileTimeSpent, usePrograms, useReports, useSlashSkillPicker, useT, useTauri, useTimeTracking, useTopics, useTranscripts, useUserCourses, useUserMetadata, useUsers, useWebContainersI18n, useWebContainersLocale };
235125
235888
  //# sourceMappingURL=index.esm.js.map