@iblai/iblai-js 2.9.5 → 2.9.7

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.
@@ -2,8 +2,8 @@ import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default, { useState, useEffect, forwardRef, createElement as createElement$3, useLayoutEffect, createContext, useContext, useMemo, useReducer, useRef, useImperativeHandle, useCallback, isValidElement, Children, PureComponent, cloneElement, Component as Component$1, useId as useId$2, useDebugValue, lazy, Suspense } from 'react';
4
4
  import * as dataLayer from '@iblai/data-layer';
5
- import { 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, useUpdateGlobalMemoryMutation, useUpdateMentorMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useDeleteMentorMemoryMutation, useGetAiSearchMentorsQuery, useStarMentorMutation, useUnstarMentorMutation, useGetUserChatHistoryReportsQuery, USER_CHAT_HISTORY_REPORT_ACTIVE_STATES, useCreateUserChatHistoryReportMutation, useLazyGetDownloadReportFromURLQuery, useGetUserChatHistoryReportStatusQuery, userChatHistoryApiSlice, USER_CHAT_HISTORY_QUERY_KEYS, useGetUserChatHistoryQuery, useGetUserChatHistoryFilterQuery, useGetMentorsQuery, useGetUserChatHistorySessionQuery, 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, useGetTenantMetadataQuery, useUpdateTenantMetadataMutation, useLazyGetTenantMetadataQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useGetAgentSpendCapQuery, useGetTenantSpendCapQuery, useListAgentUserSpendCapsQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutation, useUpsertTenantSpendCapMutation, useDeleteTenantSpendCapMutation, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutation, useGetFinancialStatsQuery, useListAgentSpendCapsQuery, useGetCreditTransactionsQuery, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetMentorSkillAssignmentsQuery, useGetAgentSkillsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useCreateMentorMemoryMutation, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useUploadLightLogoMutation, useUploadDarkLogoMutation, useUpdatePlatformInfoMutation, LOGO_ENDPOINTS, useCreateEvalDatasetMutation, useAddEvalDatasetItemsMutation, useUploadEvalDatasetCsvMutation, useDeleteEvalDatasetItemMutation, useListEvalDatasetItemsQuery, evalTotalPages, useListEvalDatasetsQuery, useGetUserProjectsQuery, useCreateSessionIdMutation, useGetMentorCategoriesQuery, useGetTenantChatPrivacyConfigQuery as useGetTenantChatPrivacyConfigQuery$1, useGetCallConfigurationsQuery, useCreateCallConfigurationMutation, useUpdateCallConfigurationMutation, chatPrivacyApiSlice, useDeleteMentorMutation, useForkMentorMutation, useGetToolsQuery, useLazyGetMCPServersQuery, useOauthFindMutation, useLazyStartOAuthFlowQuery, useCreateMCPServerMutation, usePartialUpdateMCPServerMutation, useCreateMCPServerConnectionMutation, usePatchMCPServerConnectionMutation, useGetConnectedServicesQuery, useGetMCPServersQuery, useGetMCPServerConnectionsQuery, useUpdateMCPServerMutation, useDeleteMCPServerMutation, useEditMentorJsonMutation, useDisconnectServiceMutation, useGetPromptCategoriesQuery, PRIVACY_ACTIONS, PRIVACY_ENTITY_TYPES, useGetVoicesQuery, useGetVoiceQuery, isBaseAgentMentor, useGetGradeResultQuery, useOverrideGradeResultMutation, useGetChatHistoryFilterQuery, useListGradeResultsQuery, useGetMentorGraderConfigurationQuery, useListGraderCriteriaQuery, useCreateMentorGraderConfigurationMutation, useUpdateMentorGraderConfigurationMutation, useCreateGraderCriterionMutation, useUpdateGraderCriterionMutation, useDeleteGraderCriterionMutation, useGetSpendCapStatusQuery, useGetMentorPublicSettingsQuery, useGetChatHistoryQuery, useGetMentorSummariesQuery, useGetConversationMemoriesQuery, useGetSupportTicketsQuery, useGetSupportTicketMessagesQuery, useCreateSupportTicketMessageMutation, usePatchSupportTicketMutation, useCloseSupportTicketMutation, useCreateLtiMentorMutation, useUpdateLtiMentorMutation, useGetLtiMentorsQuery, useDeleteLtiMentorMutation, useCreateLtiKeyMutation, useUpdateLtiKeyMutation, useDeleteLtiKeyMutation, useGetLtiKeysQuery, useCreateLtiToolMutation, useUpdateLtiToolMutation, useGetLtiToolsQuery, useGetPlatformInfoQuery, useCreatePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useCreateRedirectTokenMutation, useGetShareableLinkQuery, useCreateShareableLinkMutation, useUpdateShareableLinkMutation, useCreateDisclaimerMutation, useUpdateDisclaimerMutation, useGetDisclaimersQuery, useUpdateRbacMentorAccessMutation, useGetRbacMentorAccessListQuery, useStartEvalRunMutation, useEvaluateEvalRunMutation, useGetEvalRunQuery, useDeleteEvalScoreMutation, useListEvalRunJudgesQuery, useCreateEvalScoreMutation, useDeleteEvalRunMutation, useExportEvalRunMutation, useListEvalRunsQuery, useLazyGetEvalRunQuery, evaluationsApiSlice, EVALUATIONS_TAGS, useGetPersonnalizedMentorsQuery, useCreateCallCredentialsMutation, useGetGuidedPromptsQuery, useUpdateChatSessionSharedMutation, useUpdateMessageFeedbackMutation, useLazyGetPromptsSearchQuery, useLazyGetGuidedPromptsQuery, useGetPublicMentorsQuery, useGetPeriodicAgentsQuery, useGetPeriodicAgentLogsListQuery, useCreatePeriodicAgentMutation, useDeletePeriodicAgentMutation, useDeletePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useUpdateArtifactMutation, useLazyGetArtifactVersionQuery, useLazyListArtifactVersionsQuery, useSetCurrentVersionMutation, useListArtifactVersionsQuery, useLazyGetArtifactQuery, useLazyListArtifactsQuery, useEditSessionMutation } from '@iblai/data-layer';
6
- import { removeAuthItem, setAuthItem, getInitials, useTenantMetadata, useCurrentTenant, selectRbacPermissions, isPureWatcher, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, 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, removeFile, chatInputSliceActions, chatActions, WithFormPermissions, useTenantContext, TimeTracker, advancedTabsProperties, defaultSessionIds, pickWritableFields, ANONYMOUS_USERNAME as ANONYMOUS_USERNAME$3, redirectToAuthSpaJoinTenant, selectActiveTab, useAxdToken, useWelcomeMessage, markdownToPlainText, useCachedSessionId, use402ErrorCheck, use401TokenRefresh, selectTokenEnabled, selectToken, useServiceWorker, useUserAgreement, useAdvancedChat, sendMessageToParentWebsite, useMentorTools, useFileDragDrop, eventBus, RemoteEvents, selectEnableChatActionsPopup, advancedTabs, isInIframe, getAuthSpaJoinUrl, addMessage, clearFiles, MENTOR_VISIBILITY } from '@iblai/web-utils';
5
+ import { 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, useUpdateGlobalMemoryMutation, useUpdateMentorMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useDeleteMentorMemoryMutation, useGetAiSearchMentorsQuery, useStarMentorMutation, useUnstarMentorMutation, useGetUserChatHistoryReportsQuery, USER_CHAT_HISTORY_REPORT_ACTIVE_STATES, useCreateUserChatHistoryReportMutation, useLazyGetDownloadReportFromURLQuery, useGetUserChatHistoryReportStatusQuery, userChatHistoryApiSlice, USER_CHAT_HISTORY_QUERY_KEYS, useGetUserChatHistoryQuery, useGetUserChatHistoryFilterQuery, useGetMentorsQuery, useGetUserChatHistorySessionQuery, 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, useGetTenantMetadataQuery, useUpdateTenantMetadataMutation, useLazyGetTenantMetadataQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useGetAgentSpendCapQuery, useGetTenantSpendCapQuery, useListAgentUserSpendCapsQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutation, useUpsertTenantSpendCapMutation, useDeleteTenantSpendCapMutation, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutation, useGetFinancialStatsQuery, useListAgentSpendCapsQuery, useGetCreditTransactionsQuery, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useCreateMentorMemoryMutation, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetMentorSkillAssignmentsQuery, useGetAgentSkillsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useUploadLightLogoMutation, useUploadDarkLogoMutation, useUpdatePlatformInfoMutation, LOGO_ENDPOINTS, useCreateEvalDatasetMutation, useAddEvalDatasetItemsMutation, useUploadEvalDatasetCsvMutation, useDeleteEvalDatasetItemMutation, useListEvalDatasetItemsQuery, evalTotalPages, useListEvalDatasetsQuery, useGetUserProjectsQuery, useCreateSessionIdMutation, useGetMentorCategoriesQuery, useGetTenantChatPrivacyConfigQuery as useGetTenantChatPrivacyConfigQuery$1, useGetCallConfigurationsQuery, useCreateCallConfigurationMutation, useUpdateCallConfigurationMutation, chatPrivacyApiSlice, useDeleteMentorMutation, useForkMentorMutation, useGetToolsQuery, useLazyGetMCPServersQuery, useOauthFindMutation, useLazyStartOAuthFlowQuery, useCreateMCPServerMutation, usePartialUpdateMCPServerMutation, useCreateMCPServerConnectionMutation, usePatchMCPServerConnectionMutation, useGetConnectedServicesQuery, useGetMCPServersQuery, useGetMCPServerConnectionsQuery, useUpdateMCPServerMutation, useDeleteMCPServerMutation, useEditMentorJsonMutation, useDisconnectServiceMutation, useGetPromptCategoriesQuery, PRIVACY_ACTIONS, PRIVACY_ENTITY_TYPES, useGetVoicesQuery, useGetVoiceQuery, isBaseAgentMentor, useGetGradeResultQuery, useOverrideGradeResultMutation, useGetChatHistoryFilterQuery, useListGradeResultsQuery, useGetMentorGraderConfigurationQuery, useListGraderCriteriaQuery, useCreateMentorGraderConfigurationMutation, useUpdateMentorGraderConfigurationMutation, useCreateGraderCriterionMutation, useUpdateGraderCriterionMutation, useDeleteGraderCriterionMutation, useGetSpendCapStatusQuery, useGetMentorPublicSettingsQuery, useGetChatHistoryQuery, useGetMentorSummariesQuery, useGetConversationMemoriesQuery, useGetSupportTicketsQuery, useGetSupportTicketMessagesQuery, useCreateSupportTicketMessageMutation, usePatchSupportTicketMutation, useCloseSupportTicketMutation, useCreateLtiMentorMutation, useUpdateLtiMentorMutation, useGetLtiMentorsQuery, useDeleteLtiMentorMutation, useCreateLtiKeyMutation, useUpdateLtiKeyMutation, useDeleteLtiKeyMutation, useGetLtiKeysQuery, useCreateLtiToolMutation, useUpdateLtiToolMutation, useGetLtiToolsQuery, useGetPlatformInfoQuery, useCreatePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useCreateRedirectTokenMutation, useGetShareableLinkQuery, useCreateShareableLinkMutation, useUpdateShareableLinkMutation, useCreateDisclaimerMutation, useUpdateDisclaimerMutation, useGetDisclaimersQuery, useUpdateRbacMentorAccessMutation, useGetRbacMentorAccessListQuery, useStartEvalRunMutation, useEvaluateEvalRunMutation, useGetEvalRunQuery, useDeleteEvalScoreMutation, useListEvalRunJudgesQuery, useCreateEvalScoreMutation, useDeleteEvalRunMutation, useExportEvalRunMutation, useListEvalRunsQuery, useLazyGetEvalRunQuery, evaluationsApiSlice, EVALUATIONS_TAGS, useGetPersonnalizedMentorsQuery, useCreateCallCredentialsMutation, useGetGuidedPromptsQuery, useUpdateChatSessionSharedMutation, useUpdateMessageFeedbackMutation, useLazyGetPromptsSearchQuery, useLazyGetGuidedPromptsQuery, useGetPublicMentorsQuery, useGetPeriodicAgentsQuery, useGetPeriodicAgentLogsListQuery, useCreatePeriodicAgentMutation, useDeletePeriodicAgentMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useDeletePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation, useUpdateArtifactMutation, useLazyGetArtifactVersionQuery, useLazyListArtifactVersionsQuery, useSetCurrentVersionMutation, useListArtifactVersionsQuery, useLazyGetArtifactQuery, useLazyListArtifactsQuery, useEditSessionMutation } from '@iblai/data-layer';
6
+ import { removeAuthItem, setAuthItem, selectRbacPermissions, useCurrentTenant, canViewOtherUsersChatHistory, getInitials, useTenantMetadata, isPureWatcher, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, 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, removeFile, chatInputSliceActions, chatActions, WithFormPermissions, useTenantContext, TimeTracker, advancedTabsProperties, defaultSessionIds, pickWritableFields, ANONYMOUS_USERNAME as ANONYMOUS_USERNAME$3, redirectToAuthSpaJoinTenant, selectActiveTab, useAxdToken, useWelcomeMessage, markdownToPlainText, useCachedSessionId, use402ErrorCheck, use401TokenRefresh, selectTokenEnabled, selectToken, useServiceWorker, useUserAgreement, useAdvancedChat, sendMessageToParentWebsite, useMentorTools, useFileDragDrop, eventBus, RemoteEvents, selectEnableChatActionsPopup, advancedTabs, isInIframe, getAuthSpaJoinUrl, addMessage, clearFiles, MENTOR_VISIBILITY } from '@iblai/web-utils';
7
7
  import { useDispatch, useSelector } from 'react-redux';
8
8
  import { toast } from 'sonner';
9
9
  import { useSearchParams, useParams, useRouter, usePathname } from 'next/navigation';
@@ -16,8 +16,8 @@ import { RemoveScroll } from 'react-remove-scroll';
16
16
  import { skipToken } from '@reduxjs/toolkit/query';
17
17
  import * as DialogPrimitive from '@radix-ui/react-dialog';
18
18
  import { createDialogScope } from '@radix-ui/react-dialog';
19
- import { MentorVisibilityEnum, TransportEnum, PromptVisibilityEnum } from '@iblai/iblai-api';
20
19
  import dynamic from 'next/dynamic';
20
+ import { MentorVisibilityEnum, TransportEnum, PromptVisibilityEnum } from '@iblai/iblai-api';
21
21
  import Script from 'next/script';
22
22
  import { useRouter as useRouter$1 } from 'next/router';
23
23
  import { Room, RoomEvent, ConnectionState, VideoPresets, Track, ParticipantEvent } from 'livekit-client';
@@ -97448,6 +97448,7 @@ var chatHistoryChatHistoryTab$3 = {
97448
97448
  exportFailed: "Failed to export chat history. Please try again.",
97449
97449
  downloadFailed: "Failed to download report.",
97450
97450
  loadFailed: "Failed to load history.",
97451
+ forbidden: "You don't have permission to view this user's history.",
97451
97452
  noConversations: "No conversations found",
97452
97453
  noMessages: "No messages in this conversation.",
97453
97454
  conversation: "Conversation",
@@ -97468,6 +97469,7 @@ var chatHistoryReportHistory$3 = {
97468
97469
  download: "Download",
97469
97470
  allAgents: "All agents",
97470
97471
  allTime: "All time",
97472
+ createdBy: "by {owner}",
97471
97473
  agentsCount: "{count, plural, one {# agent} other {# agents}}",
97472
97474
  statePending: "Pending",
97473
97475
  stateProcessing: "Processing",
@@ -104469,6 +104471,7 @@ var chatHistoryChatHistoryTab$2 = {
104469
104471
  exportFailed: "Échec de l'exportation de l'historique. Veuillez réessayer.",
104470
104472
  downloadFailed: "Échec du téléchargement du rapport.",
104471
104473
  loadFailed: "Échec du chargement de l'historique.",
104474
+ forbidden: "Vous n'avez pas la permission de voir l'historique de cet utilisateur.",
104472
104475
  noConversations: "Aucune conversation trouvée",
104473
104476
  noMessages: "Aucun message dans cette conversation.",
104474
104477
  conversation: "Conversation",
@@ -104489,6 +104492,7 @@ var chatHistoryReportHistory$2 = {
104489
104492
  download: "Télécharger",
104490
104493
  allAgents: "Tous les agents",
104491
104494
  allTime: "Toute la période",
104495
+ createdBy: "par {owner}",
104492
104496
  agentsCount: "{count, plural, one {# agent} other {# agents}}",
104493
104497
  statePending: "En attente",
104494
104498
  stateProcessing: "En cours",
@@ -111490,6 +111494,7 @@ var chatHistoryChatHistoryTab$1 = {
111490
111494
  exportFailed: "No se pudo exportar el historial de chat. Inténtalo de nuevo.",
111491
111495
  downloadFailed: "No se pudo descargar el informe.",
111492
111496
  loadFailed: "No se pudo cargar el historial.",
111497
+ forbidden: "No tienes permiso para ver el historial de este usuario.",
111493
111498
  noConversations: "No se encontraron conversaciones",
111494
111499
  noMessages: "No hay mensajes en esta conversación.",
111495
111500
  conversation: "Conversación",
@@ -111510,6 +111515,7 @@ var chatHistoryReportHistory$1 = {
111510
111515
  download: "Descargar",
111511
111516
  allAgents: "Todos los agentes",
111512
111517
  allTime: "Todo el tiempo",
111518
+ createdBy: "por {owner}",
111513
111519
  agentsCount: "{count, plural, one {# agente} other {# agentes}}",
111514
111520
  statePending: "Pendiente",
111515
111521
  stateProcessing: "Procesando",
@@ -118511,6 +118517,7 @@ var chatHistoryChatHistoryTab = {
118511
118517
  exportFailed: "导出聊天记录失败,请重试。",
118512
118518
  downloadFailed: "下载报告失败。",
118513
118519
  loadFailed: "加载历史记录失败。",
118520
+ forbidden: "您无权查看此用户的历史记录。",
118514
118521
  noConversations: "未找到对话",
118515
118522
  noMessages: "此对话中没有消息。",
118516
118523
  conversation: "对话",
@@ -118531,6 +118538,7 @@ var chatHistoryReportHistory = {
118531
118538
  download: "下载",
118532
118539
  allAgents: "所有代理",
118533
118540
  allTime: "全部时间",
118541
+ createdBy: "由 {owner} 创建",
118534
118542
  agentsCount: "{count, plural, other {# 个代理}}",
118535
118543
  statePending: "等待中",
118536
118544
  stateProcessing: "处理中",
@@ -217694,12 +217702,12 @@ function ReportHistory({ org, username, onDownload }) {
217694
217702
  setDownloadingId(null);
217695
217703
  }
217696
217704
  };
217697
- return (jsx("div", { className: "overflow-hidden rounded-md border", children: jsx("div", { className: "overflow-x-auto sm:mx-0", 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(Spinner, {}) })) : (jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('chatHistoryReportHistory.statusColumn') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('chatHistoryReportHistory.createdColumn') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('chatHistoryReportHistory.filtersColumn') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('chatHistoryReportHistory.expiresColumn') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]" })] }) }), jsx(TableBody, { children: reports.length === 0 ? (jsx(TableRow$1, { children: jsx(TableCell$1, { colSpan: 5, className: "p-4 text-center text-[#646464]", children: t('chatHistoryReportHistory.empty') }) })) : (reports.map((report) => {
217705
+ return (jsx("div", { className: "overflow-hidden rounded-md border border-neutral-200", children: jsx("div", { className: "overflow-x-auto sm:mx-0", 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(Spinner, {}) })) : (jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b border-neutral-200", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('chatHistoryReportHistory.statusColumn') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('chatHistoryReportHistory.createdColumn') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('chatHistoryReportHistory.filtersColumn') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('chatHistoryReportHistory.expiresColumn') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]" })] }) }), jsx(TableBody, { children: reports.length === 0 ? (jsx(TableRow$1, { className: "border-neutral-200", children: jsx(TableCell$1, { colSpan: 5, className: "p-4 text-center text-[#646464]", children: t('chatHistoryReportHistory.empty') }) })) : (reports.map((report) => {
217698
217706
  var _a, _b, _c, _d;
217699
217707
  const state = (_a = report.state) !== null && _a !== void 0 ? _a : '';
217700
217708
  const active = isActiveState$1(state);
217701
217709
  const labelKey = (_b = STATE_LABEL_KEYS[state]) !== null && _b !== void 0 ? _b : 'statePending';
217702
- return (jsxs(TableRow$1, { className: "border-b", children: [jsx(TableCell$1, { className: "p-3 whitespace-nowrap", children: jsxs(Badge, { variant: "outline", className: cn(active ? ACTIVE_BADGE_CLASSES : (_c = STATE_BADGE_CLASSES[state]) !== null && _c !== void 0 ? _c : ''), children: [active && (jsx(LoaderCircle, { className: "mr-1 h-3 w-3 animate-spin", "aria-hidden": "true" })), t(`chatHistoryReportHistory.${labelKey}`)] }) }), jsx(TableCell$1, { className: "p-3 whitespace-nowrap text-[#646464]", children: timeAgo$1(report.created_at) }), jsx(TableCell$1, { className: "max-w-[280px] truncate p-3 text-[#646464]", children: filterSummary(report, t) }), jsx(TableCell$1, { className: "p-3 whitespace-nowrap text-[#646464]", children: state === 'completed' && report.expires ? timeAgo$1(report.expires) : '—' }), jsx(TableCell$1, { className: "p-3 text-right whitespace-nowrap", children: state === 'completed' && report.url && (jsxs(Button$1, { variant: "outline", size: "sm", className: "flex items-center gap-2 bg-transparent", onClick: () => handleDownload(report), disabled: downloadingId === report.report_id, children: [downloadingId === report.report_id ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin", "aria-hidden": "true" })) : (jsx(Download, { className: "h-4 w-4", "aria-hidden": "true" })), t('chatHistoryReportHistory.download')] })) })] }, (_d = report.report_id) !== null && _d !== void 0 ? _d : report.created_at));
217710
+ return (jsxs(TableRow$1, { className: "border-b border-neutral-200", children: [jsx(TableCell$1, { className: "p-3 whitespace-nowrap", children: jsxs(Badge, { variant: "outline", className: cn(active ? ACTIVE_BADGE_CLASSES : (_c = STATE_BADGE_CLASSES[state]) !== null && _c !== void 0 ? _c : ''), children: [active && (jsx(LoaderCircle, { className: "mr-1 h-3 w-3 animate-spin", "aria-hidden": "true" })), t(`chatHistoryReportHistory.${labelKey}`)] }) }), jsxs(TableCell$1, { className: "p-3 whitespace-nowrap text-[#646464]", children: [timeAgo$1(report.created_at), report.owner && report.owner !== username && (jsx("div", { className: "text-xs text-gray-500", children: t('chatHistoryReportHistory.createdBy', { owner: report.owner }) }))] }), jsx(TableCell$1, { className: "max-w-[280px] truncate p-3 text-[#646464]", children: filterSummary(report, t) }), jsx(TableCell$1, { className: "p-3 whitespace-nowrap text-[#646464]", children: state === 'completed' && report.expires ? timeAgo$1(report.expires) : '—' }), jsx(TableCell$1, { className: "p-3 text-right whitespace-nowrap", children: state === 'completed' && report.url && (jsxs(Button$1, { variant: "outline", size: "sm", className: "flex items-center gap-2 bg-transparent", onClick: () => handleDownload(report), disabled: downloadingId === report.report_id, children: [downloadingId === report.report_id ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin", "aria-hidden": "true" })) : (jsx(Download, { className: "h-4 w-4", "aria-hidden": "true" })), t('chatHistoryReportHistory.download')] })) })] }, (_d = report.report_id) !== null && _d !== void 0 ? _d : report.created_at));
217703
217711
  })) })] })) }) }) }));
217704
217712
  }
217705
217713
 
@@ -217829,8 +217837,10 @@ function buildUserChatHistoryReportBody(filters, reportFormat = 'csv') {
217829
217837
  }
217830
217838
  /**
217831
217839
  * Filter, pagination and data state for the profile History tab. All requests
217832
- * are user-scoped (`my-chat-history*`): the backend only serves the
217833
- * authenticated user's own sessions, so no RBAC checks are involved.
217840
+ * are user-scoped (`my-chat-history*`): the backend serves the user's own
217841
+ * sessions to that user, to tenant admins, and to watchers of that user. Any
217842
+ * other caller — including a watcher on a user they don't watch — gets a 403,
217843
+ * surfaced here as `isForbidden`.
217834
217844
  */
217835
217845
  function useUserChatHistory({ org, username }) {
217836
217846
  var _a, _b, _c, _d;
@@ -217859,7 +217869,8 @@ function useUserChatHistory({ org, username }) {
217859
217869
  return next;
217860
217870
  }, [filters, page]);
217861
217871
  const skip = !org || !username;
217862
- const { data: history, isLoading, isFetching, isError, } = useGetUserChatHistoryQuery({ org, userId: username, params }, { skip });
217872
+ const { data: history, isLoading, isFetching, isError, error, } = useGetUserChatHistoryQuery({ org, userId: username, params }, { skip });
217873
+ const isForbidden = !!error && error.status === 403;
217863
217874
  const { data: filterOptions } = useGetUserChatHistoryFilterQuery({
217864
217875
  org,
217865
217876
  userId: username,
@@ -217881,6 +217892,7 @@ function useUserChatHistory({ org, username }) {
217881
217892
  isLoading,
217882
217893
  isFetching,
217883
217894
  isError,
217895
+ isForbidden,
217884
217896
  filterOptions,
217885
217897
  };
217886
217898
  }
@@ -218052,7 +218064,7 @@ function ChatHistoryTab({ org, username }) {
218052
218064
  const isMobile = useIsMobile();
218053
218065
  const [selectedSession, setSelectedSession] = React__default.useState(null);
218054
218066
  const [isPreviewModalOpen, setIsPreviewModalOpen] = React__default.useState(false);
218055
- const { filters, setFilters, page, setPage, totalPages, sessions, isLoading, isFetching, isError, filterOptions, } = useUserChatHistory({ org, username });
218067
+ const { filters, setFilters, page, setPage, totalPages, sessions, isLoading, isFetching, isError, isForbidden, filterOptions, } = useUserChatHistory({ org, username });
218056
218068
  const { startExport, downloadFromUrl, isExporting } = useChatHistoryExport({ org, username });
218057
218069
  // The list payload identifies agents by unique_id only; resolve display
218058
218070
  // names and avatars from agent search (plus whatever the payload carries).
@@ -218098,11 +218110,13 @@ function ChatHistoryTab({ org, username }) {
218098
218110
  setIsPreviewModalOpen(true);
218099
218111
  }
218100
218112
  };
218101
- return (jsxs(Tabs, { defaultValue: "conversations", className: "flex h-full min-h-0 flex-col gap-4", children: [jsxs(TabsList, { className: "w-fit flex-shrink-0", children: [jsx(TabsTrigger, { value: "conversations", children: t('chatHistoryChatHistoryTab.tabConversations') }), jsx(TabsTrigger, { value: "exports", children: t('chatHistoryChatHistoryTab.tabExports') })] }), jsxs(TabsContent, { value: "conversations", className: "mt-0 flex min-h-0 flex-1 flex-col gap-4 data-[state=inactive]:hidden", children: [jsx("div", { className: "flex-shrink-0 rounded-lg border p-4", children: jsxs("div", { className: "flex flex-col gap-3 lg:flex-row", children: [jsxs("div", { className: "flex flex-1 flex-wrap gap-3", children: [jsx(AgentFilterSelect, { tenantKey: org, username: username, value: filters.agent, onChange: (agent) => setFilters({ ...filters, agent }) }), jsxs(Popover, { children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", className: "flex h-9 items-center gap-2 bg-transparent font-normal whitespace-nowrap", children: [jsx(Calendar$1, { className: "h-4 w-4" }), ((_b = filters.dateRange) === null || _b === void 0 ? void 0 : _b.from) && ((_c = filters.dateRange) === null || _c === void 0 ? void 0 : _c.to)
218113
+ return (jsxs(Tabs, { defaultValue: "conversations", className: "flex h-full min-h-0 flex-col gap-4", children: [jsxs(TabsList, { className: "w-fit flex-shrink-0", children: [jsx(TabsTrigger, { value: "conversations", children: t('chatHistoryChatHistoryTab.tabConversations') }), jsx(TabsTrigger, { value: "exports", children: t('chatHistoryChatHistoryTab.tabExports') })] }), jsxs(TabsContent, { value: "conversations", className: "mt-0 flex min-h-0 flex-1 flex-col gap-4 data-[state=inactive]:hidden", children: [jsx("div", { className: "flex-shrink-0 rounded-lg border border-neutral-200 p-4", children: jsxs("div", { className: "flex flex-col gap-3 lg:flex-row", children: [jsxs("div", { className: "flex flex-1 flex-wrap gap-3", children: [jsx(AgentFilterSelect, { tenantKey: org, username: username, value: filters.agent, onChange: (agent) => setFilters({ ...filters, agent }) }), jsxs(Popover, { children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", className: "flex h-9 items-center gap-2 bg-transparent font-normal whitespace-nowrap", children: [jsx(Calendar$1, { className: "h-4 w-4" }), ((_b = filters.dateRange) === null || _b === void 0 ? void 0 : _b.from) && ((_c = filters.dateRange) === null || _c === void 0 ? void 0 : _c.to)
218102
218114
  ? `${format$1(filters.dateRange.from, 'MMM dd')} - ${format$1(filters.dateRange.to, 'MMM dd')}`
218103
- : t('chatHistoryChatHistoryTab.pickDateRange')] }) }), jsx(PopoverContent, { className: "w-auto p-0", align: "start", portalled: false, children: jsx(Calendar, { mode: "range", selected: filters.dateRange, onSelect: (dateRange) => setFilters({ ...filters, dateRange }), numberOfMonths: 2, initialFocus: true }) })] }), jsxs(Select$1, { value: filters.sentiment || 'all', onValueChange: (value) => setFilters({ ...filters, sentiment: value === 'all' ? '' : value }), children: [jsx(SelectTrigger, { className: "w-40", "aria-label": t('chatHistoryChatHistoryTab.filterBySentiment'), children: jsx(SelectValue, { placeholder: t('chatHistoryChatHistoryTab.allSentiments') }) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "all", children: t('chatHistoryChatHistoryTab.allSentiments') }), sentimentOptions.map((sentiment) => (jsx(SelectItem, { value: sentiment, children: sentimentLabel(sentiment) }, sentiment)))] })] }), jsxs(Select$1, { value: filters.topic || 'all', onValueChange: (value) => setFilters({ ...filters, topic: value === 'all' ? '' : value }), children: [jsx(SelectTrigger, { className: "w-40", "aria-label": t('chatHistoryChatHistoryTab.filterByTopic'), children: jsx(SelectValue, { placeholder: t('chatHistoryChatHistoryTab.allTopics') }) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "all", children: t('chatHistoryChatHistoryTab.allTopics') }), ((_d = filterOptions === null || filterOptions === void 0 ? void 0 : filterOptions.topics) !== null && _d !== void 0 ? _d : []).map((topic) => (jsx(SelectItem, { value: topic.name, children: topic.name }, topic.name)))] })] })] }), jsx("div", { className: "w-full lg:w-auto", children: jsxs(Button$1, { variant: "outline", onClick: () => startExport(buildUserChatHistoryReportBody(filters, 'csv')), disabled: isExporting, className: "flex h-9 w-full items-center justify-center gap-2 bg-transparent lg:w-auto", children: [jsx(Download, { className: "h-4 w-4" }), isExporting
218115
+ : t('chatHistoryChatHistoryTab.pickDateRange')] }) }), jsx(PopoverContent, { className: "w-auto p-0", align: "start", portalled: false, children: jsx(Calendar, { mode: "range", selected: filters.dateRange, onSelect: (dateRange) => setFilters({ ...filters, dateRange }), numberOfMonths: 2, initialFocus: true }) })] }), jsxs(Select$1, { value: filters.sentiment || 'all', onValueChange: (value) => setFilters({ ...filters, sentiment: value === 'all' ? '' : value }), children: [jsx(SelectTrigger, { className: "w-40", "aria-label": t('chatHistoryChatHistoryTab.filterBySentiment'), children: jsx(SelectValue, { placeholder: t('chatHistoryChatHistoryTab.allSentiments') }) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "all", children: t('chatHistoryChatHistoryTab.allSentiments') }), sentimentOptions.map((sentiment) => (jsx(SelectItem, { value: sentiment, children: sentimentLabel(sentiment) }, sentiment)))] })] }), jsxs(Select$1, { value: filters.topic || 'all', onValueChange: (value) => setFilters({ ...filters, topic: value === 'all' ? '' : value }), children: [jsx(SelectTrigger, { className: "w-40", "aria-label": t('chatHistoryChatHistoryTab.filterByTopic'), children: jsx(SelectValue, { placeholder: t('chatHistoryChatHistoryTab.allTopics') }) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "all", children: t('chatHistoryChatHistoryTab.allTopics') }), ((_d = filterOptions === null || filterOptions === void 0 ? void 0 : filterOptions.topics) !== null && _d !== void 0 ? _d : []).map((topic) => (jsx(SelectItem, { value: topic.name, children: topic.name }, topic.name)))] })] })] }), jsx("div", { className: "w-full lg:w-auto", children: jsxs(Button$1, { variant: "outline", onClick: () => startExport(buildUserChatHistoryReportBody(filters, 'csv')), disabled: isExporting || isForbidden, className: "flex h-9 w-full items-center justify-center gap-2 bg-transparent lg:w-auto", children: [jsx(Download, { className: "h-4 w-4" }), isExporting
218104
218116
  ? t('chatHistoryChatHistoryTab.exporting')
218105
- : t('chatHistoryChatHistoryTab.export')] }) })] }) }), isLoading && (jsx("div", { className: "flex w-full flex-1 items-center justify-center py-10", children: jsx(Spinner, {}) })), isError && !isLoading && (jsx("div", { className: "flex flex-1 flex-col items-center justify-center py-6", children: jsx("p", { className: "text-sm text-gray-600", children: t('chatHistoryChatHistoryTab.loadFailed') }) })), sessions.length === 0 && !isLoading && !isError && (jsx("div", { className: "flex flex-1 flex-col items-center justify-center py-6", children: jsx("p", { className: "text-sm text-gray-600", children: t('chatHistoryChatHistoryTab.noConversations') }) })), sessions.length > 0 && (jsxs("div", { className: "grid min-h-[320px] flex-1 grid-cols-1 gap-6 md:grid-cols-2", children: [jsxs("div", { className: "col-span-full flex min-h-0 flex-col gap-3 md:col-span-1", children: [jsx("div", { className: "scrollbar-hide min-h-0 flex-1 overflow-y-auto rounded-md border", tabIndex: 0, role: "region", "aria-label": t('chatHistoryChatHistoryTab.conversationListLabel'), children: sessions.map((session) => {
218117
+ : t('chatHistoryChatHistoryTab.export')] }) })] }) }), isLoading && (jsx("div", { className: "flex w-full flex-1 items-center justify-center py-10", children: jsx(Spinner, {}) })), isError && !isLoading && (jsx("div", { className: "flex flex-1 flex-col items-center justify-center py-6", children: jsx("p", { className: "text-sm text-gray-600", children: isForbidden
218118
+ ? t('chatHistoryChatHistoryTab.forbidden')
218119
+ : t('chatHistoryChatHistoryTab.loadFailed') }) })), sessions.length === 0 && !isLoading && !isError && (jsx("div", { className: "flex flex-1 flex-col items-center justify-center py-6", children: jsx("p", { className: "text-sm text-gray-600", children: t('chatHistoryChatHistoryTab.noConversations') }) })), sessions.length > 0 && (jsxs("div", { className: "grid min-h-[320px] flex-1 grid-cols-1 gap-6 md:grid-cols-2", children: [jsxs("div", { className: "col-span-full flex min-h-0 flex-col gap-3 md:col-span-1", children: [jsx("div", { className: "scrollbar-hide min-h-0 flex-1 overflow-y-auto rounded-md border border-neutral-200", tabIndex: 0, role: "region", "aria-label": t('chatHistoryChatHistoryTab.conversationListLabel'), children: sessions.map((session) => {
218106
218120
  var _a, _b, _c, _d, _e;
218107
218121
  const firstMessage = normalizeMessages(session.messages)[0];
218108
218122
  const title = stripMarkdown$1(session.title ||
@@ -218111,13 +218125,13 @@ function ChatHistoryTab({ org, username }) {
218111
218125
  t('chatHistoryChatHistoryTab.conversation'));
218112
218126
  const preview = stripMarkdown$1((_a = firstMessage === null || firstMessage === void 0 ? void 0 : firstMessage.ai) !== null && _a !== void 0 ? _a : '');
218113
218127
  const sentiment = (_c = (_b = session.sentiment) === null || _b === void 0 ? void 0 : _b.toLowerCase()) !== null && _c !== void 0 ? _c : '';
218114
- return (jsxs("div", { role: "button", tabIndex: 0, "data-testid": "history-conversation-row", "data-session-id": session.id, className: cn('flex cursor-pointer items-center justify-between border-b p-4 last:border-b-0', (selectedSession === null || selectedSession === void 0 ? void 0 : selectedSession.id) === session.id ? 'bg-gray-100' : 'hover:bg-gray-50'), onClick: () => handleConversationClick(session), onKeyDown: (event) => {
218128
+ return (jsxs("div", { role: "button", tabIndex: 0, "data-testid": "history-conversation-row", "data-session-id": session.id, className: cn('flex cursor-pointer items-center justify-between border-b border-neutral-200 p-4 last:border-b-0', (selectedSession === null || selectedSession === void 0 ? void 0 : selectedSession.id) === session.id ? 'bg-gray-100' : 'hover:bg-gray-50'), onClick: () => handleConversationClick(session), onKeyDown: (event) => {
218115
218129
  if (event.key === 'Enter' || event.key === ' ') {
218116
218130
  event.preventDefault();
218117
218131
  handleConversationClick(session);
218118
218132
  }
218119
218133
  }, children: [jsxs("div", { className: "w-full", children: [jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [jsxs("span", { className: "flex items-center gap-2 text-sm text-gray-600", children: [timeAgo(session.inserted_at), sentiment && (jsx(Badge, { variant: "outline", className: cn('font-normal', (_d = SENTIMENT_CLASSES[sentiment]) !== null && _d !== void 0 ? _d : SENTIMENT_CLASSES.neutral), children: sentimentLabel((_e = session.sentiment) !== null && _e !== void 0 ? _e : '') }))] }), jsx("span", { className: "max-w-[100px] truncate text-sm text-gray-900 sm:max-w-[200px]", children: resolveAgent(session).name })] }), jsx("div", { className: "font-medium text-gray-900", children: textTruncate$2(title, 50) }), preview && (jsx("p", { className: "line-clamp-1 text-sm text-gray-600", children: textTruncate$2(preview, 60) }))] }), jsx("div", { className: "flex items-center gap-2 text-sm text-gray-600", children: jsx(ChevronRight, { className: "h-4 w-4" }) })] }, session.id));
218120
- }) }), totalPages > 1 && (jsx("div", { className: "flex-shrink-0", children: jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: isFetching || isLoading, disableNumberedButtons: isMobile }) }))] }), jsx("div", { className: "scrollbar-hide hidden min-h-0 flex-col overflow-y-auto rounded-lg border bg-white p-6 shadow-sm md:flex", tabIndex: 0, role: "region", "aria-label": t('chatHistoryChatHistoryTab.conversationPreviewLabel'), children: selectedSession ? (jsx(ConversationPreview, { org: org, username: username, session: selectedSession, agent: resolveAgent(selectedSession) })) : (jsx("div", { className: "flex h-full items-center justify-center text-gray-500", children: t('chatHistoryChatHistoryTab.selectPrompt') })) })] })), jsx(Dialog, { open: isPreviewModalOpen, onOpenChange: setIsPreviewModalOpen, children: jsxs(DialogContent, { className: "scrollbar-hide mx-auto max-h-[80vh] max-w-[90vw] overflow-x-hidden overflow-y-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "text-lg font-semibold text-gray-900", children: selectedSession
218134
+ }) }), totalPages > 1 && (jsx("div", { className: "flex-shrink-0", children: jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: isFetching || isLoading, disableNumberedButtons: isMobile }) }))] }), jsx("div", { className: "scrollbar-hide hidden min-h-0 flex-col overflow-y-auto rounded-lg border border-neutral-200 bg-white p-6 shadow-sm md:flex", tabIndex: 0, role: "region", "aria-label": t('chatHistoryChatHistoryTab.conversationPreviewLabel'), children: selectedSession ? (jsx(ConversationPreview, { org: org, username: username, session: selectedSession, agent: resolveAgent(selectedSession) })) : (jsx("div", { className: "flex h-full items-center justify-center text-gray-500", children: t('chatHistoryChatHistoryTab.selectPrompt') })) })] })), jsx(Dialog, { open: isPreviewModalOpen, onOpenChange: setIsPreviewModalOpen, children: jsxs(DialogContent, { className: "scrollbar-hide mx-auto max-h-[80vh] max-w-[90vw] overflow-x-hidden overflow-y-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "text-lg font-semibold text-gray-900", children: selectedSession
218121
218135
  ? stripMarkdown$1(selectedSession.title || t('chatHistoryChatHistoryTab.conversation'))
218122
218136
  : t('chatHistoryChatHistoryTab.conversation') }) }), jsx("div", { className: "mx-auto max-w-full overflow-x-hidden", children: selectedSession && (jsx(ConversationPreview, { org: org, username: username, session: selectedSession, agent: resolveAgent(selectedSession) })) })] }) })] }), jsx(TabsContent, { value: "exports", className: "mt-0 min-h-0 flex-1 overflow-y-auto data-[state=inactive]:hidden", children: jsx(ReportHistory, { org: org, username: username, onDownload: downloadFromUrl }) })] }));
218123
218137
  }
@@ -218184,6 +218198,12 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
218184
218198
  const isPurchasesEnabled = currentTenant === null || currentTenant === void 0 ? void 0 : currentTenant.enable_monetization;
218185
218199
  const isGradebookEnabled = customization.showGradebookTab;
218186
218200
  const isReadOnly = useIsProfilePreview(username);
218201
+ // The chat-history endpoints serve the user themselves, tenant admins and
218202
+ // watchers (for the users they watch), so the History tab stays on your own
218203
+ // profile and appears on someone else's only for admin/watcher viewers.
218204
+ const rbacPermissions = useSelector(selectRbacPermissions);
218205
+ const { currentTenant: viewerTenant } = useCurrentTenant();
218206
+ const isChatHistoryVisible = !isReadOnly || canViewOtherUsersChatHistory(rbacPermissions, viewerTenant);
218187
218207
  const baseTabs = [
218188
218208
  { id: 'basic', label: t('profileIndex.tabBasic'), renderIcon: renderLucideIcon(User) },
218189
218209
  { id: 'social', label: t('profileIndex.tabSocial'), renderIcon: renderLucideIcon(Globe) },
@@ -218237,9 +218257,7 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
218237
218257
  },
218238
218258
  ]
218239
218259
  : []),
218240
- // The chat-history endpoints only serve the authenticated user's own
218241
- // sessions, so the tab is hidden when previewing someone else's profile.
218242
- ...(!isReadOnly
218260
+ ...(isChatHistoryVisible
218243
218261
  ? [
218244
218262
  {
218245
218263
  id: 'chatHistory',
@@ -218425,7 +218443,7 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
218425
218443
  var _a;
218426
218444
  return (jsxs(Fragment$1, { children: [jsxs("div", { className: "relative mb-0", children: [jsx("div", { className: "absolute inset-y-0 left-4 flex items-center pointer-events-none", "aria-hidden": "true", children: jsx("div", { className: "bg-black text-white rounded w-8 h-8 flex items-center justify-center", children: jsx("span", { className: "font-bold text-sm", children: "X" }) }) }), jsx(Input, { id: "x", className: "w-full bg-gray-50 border-gray-200 focus:ring-blue-500 focus:border-blue-500 text-base py-3 pl-16 h-10", placeholder: t('profileIndex.placeholderX'), value: field.state.value, onChange: (e) => handleSocialLinkChange(e.target.value, field.handleChange, X_URL_PREFIX), disabled: socialForm.state.isSubmitting || isReadOnly })] }), jsx("p", { className: "text-red-500 dark:text-gray-400 text-sm", role: ((_a = field.state.meta.errors) === null || _a === void 0 ? void 0 : _a.length) ? 'alert' : undefined, "aria-live": "polite", children: field.state.meta.errors })] }));
218427
218445
  },
218428
- })] })] }) })), activeTab === 'education' && (jsxs(Tabs, { value: educationSubTab, onValueChange: setEducationSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "education", children: t('profileIndex.tabEducation') }), jsx(TabsTrigger, { value: "credentials", children: t('gradebookGradebookTab.typeCredentials') }), jsx(TabsTrigger, { value: "skills", children: t('gradebookGradebookTab.typeSkills') })] }), headerAddButton] }), jsx(TabsContent, { value: "education", children: jsx(EducationTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "credentials", children: jsx(CredentialsList, { org: tenant, username: username }) }), jsx(TabsContent, { value: "skills", children: jsx(SkillsList, { org: tenant, username: username }) })] })), activeTab === 'gradebook' && jsx(GradebookTab, { org: tenant, username: username }), activeTab === 'experience' && (jsxs(Tabs, { value: experienceSubTab, onValueChange: setExperienceSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "experience", children: t('profileIndex.tabExperience') }), jsx(TabsTrigger, { value: "resume", children: t('profileIndex.tabResume') })] }), headerAddButton] }), jsx(TabsContent, { value: "experience", children: jsx(ExperienceTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "resume", children: jsx(ResumeTab, { org: tenant, username: username }) })] })), activeTab === 'purchases' && jsx(PurchasesTab, { org: tenant, username: username }), activeTab === 'memory' && jsx(MemoryTab, { org: tenant, username: username }), activeTab === 'privacy' && jsx(ChatPrivacyTab, { org: tenant, username: username }), !isReadOnly && activeTab === 'chatHistory' && (jsx(ChatHistoryTab, { org: tenant, username: username })), !isReadOnly && activeTab === 'security' && (jsx(Security, { app: currentSPA || '', email: (userMetadata === null || userMetadata === void 0 ? void 0 : userMetadata.email) || '', platformKey: tenant, onAccountDeleted: onAccountDeleted })), activeTab === 'advanced' && localLLMProps && (jsx("div", { className: "space-y-6", children: jsx(LocalModelsContent, { isAvailable: localLLMProps.isAvailable, state: localLLMProps.state, ollamaStatus: localLLMProps.ollamaStatus, systemMemory: localLLMProps.systemMemory, isUsingFoundry: localLLMProps.isUsingFoundry, foundryModels: localLLMProps.foundryModels, selectedFoundryModel: localLLMProps.selectedFoundryModel, foundryStatus: localLLMProps.foundryStatus, onStartDownload: localLLMProps.onStartDownload, onCancelDownload: localLLMProps.onCancelDownload, onInstallOllama: localLLMProps.onInstallOllama, onStopManager: localLLMProps.onStopManager, onInstallFoundry: localLLMProps.onInstallFoundry, onCheckStatus: localLLMProps.onCheckStatus, onResetState: localLLMProps.onResetState, onSelectFoundryModel: localLLMProps.onSelectFoundryModel }) }))] }), !isReadOnly && ['basic', 'social'].includes(activeTab) && (jsx("div", { className: "flex-shrink-0 border-t border-gray-200 p-6 bg-white dark:bg-gray-900", children: jsxs("div", { className: "flex justify-end gap-3", children: [jsx(Button$1, { onClick: onClose, variant: "outline", children: t('profileIndex.buttonCancel') }), jsx(Button$1, { onClick: () => {
218446
+ })] })] }) })), activeTab === 'education' && (jsxs(Tabs, { value: educationSubTab, onValueChange: setEducationSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "education", children: t('profileIndex.tabEducation') }), jsx(TabsTrigger, { value: "credentials", children: t('gradebookGradebookTab.typeCredentials') }), jsx(TabsTrigger, { value: "skills", children: t('gradebookGradebookTab.typeSkills') })] }), headerAddButton] }), jsx(TabsContent, { value: "education", children: jsx(EducationTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "credentials", children: jsx(CredentialsList, { org: tenant, username: username }) }), jsx(TabsContent, { value: "skills", children: jsx(SkillsList, { org: tenant, username: username }) })] })), activeTab === 'gradebook' && jsx(GradebookTab, { org: tenant, username: username }), activeTab === 'experience' && (jsxs(Tabs, { value: experienceSubTab, onValueChange: setExperienceSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "experience", children: t('profileIndex.tabExperience') }), jsx(TabsTrigger, { value: "resume", children: t('profileIndex.tabResume') })] }), headerAddButton] }), jsx(TabsContent, { value: "experience", children: jsx(ExperienceTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "resume", children: jsx(ResumeTab, { org: tenant, username: username }) })] })), activeTab === 'purchases' && jsx(PurchasesTab, { org: tenant, username: username }), activeTab === 'memory' && jsx(MemoryTab, { org: tenant, username: username }), activeTab === 'privacy' && jsx(ChatPrivacyTab, { org: tenant, username: username }), isChatHistoryVisible && activeTab === 'chatHistory' && (jsx(ChatHistoryTab, { org: tenant, username: username })), !isReadOnly && activeTab === 'security' && (jsx(Security, { app: currentSPA || '', email: (userMetadata === null || userMetadata === void 0 ? void 0 : userMetadata.email) || '', platformKey: tenant, onAccountDeleted: onAccountDeleted })), activeTab === 'advanced' && localLLMProps && (jsx("div", { className: "space-y-6", children: jsx(LocalModelsContent, { isAvailable: localLLMProps.isAvailable, state: localLLMProps.state, ollamaStatus: localLLMProps.ollamaStatus, systemMemory: localLLMProps.systemMemory, isUsingFoundry: localLLMProps.isUsingFoundry, foundryModels: localLLMProps.foundryModels, selectedFoundryModel: localLLMProps.selectedFoundryModel, foundryStatus: localLLMProps.foundryStatus, onStartDownload: localLLMProps.onStartDownload, onCancelDownload: localLLMProps.onCancelDownload, onInstallOllama: localLLMProps.onInstallOllama, onStopManager: localLLMProps.onStopManager, onInstallFoundry: localLLMProps.onInstallFoundry, onCheckStatus: localLLMProps.onCheckStatus, onResetState: localLLMProps.onResetState, onSelectFoundryModel: localLLMProps.onSelectFoundryModel }) }))] }), !isReadOnly && ['basic', 'social'].includes(activeTab) && (jsx("div", { className: "flex-shrink-0 border-t border-gray-200 p-6 bg-white dark:bg-gray-900", children: jsxs("div", { className: "flex justify-end gap-3", children: [jsx(Button$1, { onClick: onClose, variant: "outline", children: t('profileIndex.buttonCancel') }), jsx(Button$1, { onClick: () => {
218429
218447
  if (activeTab === 'basic') {
218430
218448
  basicForm.handleSubmit();
218431
218449
  }
@@ -229471,6 +229489,514 @@ function MonetizationTab({ platformKey, authURL }) {
229471
229489
  return (jsxs("div", { className: "container mx-auto max-w-7xl !mt-0 space-y-6", children: [isOwner && jsx(StripeConnect, { platformKey: platformKey }), jsx(PaywallConfig, { platformKey: platformKey, authURL: authURL, disabled: !isStripeReady })] }));
229472
229490
  }
229473
229491
 
229492
+ /** Matches the server-side cap on the global memories listing. */
229493
+ const PAGE_SIZE$9 = 25;
229494
+ /**
229495
+ * Popup for managing one user's global memories. Reads them the way the
229496
+ * profile preview does — the caller in the path, the managed user identified
229497
+ * by their id (username) in `user_id` — while writes address the managed
229498
+ * user's path directly, which the backend resolves for admin/RBAC callers.
229499
+ * The list itself is the same {@link MemoriesList} the profile Memory tab
229500
+ * renders.
229501
+ */
229502
+ function UserMemoriesModal({ isOpen, onClose, tenantKey, adminUsername, user, }) {
229503
+ var _a, _b, _c;
229504
+ const t = useT();
229505
+ const [page, setPage] = useState(1);
229506
+ const [showAdd, setShowAdd] = useState(false);
229507
+ const [editingMemory, setEditingMemory] = useState(null);
229508
+ const [deletingId, setDeletingId] = useState(null);
229509
+ const { data: memoriesData, isLoading, error, } = useGetGlobalMemoriesQuery({
229510
+ org: tenantKey,
229511
+ userId: adminUsername,
229512
+ // `user_id` must be the managed user's id (username) — the backend does
229513
+ // not resolve emails here, so passing one returns an empty list.
229514
+ params: { page, page_size: PAGE_SIZE$9, user_id: user.username },
229515
+ });
229516
+ const memories = (_a = memoriesData === null || memoriesData === void 0 ? void 0 : memoriesData.results) !== null && _a !== void 0 ? _a : [];
229517
+ const totalPages = (memoriesData === null || memoriesData === void 0 ? void 0 : memoriesData.count) ? Math.ceil(memoriesData.count / PAGE_SIZE$9) : 0;
229518
+ const isForbidden = !!error && error.status === 403;
229519
+ // The managed user's capture/personalization toggles, addressed through
229520
+ // their path the way every admin write here is. Hidden unless they load.
229521
+ const { data: settings } = useGetUserMemorySettingsQuery({
229522
+ org: tenantKey,
229523
+ userId: user.username,
229524
+ });
229525
+ const [updateSettings, { isLoading: isUpdatingSettings }] = useUpdateUserMemorySettingsMutation();
229526
+ const handleToggleSetting = async (key, checked) => {
229527
+ try {
229528
+ await updateSettings({
229529
+ org: tenantKey,
229530
+ userId: user.username,
229531
+ settings: { [key]: checked },
229532
+ }).unwrap();
229533
+ toast.success(t('memoryMemoryTab.memorySettingUpdated'));
229534
+ }
229535
+ catch (_a) {
229536
+ toast.error(t('memoryMemoryTab.failedToUpdateMemorySetting'));
229537
+ }
229538
+ };
229539
+ const [deleteMemory] = useDeleteGlobalMemoryMutation();
229540
+ const handleDeleteMemory = async (memory) => {
229541
+ setDeletingId(memory.id);
229542
+ try {
229543
+ await deleteMemory({
229544
+ org: tenantKey,
229545
+ userId: user.username,
229546
+ memoryId: memory.id,
229547
+ }).unwrap();
229548
+ toast.success(t('memoryAdminUserMemoriesModal.memoryDeleted'));
229549
+ }
229550
+ catch (deleteError) {
229551
+ if ((deleteError === null || deleteError === void 0 ? void 0 : deleteError.status) === 403) {
229552
+ toast.error(t('memoryAdminTab.forbidden'));
229553
+ }
229554
+ else {
229555
+ toast.error(t('memoryAdminUserMemoriesModal.failedToDeleteMemory'));
229556
+ }
229557
+ }
229558
+ finally {
229559
+ setDeletingId(null);
229560
+ }
229561
+ };
229562
+ return (jsx(Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: jsxs(DialogContent, { "data-testid": "user-memories-modal", "aria-label": "user-global-memories", className: "w-full max-w-3xl max-h-[90vh] overflow-y-auto", children: [jsxs(DialogHeader, { children: [jsxs(DialogTitle, { children: [t('memoryAdminUserMemoriesModal.title'), " \u2014 ", user.email || user.username] }), jsx(DialogDescription, { children: t('memoryAdminUserMemoriesModal.description') })] }), settings && (jsxs("div", { className: "space-y-4", children: [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: (_b = settings.auto_capture_enabled) !== null && _b !== void 0 ? _b : false, onCheckedChange: (checked) => handleToggleSetting('auto_capture_enabled', checked), disabled: isUpdatingSettings, "aria-label": t('memoryMemoryTab.autoCaptureAriaLabel', {
229563
+ state: settings.auto_capture_enabled
229564
+ ? t('memoryMemoryTab.stateEnabled')
229565
+ : t('memoryMemoryTab.stateDisabled'),
229566
+ }), className: "cursor-pointer data-[state=checked]:bg-blue-500 flex-shrink-0" })] }), 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.useMemoryLabelTitle') }), jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: t('memoryMemoryTab.useMemoryLabelDesc') })] }), jsx(Switch, { checked: (_c = settings.use_memory_in_responses) !== null && _c !== void 0 ? _c : false, onCheckedChange: (checked) => handleToggleSetting('use_memory_in_responses', checked), disabled: isUpdatingSettings, "aria-label": t('memoryMemoryTab.useMemoryAriaLabel', {
229567
+ state: settings.use_memory_in_responses
229568
+ ? t('memoryMemoryTab.stateEnabled')
229569
+ : t('memoryMemoryTab.stateDisabled'),
229570
+ }), className: "cursor-pointer data-[state=checked]:bg-blue-500 flex-shrink-0" })] })] })), !isForbidden && (jsx("div", { className: "flex justify-end mb-4", children: jsxs(Button$1, { "data-testid": "user-memories-add", variant: "outline", size: "sm", onClick: () => setShowAdd(true), className: "text-xs", children: [jsx(Plus, { className: "h-3 w-3 mr-1" }), t('memoryAdminUserMemoriesModal.addMemoryButton')] }) })), isForbidden ? (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('memoryAdminUserMemoriesModal.forbidden') }) })) : error ? (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('memoryAdminUserMemoriesModal.failedToLoad') }) })) : (jsx(MemoriesList, { memories: memories, isLoading: isLoading, emptyText: t('memoryAdminUserMemoriesModal.noMemories'), deletingId: deletingId, onEdit: setEditingMemory, onDelete: handleDeleteMemory, totalPages: totalPages, currentPage: page, onPageChange: setPage })), jsx(AddMemoryDialog, { open: showAdd, onOpenChange: setShowAdd, org: tenantKey, username: user.username }), editingMemory && (jsx(EditMemoryDialog, { open: !!editingMemory, onOpenChange: (open) => !open && setEditingMemory(null), org: tenantKey, username: user.username, memory: editingMemory }))] }) }));
229571
+ }
229572
+
229573
+ const PAGE_SIZE$8 = 10;
229574
+ const SEARCH_DEBOUNCE_MS = 300;
229575
+ /**
229576
+ * Tenant users table with server-side search. Opening a row shows that user's
229577
+ * global memories in a popup where the admin can manage them.
229578
+ */
229579
+ function GlobalMemoriesSection({ tenantKey, username }) {
229580
+ var _a;
229581
+ const t = useT();
229582
+ const [page, setPage] = useState(1);
229583
+ const [searchQuery, setSearchQuery] = useState('');
229584
+ const [debouncedSearch, setDebouncedSearch] = useState(searchQuery);
229585
+ const [selectedUser, setSelectedUser] = useState(null);
229586
+ // Same debounce contract as the Management tab's user search: terms shorter
229587
+ // than three characters search as empty. Bailing out on an unchanged value
229588
+ // keeps the mount-time timer from resetting a page the user already turned.
229589
+ useEffect(() => {
229590
+ const handler = setTimeout(() => {
229591
+ setDebouncedSearch((previous) => {
229592
+ const next = searchQuery.length > 2 ? searchQuery : '';
229593
+ return previous === next ? previous : next;
229594
+ });
229595
+ }, SEARCH_DEBOUNCE_MS);
229596
+ return () => clearTimeout(handler);
229597
+ }, [searchQuery]);
229598
+ // A new search term invalidates the current page index.
229599
+ useEffect(() => {
229600
+ setPage(1);
229601
+ }, [debouncedSearch]);
229602
+ const { data, isLoading, isFetching, error } = usePlatformUsersQuery({
229603
+ platform_key: tenantKey,
229604
+ platform_org: tenantKey,
229605
+ page,
229606
+ page_size: PAGE_SIZE$8,
229607
+ query: debouncedSearch,
229608
+ return_policies: 'false',
229609
+ });
229610
+ const users = useMemo(() => {
229611
+ var _a;
229612
+ // `results` is a bare array unless policies were requested, in which case
229613
+ // the users sit under `results.data`.
229614
+ const results = data === null || data === void 0 ? void 0 : data.results;
229615
+ const platformUsers = Array.isArray(results)
229616
+ ? results
229617
+ : ((_a = results === null || results === void 0 ? void 0 : results.data) !== null && _a !== void 0 ? _a : []);
229618
+ // A user without a username cannot be addressed by the memory endpoints.
229619
+ return platformUsers
229620
+ .filter((user) => !!user.username)
229621
+ .map((user) => ({
229622
+ username: user.username,
229623
+ name: user.name,
229624
+ email: user.email,
229625
+ }));
229626
+ }, [data]);
229627
+ const totalPages = Math.ceil(((_a = data === null || data === void 0 ? void 0 : data.count) !== null && _a !== void 0 ? _a : 0) / PAGE_SIZE$8);
229628
+ const isForbidden = !!error && error.status === 403;
229629
+ return (jsxs("div", { "data-testid": "memory-admin-global-section", children: [jsxs("div", { className: "relative mb-6 max-w-sm w-full sm:w-auto", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { "data-testid": "memory-admin-users-search", type: "text", value: searchQuery, onChange: (event) => setSearchQuery(event.target.value), placeholder: t('memoryAdminTab.searchUsersPlaceholder'), className: "pl-10 pr-10 focus:ring-blue-500 focus:border-blue-500 h-[35px]", "aria-label": t('memoryAdminTab.searchUsersAriaLabel') }), searchQuery.length > 0 && (searchQuery !== debouncedSearch || isFetching) && (jsx(LoaderCircle, { "data-testid": "user-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" }))] }), isForbidden ? (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('memoryAdminTab.forbidden') }) })) : 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-[28%]", children: t('memoryAdminTab.nameColumn') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[26%]", children: t('memoryAdminTab.usernameColumn') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[30%]", children: t('memoryAdminTab.emailColumn') }), jsx("th", { className: "px-6 py-3 text-right font-medium text-gray-500 dark:text-gray-400 w-[16%]", children: t('memoryAdminTab.actionsColumn') })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [users.map((user) => (jsxs("tr", { "data-testid": `memory-admin-user-row-${user.username}`, children: [jsx("td", { className: "px-6 py-4 text-gray-900 dark:text-gray-100 max-w-0", children: jsx("div", { className: "truncate font-medium", children: user.name || '—' }) }), jsx("td", { className: "px-6 py-4 text-gray-600 dark:text-gray-300 max-w-0", children: jsx("div", { className: "truncate", children: user.username }) }), jsx("td", { className: "px-6 py-4 text-gray-600 dark:text-gray-300 max-w-0", children: jsx("div", { className: "truncate", children: user.email || '—' }) }), jsx("td", { className: "px-6 py-4", children: jsx("div", { className: "flex justify-end gap-2", children: jsx(Button$1, { "data-testid": `memory-admin-user-view-${user.username}`, variant: "ghost", size: "sm", "aria-label": t('memoryAdminTab.viewMemoriesAriaLabel', {
229630
+ name: user.email || user.username,
229631
+ }), onClick: () => setSelectedUser(user), children: jsx(Eye, { className: "h-4 w-4" }) }) }) })] }, user.username))), users.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: 4, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: isFetching ? t('memoryAdminTab.loading') : t('memoryAdminTab.noUsersFound') }) }))] })] }) }), totalPages > 1 && (jsx("div", { className: "mt-6", children: jsx(IblPagination, { totalPages: totalPages, currentPage: page, onPageChange: setPage, disabled: isFetching }) }))] })), selectedUser && (jsx(UserMemoriesModal, { isOpen: !!selectedUser, onClose: () => setSelectedUser(null), tenantKey: tenantKey, adminUsername: username, user: selectedUser }))] }));
229632
+ }
229633
+
229634
+ const EditMemoryModal$1 = dynamic(() => Promise.resolve().then(function () { return editMemoryModal; }).then((module) => ({
229635
+ default: module.EditMemoryModal,
229636
+ })), { ssr: false });
229637
+ const AddMemoryModal$1 = dynamic(() => Promise.resolve().then(function () { return addMemoryModal; }).then((module) => ({
229638
+ default: module.AddMemoryModal,
229639
+ })), { ssr: false });
229640
+ const DeleteMemoryModal = dynamic(() => Promise.resolve().then(function () { return deleteMemoryModal; }).then((module) => ({
229641
+ default: module.DeleteMemoryModal,
229642
+ })), { ssr: false });
229643
+ const BulkDeleteMemoryModal$1 = dynamic(() => Promise.resolve().then(function () { return bulkDeleteMemoryModal; }).then((module) => ({
229644
+ default: module.BulkDeleteMemoryModal,
229645
+ })), { ssr: false });
229646
+ const ManageCategoriesModal$1 = dynamic(() => Promise.resolve().then(function () { return manageCategoriesModal; }).then((module) => ({
229647
+ default: module.ManageCategoriesModal,
229648
+ })), { ssr: false });
229649
+ const PAGE_SIZE$7 = 20;
229650
+ const SNAPSHOT_PAGE_SIZE = 1000;
229651
+ function ManageMemories({ tenantKey, username, mentorId }) {
229652
+ var _a, _b, _c, _d, _e;
229653
+ const t = useT();
229654
+ const [selectedLearner, setSelectedLearner] = useState('');
229655
+ const [dateRange, setDateRange] = useState(undefined);
229656
+ const [selectedCategorySlug, setSelectedCategorySlug] = useState('all');
229657
+ const [page, setPage] = useState(1);
229658
+ // Reset to page 1 whenever any filter changes — otherwise we could land on a
229659
+ // page index that no longer exists in the new result set.
229660
+ useEffect(() => {
229661
+ setPage(1);
229662
+ }, [selectedLearner, dateRange, selectedCategorySlug]);
229663
+ const listParams = useMemo(() => {
229664
+ const params = { page, page_size: PAGE_SIZE$7 };
229665
+ if (selectedLearner)
229666
+ params.email = selectedLearner;
229667
+ if (selectedCategorySlug !== 'all')
229668
+ params.category = selectedCategorySlug;
229669
+ if (dateRange === null || dateRange === void 0 ? void 0 : dateRange.from)
229670
+ params.start_date = format$1(dateRange.from, 'yyyy-MM-dd');
229671
+ if (dateRange === null || dateRange === void 0 ? void 0 : dateRange.to)
229672
+ params.end_date = format$1(dateRange.to, 'yyyy-MM-dd');
229673
+ return params;
229674
+ }, [page, selectedLearner, selectedCategorySlug, dateRange]);
229675
+ const { data: listResponse, isLoading: isLoadingMemories } = useGetMentorMemoriesListQuery({
229676
+ org: tenantKey,
229677
+ userId: username !== null && username !== void 0 ? username : '',
229678
+ mentorId,
229679
+ params: listParams,
229680
+ }, {
229681
+ skip: !tenantKey || !username || !mentorId,
229682
+ });
229683
+ const totalPages = Math.max(1, Math.ceil(((_a = listResponse === null || listResponse === void 0 ? void 0 : listResponse.count) !== null && _a !== void 0 ? _a : 0) / PAGE_SIZE$7));
229684
+ const { data: adminCategories } = useGetMemoryCategoriesAdminQuery({
229685
+ org: tenantKey,
229686
+ mentorId,
229687
+ }, {
229688
+ skip: !tenantKey || !mentorId,
229689
+ });
229690
+ const [deleteMentorMemory, { isLoading: isDeleting }] = useDeleteMentorMemoryMutation();
229691
+ const [updateMentorMemory, { isLoading: isEditing }] = useUpdateMentorMemoryMutation();
229692
+ const [createMentorMemory, { isLoading: isSaving }] = useCreateMentorMemoryMutation();
229693
+ // Flat list of memories on the current page, mapped into the local `Memory`
229694
+ // shape used by the rest of this component.
229695
+ const memories = useMemo(() => {
229696
+ if (!(listResponse === null || listResponse === void 0 ? void 0 : listResponse.results))
229697
+ return [];
229698
+ return listResponse.results.map((memory) => ({
229699
+ id: memory.id,
229700
+ content: memory.content,
229701
+ category: {
229702
+ id: memory.category.id,
229703
+ name: memory.category.name,
229704
+ slug: memory.category.slug,
229705
+ },
229706
+ email: memory.email,
229707
+ createdAt: memory.created_at,
229708
+ }));
229709
+ }, [listResponse]);
229710
+ // Unfiltered snapshot used to derive the learner dropdown and to source the
229711
+ // bulk-delete operation, which needs the full set of memories — not just the
229712
+ // current page.
229713
+ const { data: snapshotResponse } = useGetMentorMemoriesListQuery({
229714
+ org: tenantKey,
229715
+ userId: username !== null && username !== void 0 ? username : '',
229716
+ mentorId,
229717
+ params: { page: 1, page_size: SNAPSHOT_PAGE_SIZE },
229718
+ }, {
229719
+ skip: !tenantKey || !username || !mentorId,
229720
+ });
229721
+ const learners = useMemo(() => {
229722
+ if (!(snapshotResponse === null || snapshotResponse === void 0 ? void 0 : snapshotResponse.results))
229723
+ return [];
229724
+ const emailSet = new Set();
229725
+ snapshotResponse.results.forEach((m) => {
229726
+ if (m.email)
229727
+ emailSet.add(m.email);
229728
+ });
229729
+ return Array.from(emailSet).map((email) => ({ email }));
229730
+ }, [snapshotResponse]);
229731
+ const categories = useMemo(() => {
229732
+ if (adminCategories && adminCategories.length > 0) {
229733
+ return [
229734
+ { id: 0, name: 'All', slug: 'all' },
229735
+ ...adminCategories.map((cat) => ({
229736
+ id: cat.id,
229737
+ name: cat.name,
229738
+ slug: cat.slug,
229739
+ })),
229740
+ ];
229741
+ }
229742
+ return [{ id: 0, name: 'All', slug: 'all' }];
229743
+ }, [adminCategories]);
229744
+ const [editingMemory, setEditingMemory] = useState(null);
229745
+ const [editContent, setEditContent] = useState('');
229746
+ const [editCategory, setEditCategory] = useState('');
229747
+ const [showDeleteConfirm, setShowDeleteConfirm] = useState(null);
229748
+ const [showAddMemory, setShowAddMemory] = useState(false);
229749
+ const [newMemoryContent, setNewMemoryContent] = useState('');
229750
+ const [newMemoryCategory, setNewMemoryCategory] = useState('');
229751
+ const [showMobileDropdown, setShowMobileDropdown] = useState(false);
229752
+ const [showBulkDeleteConfirm, setShowBulkDeleteConfirm] = useState(false);
229753
+ const [isBulkDeleting, setIsBulkDeleting] = useState(false);
229754
+ const [showManageCategories, setShowManageCategories] = useState(false);
229755
+ const selectedCategoryName = (_c = (_b = categories.find((c) => c.slug === selectedCategorySlug)) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : t('memoryTabManageMemories.all');
229756
+ const VISIBLE_CATEGORY_LIMIT = 6;
229757
+ const visibleCategories = categories.slice(0, VISIBLE_CATEGORY_LIMIT);
229758
+ const overflowCategories = categories.slice(VISIBLE_CATEGORY_LIMIT);
229759
+ const overflowSelected = overflowCategories.find((c) => c.slug === selectedCategorySlug);
229760
+ // Category is filtered server-side via the `category` query param now, so
229761
+ // `memories` already contains only the relevant entries for the page.
229762
+ const filteredMemories = memories;
229763
+ const handleDeleteMemory = async (id) => {
229764
+ if (!tenantKey || !username)
229765
+ return;
229766
+ try {
229767
+ await deleteMentorMemory({
229768
+ org: tenantKey,
229769
+ userId: username,
229770
+ mentorId,
229771
+ memoryId: id,
229772
+ }).unwrap();
229773
+ setShowDeleteConfirm(null);
229774
+ toast.success(t('memoryTabManageMemories.memoryDeletedSuccessfully'));
229775
+ }
229776
+ catch (error) {
229777
+ console.error('Failed to delete memory:', error);
229778
+ toast.error(t('memoryTabManageMemories.failedToDeleteMemory'));
229779
+ }
229780
+ };
229781
+ const handleBulkDelete = async () => {
229782
+ var _a;
229783
+ if (!tenantKey || !username)
229784
+ return;
229785
+ setIsBulkDeleting(true);
229786
+ try {
229787
+ // Source bulk-delete from the unfiltered snapshot — `memories` only holds
229788
+ // the current page, while bulk delete must remove every entry in the
229789
+ // selected category.
229790
+ const memoriesToDelete = ((_a = snapshotResponse === null || snapshotResponse === void 0 ? void 0 : snapshotResponse.results) !== null && _a !== void 0 ? _a : []).filter((memory) => memory.category.slug === selectedCategorySlug);
229791
+ await Promise.all(memoriesToDelete.map((memory) => deleteMentorMemory({
229792
+ org: tenantKey,
229793
+ userId: username,
229794
+ mentorId,
229795
+ memoryId: memory.id,
229796
+ }).unwrap()));
229797
+ toast.success(t('memoryTabManageMemories.allCategoryMemoriesDeleted', { category: selectedCategoryName }));
229798
+ setShowBulkDeleteConfirm(false);
229799
+ }
229800
+ catch (error) {
229801
+ console.error('Failed to delete memories:', error);
229802
+ toast.error(t('memoryTabManageMemories.failedToDeleteMemories'));
229803
+ }
229804
+ finally {
229805
+ setIsBulkDeleting(false);
229806
+ }
229807
+ };
229808
+ const startEdit = (memory) => {
229809
+ setEditingMemory(memory);
229810
+ setEditContent(memory.content);
229811
+ setEditCategory(memory.category.name);
229812
+ };
229813
+ const saveEdit = async () => {
229814
+ if (!editingMemory || !tenantKey || !username)
229815
+ return;
229816
+ try {
229817
+ const selectedCat = categories.find((c) => c.name === editCategory);
229818
+ const categoryChanged = !!selectedCat && selectedCat.slug !== editingMemory.category.slug;
229819
+ await updateMentorMemory({
229820
+ org: tenantKey,
229821
+ userId: username,
229822
+ mentorId,
229823
+ memoryId: editingMemory.id,
229824
+ data: {
229825
+ content: editContent,
229826
+ ...(categoryChanged ? { category_slug: selectedCat.slug } : {}),
229827
+ },
229828
+ }).unwrap();
229829
+ toast.success(t('memoryTabManageMemories.memoryUpdatedSuccessfully'));
229830
+ // Follow the entry to its new category tab so the user doesn't lose
229831
+ // sight of it. Skip when viewing "All" — the entry is still visible.
229832
+ if (categoryChanged && selectedCategorySlug !== 'all') {
229833
+ setSelectedCategorySlug(selectedCat.slug);
229834
+ }
229835
+ setEditingMemory(null);
229836
+ setEditContent('');
229837
+ setEditCategory('');
229838
+ }
229839
+ catch (error) {
229840
+ console.error('Failed to update memory:', error);
229841
+ toast.error(t('memoryTabManageMemories.failedToUpdateMemory'));
229842
+ }
229843
+ };
229844
+ const cancelEdit = () => {
229845
+ setEditingMemory(null);
229846
+ setEditContent('');
229847
+ setEditCategory('');
229848
+ };
229849
+ const startAddMemory = () => {
229850
+ setShowAddMemory(true);
229851
+ setNewMemoryCategory(selectedCategoryName);
229852
+ };
229853
+ const saveNewMemory = async () => {
229854
+ var _a;
229855
+ if (!newMemoryContent.trim() || !tenantKey || !username)
229856
+ return;
229857
+ try {
229858
+ const selectedCat = categories.find((c) => c.name === newMemoryCategory);
229859
+ const categorySlug = (_a = selectedCat === null || selectedCat === void 0 ? void 0 : selectedCat.slug) !== null && _a !== void 0 ? _a : selectedCategorySlug;
229860
+ await createMentorMemory({
229861
+ org: tenantKey,
229862
+ userId: username,
229863
+ mentorId,
229864
+ data: {
229865
+ category_slug: categorySlug === 'all' ? 'general' : categorySlug,
229866
+ content: newMemoryContent.trim(),
229867
+ },
229868
+ }).unwrap();
229869
+ setShowAddMemory(false);
229870
+ setNewMemoryContent('');
229871
+ setNewMemoryCategory('');
229872
+ if (selectedCat) {
229873
+ setSelectedCategorySlug(selectedCat.slug);
229874
+ }
229875
+ toast.success(t('memoryTabManageMemories.memoryCreatedSuccessfully'));
229876
+ }
229877
+ catch (error) {
229878
+ console.error('Failed to create memory:', error);
229879
+ toast.error(t('memoryTabManageMemories.failedToCreateMemory'));
229880
+ }
229881
+ };
229882
+ const cancelAddMemory = () => {
229883
+ setShowAddMemory(false);
229884
+ setNewMemoryContent('');
229885
+ setNewMemoryCategory('');
229886
+ };
229887
+ const categoryNames = categories.map((c) => c.name);
229888
+ return (jsxs(Fragment$1, { children: [jsxs("div", { className: "space-y-6", children: [jsx("div", { className: "rounded-lg border p-4", children: jsxs("div", { className: "flex flex-col gap-3 lg:flex-row", children: [jsx("div", { className: "relative min-w-[200px] flex-1", children: jsxs(Popover, { children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", role: "combobox", "aria-label": t('memoryTabManageMemories.searchForUser'), className: "w-full justify-between bg-transparent font-normal", children: [selectedLearner
229889
+ ? ((_e = (_d = learners.find((learner) => learner.email === selectedLearner)) === null || _d === void 0 ? void 0 : _d.email) !== null && _e !== void 0 ? _e : selectedLearner)
229890
+ : t('memoryTabManageMemories.searchForUser'), jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })] }) }), jsx(PopoverContent, { className: "w-full p-0", align: "start", children: jsxs(Command, { children: [jsx(CommandInput, { placeholder: t('memoryTabManageMemories.searchUsersPlaceholder') }), jsxs(CommandList, { children: [jsx(CommandEmpty, { children: t('memoryTabManageMemories.noUsersFound') }), jsxs(CommandGroup, { children: [jsxs(CommandItem, { value: "", onSelect: () => {
229891
+ setSelectedLearner('');
229892
+ }, children: [jsx(Check, { className: cn('mr-2 h-4 w-4', !selectedLearner ? 'opacity-100' : 'opacity-0') }), t('memoryTabManageMemories.allUsers')] }), learners.map((learner) => (jsxs(CommandItem, { value: learner.email, onSelect: () => {
229893
+ setSelectedLearner(learner.email);
229894
+ }, children: [jsx(Check, { className: cn('mr-2 h-4 w-4', selectedLearner === learner.email ? 'opacity-100' : 'opacity-0') }), jsx("div", { className: "flex flex-col", children: jsx("span", { className: "font-medium text-gray-700", children: learner.email }) })] }, learner.email)))] })] })] }) })] }) }), jsxs(Popover, { children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", className: "flex w-full items-center gap-2 bg-transparent 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)
229895
+ ? `${format$1(dateRange.from, 'MMM dd')} - ${format$1(dateRange.to, 'MMM dd')}`
229896
+ : t('memoryTabManageMemories.pickDateRange')] }) }), jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: jsx(Calendar, { mode: "range", selected: dateRange, onSelect: setDateRange, numberOfMonths: 2, initialFocus: true }) })] })] }) }), jsx("div", { children: jsxs("div", { className: "flex items-center justify-between gap-4", children: [jsxs("div", { className: "scrollbar-none hidden flex-1 items-center space-x-8 overflow-x-auto sm:flex", children: [visibleCategories.map((category) => (jsxs("button", { onClick: () => setSelectedCategorySlug(category.slug), className: `relative px-1 py-2 text-sm font-medium whitespace-nowrap transition-colors ${selectedCategorySlug === category.slug
229897
+ ? 'text-[#38A1E5]'
229898
+ : 'text-gray-600 hover:text-gray-900'}`, children: [category.name, selectedCategorySlug === category.slug && (jsx("div", { className: "absolute bottom-0 left-1/2 h-0.5 -translate-x-1/2 transform bg-[#38A1E5] transition-all duration-200", style: { width: `${category.name.length * 0.55}em` } }))] }, category.slug))), overflowCategories.length > 0 && (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs("button", { className: cn('relative flex items-center gap-1 px-1 py-2 text-sm font-medium whitespace-nowrap transition-colors', overflowSelected ? 'text-[#38A1E5]' : 'text-gray-600 hover:text-gray-900'), "aria-label": t('memoryTabManageMemories.moreCategories'), children: [overflowSelected ? overflowSelected.name : t('memoryTabManageMemories.more'), jsx(ChevronDown, { className: "h-3.5 w-3.5" }), overflowSelected && (jsx("div", { className: "absolute bottom-0 left-0 h-0.5 bg-[#38A1E5] transition-all duration-200", style: {
229899
+ width: `${overflowSelected.name.length * 0.55}em`,
229900
+ } }))] }) }), jsx(DropdownMenuContent, { align: "end", children: overflowCategories.map((category) => (jsx(DropdownMenuItem, { onClick: () => setSelectedCategorySlug(category.slug), className: selectedCategorySlug === category.slug ? 'bg-gray-100' : '', children: category.name }, category.slug))) })] }))] }), jsx("div", { className: "w-full py-2 sm:hidden", children: jsxs(DropdownMenu, { open: showMobileDropdown, onOpenChange: setShowMobileDropdown, children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", className: "w-full justify-between bg-transparent", children: [selectedCategoryName, jsx(ChevronDown, { className: "h-4 w-4" })] }) }), jsx(DropdownMenuContent, { className: "w-full", children: categories.map((category) => (jsx(DropdownMenuItem, { onClick: () => {
229901
+ setSelectedCategorySlug(category.slug);
229902
+ setShowMobileDropdown(false);
229903
+ }, className: selectedCategorySlug === category.slug ? 'bg-gray-100' : '', children: category.name }, category.slug))) })] }) }), jsxs(Button$1, { onClick: () => setShowManageCategories(true), size: "sm", variant: "outline", className: "shrink-0", "aria-label": t('memoryTabManageMemories.manageCategories'), children: [jsx(Tags, { className: "h-4 w-4 sm:mr-2" }), jsx("span", { className: "hidden sm:inline", children: t('memoryTabManageMemories.categories') })] }), jsxs(Button$1, { onClick: startAddMemory, size: "sm", className: "ibl-button-primary shrink-0", children: [jsx(Plus, { className: "mr-1 h-4 w-4 sm:mr-2" }), jsx("span", { className: "hidden sm:inline", children: t('memoryTabManageMemories.addMemory') }), jsx("span", { className: "sm:hidden", children: t('memoryTabManageMemories.add') })] })] }) }), jsx("div", { className: "space-y-3 px-1 sm:px-0", children: isLoadingMemories ? (jsx("div", { className: "py-8 text-center text-gray-600", children: jsx("p", { children: t('memoryTabManageMemories.loadingMemories') }) })) : (filteredMemories.map((memory) => {
229904
+ const timeAgo = memory.createdAt
229905
+ ? formatDistanceToNow(new Date(memory.createdAt), {
229906
+ addSuffix: true,
229907
+ })
229908
+ : '';
229909
+ const displayUser = memory.email || t('memoryTabManageMemories.unknown');
229910
+ return (jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-gray-200 bg-white p-3", children: [jsxs("div", { className: "flex-1", children: [(timeAgo || displayUser) && (jsxs("div", { className: "mb-2 flex items-center justify-between", children: [timeAgo && jsx("span", { className: "text-sm text-gray-600", children: timeAgo }), displayUser && (jsx("span", { className: "max-w-[100px] truncate text-sm text-gray-900 sm:max-w-[200px]", children: displayUser }))] })), jsx("div", { className: "text-sm leading-relaxed text-gray-900", children: memory.content })] }), jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { variant: "ghost", size: "sm", className: "h-6 w-6 flex-shrink-0 p-0 text-gray-600 hover:text-gray-900", children: jsx(Ellipsis, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsx(DropdownMenuItem, { onClick: () => startEdit(memory), children: t('memoryTabManageMemories.edit') }), jsx(DropdownMenuItem, { onClick: () => setShowDeleteConfirm(memory.id), children: t('memoryTabManageMemories.delete') })] })] })] }, memory.id));
229911
+ })) }), filteredMemories.length > 0 && selectedCategorySlug !== 'all' && (jsx("div", { className: "flex justify-end", children: jsx(Button$1, { variant: "outline", onClick: () => setShowBulkDeleteConfirm(true), children: t('memoryTabManageMemories.deleteAll') }) })), filteredMemories.length === 0 && !isLoadingMemories && (jsx("div", { className: "py-8 text-center text-gray-600", children: jsx("p", { children: t('memoryTabManageMemories.noSavedMemories') }) })), totalPages > 1 && (jsx("div", { className: "flex justify-center pt-2", children: jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: isLoadingMemories }) }))] }), jsx(EditMemoryModal$1, { open: !!editingMemory, onOpenChange: (open) => !open && cancelEdit(), editContent: editContent, editCategory: editCategory, onContentChange: setEditContent, onCategoryChange: setEditCategory, onSave: saveEdit, onCancel: cancelEdit, categories: categoryNames, isSaving: isEditing }), jsx(AddMemoryModal$1, { open: showAddMemory, onOpenChange: (open) => !open && cancelAddMemory(), newMemoryContent: newMemoryContent, newMemoryCategory: newMemoryCategory, onContentChange: setNewMemoryContent, onCategoryChange: setNewMemoryCategory, onSave: saveNewMemory, onCancel: cancelAddMemory, categories: categoryNames, isSaving: isSaving }), jsx(DeleteMemoryModal, { open: !!showDeleteConfirm, onOpenChange: (open) => !open && setShowDeleteConfirm(null), onConfirm: () => showDeleteConfirm !== null && handleDeleteMemory(showDeleteConfirm), onCancel: () => setShowDeleteConfirm(null), isDeleting: isDeleting }), jsx(ManageCategoriesModal$1, { open: showManageCategories, onOpenChange: setShowManageCategories, tenantKey: tenantKey, mentorId: mentorId }), jsx(BulkDeleteMemoryModal$1, { open: showBulkDeleteConfirm, onOpenChange: setShowBulkDeleteConfirm, onConfirm: handleBulkDelete, onCancel: () => setShowBulkDeleteConfirm(false), isDeleting: isBulkDeleting, selectedCategory: selectedCategoryName })] }));
229912
+ }
229913
+
229914
+ /**
229915
+ * Popup hosting the same memory manager the agent settings modal renders —
229916
+ * learner/category/date filters and full CRUD included — for one agent.
229917
+ * Laid out like the Billing tab's agent-limits popup: a fixed divider header
229918
+ * and a body that scrolls vertically while the content fits the width.
229919
+ */
229920
+ function AgentMemoriesModal({ isOpen, onClose, tenantKey, username, agent, }) {
229921
+ const t = useT();
229922
+ return (jsx(Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: jsxs(DialogContent, { "data-testid": "agent-memories-modal", "aria-label": "agent-memories", className: "flex max-h-[90vh] w-[calc(100vw-2rem)] flex-col gap-0 overflow-hidden p-0 sm:max-w-4xl", children: [jsxs(DialogHeader, { className: "flex-shrink-0 border-b border-gray-200 px-6 py-4 pr-12", children: [jsx(DialogTitle, { className: "ibl-dialog-title", children: agent.name }), jsx(DialogDescription, { children: t('memoryAdminAgentMemoriesModal.description') })] }), jsx("div", { className: "min-h-0 flex-1 overflow-y-auto p-3 lg:p-4", children: jsx("div", { className: "space-y-8", children: jsx(ManageMemories, { tenantKey: tenantKey, username: username, mentorId: agent.unique_id }) }) })] }) }));
229923
+ }
229924
+
229925
+ const PAGE_SIZE$6 = 10;
229926
+ /**
229927
+ * Agents table filtered by the same agent autocomplete the Billing tab's
229928
+ * Agent Limits section uses. Opening a row shows that agent's memories in a
229929
+ * popup hosting the same manager the agent settings modal uses.
229930
+ */
229931
+ function AgentMemoriesSection({ tenantKey, username }) {
229932
+ var _a;
229933
+ const t = useT();
229934
+ const [page, setPage] = useState(1);
229935
+ const [agentFilter, setAgentFilter] = useState(null);
229936
+ const [agentSearch, setAgentSearch] = useState('');
229937
+ const [debouncedAgentSearch] = a$3(agentSearch, 300);
229938
+ const [selectedAgent, setSelectedAgent] = useState(null);
229939
+ // A new filter invalidates the current page index.
229940
+ useEffect(() => {
229941
+ setPage(1);
229942
+ }, [agentFilter]);
229943
+ // Autocomplete options for the filter, fetched once two characters are in.
229944
+ const shouldSearchAgents = Boolean(tenantKey && debouncedAgentSearch.trim().length >= 2);
229945
+ const { data: searchResponse, isFetching: isSearchingAgents } = useGetMentorsQuery({ org: tenantKey, username, limit: 20, query: debouncedAgentSearch.trim() }, { skip: !shouldSearchAgents });
229946
+ const agentOptions = useMemo(() => {
229947
+ var _a;
229948
+ return ((_a = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.results) !== null && _a !== void 0 ? _a : [])
229949
+ .filter((mentor) => Boolean(mentor.unique_id))
229950
+ .map((mentor) => ({
229951
+ value: mentor.unique_id,
229952
+ label: mentor.name || mentor.unique_id,
229953
+ }));
229954
+ }, [searchResponse]);
229955
+ const { data, isLoading, isFetching, error } = useGetMentorsQuery({
229956
+ org: tenantKey,
229957
+ username,
229958
+ limit: PAGE_SIZE$6,
229959
+ offset: (page - 1) * PAGE_SIZE$6,
229960
+ ...(agentFilter ? { uniqueId: agentFilter.value } : {}),
229961
+ });
229962
+ const agents = ((_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : []);
229963
+ const totalPages = (data === null || data === void 0 ? void 0 : data.count) ? Math.ceil(data.count / PAGE_SIZE$6) : 0;
229964
+ const isForbidden = !!error && error.status === 403;
229965
+ return (jsxs("div", { "data-testid": "memory-admin-agent-section", children: [jsx("div", { className: "mb-6 max-w-sm", children: jsx(SearchSelect, { labels: {
229966
+ // No field label — the users tab's search carries none either.
229967
+ label: '',
229968
+ placeholder: t('memoryAdminTab.filter.placeholder'),
229969
+ typeToSearch: t('memoryAdminTab.filter.typeToSearch'),
229970
+ searching: t('memoryAdminTab.filter.searching'),
229971
+ noResults: t('memoryAdminTab.filter.noResults'),
229972
+ clear: t('memoryAdminTab.filter.clear'),
229973
+ }, selected: agentFilter, onSelect: (option) => {
229974
+ setAgentFilter(option);
229975
+ setAgentSearch('');
229976
+ }, onClear: () => setAgentFilter(null), searchTerm: agentSearch, onSearchTermChange: setAgentSearch, options: agentOptions, isLoading: isSearchingAgents, testId: "agent-memories-filter" }) }), isForbidden ? (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('memoryAdminTab.forbidden') }) })) : 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-[32%]", children: t('memoryAdminTab.agentColumn') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[52%]", children: t('memoryAdminTab.descriptionColumn') }), jsx("th", { className: "px-6 py-3 text-right font-medium text-gray-500 dark:text-gray-400 w-[16%]", children: t('memoryAdminTab.actionsColumn') })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [agents.map((agent) => (jsxs("tr", { "data-testid": `memory-admin-agent-row-${agent.unique_id}`, children: [jsx("td", { className: "px-6 py-4 text-gray-900 dark:text-gray-100 max-w-0", children: jsx("div", { className: "truncate font-medium", children: agent.name }) }), jsx("td", { className: "px-6 py-4 text-gray-600 dark:text-gray-300 max-w-0", children: jsx("div", { className: "truncate", children: agent.description || '—' }) }), jsx("td", { className: "px-6 py-4", children: jsx("div", { className: "flex justify-end gap-2", children: jsx(Button$1, { "data-testid": `memory-admin-agent-view-${agent.unique_id}`, variant: "ghost", size: "sm", "aria-label": t('memoryAdminTab.viewMemoriesAriaLabel', {
229977
+ name: agent.name,
229978
+ }), onClick: () => setSelectedAgent(agent), children: jsx(Eye, { className: "h-4 w-4" }) }) }) })] }, agent.unique_id))), agents.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: isFetching ? t('memoryAdminTab.loading') : t('memoryAdminTab.noAgentsFound') }) }))] })] }) }), totalPages > 1 && (jsx("div", { className: "mt-6", children: jsx(IblPagination, { totalPages: totalPages, currentPage: page, onPageChange: setPage, disabled: isFetching }) }))] })), selectedAgent && (jsx(AgentMemoriesModal, { isOpen: !!selectedAgent, onClose: () => setSelectedAgent(null), tenantKey: tenantKey, username: username, agent: selectedAgent }))] }));
229979
+ }
229980
+
229981
+ /**
229982
+ * Tenant-settings Memory tab. Lets admins/RBAC-granted users manage other
229983
+ * users' global memories and per-agent memories from one place, mirroring the
229984
+ * Billing tab's sub-tab layout.
229985
+ */
229986
+ function MemoryAdminTab({ tenantKey, username }) {
229987
+ const t = useT();
229988
+ // Same platform gate the profile memory tab applies: when memsearch is off
229989
+ // for the tenant there is nothing to manage.
229990
+ const { data: memsearchStatus, isLoading, isError, } = useGetMemsearchStatusQuery({ org: tenantKey, userId: username });
229991
+ if (isLoading) {
229992
+ return (jsxs("div", { className: "space-y-6", children: [jsx(Skeleton, { className: "h-10 w-full max-w-sm rounded-lg" }), jsx(Skeleton, { className: "h-40 w-full rounded-lg" })] }));
229993
+ }
229994
+ if (!isError && memsearchStatus && !memsearchStatus.enable_memsearch) {
229995
+ 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('memoryAdminTab.featureDisabled') }) }) }));
229996
+ }
229997
+ return (jsxs(Tabs, { defaultValue: "global-memories", "aria-label": t('memoryAdminTab.tabsAriaLabel'), children: [jsxs(TabsList, { "aria-label": t('memoryAdminTab.tabsAriaLabel'), className: "max-w-full overflow-x-auto justify-start px-1", children: [jsx(TabsTrigger, { "data-testid": "memory-admin-sub-tab-global", value: "global-memories", children: t('memoryAdminTab.tabGlobalMemories') }), jsx(TabsTrigger, { "data-testid": "memory-admin-sub-tab-agent", value: "agent-memories", children: t('memoryAdminTab.tabAgentMemories') })] }), jsx(TabsContent, { className: "mt-4", value: "global-memories", children: jsx(GlobalMemoriesSection, { tenantKey: tenantKey, username: username }) }), jsx(TabsContent, { className: "mt-4", value: "agent-memories", children: jsx(AgentMemoriesSection, { tenantKey: tenantKey, username: username }) })] }));
229998
+ }
229999
+
229474
230000
  // ::- Persistent data structure representing an ordered mapping from
229475
230001
  // strings to values, with some convenient update methods.
229476
230002
  function OrderedMap(content) {
@@ -258759,7 +259285,7 @@ function SlashSkillPicker({ skills, activeIndex, listboxId, onSelect, onActiveIn
258759
259285
  onMouseDown: (e) => {
258760
259286
  e.preventDefault();
258761
259287
  onSelect(skill);
258762
- }, children: jsxs("span", { className: "flex items-baseline gap-2", children: [jsx("span", { className: "text-sm font-medium text-gray-800", children: skill.name }), jsxs("span", { className: "text-xs text-gray-400", children: ["/", skill.slug] }), skill.category && (jsx("span", { className: "ml-auto rounded-full bg-gray-100 px-2 py-0.5 text-[0.625rem] text-gray-500", children: skill.category }))] }) }, skill.unique_id))), isFetchingMore && (jsxs("li", { role: "presentation", className: "flex items-center gap-2 px-3 py-2", "data-testid": "slash-skill-picker-loading-more", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500" }), jsx("span", { className: "text-xs text-gray-500", children: t('slashSkillPicker.loading') })] }))] }))] }));
259288
+ }, children: jsxs("span", { className: "flex items-start gap-2", children: [jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [jsx("span", { "data-testid": "slash-skill-picker-option-name", className: "text-sm font-medium break-words text-gray-800", children: skill.name }), jsxs("span", { "data-testid": "slash-skill-picker-option-slug", className: "text-xs break-all text-gray-400", children: ["/", skill.slug] })] }), skill.category && (jsx("span", { className: "shrink-0 rounded-full bg-gray-100 px-2 py-0.5 text-[0.625rem] text-gray-500", children: skill.category }))] }) }, skill.unique_id))), isFetchingMore && (jsxs("li", { role: "presentation", className: "flex items-center gap-2 px-3 py-2", "data-testid": "slash-skill-picker-loading-more", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500" }), jsx("span", { className: "text-xs text-gray-500", children: t('slashSkillPicker.loading') })] }))] }))] }));
258763
259289
  }
258764
259290
 
258765
259291
  /** Matches a composer value that is a single `/`-prefixed token (no whitespace). */
@@ -259694,7 +260220,7 @@ function RetrievedDocumentsButton({ sessionId }) {
259694
260220
  return (jsxs(Fragment$1, { children: [jsxs(Button$1, { variant: "outline", size: "sm", className: "flex items-center gap-2 border-gray-200 bg-white text-gray-700 hover:bg-gray-50", onClick: () => setIsOpen(true), children: [jsx(FileText, { className: "h-4 w-4 text-blue-600" }), jsx("span", { children: t('retrievedDocumentsButton.title') })] }), jsx(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: jsxs(DialogContent, { className: "flex max-h-[80vh] flex-col gap-0 p-0 sm:max-w-[425px] md:max-w-[600px]", children: [jsx(DialogHeader, { className: "border-b px-4 py-2", children: jsxs(DialogTitle, { className: "flex items-center gap-2 text-base font-medium text-[#646464]", children: [jsx(FileText, { className: "h-5 w-5 text-blue-600" }), t('retrievedDocumentsButton.title')] }) }), jsx("div", { className: "flex-1 overflow-hidden", children: jsx(DocumentSidebar, { isModal: true, sessionId: sessionId }) })] }) })] }));
259695
260221
  }
259696
260222
 
259697
- const PAGE_SIZE$9 = 10;
260223
+ const PAGE_SIZE$5 = 10;
259698
260224
  const MemoryMenu = ({ onClose, mentorId, tenantKey, username }) => {
259699
260225
  const t = useT();
259700
260226
  const [page, setPage] = useState(1);
@@ -259712,7 +260238,7 @@ const MemoryMenu = ({ onClose, mentorId, tenantKey, username }) => {
259712
260238
  mentorId,
259713
260239
  params: {
259714
260240
  page,
259715
- page_size: PAGE_SIZE$9,
260241
+ page_size: PAGE_SIZE$5,
259716
260242
  my_memory: true,
259717
260243
  },
259718
260244
  }, {
@@ -263627,7 +264153,7 @@ function DeleteItemConfirm({ isOpen, onClose, tenantKey, username, datasetName,
263627
264153
  : t('benchmarksDeleteItemConfirm.delete') })] })] }) }));
263628
264154
  }
263629
264155
 
263630
- const PAGE_SIZE$8 = 10;
264156
+ const PAGE_SIZE$4 = 10;
263631
264157
  function BenchmarkItemsModal({ isOpen, onClose, tenantKey, username, datasetName }) {
263632
264158
  var _a;
263633
264159
  const t = useT();
@@ -263639,17 +264165,17 @@ function BenchmarkItemsModal({ isOpen, onClose, tenantKey, username, datasetName
263639
264165
  userId: username,
263640
264166
  datasetName,
263641
264167
  page,
263642
- limit: PAGE_SIZE$8,
264168
+ limit: PAGE_SIZE$4,
263643
264169
  });
263644
264170
  const items = (_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : [];
263645
- const totalPages = evalTotalPages(data === null || data === void 0 ? void 0 : data.count, PAGE_SIZE$8);
264171
+ const totalPages = evalTotalPages(data === null || data === void 0 ? void 0 : data.count, PAGE_SIZE$4);
263646
264172
  return (jsx(Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: jsxs(DialogContent, { "aria-label": "benchmark-items", className: "w-full max-w-4xl max-h-[90vh] overflow-y-auto", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { children: datasetName }), jsx(DialogDescription, { children: t('benchmarksBenchmarkItemsModal.description') })] }), jsx("div", { className: "flex justify-end mb-4", children: jsxs(Button$1, { onClick: () => setShowAdd(true), className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white h-[35px]", children: [jsx(Plus, { className: "h-4 w-4 mr-1" }), t('benchmarksBenchmarkItemsModal.addItems')] }) }), isLoading ? (jsx("div", { className: "flex justify-center items-center h-40", 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-4 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[45%]", children: t('benchmarksBenchmarkItemsModal.questionColumn') }), jsx("th", { className: "px-4 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[45%]", children: t('benchmarksBenchmarkItemsModal.answerColumn') }), jsx("th", { className: "px-4 py-3 text-right font-medium text-gray-500 dark:text-gray-400 w-[10%]", children: t('benchmarksBenchmarkItemsModal.actionsColumn') })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [items.map((item) => {
263647
264173
  var _a;
263648
264174
  return (jsxs("tr", { className: "align-top", children: [jsx("td", { className: "px-4 py-3 text-gray-900 dark:text-gray-100", children: jsx("div", { className: "line-clamp-3 break-words", children: typeof item.input === 'string' ? item.input : JSON.stringify(item.input) }) }), jsx("td", { className: "px-4 py-3 text-gray-600 dark:text-gray-300", children: jsx("div", { className: "line-clamp-3 break-words", children: (_a = item.expected_output) !== null && _a !== void 0 ? _a : jsx("span", { className: "text-gray-400", children: "\u2014" }) }) }), jsx("td", { className: "px-4 py-3 text-right", children: jsx(Button$1, { variant: "ghost", size: "sm", "aria-label": t('benchmarksBenchmarkItemsModal.deleteItemAriaLabel'), onClick: () => setDeleteItemId(item.id), children: jsx(Trash2, { className: "h-4 w-4 text-red-500" }) }) })] }, item.id));
263649
264175
  }), items.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-4 py-8 text-center text-gray-500 dark:text-gray-400", children: t('benchmarksBenchmarkItemsModal.empty') }) }))] })] }) }), totalPages > 1 && (jsx("div", { className: "mt-6", children: jsx(AdvancedPagination, { totalPages: totalPages, currentPage: page, onPageChange: setPage }) }))] })), jsx(AddItemsModal, { isOpen: showAdd, onClose: () => setShowAdd(false), tenantKey: tenantKey, username: username, datasetName: datasetName }), deleteItemId && (jsx(DeleteItemConfirm, { isOpen: !!deleteItemId, onClose: () => setDeleteItemId(null), tenantKey: tenantKey, username: username, datasetName: datasetName, itemId: deleteItemId }))] }) }));
263650
264176
  }
263651
264177
 
263652
- const PAGE_SIZE$7 = 10;
264178
+ const PAGE_SIZE$3 = 10;
263653
264179
  function BenchmarksTab({ tenantKey, username, }) {
263654
264180
  var _a;
263655
264181
  const t = useT();
@@ -263661,13 +264187,13 @@ function BenchmarksTab({ tenantKey, username, }) {
263661
264187
  org: tenantKey,
263662
264188
  userId: username,
263663
264189
  page,
263664
- limit: PAGE_SIZE$7,
264190
+ limit: PAGE_SIZE$3,
263665
264191
  });
263666
264192
  const benchmarks = (_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : [];
263667
264193
  const filtered = searchQuery.trim()
263668
264194
  ? benchmarks.filter((benchmark) => benchmark.name.toLowerCase().includes(searchQuery.toLowerCase()))
263669
264195
  : benchmarks;
263670
- const totalPages = evalTotalPages(data === null || data === void 0 ? void 0 : data.count, PAGE_SIZE$7);
264196
+ const totalPages = evalTotalPages(data === null || data === void 0 ? void 0 : data.count, PAGE_SIZE$3);
263671
264197
  return (jsxs("div", { className: "mt-4", children: [jsxs("div", { className: "flex justify-between items-center gap-1 flex-wrap", children: [jsxs("div", { className: "relative mb-6 max-w-sm w-full sm:w-auto", 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) => setSearchQuery(event.target.value), placeholder: t('benchmarksIndex.searchPlaceholder'), className: "pl-10 pr-10 focus:ring-blue-500 focus:border-blue-500 h-[35px]", "aria-label": t('benchmarksIndex.searchAriaLabel') })] }), jsx("div", { className: "mb-6", children: jsxs(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white h-[35px]", onClick: () => setShowCreate(true), children: [jsx(Plus, { className: "h-4 w-4 mr-1" }), t('benchmarksIndex.newBenchmark')] }) })] }), 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-[28%]", children: t('benchmarksIndex.nameColumn') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[36%]", children: t('benchmarksIndex.descriptionColumn') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[20%]", children: t('benchmarksIndex.createdColumn') }), jsx("th", { className: "px-6 py-3 text-right font-medium text-gray-500 dark:text-gray-400 w-[16%]", children: t('benchmarksIndex.actionsColumn') })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [filtered.map((benchmark) => (jsxs("tr", { children: [jsx("td", { className: "px-6 py-4 text-gray-900 dark:text-gray-100 max-w-0", children: jsx("div", { className: "truncate font-medium", children: benchmark.name }) }), jsx("td", { className: "px-6 py-4 text-gray-600 dark:text-gray-300 max-w-0", children: jsx("div", { className: "truncate", children: benchmark.description || '—' }) }), jsx("td", { className: "px-6 py-4 text-gray-600 dark:text-gray-300 whitespace-nowrap", children: benchmark.created_at
263672
264198
  ? formatDistanceToNow(new Date(benchmark.created_at), {
263673
264199
  addSuffix: true,
@@ -263677,514 +264203,6 @@ function BenchmarksTab({ tenantKey, username, }) {
263677
264203
  }), onClick: () => setViewBenchmark(benchmark.name), children: jsx(Eye, { className: "h-4 w-4" }) }) }) })] }, benchmark.name))), filtered.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: 4, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: isFetching ? t('benchmarksIndex.loading') : t('benchmarksIndex.empty') }) }))] })] }) }), totalPages > 1 && (jsx("div", { className: "mt-6", children: jsx(AdvancedPagination, { totalPages: totalPages, currentPage: page, onPageChange: setPage }) }))] })), jsx(CreateBenchmarkModal, { isOpen: showCreate, onClose: () => setShowCreate(false), tenantKey: tenantKey, username: username }), viewBenchmark && (jsx(BenchmarkItemsModal, { isOpen: !!viewBenchmark, onClose: () => setViewBenchmark(null), tenantKey: tenantKey, username: username, datasetName: viewBenchmark }))] }));
263678
264204
  }
263679
264205
 
263680
- /** Matches the server-side cap on the global memories listing. */
263681
- const PAGE_SIZE$6 = 25;
263682
- /**
263683
- * Popup for managing one user's global memories. Reads them the way the
263684
- * profile preview does — the caller in the path, the managed user identified
263685
- * by their id (username) in `user_id` — while writes address the managed
263686
- * user's path directly, which the backend resolves for admin/RBAC callers.
263687
- * The list itself is the same {@link MemoriesList} the profile Memory tab
263688
- * renders.
263689
- */
263690
- function UserMemoriesModal({ isOpen, onClose, tenantKey, adminUsername, user, }) {
263691
- var _a, _b, _c;
263692
- const t = useT();
263693
- const [page, setPage] = useState(1);
263694
- const [showAdd, setShowAdd] = useState(false);
263695
- const [editingMemory, setEditingMemory] = useState(null);
263696
- const [deletingId, setDeletingId] = useState(null);
263697
- const { data: memoriesData, isLoading, error, } = useGetGlobalMemoriesQuery({
263698
- org: tenantKey,
263699
- userId: adminUsername,
263700
- // `user_id` must be the managed user's id (username) — the backend does
263701
- // not resolve emails here, so passing one returns an empty list.
263702
- params: { page, page_size: PAGE_SIZE$6, user_id: user.username },
263703
- });
263704
- const memories = (_a = memoriesData === null || memoriesData === void 0 ? void 0 : memoriesData.results) !== null && _a !== void 0 ? _a : [];
263705
- const totalPages = (memoriesData === null || memoriesData === void 0 ? void 0 : memoriesData.count) ? Math.ceil(memoriesData.count / PAGE_SIZE$6) : 0;
263706
- const isForbidden = !!error && error.status === 403;
263707
- // The managed user's capture/personalization toggles, addressed through
263708
- // their path the way every admin write here is. Hidden unless they load.
263709
- const { data: settings } = useGetUserMemorySettingsQuery({
263710
- org: tenantKey,
263711
- userId: user.username,
263712
- });
263713
- const [updateSettings, { isLoading: isUpdatingSettings }] = useUpdateUserMemorySettingsMutation();
263714
- const handleToggleSetting = async (key, checked) => {
263715
- try {
263716
- await updateSettings({
263717
- org: tenantKey,
263718
- userId: user.username,
263719
- settings: { [key]: checked },
263720
- }).unwrap();
263721
- toast.success(t('memoryMemoryTab.memorySettingUpdated'));
263722
- }
263723
- catch (_a) {
263724
- toast.error(t('memoryMemoryTab.failedToUpdateMemorySetting'));
263725
- }
263726
- };
263727
- const [deleteMemory] = useDeleteGlobalMemoryMutation();
263728
- const handleDeleteMemory = async (memory) => {
263729
- setDeletingId(memory.id);
263730
- try {
263731
- await deleteMemory({
263732
- org: tenantKey,
263733
- userId: user.username,
263734
- memoryId: memory.id,
263735
- }).unwrap();
263736
- toast.success(t('memoryAdminUserMemoriesModal.memoryDeleted'));
263737
- }
263738
- catch (deleteError) {
263739
- if ((deleteError === null || deleteError === void 0 ? void 0 : deleteError.status) === 403) {
263740
- toast.error(t('memoryAdminTab.forbidden'));
263741
- }
263742
- else {
263743
- toast.error(t('memoryAdminUserMemoriesModal.failedToDeleteMemory'));
263744
- }
263745
- }
263746
- finally {
263747
- setDeletingId(null);
263748
- }
263749
- };
263750
- return (jsx(Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: jsxs(DialogContent, { "data-testid": "user-memories-modal", "aria-label": "user-global-memories", className: "w-full max-w-3xl max-h-[90vh] overflow-y-auto", children: [jsxs(DialogHeader, { children: [jsxs(DialogTitle, { children: [t('memoryAdminUserMemoriesModal.title'), " \u2014 ", user.email || user.username] }), jsx(DialogDescription, { children: t('memoryAdminUserMemoriesModal.description') })] }), settings && (jsxs("div", { className: "space-y-4", children: [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: (_b = settings.auto_capture_enabled) !== null && _b !== void 0 ? _b : false, onCheckedChange: (checked) => handleToggleSetting('auto_capture_enabled', checked), disabled: isUpdatingSettings, "aria-label": t('memoryMemoryTab.autoCaptureAriaLabel', {
263751
- state: settings.auto_capture_enabled
263752
- ? t('memoryMemoryTab.stateEnabled')
263753
- : t('memoryMemoryTab.stateDisabled'),
263754
- }), className: "cursor-pointer data-[state=checked]:bg-blue-500 flex-shrink-0" })] }), 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.useMemoryLabelTitle') }), jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: t('memoryMemoryTab.useMemoryLabelDesc') })] }), jsx(Switch, { checked: (_c = settings.use_memory_in_responses) !== null && _c !== void 0 ? _c : false, onCheckedChange: (checked) => handleToggleSetting('use_memory_in_responses', checked), disabled: isUpdatingSettings, "aria-label": t('memoryMemoryTab.useMemoryAriaLabel', {
263755
- state: settings.use_memory_in_responses
263756
- ? t('memoryMemoryTab.stateEnabled')
263757
- : t('memoryMemoryTab.stateDisabled'),
263758
- }), className: "cursor-pointer data-[state=checked]:bg-blue-500 flex-shrink-0" })] })] })), !isForbidden && (jsx("div", { className: "flex justify-end mb-4", children: jsxs(Button$1, { "data-testid": "user-memories-add", variant: "outline", size: "sm", onClick: () => setShowAdd(true), className: "text-xs", children: [jsx(Plus, { className: "h-3 w-3 mr-1" }), t('memoryAdminUserMemoriesModal.addMemoryButton')] }) })), isForbidden ? (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('memoryAdminUserMemoriesModal.forbidden') }) })) : error ? (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('memoryAdminUserMemoriesModal.failedToLoad') }) })) : (jsx(MemoriesList, { memories: memories, isLoading: isLoading, emptyText: t('memoryAdminUserMemoriesModal.noMemories'), deletingId: deletingId, onEdit: setEditingMemory, onDelete: handleDeleteMemory, totalPages: totalPages, currentPage: page, onPageChange: setPage })), jsx(AddMemoryDialog, { open: showAdd, onOpenChange: setShowAdd, org: tenantKey, username: user.username }), editingMemory && (jsx(EditMemoryDialog, { open: !!editingMemory, onOpenChange: (open) => !open && setEditingMemory(null), org: tenantKey, username: user.username, memory: editingMemory }))] }) }));
263759
- }
263760
-
263761
- const PAGE_SIZE$5 = 10;
263762
- const SEARCH_DEBOUNCE_MS = 300;
263763
- /**
263764
- * Tenant users table with server-side search. Opening a row shows that user's
263765
- * global memories in a popup where the admin can manage them.
263766
- */
263767
- function GlobalMemoriesSection({ tenantKey, username }) {
263768
- var _a;
263769
- const t = useT();
263770
- const [page, setPage] = useState(1);
263771
- const [searchQuery, setSearchQuery] = useState('');
263772
- const [debouncedSearch, setDebouncedSearch] = useState(searchQuery);
263773
- const [selectedUser, setSelectedUser] = useState(null);
263774
- // Same debounce contract as the Management tab's user search: terms shorter
263775
- // than three characters search as empty. Bailing out on an unchanged value
263776
- // keeps the mount-time timer from resetting a page the user already turned.
263777
- useEffect(() => {
263778
- const handler = setTimeout(() => {
263779
- setDebouncedSearch((previous) => {
263780
- const next = searchQuery.length > 2 ? searchQuery : '';
263781
- return previous === next ? previous : next;
263782
- });
263783
- }, SEARCH_DEBOUNCE_MS);
263784
- return () => clearTimeout(handler);
263785
- }, [searchQuery]);
263786
- // A new search term invalidates the current page index.
263787
- useEffect(() => {
263788
- setPage(1);
263789
- }, [debouncedSearch]);
263790
- const { data, isLoading, isFetching, error } = usePlatformUsersQuery({
263791
- platform_key: tenantKey,
263792
- platform_org: tenantKey,
263793
- page,
263794
- page_size: PAGE_SIZE$5,
263795
- query: debouncedSearch,
263796
- return_policies: 'false',
263797
- });
263798
- const users = useMemo(() => {
263799
- var _a;
263800
- // `results` is a bare array unless policies were requested, in which case
263801
- // the users sit under `results.data`.
263802
- const results = data === null || data === void 0 ? void 0 : data.results;
263803
- const platformUsers = Array.isArray(results)
263804
- ? results
263805
- : ((_a = results === null || results === void 0 ? void 0 : results.data) !== null && _a !== void 0 ? _a : []);
263806
- // A user without a username cannot be addressed by the memory endpoints.
263807
- return platformUsers
263808
- .filter((user) => !!user.username)
263809
- .map((user) => ({
263810
- username: user.username,
263811
- name: user.name,
263812
- email: user.email,
263813
- }));
263814
- }, [data]);
263815
- const totalPages = Math.ceil(((_a = data === null || data === void 0 ? void 0 : data.count) !== null && _a !== void 0 ? _a : 0) / PAGE_SIZE$5);
263816
- const isForbidden = !!error && error.status === 403;
263817
- return (jsxs("div", { "data-testid": "memory-admin-global-section", children: [jsxs("div", { className: "relative mb-6 max-w-sm w-full sm:w-auto", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { "data-testid": "memory-admin-users-search", type: "text", value: searchQuery, onChange: (event) => setSearchQuery(event.target.value), placeholder: t('memoryAdminTab.searchUsersPlaceholder'), className: "pl-10 pr-10 focus:ring-blue-500 focus:border-blue-500 h-[35px]", "aria-label": t('memoryAdminTab.searchUsersAriaLabel') }), searchQuery.length > 0 && (searchQuery !== debouncedSearch || isFetching) && (jsx(LoaderCircle, { "data-testid": "user-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" }))] }), isForbidden ? (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('memoryAdminTab.forbidden') }) })) : 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-[28%]", children: t('memoryAdminTab.nameColumn') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[26%]", children: t('memoryAdminTab.usernameColumn') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[30%]", children: t('memoryAdminTab.emailColumn') }), jsx("th", { className: "px-6 py-3 text-right font-medium text-gray-500 dark:text-gray-400 w-[16%]", children: t('memoryAdminTab.actionsColumn') })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [users.map((user) => (jsxs("tr", { "data-testid": `memory-admin-user-row-${user.username}`, children: [jsx("td", { className: "px-6 py-4 text-gray-900 dark:text-gray-100 max-w-0", children: jsx("div", { className: "truncate font-medium", children: user.name || '—' }) }), jsx("td", { className: "px-6 py-4 text-gray-600 dark:text-gray-300 max-w-0", children: jsx("div", { className: "truncate", children: user.username }) }), jsx("td", { className: "px-6 py-4 text-gray-600 dark:text-gray-300 max-w-0", children: jsx("div", { className: "truncate", children: user.email || '—' }) }), jsx("td", { className: "px-6 py-4", children: jsx("div", { className: "flex justify-end gap-2", children: jsx(Button$1, { "data-testid": `memory-admin-user-view-${user.username}`, variant: "ghost", size: "sm", "aria-label": t('memoryAdminTab.viewMemoriesAriaLabel', {
263818
- name: user.email || user.username,
263819
- }), onClick: () => setSelectedUser(user), children: jsx(Eye, { className: "h-4 w-4" }) }) }) })] }, user.username))), users.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: 4, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: isFetching ? t('memoryAdminTab.loading') : t('memoryAdminTab.noUsersFound') }) }))] })] }) }), totalPages > 1 && (jsx("div", { className: "mt-6", children: jsx(IblPagination, { totalPages: totalPages, currentPage: page, onPageChange: setPage, disabled: isFetching }) }))] })), selectedUser && (jsx(UserMemoriesModal, { isOpen: !!selectedUser, onClose: () => setSelectedUser(null), tenantKey: tenantKey, adminUsername: username, user: selectedUser }))] }));
263820
- }
263821
-
263822
- const EditMemoryModal$1 = dynamic(() => Promise.resolve().then(function () { return editMemoryModal; }).then((module) => ({
263823
- default: module.EditMemoryModal,
263824
- })), { ssr: false });
263825
- const AddMemoryModal$1 = dynamic(() => Promise.resolve().then(function () { return addMemoryModal; }).then((module) => ({
263826
- default: module.AddMemoryModal,
263827
- })), { ssr: false });
263828
- const DeleteMemoryModal = dynamic(() => Promise.resolve().then(function () { return deleteMemoryModal; }).then((module) => ({
263829
- default: module.DeleteMemoryModal,
263830
- })), { ssr: false });
263831
- const BulkDeleteMemoryModal$1 = dynamic(() => Promise.resolve().then(function () { return bulkDeleteMemoryModal; }).then((module) => ({
263832
- default: module.BulkDeleteMemoryModal,
263833
- })), { ssr: false });
263834
- const ManageCategoriesModal$1 = dynamic(() => Promise.resolve().then(function () { return manageCategoriesModal; }).then((module) => ({
263835
- default: module.ManageCategoriesModal,
263836
- })), { ssr: false });
263837
- const PAGE_SIZE$4 = 20;
263838
- const SNAPSHOT_PAGE_SIZE = 1000;
263839
- function ManageMemories({ tenantKey, username, mentorId }) {
263840
- var _a, _b, _c, _d, _e;
263841
- const t = useT();
263842
- const [selectedLearner, setSelectedLearner] = useState('');
263843
- const [dateRange, setDateRange] = useState(undefined);
263844
- const [selectedCategorySlug, setSelectedCategorySlug] = useState('all');
263845
- const [page, setPage] = useState(1);
263846
- // Reset to page 1 whenever any filter changes — otherwise we could land on a
263847
- // page index that no longer exists in the new result set.
263848
- useEffect(() => {
263849
- setPage(1);
263850
- }, [selectedLearner, dateRange, selectedCategorySlug]);
263851
- const listParams = useMemo(() => {
263852
- const params = { page, page_size: PAGE_SIZE$4 };
263853
- if (selectedLearner)
263854
- params.email = selectedLearner;
263855
- if (selectedCategorySlug !== 'all')
263856
- params.category = selectedCategorySlug;
263857
- if (dateRange === null || dateRange === void 0 ? void 0 : dateRange.from)
263858
- params.start_date = format$1(dateRange.from, 'yyyy-MM-dd');
263859
- if (dateRange === null || dateRange === void 0 ? void 0 : dateRange.to)
263860
- params.end_date = format$1(dateRange.to, 'yyyy-MM-dd');
263861
- return params;
263862
- }, [page, selectedLearner, selectedCategorySlug, dateRange]);
263863
- const { data: listResponse, isLoading: isLoadingMemories } = useGetMentorMemoriesListQuery({
263864
- org: tenantKey,
263865
- userId: username !== null && username !== void 0 ? username : '',
263866
- mentorId,
263867
- params: listParams,
263868
- }, {
263869
- skip: !tenantKey || !username || !mentorId,
263870
- });
263871
- const totalPages = Math.max(1, Math.ceil(((_a = listResponse === null || listResponse === void 0 ? void 0 : listResponse.count) !== null && _a !== void 0 ? _a : 0) / PAGE_SIZE$4));
263872
- const { data: adminCategories } = useGetMemoryCategoriesAdminQuery({
263873
- org: tenantKey,
263874
- mentorId,
263875
- }, {
263876
- skip: !tenantKey || !mentorId,
263877
- });
263878
- const [deleteMentorMemory, { isLoading: isDeleting }] = useDeleteMentorMemoryMutation();
263879
- const [updateMentorMemory, { isLoading: isEditing }] = useUpdateMentorMemoryMutation();
263880
- const [createMentorMemory, { isLoading: isSaving }] = useCreateMentorMemoryMutation();
263881
- // Flat list of memories on the current page, mapped into the local `Memory`
263882
- // shape used by the rest of this component.
263883
- const memories = useMemo(() => {
263884
- if (!(listResponse === null || listResponse === void 0 ? void 0 : listResponse.results))
263885
- return [];
263886
- return listResponse.results.map((memory) => ({
263887
- id: memory.id,
263888
- content: memory.content,
263889
- category: {
263890
- id: memory.category.id,
263891
- name: memory.category.name,
263892
- slug: memory.category.slug,
263893
- },
263894
- email: memory.email,
263895
- createdAt: memory.created_at,
263896
- }));
263897
- }, [listResponse]);
263898
- // Unfiltered snapshot used to derive the learner dropdown and to source the
263899
- // bulk-delete operation, which needs the full set of memories — not just the
263900
- // current page.
263901
- const { data: snapshotResponse } = useGetMentorMemoriesListQuery({
263902
- org: tenantKey,
263903
- userId: username !== null && username !== void 0 ? username : '',
263904
- mentorId,
263905
- params: { page: 1, page_size: SNAPSHOT_PAGE_SIZE },
263906
- }, {
263907
- skip: !tenantKey || !username || !mentorId,
263908
- });
263909
- const learners = useMemo(() => {
263910
- if (!(snapshotResponse === null || snapshotResponse === void 0 ? void 0 : snapshotResponse.results))
263911
- return [];
263912
- const emailSet = new Set();
263913
- snapshotResponse.results.forEach((m) => {
263914
- if (m.email)
263915
- emailSet.add(m.email);
263916
- });
263917
- return Array.from(emailSet).map((email) => ({ email }));
263918
- }, [snapshotResponse]);
263919
- const categories = useMemo(() => {
263920
- if (adminCategories && adminCategories.length > 0) {
263921
- return [
263922
- { id: 0, name: 'All', slug: 'all' },
263923
- ...adminCategories.map((cat) => ({
263924
- id: cat.id,
263925
- name: cat.name,
263926
- slug: cat.slug,
263927
- })),
263928
- ];
263929
- }
263930
- return [{ id: 0, name: 'All', slug: 'all' }];
263931
- }, [adminCategories]);
263932
- const [editingMemory, setEditingMemory] = useState(null);
263933
- const [editContent, setEditContent] = useState('');
263934
- const [editCategory, setEditCategory] = useState('');
263935
- const [showDeleteConfirm, setShowDeleteConfirm] = useState(null);
263936
- const [showAddMemory, setShowAddMemory] = useState(false);
263937
- const [newMemoryContent, setNewMemoryContent] = useState('');
263938
- const [newMemoryCategory, setNewMemoryCategory] = useState('');
263939
- const [showMobileDropdown, setShowMobileDropdown] = useState(false);
263940
- const [showBulkDeleteConfirm, setShowBulkDeleteConfirm] = useState(false);
263941
- const [isBulkDeleting, setIsBulkDeleting] = useState(false);
263942
- const [showManageCategories, setShowManageCategories] = useState(false);
263943
- const selectedCategoryName = (_c = (_b = categories.find((c) => c.slug === selectedCategorySlug)) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : t('memoryTabManageMemories.all');
263944
- const VISIBLE_CATEGORY_LIMIT = 6;
263945
- const visibleCategories = categories.slice(0, VISIBLE_CATEGORY_LIMIT);
263946
- const overflowCategories = categories.slice(VISIBLE_CATEGORY_LIMIT);
263947
- const overflowSelected = overflowCategories.find((c) => c.slug === selectedCategorySlug);
263948
- // Category is filtered server-side via the `category` query param now, so
263949
- // `memories` already contains only the relevant entries for the page.
263950
- const filteredMemories = memories;
263951
- const handleDeleteMemory = async (id) => {
263952
- if (!tenantKey || !username)
263953
- return;
263954
- try {
263955
- await deleteMentorMemory({
263956
- org: tenantKey,
263957
- userId: username,
263958
- mentorId,
263959
- memoryId: id,
263960
- }).unwrap();
263961
- setShowDeleteConfirm(null);
263962
- toast.success(t('memoryTabManageMemories.memoryDeletedSuccessfully'));
263963
- }
263964
- catch (error) {
263965
- console.error('Failed to delete memory:', error);
263966
- toast.error(t('memoryTabManageMemories.failedToDeleteMemory'));
263967
- }
263968
- };
263969
- const handleBulkDelete = async () => {
263970
- var _a;
263971
- if (!tenantKey || !username)
263972
- return;
263973
- setIsBulkDeleting(true);
263974
- try {
263975
- // Source bulk-delete from the unfiltered snapshot — `memories` only holds
263976
- // the current page, while bulk delete must remove every entry in the
263977
- // selected category.
263978
- const memoriesToDelete = ((_a = snapshotResponse === null || snapshotResponse === void 0 ? void 0 : snapshotResponse.results) !== null && _a !== void 0 ? _a : []).filter((memory) => memory.category.slug === selectedCategorySlug);
263979
- await Promise.all(memoriesToDelete.map((memory) => deleteMentorMemory({
263980
- org: tenantKey,
263981
- userId: username,
263982
- mentorId,
263983
- memoryId: memory.id,
263984
- }).unwrap()));
263985
- toast.success(t('memoryTabManageMemories.allCategoryMemoriesDeleted', { category: selectedCategoryName }));
263986
- setShowBulkDeleteConfirm(false);
263987
- }
263988
- catch (error) {
263989
- console.error('Failed to delete memories:', error);
263990
- toast.error(t('memoryTabManageMemories.failedToDeleteMemories'));
263991
- }
263992
- finally {
263993
- setIsBulkDeleting(false);
263994
- }
263995
- };
263996
- const startEdit = (memory) => {
263997
- setEditingMemory(memory);
263998
- setEditContent(memory.content);
263999
- setEditCategory(memory.category.name);
264000
- };
264001
- const saveEdit = async () => {
264002
- if (!editingMemory || !tenantKey || !username)
264003
- return;
264004
- try {
264005
- const selectedCat = categories.find((c) => c.name === editCategory);
264006
- const categoryChanged = !!selectedCat && selectedCat.slug !== editingMemory.category.slug;
264007
- await updateMentorMemory({
264008
- org: tenantKey,
264009
- userId: username,
264010
- mentorId,
264011
- memoryId: editingMemory.id,
264012
- data: {
264013
- content: editContent,
264014
- ...(categoryChanged ? { category_slug: selectedCat.slug } : {}),
264015
- },
264016
- }).unwrap();
264017
- toast.success(t('memoryTabManageMemories.memoryUpdatedSuccessfully'));
264018
- // Follow the entry to its new category tab so the user doesn't lose
264019
- // sight of it. Skip when viewing "All" — the entry is still visible.
264020
- if (categoryChanged && selectedCategorySlug !== 'all') {
264021
- setSelectedCategorySlug(selectedCat.slug);
264022
- }
264023
- setEditingMemory(null);
264024
- setEditContent('');
264025
- setEditCategory('');
264026
- }
264027
- catch (error) {
264028
- console.error('Failed to update memory:', error);
264029
- toast.error(t('memoryTabManageMemories.failedToUpdateMemory'));
264030
- }
264031
- };
264032
- const cancelEdit = () => {
264033
- setEditingMemory(null);
264034
- setEditContent('');
264035
- setEditCategory('');
264036
- };
264037
- const startAddMemory = () => {
264038
- setShowAddMemory(true);
264039
- setNewMemoryCategory(selectedCategoryName);
264040
- };
264041
- const saveNewMemory = async () => {
264042
- var _a;
264043
- if (!newMemoryContent.trim() || !tenantKey || !username)
264044
- return;
264045
- try {
264046
- const selectedCat = categories.find((c) => c.name === newMemoryCategory);
264047
- const categorySlug = (_a = selectedCat === null || selectedCat === void 0 ? void 0 : selectedCat.slug) !== null && _a !== void 0 ? _a : selectedCategorySlug;
264048
- await createMentorMemory({
264049
- org: tenantKey,
264050
- userId: username,
264051
- mentorId,
264052
- data: {
264053
- category_slug: categorySlug === 'all' ? 'general' : categorySlug,
264054
- content: newMemoryContent.trim(),
264055
- },
264056
- }).unwrap();
264057
- setShowAddMemory(false);
264058
- setNewMemoryContent('');
264059
- setNewMemoryCategory('');
264060
- if (selectedCat) {
264061
- setSelectedCategorySlug(selectedCat.slug);
264062
- }
264063
- toast.success(t('memoryTabManageMemories.memoryCreatedSuccessfully'));
264064
- }
264065
- catch (error) {
264066
- console.error('Failed to create memory:', error);
264067
- toast.error(t('memoryTabManageMemories.failedToCreateMemory'));
264068
- }
264069
- };
264070
- const cancelAddMemory = () => {
264071
- setShowAddMemory(false);
264072
- setNewMemoryContent('');
264073
- setNewMemoryCategory('');
264074
- };
264075
- const categoryNames = categories.map((c) => c.name);
264076
- return (jsxs(Fragment$1, { children: [jsxs("div", { className: "space-y-6", children: [jsx("div", { className: "rounded-lg border p-4", children: jsxs("div", { className: "flex flex-col gap-3 lg:flex-row", children: [jsx("div", { className: "relative min-w-[200px] flex-1", children: jsxs(Popover, { children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", role: "combobox", "aria-label": t('memoryTabManageMemories.searchForUser'), className: "w-full justify-between bg-transparent font-normal", children: [selectedLearner
264077
- ? ((_e = (_d = learners.find((learner) => learner.email === selectedLearner)) === null || _d === void 0 ? void 0 : _d.email) !== null && _e !== void 0 ? _e : selectedLearner)
264078
- : t('memoryTabManageMemories.searchForUser'), jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })] }) }), jsx(PopoverContent, { className: "w-full p-0", align: "start", children: jsxs(Command, { children: [jsx(CommandInput, { placeholder: t('memoryTabManageMemories.searchUsersPlaceholder') }), jsxs(CommandList, { children: [jsx(CommandEmpty, { children: t('memoryTabManageMemories.noUsersFound') }), jsxs(CommandGroup, { children: [jsxs(CommandItem, { value: "", onSelect: () => {
264079
- setSelectedLearner('');
264080
- }, children: [jsx(Check, { className: cn('mr-2 h-4 w-4', !selectedLearner ? 'opacity-100' : 'opacity-0') }), t('memoryTabManageMemories.allUsers')] }), learners.map((learner) => (jsxs(CommandItem, { value: learner.email, onSelect: () => {
264081
- setSelectedLearner(learner.email);
264082
- }, children: [jsx(Check, { className: cn('mr-2 h-4 w-4', selectedLearner === learner.email ? 'opacity-100' : 'opacity-0') }), jsx("div", { className: "flex flex-col", children: jsx("span", { className: "font-medium text-gray-700", children: learner.email }) })] }, learner.email)))] })] })] }) })] }) }), jsxs(Popover, { children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", className: "flex w-full items-center gap-2 bg-transparent 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)
264083
- ? `${format$1(dateRange.from, 'MMM dd')} - ${format$1(dateRange.to, 'MMM dd')}`
264084
- : t('memoryTabManageMemories.pickDateRange')] }) }), jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: jsx(Calendar, { mode: "range", selected: dateRange, onSelect: setDateRange, numberOfMonths: 2, initialFocus: true }) })] })] }) }), jsx("div", { children: jsxs("div", { className: "flex items-center justify-between gap-4", children: [jsxs("div", { className: "scrollbar-none hidden flex-1 items-center space-x-8 overflow-x-auto sm:flex", children: [visibleCategories.map((category) => (jsxs("button", { onClick: () => setSelectedCategorySlug(category.slug), className: `relative px-1 py-2 text-sm font-medium whitespace-nowrap transition-colors ${selectedCategorySlug === category.slug
264085
- ? 'text-[#38A1E5]'
264086
- : 'text-gray-600 hover:text-gray-900'}`, children: [category.name, selectedCategorySlug === category.slug && (jsx("div", { className: "absolute bottom-0 left-1/2 h-0.5 -translate-x-1/2 transform bg-[#38A1E5] transition-all duration-200", style: { width: `${category.name.length * 0.55}em` } }))] }, category.slug))), overflowCategories.length > 0 && (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs("button", { className: cn('relative flex items-center gap-1 px-1 py-2 text-sm font-medium whitespace-nowrap transition-colors', overflowSelected ? 'text-[#38A1E5]' : 'text-gray-600 hover:text-gray-900'), "aria-label": t('memoryTabManageMemories.moreCategories'), children: [overflowSelected ? overflowSelected.name : t('memoryTabManageMemories.more'), jsx(ChevronDown, { className: "h-3.5 w-3.5" }), overflowSelected && (jsx("div", { className: "absolute bottom-0 left-0 h-0.5 bg-[#38A1E5] transition-all duration-200", style: {
264087
- width: `${overflowSelected.name.length * 0.55}em`,
264088
- } }))] }) }), jsx(DropdownMenuContent, { align: "end", children: overflowCategories.map((category) => (jsx(DropdownMenuItem, { onClick: () => setSelectedCategorySlug(category.slug), className: selectedCategorySlug === category.slug ? 'bg-gray-100' : '', children: category.name }, category.slug))) })] }))] }), jsx("div", { className: "w-full py-2 sm:hidden", children: jsxs(DropdownMenu, { open: showMobileDropdown, onOpenChange: setShowMobileDropdown, children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", className: "w-full justify-between bg-transparent", children: [selectedCategoryName, jsx(ChevronDown, { className: "h-4 w-4" })] }) }), jsx(DropdownMenuContent, { className: "w-full", children: categories.map((category) => (jsx(DropdownMenuItem, { onClick: () => {
264089
- setSelectedCategorySlug(category.slug);
264090
- setShowMobileDropdown(false);
264091
- }, className: selectedCategorySlug === category.slug ? 'bg-gray-100' : '', children: category.name }, category.slug))) })] }) }), jsxs(Button$1, { onClick: () => setShowManageCategories(true), size: "sm", variant: "outline", className: "shrink-0", "aria-label": t('memoryTabManageMemories.manageCategories'), children: [jsx(Tags, { className: "h-4 w-4 sm:mr-2" }), jsx("span", { className: "hidden sm:inline", children: t('memoryTabManageMemories.categories') })] }), jsxs(Button$1, { onClick: startAddMemory, size: "sm", className: "ibl-button-primary shrink-0", children: [jsx(Plus, { className: "mr-1 h-4 w-4 sm:mr-2" }), jsx("span", { className: "hidden sm:inline", children: t('memoryTabManageMemories.addMemory') }), jsx("span", { className: "sm:hidden", children: t('memoryTabManageMemories.add') })] })] }) }), jsx("div", { className: "space-y-3 px-1 sm:px-0", children: isLoadingMemories ? (jsx("div", { className: "py-8 text-center text-gray-600", children: jsx("p", { children: t('memoryTabManageMemories.loadingMemories') }) })) : (filteredMemories.map((memory) => {
264092
- const timeAgo = memory.createdAt
264093
- ? formatDistanceToNow(new Date(memory.createdAt), {
264094
- addSuffix: true,
264095
- })
264096
- : '';
264097
- const displayUser = memory.email || t('memoryTabManageMemories.unknown');
264098
- return (jsxs("div", { className: "flex items-start gap-3 rounded-lg border border-gray-200 bg-white p-3", children: [jsxs("div", { className: "flex-1", children: [(timeAgo || displayUser) && (jsxs("div", { className: "mb-2 flex items-center justify-between", children: [timeAgo && jsx("span", { className: "text-sm text-gray-600", children: timeAgo }), displayUser && (jsx("span", { className: "max-w-[100px] truncate text-sm text-gray-900 sm:max-w-[200px]", children: displayUser }))] })), jsx("div", { className: "text-sm leading-relaxed text-gray-900", children: memory.content })] }), jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { variant: "ghost", size: "sm", className: "h-6 w-6 flex-shrink-0 p-0 text-gray-600 hover:text-gray-900", children: jsx(Ellipsis, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsx(DropdownMenuItem, { onClick: () => startEdit(memory), children: t('memoryTabManageMemories.edit') }), jsx(DropdownMenuItem, { onClick: () => setShowDeleteConfirm(memory.id), children: t('memoryTabManageMemories.delete') })] })] })] }, memory.id));
264099
- })) }), filteredMemories.length > 0 && selectedCategorySlug !== 'all' && (jsx("div", { className: "flex justify-end", children: jsx(Button$1, { variant: "outline", onClick: () => setShowBulkDeleteConfirm(true), children: t('memoryTabManageMemories.deleteAll') }) })), filteredMemories.length === 0 && !isLoadingMemories && (jsx("div", { className: "py-8 text-center text-gray-600", children: jsx("p", { children: t('memoryTabManageMemories.noSavedMemories') }) })), totalPages > 1 && (jsx("div", { className: "flex justify-center pt-2", children: jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: isLoadingMemories }) }))] }), jsx(EditMemoryModal$1, { open: !!editingMemory, onOpenChange: (open) => !open && cancelEdit(), editContent: editContent, editCategory: editCategory, onContentChange: setEditContent, onCategoryChange: setEditCategory, onSave: saveEdit, onCancel: cancelEdit, categories: categoryNames, isSaving: isEditing }), jsx(AddMemoryModal$1, { open: showAddMemory, onOpenChange: (open) => !open && cancelAddMemory(), newMemoryContent: newMemoryContent, newMemoryCategory: newMemoryCategory, onContentChange: setNewMemoryContent, onCategoryChange: setNewMemoryCategory, onSave: saveNewMemory, onCancel: cancelAddMemory, categories: categoryNames, isSaving: isSaving }), jsx(DeleteMemoryModal, { open: !!showDeleteConfirm, onOpenChange: (open) => !open && setShowDeleteConfirm(null), onConfirm: () => showDeleteConfirm !== null && handleDeleteMemory(showDeleteConfirm), onCancel: () => setShowDeleteConfirm(null), isDeleting: isDeleting }), jsx(ManageCategoriesModal$1, { open: showManageCategories, onOpenChange: setShowManageCategories, tenantKey: tenantKey, mentorId: mentorId }), jsx(BulkDeleteMemoryModal$1, { open: showBulkDeleteConfirm, onOpenChange: setShowBulkDeleteConfirm, onConfirm: handleBulkDelete, onCancel: () => setShowBulkDeleteConfirm(false), isDeleting: isBulkDeleting, selectedCategory: selectedCategoryName })] }));
264100
- }
264101
-
264102
- /**
264103
- * Popup hosting the same memory manager the agent settings modal renders —
264104
- * learner/category/date filters and full CRUD included — for one agent.
264105
- * Laid out like the Billing tab's agent-limits popup: a fixed divider header
264106
- * and a body that scrolls vertically while the content fits the width.
264107
- */
264108
- function AgentMemoriesModal({ isOpen, onClose, tenantKey, username, agent, }) {
264109
- const t = useT();
264110
- return (jsx(Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: jsxs(DialogContent, { "data-testid": "agent-memories-modal", "aria-label": "agent-memories", className: "flex max-h-[90vh] w-[calc(100vw-2rem)] flex-col gap-0 overflow-hidden p-0 sm:max-w-4xl", children: [jsxs(DialogHeader, { className: "flex-shrink-0 border-b border-gray-200 px-6 py-4 pr-12", children: [jsx(DialogTitle, { className: "ibl-dialog-title", children: agent.name }), jsx(DialogDescription, { children: t('memoryAdminAgentMemoriesModal.description') })] }), jsx("div", { className: "min-h-0 flex-1 overflow-y-auto p-3 lg:p-4", children: jsx("div", { className: "space-y-8", children: jsx(ManageMemories, { tenantKey: tenantKey, username: username, mentorId: agent.unique_id }) }) })] }) }));
264111
- }
264112
-
264113
- const PAGE_SIZE$3 = 10;
264114
- /**
264115
- * Agents table filtered by the same agent autocomplete the Billing tab's
264116
- * Agent Limits section uses. Opening a row shows that agent's memories in a
264117
- * popup hosting the same manager the agent settings modal uses.
264118
- */
264119
- function AgentMemoriesSection({ tenantKey, username }) {
264120
- var _a;
264121
- const t = useT();
264122
- const [page, setPage] = useState(1);
264123
- const [agentFilter, setAgentFilter] = useState(null);
264124
- const [agentSearch, setAgentSearch] = useState('');
264125
- const [debouncedAgentSearch] = a$3(agentSearch, 300);
264126
- const [selectedAgent, setSelectedAgent] = useState(null);
264127
- // A new filter invalidates the current page index.
264128
- useEffect(() => {
264129
- setPage(1);
264130
- }, [agentFilter]);
264131
- // Autocomplete options for the filter, fetched once two characters are in.
264132
- const shouldSearchAgents = Boolean(tenantKey && debouncedAgentSearch.trim().length >= 2);
264133
- const { data: searchResponse, isFetching: isSearchingAgents } = useGetMentorsQuery({ org: tenantKey, username, limit: 20, query: debouncedAgentSearch.trim() }, { skip: !shouldSearchAgents });
264134
- const agentOptions = useMemo(() => {
264135
- var _a;
264136
- return ((_a = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.results) !== null && _a !== void 0 ? _a : [])
264137
- .filter((mentor) => Boolean(mentor.unique_id))
264138
- .map((mentor) => ({
264139
- value: mentor.unique_id,
264140
- label: mentor.name || mentor.unique_id,
264141
- }));
264142
- }, [searchResponse]);
264143
- const { data, isLoading, isFetching, error } = useGetMentorsQuery({
264144
- org: tenantKey,
264145
- username,
264146
- limit: PAGE_SIZE$3,
264147
- offset: (page - 1) * PAGE_SIZE$3,
264148
- ...(agentFilter ? { uniqueId: agentFilter.value } : {}),
264149
- });
264150
- const agents = ((_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : []);
264151
- const totalPages = (data === null || data === void 0 ? void 0 : data.count) ? Math.ceil(data.count / PAGE_SIZE$3) : 0;
264152
- const isForbidden = !!error && error.status === 403;
264153
- return (jsxs("div", { "data-testid": "memory-admin-agent-section", children: [jsx("div", { className: "mb-6 max-w-sm", children: jsx(SearchSelect, { labels: {
264154
- // No field label — the users tab's search carries none either.
264155
- label: '',
264156
- placeholder: t('memoryAdminTab.filter.placeholder'),
264157
- typeToSearch: t('memoryAdminTab.filter.typeToSearch'),
264158
- searching: t('memoryAdminTab.filter.searching'),
264159
- noResults: t('memoryAdminTab.filter.noResults'),
264160
- clear: t('memoryAdminTab.filter.clear'),
264161
- }, selected: agentFilter, onSelect: (option) => {
264162
- setAgentFilter(option);
264163
- setAgentSearch('');
264164
- }, onClear: () => setAgentFilter(null), searchTerm: agentSearch, onSearchTermChange: setAgentSearch, options: agentOptions, isLoading: isSearchingAgents, testId: "agent-memories-filter" }) }), isForbidden ? (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('memoryAdminTab.forbidden') }) })) : 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-[32%]", children: t('memoryAdminTab.agentColumn') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[52%]", children: t('memoryAdminTab.descriptionColumn') }), jsx("th", { className: "px-6 py-3 text-right font-medium text-gray-500 dark:text-gray-400 w-[16%]", children: t('memoryAdminTab.actionsColumn') })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [agents.map((agent) => (jsxs("tr", { "data-testid": `memory-admin-agent-row-${agent.unique_id}`, children: [jsx("td", { className: "px-6 py-4 text-gray-900 dark:text-gray-100 max-w-0", children: jsx("div", { className: "truncate font-medium", children: agent.name }) }), jsx("td", { className: "px-6 py-4 text-gray-600 dark:text-gray-300 max-w-0", children: jsx("div", { className: "truncate", children: agent.description || '—' }) }), jsx("td", { className: "px-6 py-4", children: jsx("div", { className: "flex justify-end gap-2", children: jsx(Button$1, { "data-testid": `memory-admin-agent-view-${agent.unique_id}`, variant: "ghost", size: "sm", "aria-label": t('memoryAdminTab.viewMemoriesAriaLabel', {
264165
- name: agent.name,
264166
- }), onClick: () => setSelectedAgent(agent), children: jsx(Eye, { className: "h-4 w-4" }) }) }) })] }, agent.unique_id))), agents.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: isFetching ? t('memoryAdminTab.loading') : t('memoryAdminTab.noAgentsFound') }) }))] })] }) }), totalPages > 1 && (jsx("div", { className: "mt-6", children: jsx(IblPagination, { totalPages: totalPages, currentPage: page, onPageChange: setPage, disabled: isFetching }) }))] })), selectedAgent && (jsx(AgentMemoriesModal, { isOpen: !!selectedAgent, onClose: () => setSelectedAgent(null), tenantKey: tenantKey, username: username, agent: selectedAgent }))] }));
264167
- }
264168
-
264169
- /**
264170
- * Tenant-settings Memory tab. Lets admins/RBAC-granted users manage other
264171
- * users' global memories and per-agent memories from one place, mirroring the
264172
- * Billing tab's sub-tab layout.
264173
- */
264174
- function MemoryAdminTab({ tenantKey, username }) {
264175
- const t = useT();
264176
- // Same platform gate the profile memory tab applies: when memsearch is off
264177
- // for the tenant there is nothing to manage.
264178
- const { data: memsearchStatus, isLoading, isError, } = useGetMemsearchStatusQuery({ org: tenantKey, userId: username });
264179
- if (isLoading) {
264180
- return (jsxs("div", { className: "space-y-6", children: [jsx(Skeleton, { className: "h-10 w-full max-w-sm rounded-lg" }), jsx(Skeleton, { className: "h-40 w-full rounded-lg" })] }));
264181
- }
264182
- if (!isError && memsearchStatus && !memsearchStatus.enable_memsearch) {
264183
- 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('memoryAdminTab.featureDisabled') }) }) }));
264184
- }
264185
- return (jsxs(Tabs, { defaultValue: "global-memories", "aria-label": t('memoryAdminTab.tabsAriaLabel'), children: [jsxs(TabsList, { "aria-label": t('memoryAdminTab.tabsAriaLabel'), className: "max-w-full overflow-x-auto justify-start px-1", children: [jsx(TabsTrigger, { "data-testid": "memory-admin-sub-tab-global", value: "global-memories", children: t('memoryAdminTab.tabGlobalMemories') }), jsx(TabsTrigger, { "data-testid": "memory-admin-sub-tab-agent", value: "agent-memories", children: t('memoryAdminTab.tabAgentMemories') })] }), jsx(TabsContent, { className: "mt-4", value: "global-memories", children: jsx(GlobalMemoriesSection, { tenantKey: tenantKey, username: username }) }), jsx(TabsContent, { className: "mt-4", value: "agent-memories", children: jsx(AgentMemoriesSection, { tenantKey: tenantKey, username: username }) })] }));
264186
- }
264187
-
264188
264206
  function Account({ tenant, tenants = [], username, onInviteClick, email, mainPlatformKey, userActiveApp = null, showPlatformName = false, isAdmin = false, targetTab = 'basic', currentPlan: _currentPlan = '', currentSPA = '', authURL, onTenantUpdate, currentPlatformBaseDomain = '', enableRbac = false, showBenchmarks = false, rbacPermissions = {}, onLoadGroupPermissions, onTabChange, defaultSupportPhone = '', enableSupportPhone, showGradebookTab = false, onboardingBasePath = '', }) {
264189
264207
  var _a, _b, _c, _d;
264190
264208
  const t = useT();
@@ -287248,6 +287266,175 @@ function AgentTasksTab({ PaginationComponent = DefaultTasksPagination, labels: l
287248
287266
  }, selectedLog: selectedLog, labels: labels }))] }));
287249
287267
  }
287250
287268
 
287269
+ function EditMemoryModal({ open, onOpenChange, editContent, editCategory, onContentChange, onCategoryChange, onSave, onCancel, categories, isSaving, }) {
287270
+ const t = useT();
287271
+ return (jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: jsxs(DialogContent, { className: "mx-4 max-w-2xl sm:mx-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "text-gray-700", children: t('memoryTabEditMemoryModal.editMemory') }) }), jsxs("div", { className: "mt-4 space-y-4", children: [jsxs("div", { children: [jsx("label", { className: "text-sm font-medium text-gray-600", children: t('memoryTabEditMemoryModal.category') }), jsxs(Select$1, { value: editCategory, onValueChange: onCategoryChange, children: [jsx(SelectTrigger, { className: "mt-1", children: jsx(SelectValue, { placeholder: t('memoryTabEditMemoryModal.selectCategory') }) }), jsx(SelectContent, { children: categories
287272
+ .filter((cat) => cat !== 'All')
287273
+ .map((category) => (jsx(SelectItem, { value: category, children: category }, category))) })] })] }), jsxs("div", { children: [jsx("label", { className: "text-sm font-medium text-gray-600", children: t('memoryTabEditMemoryModal.memory') }), jsx(Textarea, { value: editContent, onChange: (e) => onContentChange(e.target.value), placeholder: t('memoryTabEditMemoryModal.enterMemoryContent'), className: "mt-1" }), jsx("p", { className: "mt-1 text-xs text-gray-500", children: editContent.trim().length < 10
287274
+ ? t('memoryTabEditMemoryModal.charCountMinimum', {
287275
+ count: editContent.trim().length,
287276
+ })
287277
+ : t('memoryTabEditMemoryModal.charCount', { count: editContent.trim().length }) })] }), jsxs("div", { className: "flex justify-end gap-2", children: [jsx(Button$1, { variant: "outline", onClick: onCancel, children: t('memoryTabEditMemoryModal.cancel') }), jsx(Button$1, { onClick: onSave, className: "ibl-button-primary", disabled: editContent.trim().length < 10 || isSaving, children: isSaving ? t('memoryTabEditMemoryModal.saving') : t('memoryTabEditMemoryModal.save') })] })] })] }) }));
287278
+ }
287279
+
287280
+ var editMemoryModal = /*#__PURE__*/Object.freeze({
287281
+ __proto__: null,
287282
+ EditMemoryModal: EditMemoryModal
287283
+ });
287284
+
287285
+ function AddMemoryModal({ open, onOpenChange, newMemoryContent, newMemoryCategory, onContentChange, onCategoryChange, onSave, onCancel, categories, isSaving, }) {
287286
+ const t = useT();
287287
+ return (jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: jsxs(DialogContent, { className: "mx-4 max-w-2xl sm:mx-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "text-gray-700", children: t('memoryTabAddMemoryModal.addMemory') }) }), jsxs("div", { className: "mt-4 space-y-4", children: [jsxs("div", { children: [jsx("label", { className: "text-sm font-medium text-gray-600", children: t('memoryTabAddMemoryModal.category') }), jsxs(Select$1, { value: newMemoryCategory, onValueChange: onCategoryChange, children: [jsx(SelectTrigger, { className: "mt-1", children: jsx(SelectValue, { placeholder: t('memoryTabAddMemoryModal.selectCategory') }) }), jsx(SelectContent, { children: categories
287288
+ .filter((cat) => cat !== 'All')
287289
+ .map((category) => (jsx(SelectItem, { value: category, children: category }, category))) })] })] }), jsxs("div", { children: [jsx("label", { className: "text-sm font-medium text-gray-600", children: t('memoryTabAddMemoryModal.memory') }), jsx(Textarea, { value: newMemoryContent, onChange: (e) => onContentChange(e.target.value), placeholder: t('memoryTabAddMemoryModal.enterMemoryContent'), className: "mt-1" }), jsx("p", { className: "mt-1 text-xs text-gray-500", children: newMemoryContent.trim().length < 10
287290
+ ? t('memoryTabAddMemoryModal.charactersMinimum', {
287291
+ count: newMemoryContent.trim().length,
287292
+ })
287293
+ : t('memoryTabAddMemoryModal.characters', {
287294
+ count: newMemoryContent.trim().length,
287295
+ }) })] }), jsxs("div", { className: "flex justify-end gap-2", children: [jsx(Button$1, { variant: "outline", onClick: onCancel, children: t('memoryTabAddMemoryModal.cancel') }), jsx(Button$1, { onClick: onSave, disabled: newMemoryContent.trim().length < 10 || isSaving, className: "ibl-button-primary", children: isSaving ? t('memoryTabAddMemoryModal.saving') : t('memoryTabAddMemoryModal.save') })] })] })] }) }));
287296
+ }
287297
+
287298
+ var addMemoryModal = /*#__PURE__*/Object.freeze({
287299
+ __proto__: null,
287300
+ AddMemoryModal: AddMemoryModal
287301
+ });
287302
+
287303
+ function BulkDeleteMemoryModal({ open, onOpenChange, onConfirm, onCancel, isDeleting, selectedCategory, }) {
287304
+ const isDeleteAll = selectedCategory === 'All';
287305
+ const getConfirmationText = () => {
287306
+ if (isDeleteAll) {
287307
+ return 'Are you sure you want to delete all memories? This action cannot be undone.';
287308
+ }
287309
+ return `Are you sure you want to delete all memories in the ${selectedCategory} category? This action cannot be undone.`;
287310
+ };
287311
+ const getTitle = () => {
287312
+ if (isDeleteAll) {
287313
+ return 'Delete All Memories';
287314
+ }
287315
+ return `Delete All ${selectedCategory} Memories`;
287316
+ };
287317
+ return (jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: jsxs(DialogContent, { className: "mx-4 max-w-md sm:mx-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { children: getTitle() }) }), jsx("p", { className: "text-muted-foreground text-sm", children: getConfirmationText() }), jsxs("div", { className: "mt-4 flex justify-end gap-2", children: [jsx(Button$1, { variant: "outline", onClick: onCancel, disabled: isDeleting, children: "Cancel" }), jsx(Button$1, { className: "ibl-button-primary", onClick: onConfirm, disabled: isDeleting, children: isDeleting ? 'Deleting...' : 'Delete' })] })] }) }));
287318
+ }
287319
+
287320
+ var bulkDeleteMemoryModal = /*#__PURE__*/Object.freeze({
287321
+ __proto__: null,
287322
+ BulkDeleteMemoryModal: BulkDeleteMemoryModal
287323
+ });
287324
+
287325
+ const toSlug = (name) => name
287326
+ .trim()
287327
+ .toLowerCase()
287328
+ .replace(/[^a-z0-9]+/g, '_')
287329
+ .replace(/^_+|_+$/g, '');
287330
+ function ManageCategoriesModal({ open, onOpenChange, tenantKey, mentorId, }) {
287331
+ const t = useT();
287332
+ const { data: categories = [], isLoading } = useGetMemoryCategoriesAdminQuery({ org: tenantKey, mentorId }, { skip: !open || !tenantKey || !mentorId });
287333
+ const [createCategory, { isLoading: isCreating }] = useCreateMemoryCategoryMutation();
287334
+ const [updateCategory, { isLoading: isUpdating }] = useUpdateMemoryCategoryMutation();
287335
+ const [deleteCategory, { isLoading: isDeleting }] = useDeleteMemoryCategoryMutation();
287336
+ const [newName, setNewName] = useState('');
287337
+ const [editingId, setEditingId] = useState(null);
287338
+ const [editName, setEditName] = useState('');
287339
+ const [confirmDeleteId, setConfirmDeleteId] = useState(null);
287340
+ const handleCreate = async () => {
287341
+ const name = newName.trim();
287342
+ if (!name)
287343
+ return;
287344
+ try {
287345
+ await createCategory({
287346
+ org: tenantKey,
287347
+ mentorId,
287348
+ data: { name, slug: toSlug(name) },
287349
+ }).unwrap();
287350
+ setNewName('');
287351
+ toast.success(t('memoryTabManageCategoriesModal.categoryCreated'));
287352
+ }
287353
+ catch (error) {
287354
+ console.error('Failed to create category:', error);
287355
+ toast.error(t('memoryTabManageCategoriesModal.failedToCreateCategory'));
287356
+ }
287357
+ };
287358
+ const startEdit = (category) => {
287359
+ setEditingId(category.id);
287360
+ setEditName(category.name);
287361
+ };
287362
+ const cancelEdit = () => {
287363
+ setEditingId(null);
287364
+ setEditName('');
287365
+ };
287366
+ const saveEdit = async (categoryId) => {
287367
+ const name = editName.trim();
287368
+ if (!name)
287369
+ return;
287370
+ try {
287371
+ await updateCategory({
287372
+ org: tenantKey,
287373
+ mentorId,
287374
+ categoryId,
287375
+ data: { name },
287376
+ }).unwrap();
287377
+ cancelEdit();
287378
+ toast.success(t('memoryTabManageCategoriesModal.categoryUpdated'));
287379
+ }
287380
+ catch (error) {
287381
+ console.error('Failed to update category:', error);
287382
+ toast.error(t('memoryTabManageCategoriesModal.failedToUpdateCategory'));
287383
+ }
287384
+ };
287385
+ const handleDelete = async (categoryId) => {
287386
+ try {
287387
+ await deleteCategory({
287388
+ org: tenantKey,
287389
+ mentorId,
287390
+ categoryId,
287391
+ }).unwrap();
287392
+ setConfirmDeleteId(null);
287393
+ toast.success(t('memoryTabManageCategoriesModal.categoryDeleted'));
287394
+ }
287395
+ catch (error) {
287396
+ console.error('Failed to delete category:', error);
287397
+ toast.error(t('memoryTabManageCategoriesModal.failedToDeleteCategory'));
287398
+ }
287399
+ };
287400
+ return (jsx(Dialog, { open: open, onOpenChange: (next) => {
287401
+ if (!next) {
287402
+ cancelEdit();
287403
+ setConfirmDeleteId(null);
287404
+ setNewName('');
287405
+ }
287406
+ onOpenChange(next);
287407
+ }, children: jsxs(DialogContent, { className: "mx-4 max-w-md sm:mx-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { children: t('memoryTabManageCategoriesModal.manageCategories') }) }), jsxs("div", { className: "flex gap-2", children: [jsx(Input, { value: newName, onChange: (e) => setNewName(e.target.value), placeholder: t('memoryTabManageCategoriesModal.newCategoryNamePlaceholder'), onKeyDown: (e) => {
287408
+ if (e.key === 'Enter') {
287409
+ e.preventDefault();
287410
+ handleCreate();
287411
+ }
287412
+ } }), jsxs(Button$1, { className: "ibl-button-primary", onClick: handleCreate, disabled: !newName.trim() || isCreating, children: [jsx(Plus, { className: "mr-1 h-4 w-4" }), t('memoryTabManageCategoriesModal.add')] })] }), jsx("div", { className: "max-h-[320px] space-y-2 overflow-y-auto", children: isLoading ? (jsx("p", { className: "text-muted-foreground py-4 text-center text-sm", children: t('memoryTabManageCategoriesModal.loadingCategories') })) : categories.length === 0 ? (jsx("p", { className: "text-muted-foreground py-4 text-center text-sm", children: t('memoryTabManageCategoriesModal.noCategoriesYet') })) : (categories.map((category) => {
287413
+ const isEditing = editingId === category.id;
287414
+ const isConfirming = confirmDeleteId === category.id;
287415
+ return (jsx("div", { className: "flex items-center gap-2 rounded-lg border border-gray-200 bg-white p-2", children: isEditing ? (jsxs(Fragment$1, { children: [jsx(Input, { value: editName, onChange: (e) => setEditName(e.target.value), autoFocus: true, onKeyDown: (e) => {
287416
+ if (e.key === 'Enter') {
287417
+ e.preventDefault();
287418
+ saveEdit(category.id);
287419
+ }
287420
+ else if (e.key === 'Escape') {
287421
+ cancelEdit();
287422
+ }
287423
+ }, className: "h-8" }), jsx(Button$1, { variant: "ghost", size: "sm", className: "h-8 w-8 p-0", onClick: () => saveEdit(category.id), disabled: !editName.trim() || isUpdating, "aria-label": t('memoryTabManageCategoriesModal.saveCategory'), children: jsx(Check, { className: "h-4 w-4" }) }), jsx(Button$1, { variant: "ghost", size: "sm", className: "h-8 w-8 p-0", onClick: cancelEdit, "aria-label": t('memoryTabManageCategoriesModal.cancelEdit'), children: jsx(X$2, { className: "h-4 w-4" }) })] })) : isConfirming ? (jsxs(Fragment$1, { children: [jsx("span", { className: "flex-1 text-sm text-gray-900", children: t('memoryTabManageCategoriesModal.confirmDelete', { name: category.name }) }), jsx(Button$1, { variant: "ghost", size: "sm", onClick: () => setConfirmDeleteId(null), children: t('memoryTabManageCategoriesModal.cancel') }), jsx(Button$1, { variant: "destructive", size: "sm", onClick: () => handleDelete(category.id), disabled: isDeleting, children: isDeleting
287424
+ ? t('memoryTabManageCategoriesModal.deleting')
287425
+ : t('memoryTabManageCategoriesModal.delete') })] })) : (jsxs(Fragment$1, { children: [jsx("span", { className: "flex-1 text-sm text-gray-900", children: category.name }), jsx(Button$1, { variant: "ghost", size: "sm", className: "h-8 w-8 p-0", onClick: () => startEdit(category), "aria-label": t('memoryTabManageCategoriesModal.editCategory', {
287426
+ name: category.name,
287427
+ }), children: jsx(Pencil, { className: "h-4 w-4" }) }), jsx(Button$1, { variant: "ghost", size: "sm", className: "h-8 w-8 p-0 text-red-600 hover:text-red-700", onClick: () => setConfirmDeleteId(category.id), "aria-label": t('memoryTabManageCategoriesModal.deleteCategory', {
287428
+ name: category.name,
287429
+ }), children: jsx(Trash2, { className: "h-4 w-4" }) })] })) }, category.id));
287430
+ })) }), jsx("div", { className: "mt-2 flex justify-end", children: jsx(Button$1, { variant: "outline", onClick: () => onOpenChange(false), children: t('memoryTabManageCategoriesModal.done') }) })] }) }));
287431
+ }
287432
+
287433
+ var manageCategoriesModal = /*#__PURE__*/Object.freeze({
287434
+ __proto__: null,
287435
+ ManageCategoriesModal: ManageCategoriesModal
287436
+ });
287437
+
287251
287438
  const defaultValues = {
287252
287439
  category: '',
287253
287440
  prompt: '',
@@ -287620,175 +287807,6 @@ var trainOrDeleteModal = /*#__PURE__*/Object.freeze({
287620
287807
  TrainOrDeleteModal: TrainOrDeleteModal
287621
287808
  });
287622
287809
 
287623
- function EditMemoryModal({ open, onOpenChange, editContent, editCategory, onContentChange, onCategoryChange, onSave, onCancel, categories, isSaving, }) {
287624
- const t = useT();
287625
- return (jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: jsxs(DialogContent, { className: "mx-4 max-w-2xl sm:mx-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "text-gray-700", children: t('memoryTabEditMemoryModal.editMemory') }) }), jsxs("div", { className: "mt-4 space-y-4", children: [jsxs("div", { children: [jsx("label", { className: "text-sm font-medium text-gray-600", children: t('memoryTabEditMemoryModal.category') }), jsxs(Select$1, { value: editCategory, onValueChange: onCategoryChange, children: [jsx(SelectTrigger, { className: "mt-1", children: jsx(SelectValue, { placeholder: t('memoryTabEditMemoryModal.selectCategory') }) }), jsx(SelectContent, { children: categories
287626
- .filter((cat) => cat !== 'All')
287627
- .map((category) => (jsx(SelectItem, { value: category, children: category }, category))) })] })] }), jsxs("div", { children: [jsx("label", { className: "text-sm font-medium text-gray-600", children: t('memoryTabEditMemoryModal.memory') }), jsx(Textarea, { value: editContent, onChange: (e) => onContentChange(e.target.value), placeholder: t('memoryTabEditMemoryModal.enterMemoryContent'), className: "mt-1" }), jsx("p", { className: "mt-1 text-xs text-gray-500", children: editContent.trim().length < 10
287628
- ? t('memoryTabEditMemoryModal.charCountMinimum', {
287629
- count: editContent.trim().length,
287630
- })
287631
- : t('memoryTabEditMemoryModal.charCount', { count: editContent.trim().length }) })] }), jsxs("div", { className: "flex justify-end gap-2", children: [jsx(Button$1, { variant: "outline", onClick: onCancel, children: t('memoryTabEditMemoryModal.cancel') }), jsx(Button$1, { onClick: onSave, className: "ibl-button-primary", disabled: editContent.trim().length < 10 || isSaving, children: isSaving ? t('memoryTabEditMemoryModal.saving') : t('memoryTabEditMemoryModal.save') })] })] })] }) }));
287632
- }
287633
-
287634
- var editMemoryModal = /*#__PURE__*/Object.freeze({
287635
- __proto__: null,
287636
- EditMemoryModal: EditMemoryModal
287637
- });
287638
-
287639
- function AddMemoryModal({ open, onOpenChange, newMemoryContent, newMemoryCategory, onContentChange, onCategoryChange, onSave, onCancel, categories, isSaving, }) {
287640
- const t = useT();
287641
- return (jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: jsxs(DialogContent, { className: "mx-4 max-w-2xl sm:mx-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "text-gray-700", children: t('memoryTabAddMemoryModal.addMemory') }) }), jsxs("div", { className: "mt-4 space-y-4", children: [jsxs("div", { children: [jsx("label", { className: "text-sm font-medium text-gray-600", children: t('memoryTabAddMemoryModal.category') }), jsxs(Select$1, { value: newMemoryCategory, onValueChange: onCategoryChange, children: [jsx(SelectTrigger, { className: "mt-1", children: jsx(SelectValue, { placeholder: t('memoryTabAddMemoryModal.selectCategory') }) }), jsx(SelectContent, { children: categories
287642
- .filter((cat) => cat !== 'All')
287643
- .map((category) => (jsx(SelectItem, { value: category, children: category }, category))) })] })] }), jsxs("div", { children: [jsx("label", { className: "text-sm font-medium text-gray-600", children: t('memoryTabAddMemoryModal.memory') }), jsx(Textarea, { value: newMemoryContent, onChange: (e) => onContentChange(e.target.value), placeholder: t('memoryTabAddMemoryModal.enterMemoryContent'), className: "mt-1" }), jsx("p", { className: "mt-1 text-xs text-gray-500", children: newMemoryContent.trim().length < 10
287644
- ? t('memoryTabAddMemoryModal.charactersMinimum', {
287645
- count: newMemoryContent.trim().length,
287646
- })
287647
- : t('memoryTabAddMemoryModal.characters', {
287648
- count: newMemoryContent.trim().length,
287649
- }) })] }), jsxs("div", { className: "flex justify-end gap-2", children: [jsx(Button$1, { variant: "outline", onClick: onCancel, children: t('memoryTabAddMemoryModal.cancel') }), jsx(Button$1, { onClick: onSave, disabled: newMemoryContent.trim().length < 10 || isSaving, className: "ibl-button-primary", children: isSaving ? t('memoryTabAddMemoryModal.saving') : t('memoryTabAddMemoryModal.save') })] })] })] }) }));
287650
- }
287651
-
287652
- var addMemoryModal = /*#__PURE__*/Object.freeze({
287653
- __proto__: null,
287654
- AddMemoryModal: AddMemoryModal
287655
- });
287656
-
287657
- function BulkDeleteMemoryModal({ open, onOpenChange, onConfirm, onCancel, isDeleting, selectedCategory, }) {
287658
- const isDeleteAll = selectedCategory === 'All';
287659
- const getConfirmationText = () => {
287660
- if (isDeleteAll) {
287661
- return 'Are you sure you want to delete all memories? This action cannot be undone.';
287662
- }
287663
- return `Are you sure you want to delete all memories in the ${selectedCategory} category? This action cannot be undone.`;
287664
- };
287665
- const getTitle = () => {
287666
- if (isDeleteAll) {
287667
- return 'Delete All Memories';
287668
- }
287669
- return `Delete All ${selectedCategory} Memories`;
287670
- };
287671
- return (jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: jsxs(DialogContent, { className: "mx-4 max-w-md sm:mx-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { children: getTitle() }) }), jsx("p", { className: "text-muted-foreground text-sm", children: getConfirmationText() }), jsxs("div", { className: "mt-4 flex justify-end gap-2", children: [jsx(Button$1, { variant: "outline", onClick: onCancel, disabled: isDeleting, children: "Cancel" }), jsx(Button$1, { className: "ibl-button-primary", onClick: onConfirm, disabled: isDeleting, children: isDeleting ? 'Deleting...' : 'Delete' })] })] }) }));
287672
- }
287673
-
287674
- var bulkDeleteMemoryModal = /*#__PURE__*/Object.freeze({
287675
- __proto__: null,
287676
- BulkDeleteMemoryModal: BulkDeleteMemoryModal
287677
- });
287678
-
287679
- const toSlug = (name) => name
287680
- .trim()
287681
- .toLowerCase()
287682
- .replace(/[^a-z0-9]+/g, '_')
287683
- .replace(/^_+|_+$/g, '');
287684
- function ManageCategoriesModal({ open, onOpenChange, tenantKey, mentorId, }) {
287685
- const t = useT();
287686
- const { data: categories = [], isLoading } = useGetMemoryCategoriesAdminQuery({ org: tenantKey, mentorId }, { skip: !open || !tenantKey || !mentorId });
287687
- const [createCategory, { isLoading: isCreating }] = useCreateMemoryCategoryMutation();
287688
- const [updateCategory, { isLoading: isUpdating }] = useUpdateMemoryCategoryMutation();
287689
- const [deleteCategory, { isLoading: isDeleting }] = useDeleteMemoryCategoryMutation();
287690
- const [newName, setNewName] = useState('');
287691
- const [editingId, setEditingId] = useState(null);
287692
- const [editName, setEditName] = useState('');
287693
- const [confirmDeleteId, setConfirmDeleteId] = useState(null);
287694
- const handleCreate = async () => {
287695
- const name = newName.trim();
287696
- if (!name)
287697
- return;
287698
- try {
287699
- await createCategory({
287700
- org: tenantKey,
287701
- mentorId,
287702
- data: { name, slug: toSlug(name) },
287703
- }).unwrap();
287704
- setNewName('');
287705
- toast.success(t('memoryTabManageCategoriesModal.categoryCreated'));
287706
- }
287707
- catch (error) {
287708
- console.error('Failed to create category:', error);
287709
- toast.error(t('memoryTabManageCategoriesModal.failedToCreateCategory'));
287710
- }
287711
- };
287712
- const startEdit = (category) => {
287713
- setEditingId(category.id);
287714
- setEditName(category.name);
287715
- };
287716
- const cancelEdit = () => {
287717
- setEditingId(null);
287718
- setEditName('');
287719
- };
287720
- const saveEdit = async (categoryId) => {
287721
- const name = editName.trim();
287722
- if (!name)
287723
- return;
287724
- try {
287725
- await updateCategory({
287726
- org: tenantKey,
287727
- mentorId,
287728
- categoryId,
287729
- data: { name },
287730
- }).unwrap();
287731
- cancelEdit();
287732
- toast.success(t('memoryTabManageCategoriesModal.categoryUpdated'));
287733
- }
287734
- catch (error) {
287735
- console.error('Failed to update category:', error);
287736
- toast.error(t('memoryTabManageCategoriesModal.failedToUpdateCategory'));
287737
- }
287738
- };
287739
- const handleDelete = async (categoryId) => {
287740
- try {
287741
- await deleteCategory({
287742
- org: tenantKey,
287743
- mentorId,
287744
- categoryId,
287745
- }).unwrap();
287746
- setConfirmDeleteId(null);
287747
- toast.success(t('memoryTabManageCategoriesModal.categoryDeleted'));
287748
- }
287749
- catch (error) {
287750
- console.error('Failed to delete category:', error);
287751
- toast.error(t('memoryTabManageCategoriesModal.failedToDeleteCategory'));
287752
- }
287753
- };
287754
- return (jsx(Dialog, { open: open, onOpenChange: (next) => {
287755
- if (!next) {
287756
- cancelEdit();
287757
- setConfirmDeleteId(null);
287758
- setNewName('');
287759
- }
287760
- onOpenChange(next);
287761
- }, children: jsxs(DialogContent, { className: "mx-4 max-w-md sm:mx-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { children: t('memoryTabManageCategoriesModal.manageCategories') }) }), jsxs("div", { className: "flex gap-2", children: [jsx(Input, { value: newName, onChange: (e) => setNewName(e.target.value), placeholder: t('memoryTabManageCategoriesModal.newCategoryNamePlaceholder'), onKeyDown: (e) => {
287762
- if (e.key === 'Enter') {
287763
- e.preventDefault();
287764
- handleCreate();
287765
- }
287766
- } }), jsxs(Button$1, { className: "ibl-button-primary", onClick: handleCreate, disabled: !newName.trim() || isCreating, children: [jsx(Plus, { className: "mr-1 h-4 w-4" }), t('memoryTabManageCategoriesModal.add')] })] }), jsx("div", { className: "max-h-[320px] space-y-2 overflow-y-auto", children: isLoading ? (jsx("p", { className: "text-muted-foreground py-4 text-center text-sm", children: t('memoryTabManageCategoriesModal.loadingCategories') })) : categories.length === 0 ? (jsx("p", { className: "text-muted-foreground py-4 text-center text-sm", children: t('memoryTabManageCategoriesModal.noCategoriesYet') })) : (categories.map((category) => {
287767
- const isEditing = editingId === category.id;
287768
- const isConfirming = confirmDeleteId === category.id;
287769
- return (jsx("div", { className: "flex items-center gap-2 rounded-lg border border-gray-200 bg-white p-2", children: isEditing ? (jsxs(Fragment$1, { children: [jsx(Input, { value: editName, onChange: (e) => setEditName(e.target.value), autoFocus: true, onKeyDown: (e) => {
287770
- if (e.key === 'Enter') {
287771
- e.preventDefault();
287772
- saveEdit(category.id);
287773
- }
287774
- else if (e.key === 'Escape') {
287775
- cancelEdit();
287776
- }
287777
- }, className: "h-8" }), jsx(Button$1, { variant: "ghost", size: "sm", className: "h-8 w-8 p-0", onClick: () => saveEdit(category.id), disabled: !editName.trim() || isUpdating, "aria-label": t('memoryTabManageCategoriesModal.saveCategory'), children: jsx(Check, { className: "h-4 w-4" }) }), jsx(Button$1, { variant: "ghost", size: "sm", className: "h-8 w-8 p-0", onClick: cancelEdit, "aria-label": t('memoryTabManageCategoriesModal.cancelEdit'), children: jsx(X$2, { className: "h-4 w-4" }) })] })) : isConfirming ? (jsxs(Fragment$1, { children: [jsx("span", { className: "flex-1 text-sm text-gray-900", children: t('memoryTabManageCategoriesModal.confirmDelete', { name: category.name }) }), jsx(Button$1, { variant: "ghost", size: "sm", onClick: () => setConfirmDeleteId(null), children: t('memoryTabManageCategoriesModal.cancel') }), jsx(Button$1, { variant: "destructive", size: "sm", onClick: () => handleDelete(category.id), disabled: isDeleting, children: isDeleting
287778
- ? t('memoryTabManageCategoriesModal.deleting')
287779
- : t('memoryTabManageCategoriesModal.delete') })] })) : (jsxs(Fragment$1, { children: [jsx("span", { className: "flex-1 text-sm text-gray-900", children: category.name }), jsx(Button$1, { variant: "ghost", size: "sm", className: "h-8 w-8 p-0", onClick: () => startEdit(category), "aria-label": t('memoryTabManageCategoriesModal.editCategory', {
287780
- name: category.name,
287781
- }), children: jsx(Pencil, { className: "h-4 w-4" }) }), jsx(Button$1, { variant: "ghost", size: "sm", className: "h-8 w-8 p-0 text-red-600 hover:text-red-700", onClick: () => setConfirmDeleteId(category.id), "aria-label": t('memoryTabManageCategoriesModal.deleteCategory', {
287782
- name: category.name,
287783
- }), children: jsx(Trash2, { className: "h-4 w-4" }) })] })) }, category.id));
287784
- })) }), jsx("div", { className: "mt-2 flex justify-end", children: jsx(Button$1, { variant: "outline", onClick: () => onOpenChange(false), children: t('memoryTabManageCategoriesModal.done') }) })] }) }));
287785
- }
287786
-
287787
- var manageCategoriesModal = /*#__PURE__*/Object.freeze({
287788
- __proto__: null,
287789
- ManageCategoriesModal: ManageCategoriesModal
287790
- });
287791
-
287792
287810
  function ImagePreviewModal({ url, onClose }) {
287793
287811
  return (jsx("div", { className: "bg-opacity-75 fixed inset-0 z-50 flex items-center justify-center bg-black p-4", onClick: onClose, children: jsxs("div", { className: "relative flex h-full w-full items-center justify-center", children: [jsx("button", { className: "bg-opacity-50 hover:bg-opacity-70 absolute top-2 right-2 rounded-full bg-black p-1 text-white", onClick: (e) => {
287794
287812
  e.stopPropagation();