@iblai/iblai-js 2.4.3 → 2.4.4
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.
|
@@ -3,7 +3,7 @@ import React__default, { useRef, useEffect, useState, useCallback, useLayoutEffe
|
|
|
3
3
|
import { useDispatch, useSelector } from 'react-redux';
|
|
4
4
|
import { selectSessionId, selectActiveChatMessages, useCachedSessionId, chatActions, LOCAL_STORAGE_KEYS, TimeTracker, getInitials, useTenantMetadata, useCurrentTenant, selectRbacPermissions, isPureWatcher, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, getTimeAgo, REQUIRED_ACTIONS_FOR_GROUPS, getVisibleAnalyticsTabs, formatRelativeTime as formatRelativeTime$2, ANONYMOUS_USERNAME, combineCSVData, WATCHER_HIDDEN_REPORTS, canViewPlatformAuditLogs, redirectToAuthSpaJoinTenant, redirectToAuthSpa, getAuthSpaJoinUrl, useOS, selectNumberOfActiveChatMessages, useUsername, selectStreaming, isLoggedIn, TOOLS, hasRemoteAiConfig, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, chatInputSliceActions, removeFile, WithFormPermissions, MENTOR_VISIBILITY } from '@iblai/web-utils';
|
|
5
5
|
import * as dataLayer from '@iblai/data-layer';
|
|
6
|
-
import { useCreateSessionIdMutation, useTimeTrackingMutation, useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, useGetAccessibleUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useUpdateTenantMetadataMutation, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useGetAiSearchMentorsQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetNotificationsCountQuery, useLazyGetNotificationsQuery, useMarkAllAsReadMutation, useCreateNotificationPreviewMutation, useSendNotificationMutation, useGetMentorsQuery, useUpdateTemplateMutation, useGetTemplateDetailsQuery, useGetTemplatesQuery, useLazyGetTemplateDetailsQuery, useToggleTemplateMutation, useGetTopicsStatsQuery, useGetUsersStatsQuery, useGetSessionStatsQuery, useGetTopicsDetailsStatsQuery, useGetAccessTimeHeatmapQuery, useGetUserDetailsStatsQuery, useGetTranscriptsConversationHeadlineQuery, useGetAverageRatingQuery, useGetFinancialStatsQuery, useGetDetailedFinancialStatsQuery, useGetTranscriptsMessagesDetailsQuery, useGetTranscriptsMessagesQuery, useGetReportDetailQuery, useLazyGetDownloadReportFromURLQuery, useGetMentorPublicSettingsQuery, useGetReportsQuery, useCreateReportMutation, useGetContentAnalyticsQuery, useGetContentAnalyticsDetailsQuery, useGetRevenueQuery, useListSubscribersQuery, useGetAuditLogsQuery, useGetPlatformAuditLogsQuery, PLATFORM_AUDIT_EVENT_TYPES, PLATFORM_AUDIT_ACTION_CODES, useGetMentorMemoriesListQuery, useGetMentorMemoriesQuery, useGetMemoryCategoriesAdminQuery, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetUserEnrolledCoursesQuery, useLazyGetUserAssignedCoursesQuery, useLazyGetUserCredentialsQuery, useLazyGetOverTimeActivityQuery, useLazyGetCatalogSearchQuery, useCreateOrUpdateUserReportedSkillMutation, useCreateOrUpdateUserDesiredSkillMutation, useLazyGetPathwayListQuery, useLazyGetUserAssignedPathwaysQuery, useLazyGetUserEnrolledPathwaysQuery, useLazyGetPathwayCompletionQuery, useLazyGetProgramListQuery, useLazyGetProgramCompletionQuery, useLazyGetUserEnrolledProgramsQuery, useLazyGetAssignedProgramsQuery, useLazyGetUserSkillsPointsQuery, useLazyGetUserReportedSkillsQuery, useLazyGetUserDesiredSkillsQuery, useLazyGetUserCatalogPathwaysQuery, useLazyGetPerLearnerInfoQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useLazyGetPersonnalizedSearchQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetClawMentorConfigQuery, useGetClawInstancesQuery, useGetAgentConfigQuery, useUpdateClawMentorConfigMutation, useCreateClawMentorConfigMutation, useDeleteClawMentorConfigMutation, usePushClawConfigMutation, useCreateClawInstanceMutation, useDeleteClawInstanceMutation, useUpdateAgentConfigMutation, useHealthCheckClawInstanceMutation, useTestConnectivityClawInstanceMutation, useUpdateClawInstanceMutation, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetAgentSkillsQuery, useGetMentorSkillAssignmentsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, resolveEffectiveAgentSkills, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useCreateCheckoutMutation, useGetUserProjectsQuery, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useDeleteMentorMemoryMutation, useUpdateMentorMemoryMutation, useCreateMentorMemoryMutation, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useGetMentorCategoriesQuery, useCreateMentorMutation, useUpdateUserPlatformMetadataMutation, useGetApplicationStatusQuery, useListOwnApplicationsQuery, useGetApplicationFormQuery, useWithdrawApplicationMutation, useRenewApplicationMutation, useCreateApplicationDraftMutation, useSubmitApplicationMutation, useUpdateApplicationMutation, useUploadApplicationAttachmentMutation, useDeleteApplicationAttachmentMutation, useGetPromptCategoriesQuery, useCreatePromptMutation, useDeletePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation } from '@iblai/data-layer';
|
|
6
|
+
import { useCreateSessionIdMutation, useTimeTrackingMutation, useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, useGetAccessibleUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useUpdateTenantMetadataMutation, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useGetAiSearchMentorsQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetNotificationsCountQuery, useLazyGetNotificationsQuery, useMarkAllAsReadMutation, useCreateNotificationPreviewMutation, useSendNotificationMutation, useGetMentorsQuery, USER_PROGRESS_DATA_POINTS, useResetTemplateMutation, useSendTestTemplateEmailMutation, useUpdateTemplateMutation, useGetTemplateDetailsQuery, USER_PROGRESS_SUMMARY_TYPE, useGetTemplatesQuery, useLazyGetTemplateDetailsQuery, useToggleTemplateMutation, useGetTopicsStatsQuery, useGetUsersStatsQuery, useGetSessionStatsQuery, useGetTopicsDetailsStatsQuery, useGetAccessTimeHeatmapQuery, useGetUserDetailsStatsQuery, useGetTranscriptsConversationHeadlineQuery, useGetAverageRatingQuery, useGetFinancialStatsQuery, useGetDetailedFinancialStatsQuery, useGetTranscriptsMessagesDetailsQuery, useGetTranscriptsMessagesQuery, useGetReportDetailQuery, useLazyGetDownloadReportFromURLQuery, useGetMentorPublicSettingsQuery, useGetReportsQuery, useCreateReportMutation, useGetContentAnalyticsQuery, useGetContentAnalyticsDetailsQuery, useGetRevenueQuery, useListSubscribersQuery, useGetAuditLogsQuery, useGetPlatformAuditLogsQuery, PLATFORM_AUDIT_EVENT_TYPES, PLATFORM_AUDIT_ACTION_CODES, useGetMentorMemoriesListQuery, useGetMentorMemoriesQuery, useGetMemoryCategoriesAdminQuery, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetUserEnrolledCoursesQuery, useLazyGetUserAssignedCoursesQuery, useLazyGetUserCredentialsQuery, useLazyGetOverTimeActivityQuery, useLazyGetCatalogSearchQuery, useCreateOrUpdateUserReportedSkillMutation, useCreateOrUpdateUserDesiredSkillMutation, useLazyGetPathwayListQuery, useLazyGetUserAssignedPathwaysQuery, useLazyGetUserEnrolledPathwaysQuery, useLazyGetPathwayCompletionQuery, useLazyGetProgramListQuery, useLazyGetProgramCompletionQuery, useLazyGetUserEnrolledProgramsQuery, useLazyGetAssignedProgramsQuery, useLazyGetUserSkillsPointsQuery, useLazyGetUserReportedSkillsQuery, useLazyGetUserDesiredSkillsQuery, useLazyGetUserCatalogPathwaysQuery, useLazyGetPerLearnerInfoQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useLazyGetPersonnalizedSearchQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetClawMentorConfigQuery, useGetClawInstancesQuery, useGetAgentConfigQuery, useUpdateClawMentorConfigMutation, useCreateClawMentorConfigMutation, useDeleteClawMentorConfigMutation, usePushClawConfigMutation, useCreateClawInstanceMutation, useDeleteClawInstanceMutation, useUpdateAgentConfigMutation, useHealthCheckClawInstanceMutation, useTestConnectivityClawInstanceMutation, useUpdateClawInstanceMutation, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetAgentSkillsQuery, useGetMentorSkillAssignmentsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, resolveEffectiveAgentSkills, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useCreateCheckoutMutation, useGetUserProjectsQuery, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useDeleteMentorMemoryMutation, useUpdateMentorMemoryMutation, useCreateMentorMemoryMutation, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useGetMentorCategoriesQuery, useCreateMentorMutation, useUpdateUserPlatformMetadataMutation, useGetApplicationStatusQuery, useListOwnApplicationsQuery, useGetApplicationFormQuery, useWithdrawApplicationMutation, useRenewApplicationMutation, useCreateApplicationDraftMutation, useSubmitApplicationMutation, useUpdateApplicationMutation, useUploadApplicationAttachmentMutation, useDeleteApplicationAttachmentMutation, useGetPromptCategoriesQuery, useCreatePromptMutation, useDeletePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation } from '@iblai/data-layer';
|
|
7
7
|
import { toast } from 'sonner';
|
|
8
8
|
import { jsx, Fragment as Fragment$1, jsxs } from 'react/jsx-runtime';
|
|
9
9
|
import * as ReactDOM from 'react-dom';
|
|
@@ -61892,6 +61892,92 @@ var componentsProactiveSettingsSection$3 = {
|
|
|
61892
61892
|
editAgentPromptAriaLabel: "Edit agent prompt",
|
|
61893
61893
|
periodicAgentsHelp: "Optional. Select agents to include in the proactive outreach rotation."
|
|
61894
61894
|
};
|
|
61895
|
+
var componentsTemplateActionsSection$3 = {
|
|
61896
|
+
title: "Test & Reset",
|
|
61897
|
+
description: "Preview the template in your inbox, or discard this platform's customizations.",
|
|
61898
|
+
testEmailLabel: "Send a test email",
|
|
61899
|
+
testEmailHelper: "Sends one rendering of this template to the address you enter.",
|
|
61900
|
+
testEmailPlaceholder: "you@example.com",
|
|
61901
|
+
sendTest: "Send test email",
|
|
61902
|
+
sendingTest: "Sending...",
|
|
61903
|
+
testSuccessTitle: "Test email sent",
|
|
61904
|
+
testSuccessDescription: "Sent to {email}.",
|
|
61905
|
+
testErrorTitle: "Could not send test email",
|
|
61906
|
+
testErrorDescription: "Please check the address and try again.",
|
|
61907
|
+
resetLabel: "Reset to default",
|
|
61908
|
+
resetHelper: "Discards this platform's copy and restores the default template.",
|
|
61909
|
+
reset: "Reset to default",
|
|
61910
|
+
resetting: "Resetting...",
|
|
61911
|
+
resetConfirmTitle: "Reset this template?",
|
|
61912
|
+
resetConfirmDescription: "This platform's customizations will be discarded and the default template restored. This cannot be undone.",
|
|
61913
|
+
resetConfirmCancel: "Cancel",
|
|
61914
|
+
resetConfirmAction: "Reset template",
|
|
61915
|
+
resetSuccessTitle: "Template reset",
|
|
61916
|
+
resetSuccessDescription: "The platform default has been restored.",
|
|
61917
|
+
resetErrorTitle: "Could not reset template",
|
|
61918
|
+
resetErrorDescription: "Please try again."
|
|
61919
|
+
};
|
|
61920
|
+
var componentsTemplateVariablesHelper$3 = {
|
|
61921
|
+
title: "Variables you can use",
|
|
61922
|
+
copyHint: "Click a variable to copy it, then paste it into the subject or body.",
|
|
61923
|
+
insertHint: "Click a variable to insert it.",
|
|
61924
|
+
copiedToast: "Copied {token} to your clipboard.",
|
|
61925
|
+
copyUnavailableToast: "Copy {token} manually — clipboard access is unavailable.",
|
|
61926
|
+
copyAriaLabel: "Copy the {name} variable",
|
|
61927
|
+
insertAriaLabel: "Insert the {name} variable"
|
|
61928
|
+
};
|
|
61929
|
+
var componentsUserProgressSettingsSection$3 = {
|
|
61930
|
+
scheduleTitle: "Schedule & Reporting Period",
|
|
61931
|
+
scheduleDescription: "Choose how often the summary is sent and how far back it looks.",
|
|
61932
|
+
frequencyLabel: "Frequency",
|
|
61933
|
+
selectFrequencyAriaLabel: "Select frequency",
|
|
61934
|
+
selectFrequencyPlaceholder: "Select frequency",
|
|
61935
|
+
daily: "Daily",
|
|
61936
|
+
weekly: "Weekly",
|
|
61937
|
+
monthly: "Monthly",
|
|
61938
|
+
custom: "Custom",
|
|
61939
|
+
cadenceDaily: "Sends every day at the time below.",
|
|
61940
|
+
cadenceWeekly: "Sends every Monday at the time below.",
|
|
61941
|
+
cadenceMonthly: "Sends on the 1st of each month at the time below.",
|
|
61942
|
+
cadenceCustom: "Sends every {days} days at the time below.",
|
|
61943
|
+
cadenceCustomUnset: "Set a custom interval to choose how often the summary is sent.",
|
|
61944
|
+
executionTimeLabel: "Send Time",
|
|
61945
|
+
executionTimeRequired: "Specify the time the summary should be sent.",
|
|
61946
|
+
timezoneLabel: "Timezone",
|
|
61947
|
+
selectTimezoneAriaLabel: "Select timezone",
|
|
61948
|
+
selectTimezonePlaceholder: "Select timezone",
|
|
61949
|
+
useLocalTimezone: "Use local timezone ({timezone})",
|
|
61950
|
+
customIntervalLabel: "Custom Interval (days)",
|
|
61951
|
+
customIntervalRequired: "Set how many days should pass between sends.",
|
|
61952
|
+
dayRangeError: "Enter a whole number of days between 1 and 365.",
|
|
61953
|
+
lookbackLabel: "Reporting Window (days)",
|
|
61954
|
+
lookbackHelp: "How far back each summary looks. This is separate from how often the email is sent — a weekly email can still report on the last 30 days.",
|
|
61955
|
+
lookbackRequired: "Set the reporting window in days.",
|
|
61956
|
+
dataPointsLabel: "Included Data Points",
|
|
61957
|
+
dataPointsHelp: "The email only shows sections that are enabled and have data for that learner.",
|
|
61958
|
+
dataPointCoursesProgressed: "Courses progressed",
|
|
61959
|
+
dataPointCoursesCompleted: "Courses completed",
|
|
61960
|
+
dataPointCredentialsEarned: "Credentials earned",
|
|
61961
|
+
dataPointTimeSpent: "Time spent",
|
|
61962
|
+
dataPointActiveDays: "Active days",
|
|
61963
|
+
dataPointMentorsAccessed: "AI agent activity",
|
|
61964
|
+
noDataPointsWarning: "No data points selected — the summary will have no content to show."
|
|
61965
|
+
};
|
|
61966
|
+
var componentsWatcherEmailSection$3 = {
|
|
61967
|
+
title: "Watcher Email",
|
|
61968
|
+
description: "Sent to a learner's watchers, such as a parent or manager.",
|
|
61969
|
+
fallbackNotice: "Watchers currently receive the learner email. Customize it to send them a different message.",
|
|
61970
|
+
customize: "Customize watcher email",
|
|
61971
|
+
useLearnerEmail: "Use the learner email",
|
|
61972
|
+
subjectLabel: "Watcher Email Subject",
|
|
61973
|
+
subjectHelper: "Supports the same variables as the learner email, plus learner_name.",
|
|
61974
|
+
subjectFallbackHelper: "Leave empty and watchers receive the learner email subject.",
|
|
61975
|
+
subjectPlaceholder: "Enter the watcher email subject...",
|
|
61976
|
+
bodyLabel: "Watcher Email Body",
|
|
61977
|
+
bodyHelper: "Supports the same variables as the learner email, plus learner_name.",
|
|
61978
|
+
bodyFallbackHelper: "Leave empty and watchers receive the learner email body.",
|
|
61979
|
+
bodyPlaceholder: "Enter the watcher email body..."
|
|
61980
|
+
};
|
|
61895
61981
|
var courseContentAccessiblePaginate$3 = {
|
|
61896
61982
|
pagination: "Pagination"
|
|
61897
61983
|
};
|
|
@@ -63094,7 +63180,14 @@ var notificationsEditAlertDialog$3 = {
|
|
|
63094
63180
|
toastErrorDescription: "Failed to update template. Please try again.",
|
|
63095
63181
|
cancel: "Cancel",
|
|
63096
63182
|
saving: "Saving...",
|
|
63097
|
-
saveChanges: "Save Changes"
|
|
63183
|
+
saveChanges: "Save Changes",
|
|
63184
|
+
learnerEmailSubjectLabel: "Learner Email Subject",
|
|
63185
|
+
learnerEmailSubjectHelper: "Required. Supports template variables — see the list below the body.",
|
|
63186
|
+
learnerEmailBodyLabel: "Learner Email Body",
|
|
63187
|
+
learnerEmailBodyHelper: "Required. Greet with \"Hey,\" rather than a username — usernames are often auto-generated.",
|
|
63188
|
+
noChangesToast: "No changes to save.",
|
|
63189
|
+
toastValidationTitle: "Check the highlighted fields",
|
|
63190
|
+
toastValidationDescription: "Some values were rejected. Review the fields marked in red."
|
|
63098
63191
|
};
|
|
63099
63192
|
var notificationsNotificationDisplay$3 = {
|
|
63100
63193
|
notificationsAriaLabel: "Notifications",
|
|
@@ -66244,6 +66337,10 @@ var en = {
|
|
|
66244
66337
|
componentsPolicyAssignmentSection: componentsPolicyAssignmentSection$3,
|
|
66245
66338
|
componentsPolicyConfigDialog: componentsPolicyConfigDialog$3,
|
|
66246
66339
|
componentsProactiveSettingsSection: componentsProactiveSettingsSection$3,
|
|
66340
|
+
componentsTemplateActionsSection: componentsTemplateActionsSection$3,
|
|
66341
|
+
componentsTemplateVariablesHelper: componentsTemplateVariablesHelper$3,
|
|
66342
|
+
componentsUserProgressSettingsSection: componentsUserProgressSettingsSection$3,
|
|
66343
|
+
componentsWatcherEmailSection: componentsWatcherEmailSection$3,
|
|
66247
66344
|
courseContentAccessiblePaginate: courseContentAccessiblePaginate$3,
|
|
66248
66345
|
courseContentCourseContentLayout: courseContentCourseContentLayout$3,
|
|
66249
66346
|
courseContentDiscoverFacetsFilter: courseContentDiscoverFacetsFilter$3,
|
|
@@ -68531,6 +68628,92 @@ var componentsProactiveSettingsSection$2 = {
|
|
|
68531
68628
|
editAgentPromptAriaLabel: "Modifier le prompt de l'agent",
|
|
68532
68629
|
periodicAgentsHelp: "Facultatif. Sélectionnez les agents à inclure dans la rotation de contact proactif."
|
|
68533
68630
|
};
|
|
68631
|
+
var componentsTemplateActionsSection$2 = {
|
|
68632
|
+
title: "Tester et réinitialiser",
|
|
68633
|
+
description: "Prévisualisez le modèle dans votre boîte de réception ou annulez les personnalisations de cette plateforme.",
|
|
68634
|
+
testEmailLabel: "Envoyer un e-mail de test",
|
|
68635
|
+
testEmailHelper: "Envoie un rendu de ce modèle à l'adresse que vous saisissez.",
|
|
68636
|
+
testEmailPlaceholder: "vous@exemple.com",
|
|
68637
|
+
sendTest: "Envoyer l'e-mail de test",
|
|
68638
|
+
sendingTest: "Envoi...",
|
|
68639
|
+
testSuccessTitle: "E-mail de test envoyé",
|
|
68640
|
+
testSuccessDescription: "Envoyé à {email}.",
|
|
68641
|
+
testErrorTitle: "Impossible d'envoyer l'e-mail de test",
|
|
68642
|
+
testErrorDescription: "Vérifiez l'adresse et réessayez.",
|
|
68643
|
+
resetLabel: "Réinitialiser par défaut",
|
|
68644
|
+
resetHelper: "Supprime la copie de cette plateforme et restaure le modèle par défaut.",
|
|
68645
|
+
reset: "Réinitialiser par défaut",
|
|
68646
|
+
resetting: "Réinitialisation...",
|
|
68647
|
+
resetConfirmTitle: "Réinitialiser ce modèle ?",
|
|
68648
|
+
resetConfirmDescription: "Les personnalisations de cette plateforme seront supprimées et le modèle par défaut restauré. Cette action est irréversible.",
|
|
68649
|
+
resetConfirmCancel: "Annuler",
|
|
68650
|
+
resetConfirmAction: "Réinitialiser le modèle",
|
|
68651
|
+
resetSuccessTitle: "Modèle réinitialisé",
|
|
68652
|
+
resetSuccessDescription: "Le modèle par défaut de la plateforme a été restauré.",
|
|
68653
|
+
resetErrorTitle: "Impossible de réinitialiser le modèle",
|
|
68654
|
+
resetErrorDescription: "Veuillez réessayer."
|
|
68655
|
+
};
|
|
68656
|
+
var componentsTemplateVariablesHelper$2 = {
|
|
68657
|
+
title: "Variables disponibles",
|
|
68658
|
+
copyHint: "Cliquez sur une variable pour la copier, puis collez-la dans l’objet ou le corps.",
|
|
68659
|
+
insertHint: "Cliquez sur une variable pour l’insérer.",
|
|
68660
|
+
copiedToast: "{token} copié dans le presse-papiers.",
|
|
68661
|
+
copyUnavailableToast: "Copiez {token} manuellement : le presse-papiers est indisponible.",
|
|
68662
|
+
copyAriaLabel: "Copier la variable {name}",
|
|
68663
|
+
insertAriaLabel: "Insérer la variable {name}"
|
|
68664
|
+
};
|
|
68665
|
+
var componentsUserProgressSettingsSection$2 = {
|
|
68666
|
+
scheduleTitle: "Planification et période de rapport",
|
|
68667
|
+
scheduleDescription: "Choisissez la fréquence d’envoi du résumé et la période qu’il couvre.",
|
|
68668
|
+
frequencyLabel: "Fréquence",
|
|
68669
|
+
selectFrequencyAriaLabel: "Sélectionner la fréquence",
|
|
68670
|
+
selectFrequencyPlaceholder: "Sélectionner la fréquence",
|
|
68671
|
+
daily: "Quotidienne",
|
|
68672
|
+
weekly: "Hebdomadaire",
|
|
68673
|
+
monthly: "Mensuelle",
|
|
68674
|
+
custom: "Personnalisée",
|
|
68675
|
+
cadenceDaily: "Envoyé chaque jour à l’heure indiquée ci-dessous.",
|
|
68676
|
+
cadenceWeekly: "Envoyé chaque lundi à l’heure indiquée ci-dessous.",
|
|
68677
|
+
cadenceMonthly: "Envoyé le 1er de chaque mois à l’heure indiquée ci-dessous.",
|
|
68678
|
+
cadenceCustom: "Envoyé tous les {days} jours à l’heure indiquée ci-dessous.",
|
|
68679
|
+
cadenceCustomUnset: "Définissez un intervalle personnalisé pour choisir la fréquence d’envoi du résumé.",
|
|
68680
|
+
executionTimeLabel: "Heure d’envoi",
|
|
68681
|
+
executionTimeRequired: "Indiquez l’heure à laquelle le résumé doit être envoyé.",
|
|
68682
|
+
timezoneLabel: "Fuseau horaire",
|
|
68683
|
+
selectTimezoneAriaLabel: "Sélectionner le fuseau horaire",
|
|
68684
|
+
selectTimezonePlaceholder: "Sélectionner le fuseau horaire",
|
|
68685
|
+
useLocalTimezone: "Utiliser le fuseau horaire local ({timezone})",
|
|
68686
|
+
customIntervalLabel: "Intervalle personnalisé (jours)",
|
|
68687
|
+
customIntervalRequired: "Indiquez le nombre de jours entre deux envois.",
|
|
68688
|
+
dayRangeError: "Saisissez un nombre entier de jours compris entre 1 et 365.",
|
|
68689
|
+
lookbackLabel: "Période de rapport (jours)",
|
|
68690
|
+
lookbackHelp: "La période couverte par chaque résumé. Elle est indépendante de la fréquence d’envoi : un e-mail hebdomadaire peut couvrir les 30 derniers jours.",
|
|
68691
|
+
lookbackRequired: "Indiquez la période de rapport en jours.",
|
|
68692
|
+
dataPointsLabel: "Données incluses",
|
|
68693
|
+
dataPointsHelp: "L’e-mail n’affiche que les sections activées et pour lesquelles l’apprenant a des données.",
|
|
68694
|
+
dataPointCoursesProgressed: "Cours en progression",
|
|
68695
|
+
dataPointCoursesCompleted: "Cours terminés",
|
|
68696
|
+
dataPointCredentialsEarned: "Certifications obtenues",
|
|
68697
|
+
dataPointTimeSpent: "Temps passé",
|
|
68698
|
+
dataPointActiveDays: "Jours actifs",
|
|
68699
|
+
dataPointMentorsAccessed: "Activité des agents IA",
|
|
68700
|
+
noDataPointsWarning: "Aucune donnée sélectionnée : le résumé n’aura aucun contenu à afficher."
|
|
68701
|
+
};
|
|
68702
|
+
var componentsWatcherEmailSection$2 = {
|
|
68703
|
+
title: "E-mail des observateurs",
|
|
68704
|
+
description: "Envoyé aux observateurs de l’apprenant, par exemple un parent ou un responsable.",
|
|
68705
|
+
fallbackNotice: "Les observateurs reçoivent actuellement l’e-mail de l’apprenant. Personnalisez-le pour leur envoyer un message différent.",
|
|
68706
|
+
customize: "Personnaliser l’e-mail des observateurs",
|
|
68707
|
+
useLearnerEmail: "Utiliser l’e-mail de l’apprenant",
|
|
68708
|
+
subjectLabel: "Objet de l’e-mail des observateurs",
|
|
68709
|
+
subjectHelper: "Prend en charge les mêmes variables que l’e-mail de l’apprenant, plus learner_name.",
|
|
68710
|
+
subjectFallbackHelper: "Laissez vide et les observateurs recevront l’objet de l’e-mail de l’apprenant.",
|
|
68711
|
+
subjectPlaceholder: "Saisissez l’objet de l’e-mail des observateurs...",
|
|
68712
|
+
bodyLabel: "Corps de l’e-mail des observateurs",
|
|
68713
|
+
bodyHelper: "Prend en charge les mêmes variables que l’e-mail de l’apprenant, plus learner_name.",
|
|
68714
|
+
bodyFallbackHelper: "Laissez vide et les observateurs recevront le corps de l’e-mail de l’apprenant.",
|
|
68715
|
+
bodyPlaceholder: "Saisissez le corps de l’e-mail des observateurs..."
|
|
68716
|
+
};
|
|
68534
68717
|
var courseContentAccessiblePaginate$2 = {
|
|
68535
68718
|
pagination: "Pagination"
|
|
68536
68719
|
};
|
|
@@ -69733,7 +69916,14 @@ var notificationsEditAlertDialog$2 = {
|
|
|
69733
69916
|
toastErrorDescription: "Échec de la mise à jour du modèle. Veuillez réessayer.",
|
|
69734
69917
|
cancel: "Annuler",
|
|
69735
69918
|
saving: "Enregistrement...",
|
|
69736
|
-
saveChanges: "Enregistrer les modifications"
|
|
69919
|
+
saveChanges: "Enregistrer les modifications",
|
|
69920
|
+
learnerEmailSubjectLabel: "Objet de l’e-mail de l’apprenant",
|
|
69921
|
+
learnerEmailSubjectHelper: "Obligatoire. Prend en charge les variables de modèle : voir la liste sous le corps.",
|
|
69922
|
+
learnerEmailBodyLabel: "Corps de l’e-mail de l’apprenant",
|
|
69923
|
+
learnerEmailBodyHelper: "Obligatoire. Utilisez « Bonjour, » plutôt que le nom d’utilisateur : ceux-ci sont souvent générés automatiquement.",
|
|
69924
|
+
noChangesToast: "Aucune modification à enregistrer.",
|
|
69925
|
+
toastValidationTitle: "Vérifiez les champs signalés",
|
|
69926
|
+
toastValidationDescription: "Certaines valeurs ont été rejetées. Vérifiez les champs marqués en rouge."
|
|
69737
69927
|
};
|
|
69738
69928
|
var notificationsNotificationDisplay$2 = {
|
|
69739
69929
|
notificationsAriaLabel: "Notifications",
|
|
@@ -72718,6 +72908,10 @@ var fr = {
|
|
|
72718
72908
|
componentsPolicyAssignmentSection: componentsPolicyAssignmentSection$2,
|
|
72719
72909
|
componentsPolicyConfigDialog: componentsPolicyConfigDialog$2,
|
|
72720
72910
|
componentsProactiveSettingsSection: componentsProactiveSettingsSection$2,
|
|
72911
|
+
componentsTemplateActionsSection: componentsTemplateActionsSection$2,
|
|
72912
|
+
componentsTemplateVariablesHelper: componentsTemplateVariablesHelper$2,
|
|
72913
|
+
componentsUserProgressSettingsSection: componentsUserProgressSettingsSection$2,
|
|
72914
|
+
componentsWatcherEmailSection: componentsWatcherEmailSection$2,
|
|
72721
72915
|
courseContentAccessiblePaginate: courseContentAccessiblePaginate$2,
|
|
72722
72916
|
courseContentCourseContentLayout: courseContentCourseContentLayout$2,
|
|
72723
72917
|
courseContentDiscoverFacetsFilter: courseContentDiscoverFacetsFilter$2,
|
|
@@ -75004,6 +75198,92 @@ var componentsProactiveSettingsSection$1 = {
|
|
|
75004
75198
|
editAgentPromptAriaLabel: "Editar prompt del agente",
|
|
75005
75199
|
periodicAgentsHelp: "Opcional. Seleccione los agentes a incluir en la rotación de contacto proactivo."
|
|
75006
75200
|
};
|
|
75201
|
+
var componentsTemplateActionsSection$1 = {
|
|
75202
|
+
title: "Probar y restablecer",
|
|
75203
|
+
description: "Previsualice la plantilla en su bandeja de entrada o descarte las personalizaciones de esta plataforma.",
|
|
75204
|
+
testEmailLabel: "Enviar un correo de prueba",
|
|
75205
|
+
testEmailHelper: "Envía una versión de esta plantilla a la dirección que indique.",
|
|
75206
|
+
testEmailPlaceholder: "usted@ejemplo.com",
|
|
75207
|
+
sendTest: "Enviar correo de prueba",
|
|
75208
|
+
sendingTest: "Enviando...",
|
|
75209
|
+
testSuccessTitle: "Correo de prueba enviado",
|
|
75210
|
+
testSuccessDescription: "Enviado a {email}.",
|
|
75211
|
+
testErrorTitle: "No se pudo enviar el correo de prueba",
|
|
75212
|
+
testErrorDescription: "Verifique la dirección e inténtelo de nuevo.",
|
|
75213
|
+
resetLabel: "Restablecer al valor predeterminado",
|
|
75214
|
+
resetHelper: "Descarta la copia de esta plataforma y restaura la plantilla predeterminada.",
|
|
75215
|
+
reset: "Restablecer al valor predeterminado",
|
|
75216
|
+
resetting: "Restableciendo...",
|
|
75217
|
+
resetConfirmTitle: "¿Restablecer esta plantilla?",
|
|
75218
|
+
resetConfirmDescription: "Las personalizaciones de esta plataforma se descartarán y se restaurará la plantilla predeterminada. Esta acción no se puede deshacer.",
|
|
75219
|
+
resetConfirmCancel: "Cancelar",
|
|
75220
|
+
resetConfirmAction: "Restablecer plantilla",
|
|
75221
|
+
resetSuccessTitle: "Plantilla restablecida",
|
|
75222
|
+
resetSuccessDescription: "Se restauró el valor predeterminado de la plataforma.",
|
|
75223
|
+
resetErrorTitle: "No se pudo restablecer la plantilla",
|
|
75224
|
+
resetErrorDescription: "Inténtelo de nuevo."
|
|
75225
|
+
};
|
|
75226
|
+
var componentsTemplateVariablesHelper$1 = {
|
|
75227
|
+
title: "Variables que puede usar",
|
|
75228
|
+
copyHint: "Haga clic en una variable para copiarla y péguela en el asunto o el cuerpo.",
|
|
75229
|
+
insertHint: "Haga clic en una variable para insertarla.",
|
|
75230
|
+
copiedToast: "Se copió {token} al portapapeles.",
|
|
75231
|
+
copyUnavailableToast: "Copie {token} manualmente: el portapapeles no está disponible.",
|
|
75232
|
+
copyAriaLabel: "Copiar la variable {name}",
|
|
75233
|
+
insertAriaLabel: "Insertar la variable {name}"
|
|
75234
|
+
};
|
|
75235
|
+
var componentsUserProgressSettingsSection$1 = {
|
|
75236
|
+
scheduleTitle: "Programación y período del informe",
|
|
75237
|
+
scheduleDescription: "Elija con qué frecuencia se envía el resumen y qué período abarca.",
|
|
75238
|
+
frequencyLabel: "Frecuencia",
|
|
75239
|
+
selectFrequencyAriaLabel: "Seleccionar frecuencia",
|
|
75240
|
+
selectFrequencyPlaceholder: "Seleccionar frecuencia",
|
|
75241
|
+
daily: "Diaria",
|
|
75242
|
+
weekly: "Semanal",
|
|
75243
|
+
monthly: "Mensual",
|
|
75244
|
+
custom: "Personalizada",
|
|
75245
|
+
cadenceDaily: "Se envía todos los días a la hora indicada abajo.",
|
|
75246
|
+
cadenceWeekly: "Se envía todos los lunes a la hora indicada abajo.",
|
|
75247
|
+
cadenceMonthly: "Se envía el día 1 de cada mes a la hora indicada abajo.",
|
|
75248
|
+
cadenceCustom: "Se envía cada {days} días a la hora indicada abajo.",
|
|
75249
|
+
cadenceCustomUnset: "Defina un intervalo personalizado para elegir con qué frecuencia se envía el resumen.",
|
|
75250
|
+
executionTimeLabel: "Hora de envío",
|
|
75251
|
+
executionTimeRequired: "Indique la hora a la que debe enviarse el resumen.",
|
|
75252
|
+
timezoneLabel: "Zona horaria",
|
|
75253
|
+
selectTimezoneAriaLabel: "Seleccionar zona horaria",
|
|
75254
|
+
selectTimezonePlaceholder: "Seleccionar zona horaria",
|
|
75255
|
+
useLocalTimezone: "Usar la zona horaria local ({timezone})",
|
|
75256
|
+
customIntervalLabel: "Intervalo personalizado (días)",
|
|
75257
|
+
customIntervalRequired: "Indique cuántos días deben pasar entre envíos.",
|
|
75258
|
+
dayRangeError: "Introduzca un número entero de días entre 1 y 365.",
|
|
75259
|
+
lookbackLabel: "Período del informe (días)",
|
|
75260
|
+
lookbackHelp: "Cuánto tiempo hacia atrás abarca cada resumen. Es independiente de la frecuencia de envío: un correo semanal puede informar sobre los últimos 30 días.",
|
|
75261
|
+
lookbackRequired: "Indique el período del informe en días.",
|
|
75262
|
+
dataPointsLabel: "Datos incluidos",
|
|
75263
|
+
dataPointsHelp: "El correo solo muestra las secciones que están activadas y tienen datos para ese estudiante.",
|
|
75264
|
+
dataPointCoursesProgressed: "Cursos en progreso",
|
|
75265
|
+
dataPointCoursesCompleted: "Cursos completados",
|
|
75266
|
+
dataPointCredentialsEarned: "Credenciales obtenidas",
|
|
75267
|
+
dataPointTimeSpent: "Tiempo dedicado",
|
|
75268
|
+
dataPointActiveDays: "Días activos",
|
|
75269
|
+
dataPointMentorsAccessed: "Actividad de agentes de IA",
|
|
75270
|
+
noDataPointsWarning: "No se seleccionó ningún dato: el resumen no tendrá contenido que mostrar."
|
|
75271
|
+
};
|
|
75272
|
+
var componentsWatcherEmailSection$1 = {
|
|
75273
|
+
title: "Correo para observadores",
|
|
75274
|
+
description: "Se envía a los observadores del estudiante, como un padre, una madre o un supervisor.",
|
|
75275
|
+
fallbackNotice: "Actualmente los observadores reciben el correo del estudiante. Personalícelo para enviarles un mensaje distinto.",
|
|
75276
|
+
customize: "Personalizar el correo para observadores",
|
|
75277
|
+
useLearnerEmail: "Usar el correo del estudiante",
|
|
75278
|
+
subjectLabel: "Asunto del correo para observadores",
|
|
75279
|
+
subjectHelper: "Admite las mismas variables que el correo del estudiante, más learner_name.",
|
|
75280
|
+
subjectFallbackHelper: "Si lo deja vacío, los observadores reciben el asunto del correo del estudiante.",
|
|
75281
|
+
subjectPlaceholder: "Escriba el asunto del correo para observadores...",
|
|
75282
|
+
bodyLabel: "Cuerpo del correo para observadores",
|
|
75283
|
+
bodyHelper: "Admite las mismas variables que el correo del estudiante, más learner_name.",
|
|
75284
|
+
bodyFallbackHelper: "Si lo deja vacío, los observadores reciben el cuerpo del correo del estudiante.",
|
|
75285
|
+
bodyPlaceholder: "Escriba el cuerpo del correo para observadores..."
|
|
75286
|
+
};
|
|
75007
75287
|
var courseContentAccessiblePaginate$1 = {
|
|
75008
75288
|
pagination: "Paginación"
|
|
75009
75289
|
};
|
|
@@ -76206,7 +76486,14 @@ var notificationsEditAlertDialog$1 = {
|
|
|
76206
76486
|
toastErrorDescription: "No se pudo actualizar la plantilla. Por favor, inténtelo de nuevo.",
|
|
76207
76487
|
cancel: "Cancelar",
|
|
76208
76488
|
saving: "Guardando...",
|
|
76209
|
-
saveChanges: "Guardar cambios"
|
|
76489
|
+
saveChanges: "Guardar cambios",
|
|
76490
|
+
learnerEmailSubjectLabel: "Asunto del correo del estudiante",
|
|
76491
|
+
learnerEmailSubjectHelper: "Obligatorio. Admite variables de plantilla: consulte la lista debajo del cuerpo.",
|
|
76492
|
+
learnerEmailBodyLabel: "Cuerpo del correo del estudiante",
|
|
76493
|
+
learnerEmailBodyHelper: "Obligatorio. Salude con «Hola,» en lugar de usar el nombre de usuario: suelen generarse automáticamente.",
|
|
76494
|
+
noChangesToast: "No hay cambios que guardar.",
|
|
76495
|
+
toastValidationTitle: "Revise los campos resaltados",
|
|
76496
|
+
toastValidationDescription: "Se rechazaron algunos valores. Revise los campos marcados en rojo."
|
|
76210
76497
|
};
|
|
76211
76498
|
var notificationsNotificationDisplay$1 = {
|
|
76212
76499
|
notificationsAriaLabel: "Notificaciones",
|
|
@@ -79191,6 +79478,10 @@ var es = {
|
|
|
79191
79478
|
componentsPolicyAssignmentSection: componentsPolicyAssignmentSection$1,
|
|
79192
79479
|
componentsPolicyConfigDialog: componentsPolicyConfigDialog$1,
|
|
79193
79480
|
componentsProactiveSettingsSection: componentsProactiveSettingsSection$1,
|
|
79481
|
+
componentsTemplateActionsSection: componentsTemplateActionsSection$1,
|
|
79482
|
+
componentsTemplateVariablesHelper: componentsTemplateVariablesHelper$1,
|
|
79483
|
+
componentsUserProgressSettingsSection: componentsUserProgressSettingsSection$1,
|
|
79484
|
+
componentsWatcherEmailSection: componentsWatcherEmailSection$1,
|
|
79194
79485
|
courseContentAccessiblePaginate: courseContentAccessiblePaginate$1,
|
|
79195
79486
|
courseContentCourseContentLayout: courseContentCourseContentLayout$1,
|
|
79196
79487
|
courseContentDiscoverFacetsFilter: courseContentDiscoverFacetsFilter$1,
|
|
@@ -81477,6 +81768,92 @@ var componentsProactiveSettingsSection = {
|
|
|
81477
81768
|
editAgentPromptAriaLabel: "编辑代理提示",
|
|
81478
81769
|
periodicAgentsHelp: "可选。选择要包含在主动外联轮换中的代理。"
|
|
81479
81770
|
};
|
|
81771
|
+
var componentsTemplateActionsSection = {
|
|
81772
|
+
title: "测试与重置",
|
|
81773
|
+
description: "在您的收件箱中预览模板,或放弃本平台的自定义内容。",
|
|
81774
|
+
testEmailLabel: "发送测试邮件",
|
|
81775
|
+
testEmailHelper: "将此模板的一次渲染结果发送至您输入的地址。",
|
|
81776
|
+
testEmailPlaceholder: "you@example.com",
|
|
81777
|
+
sendTest: "发送测试邮件",
|
|
81778
|
+
sendingTest: "发送中...",
|
|
81779
|
+
testSuccessTitle: "测试邮件已发送",
|
|
81780
|
+
testSuccessDescription: "已发送至 {email}。",
|
|
81781
|
+
testErrorTitle: "无法发送测试邮件",
|
|
81782
|
+
testErrorDescription: "请检查地址后重试。",
|
|
81783
|
+
resetLabel: "重置为默认值",
|
|
81784
|
+
resetHelper: "放弃本平台的副本并恢复默认模板。",
|
|
81785
|
+
reset: "重置为默认值",
|
|
81786
|
+
resetting: "重置中...",
|
|
81787
|
+
resetConfirmTitle: "要重置此模板吗?",
|
|
81788
|
+
resetConfirmDescription: "本平台的自定义内容将被放弃并恢复默认模板。此操作无法撤销。",
|
|
81789
|
+
resetConfirmCancel: "取消",
|
|
81790
|
+
resetConfirmAction: "重置模板",
|
|
81791
|
+
resetSuccessTitle: "模板已重置",
|
|
81792
|
+
resetSuccessDescription: "已恢复平台默认设置。",
|
|
81793
|
+
resetErrorTitle: "无法重置模板",
|
|
81794
|
+
resetErrorDescription: "请重试。"
|
|
81795
|
+
};
|
|
81796
|
+
var componentsTemplateVariablesHelper = {
|
|
81797
|
+
title: "可用变量",
|
|
81798
|
+
copyHint: "点击变量即可复制,然后粘贴到主题或正文中。",
|
|
81799
|
+
insertHint: "点击变量即可插入。",
|
|
81800
|
+
copiedToast: "已将 {token} 复制到剪贴板。",
|
|
81801
|
+
copyUnavailableToast: "请手动复制 {token}:剪贴板不可用。",
|
|
81802
|
+
copyAriaLabel: "复制变量 {name}",
|
|
81803
|
+
insertAriaLabel: "插入变量 {name}"
|
|
81804
|
+
};
|
|
81805
|
+
var componentsUserProgressSettingsSection = {
|
|
81806
|
+
scheduleTitle: "发送计划与统计周期",
|
|
81807
|
+
scheduleDescription: "选择摘要的发送频率及其涵盖的时间范围。",
|
|
81808
|
+
frequencyLabel: "频率",
|
|
81809
|
+
selectFrequencyAriaLabel: "选择频率",
|
|
81810
|
+
selectFrequencyPlaceholder: "选择频率",
|
|
81811
|
+
daily: "每天",
|
|
81812
|
+
weekly: "每周",
|
|
81813
|
+
monthly: "每月",
|
|
81814
|
+
custom: "自定义",
|
|
81815
|
+
cadenceDaily: "每天在下方设定的时间发送。",
|
|
81816
|
+
cadenceWeekly: "每周一在下方设定的时间发送。",
|
|
81817
|
+
cadenceMonthly: "每月 1 日在下方设定的时间发送。",
|
|
81818
|
+
cadenceCustom: "每 {days} 天在下方设定的时间发送。",
|
|
81819
|
+
cadenceCustomUnset: "设置自定义间隔以确定摘要的发送频率。",
|
|
81820
|
+
executionTimeLabel: "发送时间",
|
|
81821
|
+
executionTimeRequired: "请指定摘要的发送时间。",
|
|
81822
|
+
timezoneLabel: "时区",
|
|
81823
|
+
selectTimezoneAriaLabel: "选择时区",
|
|
81824
|
+
selectTimezonePlaceholder: "选择时区",
|
|
81825
|
+
useLocalTimezone: "使用本地时区({timezone})",
|
|
81826
|
+
customIntervalLabel: "自定义间隔(天)",
|
|
81827
|
+
customIntervalRequired: "请设置两次发送之间相隔的天数。",
|
|
81828
|
+
dayRangeError: "请输入 1 到 365 之间的整数天数。",
|
|
81829
|
+
lookbackLabel: "统计周期(天)",
|
|
81830
|
+
lookbackHelp: "每份摘要回溯统计的时间范围。它与发送频率相互独立——每周发送的邮件也可以统计最近 30 天的数据。",
|
|
81831
|
+
lookbackRequired: "请设置以天为单位的统计周期。",
|
|
81832
|
+
dataPointsLabel: "包含的数据项",
|
|
81833
|
+
dataPointsHelp: "邮件仅显示已启用且该学习者有相应数据的板块。",
|
|
81834
|
+
dataPointCoursesProgressed: "课程进展",
|
|
81835
|
+
dataPointCoursesCompleted: "已完成课程",
|
|
81836
|
+
dataPointCredentialsEarned: "已获得证书",
|
|
81837
|
+
dataPointTimeSpent: "学习时长",
|
|
81838
|
+
dataPointActiveDays: "活跃天数",
|
|
81839
|
+
dataPointMentorsAccessed: "AI 代理活动",
|
|
81840
|
+
noDataPointsWarning: "未选择任何数据项——摘要将没有内容可显示。"
|
|
81841
|
+
};
|
|
81842
|
+
var componentsWatcherEmailSection = {
|
|
81843
|
+
title: "关注者邮件",
|
|
81844
|
+
description: "发送给学习者的关注者,例如家长或主管。",
|
|
81845
|
+
fallbackNotice: "关注者目前收到的是学习者邮件。自定义后可向他们发送不同的内容。",
|
|
81846
|
+
customize: "自定义关注者邮件",
|
|
81847
|
+
useLearnerEmail: "使用学习者邮件",
|
|
81848
|
+
subjectLabel: "关注者邮件主题",
|
|
81849
|
+
subjectHelper: "支持与学习者邮件相同的变量,另加 learner_name。",
|
|
81850
|
+
subjectFallbackHelper: "留空则关注者收到学习者邮件的主题。",
|
|
81851
|
+
subjectPlaceholder: "请输入关注者邮件主题...",
|
|
81852
|
+
bodyLabel: "关注者邮件正文",
|
|
81853
|
+
bodyHelper: "支持与学习者邮件相同的变量,另加 learner_name。",
|
|
81854
|
+
bodyFallbackHelper: "留空则关注者收到学习者邮件的正文。",
|
|
81855
|
+
bodyPlaceholder: "请输入关注者邮件正文..."
|
|
81856
|
+
};
|
|
81480
81857
|
var courseContentAccessiblePaginate = {
|
|
81481
81858
|
pagination: "分页"
|
|
81482
81859
|
};
|
|
@@ -82679,7 +83056,14 @@ var notificationsEditAlertDialog = {
|
|
|
82679
83056
|
toastErrorDescription: "更新模板失败,请重试。",
|
|
82680
83057
|
cancel: "取消",
|
|
82681
83058
|
saving: "保存中...",
|
|
82682
|
-
saveChanges: "保存更改"
|
|
83059
|
+
saveChanges: "保存更改",
|
|
83060
|
+
learnerEmailSubjectLabel: "学习者邮件主题",
|
|
83061
|
+
learnerEmailSubjectHelper: "必填。支持模板变量——请参阅正文下方的列表。",
|
|
83062
|
+
learnerEmailBodyLabel: "学习者邮件正文",
|
|
83063
|
+
learnerEmailBodyHelper: "必填。请使用“您好,”问候,而不要使用用户名——用户名通常是自动生成的。",
|
|
83064
|
+
noChangesToast: "没有需要保存的更改。",
|
|
83065
|
+
toastValidationTitle: "请检查高亮显示的字段",
|
|
83066
|
+
toastValidationDescription: "部分值被拒绝。请检查标记为红色的字段。"
|
|
82683
83067
|
};
|
|
82684
83068
|
var notificationsNotificationDisplay = {
|
|
82685
83069
|
notificationsAriaLabel: "通知",
|
|
@@ -85664,6 +86048,10 @@ var zh = {
|
|
|
85664
86048
|
componentsPolicyAssignmentSection: componentsPolicyAssignmentSection,
|
|
85665
86049
|
componentsPolicyConfigDialog: componentsPolicyConfigDialog,
|
|
85666
86050
|
componentsProactiveSettingsSection: componentsProactiveSettingsSection,
|
|
86051
|
+
componentsTemplateActionsSection: componentsTemplateActionsSection,
|
|
86052
|
+
componentsTemplateVariablesHelper: componentsTemplateVariablesHelper,
|
|
86053
|
+
componentsUserProgressSettingsSection: componentsUserProgressSettingsSection,
|
|
86054
|
+
componentsWatcherEmailSection: componentsWatcherEmailSection,
|
|
85667
86055
|
courseContentAccessiblePaginate: courseContentAccessiblePaginate,
|
|
85668
86056
|
courseContentCourseContentLayout: courseContentCourseContentLayout,
|
|
85669
86057
|
courseContentDiscoverFacetsFilter: courseContentDiscoverFacetsFilter,
|
|
@@ -186339,6 +186727,548 @@ function HumanSupportSection({ platformKey, isSaving, recipientMode, onRecipient
|
|
|
186339
186727
|
return (jsxs("div", { className: "space-y-4 border-t border-gray-200 pt-4", children: [jsxs("div", { className: "space-y-1", children: [jsx("h3", { className: "text-sm font-semibold text-gray-900", children: t('componentsHumanSupportSection.heading') }), jsx("p", { className: "text-xs text-gray-500", children: t('componentsHumanSupportSection.headingDescription') })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "recipient-mode", className: "text-sm font-medium text-gray-700", children: t('componentsHumanSupportSection.recipientModeLabel') }), jsxs(Select$1, { value: recipientMode, onValueChange: (value) => onRecipientModeChange(value), disabled: isSaving, children: [jsx(SelectTrigger, { id: "recipient-mode", className: "w-full", children: jsx(SelectValue, { placeholder: t('componentsHumanSupportSection.recipientModePlaceholder') }) }), jsx(SelectContent, { children: RECIPIENT_MODE_OPTIONS.map((option) => (jsx(SelectItem, { value: option.value, children: t(option.labelKey) }, option.value))) })] }), jsx("p", { id: "recipient-mode-help", className: "text-xs text-gray-500", children: t('componentsHumanSupportSection.recipientModeHelp') })] }), isCustomMode && (jsxs("div", { className: "space-y-4 pl-4 border-l-2 border-gray-200", children: [jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", htmlFor: "custom-users", children: t('componentsHumanSupportSection.usersLabel') }), jsx(SearchableMultiSelect, { items: userList, selectedItems: selectedUsers, onSelectionChange: handleUserSelectionChange, searchQuery: userSearch, onSearchChange: setUserSearch, isLoading: isUsersLoading, placeholder: t('componentsHumanSupportSection.usersSearchPlaceholder'), getItemValue: (user) => String(user.user_id), getItemLabel: (user) => user.name || user.username || user.email || String(user.user_id), inputId: "custom-users", ariaDescribedBy: "custom-users-help", className: "max-w-full" }), jsx("p", { id: "custom-users-help", className: "text-xs text-gray-500", children: t('componentsHumanSupportSection.usersHelp') })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", htmlFor: "custom-groups", children: t('componentsHumanSupportSection.groupsLabel') }), jsx(SearchableMultiSelect, { items: groupList, selectedItems: selectedGroups, onSelectionChange: handleGroupSelectionChange, searchQuery: groupSearch, onSearchChange: setGroupSearch, isLoading: isGroupsLoading, placeholder: t('componentsHumanSupportSection.groupsSearchPlaceholder'), getItemValue: (group) => String(group.id), getItemLabel: (group) => group.name, inputId: "custom-groups", ariaDescribedBy: "custom-groups-help", className: "max-w-full" }), jsx("p", { id: "custom-groups-help", className: "text-xs text-gray-500", children: t('componentsHumanSupportSection.groupsHelp') })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", htmlFor: "custom-policies", children: t('componentsHumanSupportSection.policiesLabel') }), jsx(SearchableMultiSelect, { items: policyList, selectedItems: selectedPolicies, onSelectionChange: handlePolicySelectionChange, searchQuery: policySearch, onSearchChange: setPolicySearch, isLoading: isPoliciesLoading, placeholder: t('componentsHumanSupportSection.policiesSearchPlaceholder'), getItemValue: (policy) => String(policy.id), getItemLabel: (policy) => policy.name, inputId: "custom-policies", ariaDescribedBy: "custom-policies-help", className: "max-w-full" }), jsx("p", { id: "custom-policies-help", className: "text-xs text-gray-500", children: t('componentsHumanSupportSection.policiesHelp') })] })] }))] }));
|
|
186340
186728
|
}
|
|
186341
186729
|
|
|
186730
|
+
/**
|
|
186731
|
+
* Timezone option list for schedule pickers.
|
|
186732
|
+
*
|
|
186733
|
+
* `Intl.supportedValuesOf` is the source of truth where available; the fallback
|
|
186734
|
+
* covers the older runtimes that lack it, and any value already stored on the
|
|
186735
|
+
* template is always included so an existing selection is never dropped.
|
|
186736
|
+
*/
|
|
186737
|
+
const FALLBACK_TIMEZONES = [
|
|
186738
|
+
'UTC',
|
|
186739
|
+
'Africa/Cairo',
|
|
186740
|
+
'Africa/Johannesburg',
|
|
186741
|
+
'Africa/Lagos',
|
|
186742
|
+
'Africa/Nairobi',
|
|
186743
|
+
'America/Anchorage',
|
|
186744
|
+
'America/Argentina/Buenos_Aires',
|
|
186745
|
+
'America/Bogota',
|
|
186746
|
+
'America/Chicago',
|
|
186747
|
+
'America/Denver',
|
|
186748
|
+
'America/Halifax',
|
|
186749
|
+
'America/Lima',
|
|
186750
|
+
'America/Los_Angeles',
|
|
186751
|
+
'America/Mexico_City',
|
|
186752
|
+
'America/New_York',
|
|
186753
|
+
'America/Phoenix',
|
|
186754
|
+
'America/Sao_Paulo',
|
|
186755
|
+
'America/Toronto',
|
|
186756
|
+
'America/Vancouver',
|
|
186757
|
+
'Asia/Bangkok',
|
|
186758
|
+
'Asia/Dubai',
|
|
186759
|
+
'Asia/Hong_Kong',
|
|
186760
|
+
'Asia/Jakarta',
|
|
186761
|
+
'Asia/Jerusalem',
|
|
186762
|
+
'Asia/Kolkata',
|
|
186763
|
+
'Asia/Karachi',
|
|
186764
|
+
'Asia/Manila',
|
|
186765
|
+
'Asia/Riyadh',
|
|
186766
|
+
'Asia/Seoul',
|
|
186767
|
+
'Asia/Shanghai',
|
|
186768
|
+
'Asia/Singapore',
|
|
186769
|
+
'Asia/Tokyo',
|
|
186770
|
+
'Australia/Adelaide',
|
|
186771
|
+
'Australia/Brisbane',
|
|
186772
|
+
'Australia/Melbourne',
|
|
186773
|
+
'Australia/Perth',
|
|
186774
|
+
'Australia/Sydney',
|
|
186775
|
+
'Europe/Amsterdam',
|
|
186776
|
+
'Europe/Athens',
|
|
186777
|
+
'Europe/Berlin',
|
|
186778
|
+
'Europe/Brussels',
|
|
186779
|
+
'Europe/Dublin',
|
|
186780
|
+
'Europe/Istanbul',
|
|
186781
|
+
'Europe/Lisbon',
|
|
186782
|
+
'Europe/London',
|
|
186783
|
+
'Europe/Madrid',
|
|
186784
|
+
'Europe/Moscow',
|
|
186785
|
+
'Europe/Paris',
|
|
186786
|
+
'Europe/Rome',
|
|
186787
|
+
'Europe/Stockholm',
|
|
186788
|
+
'Europe/Warsaw',
|
|
186789
|
+
'Europe/Zurich',
|
|
186790
|
+
'Pacific/Auckland',
|
|
186791
|
+
'Pacific/Honolulu',
|
|
186792
|
+
];
|
|
186793
|
+
/**
|
|
186794
|
+
* Returns the sorted IANA timezone names to offer, guaranteeing that every
|
|
186795
|
+
* value in `ensure` appears in the list.
|
|
186796
|
+
*/
|
|
186797
|
+
const getTimezoneOptions = (...ensure) => {
|
|
186798
|
+
let zones = [];
|
|
186799
|
+
const supportedValuesOf = Intl.supportedValuesOf;
|
|
186800
|
+
if (typeof supportedValuesOf === 'function') {
|
|
186801
|
+
try {
|
|
186802
|
+
zones = supportedValuesOf('timeZone');
|
|
186803
|
+
}
|
|
186804
|
+
catch (_a) {
|
|
186805
|
+
zones = [];
|
|
186806
|
+
}
|
|
186807
|
+
}
|
|
186808
|
+
const options = new Set(zones.length ? zones : FALLBACK_TIMEZONES);
|
|
186809
|
+
for (const zone of ensure) {
|
|
186810
|
+
if (zone) {
|
|
186811
|
+
options.add(zone);
|
|
186812
|
+
}
|
|
186813
|
+
}
|
|
186814
|
+
return Array.from(options).sort((a, b) => a.localeCompare(b));
|
|
186815
|
+
};
|
|
186816
|
+
|
|
186817
|
+
const DAY_BOUNDS = { min: 1, max: 365 };
|
|
186818
|
+
const DATA_POINT_LABEL_KEYS = {
|
|
186819
|
+
courses_progressed: 'dataPointCoursesProgressed',
|
|
186820
|
+
courses_completed: 'dataPointCoursesCompleted',
|
|
186821
|
+
credentials_earned: 'dataPointCredentialsEarned',
|
|
186822
|
+
time_spent: 'dataPointTimeSpent',
|
|
186823
|
+
active_days: 'dataPointActiveDays',
|
|
186824
|
+
mentors_accessed: 'dataPointMentorsAccessed',
|
|
186825
|
+
};
|
|
186826
|
+
const isDayCountInRange = (value) => {
|
|
186827
|
+
const parsed = Number(value);
|
|
186828
|
+
return Number.isInteger(parsed) && parsed >= DAY_BOUNDS.min && parsed <= DAY_BOUNDS.max;
|
|
186829
|
+
};
|
|
186830
|
+
/**
|
|
186831
|
+
* Client-side rules for the schedule fields, shared by the section (which
|
|
186832
|
+
* renders the messages) and the parent dialog (which gates saving on it).
|
|
186833
|
+
*/
|
|
186834
|
+
const validateUserProgressSettings = ({ frequency, executionTime, customIntervalDays, lookbackDays, }) => {
|
|
186835
|
+
const errors = {};
|
|
186836
|
+
if (!executionTime.trim()) {
|
|
186837
|
+
errors.executionTime = 'required';
|
|
186838
|
+
}
|
|
186839
|
+
if (frequency === 'CUSTOM') {
|
|
186840
|
+
if (!customIntervalDays.trim()) {
|
|
186841
|
+
errors.customIntervalDays = 'required';
|
|
186842
|
+
}
|
|
186843
|
+
else if (!isDayCountInRange(customIntervalDays)) {
|
|
186844
|
+
errors.customIntervalDays = 'range';
|
|
186845
|
+
}
|
|
186846
|
+
}
|
|
186847
|
+
if (!lookbackDays.trim()) {
|
|
186848
|
+
errors.lookbackDays = 'required';
|
|
186849
|
+
}
|
|
186850
|
+
else if (!isDayCountInRange(lookbackDays)) {
|
|
186851
|
+
errors.lookbackDays = 'range';
|
|
186852
|
+
}
|
|
186853
|
+
return errors;
|
|
186854
|
+
};
|
|
186855
|
+
/**
|
|
186856
|
+
* Schedule, reporting window and data-point configuration for the User Progress
|
|
186857
|
+
* Summary template.
|
|
186858
|
+
*
|
|
186859
|
+
* Deliberately renders no day-of-week / day-of-month picker: `WEEKLY` always
|
|
186860
|
+
* sends on Monday and `MONTHLY` on day 1, so only the time, timezone and (for
|
|
186861
|
+
* `CUSTOM`) the interval are adjustable.
|
|
186862
|
+
*/
|
|
186863
|
+
function UserProgressSettingsSection({ isSaving, userLocalTimezone, frequency, onFrequencyChange, executionTime, onExecutionTimeChange, timezone, onTimezoneChange, customIntervalDays, onCustomIntervalDaysChange, lookbackDays, onLookbackDaysChange, enabledDataPoints, onEnabledDataPointsChange, serverErrors, }) {
|
|
186864
|
+
var _a, _b, _c, _d, _e, _f;
|
|
186865
|
+
const t = useT();
|
|
186866
|
+
const executionTimeErrorId = 'user-progress-execution-time-error';
|
|
186867
|
+
const customIntervalErrorId = 'user-progress-custom-interval-error';
|
|
186868
|
+
const lookbackErrorId = 'user-progress-lookback-error';
|
|
186869
|
+
const lookbackHelpId = 'user-progress-lookback-help';
|
|
186870
|
+
const cadenceNoticeId = 'user-progress-cadence-notice';
|
|
186871
|
+
const dataPointsHelpId = 'user-progress-data-points-help';
|
|
186872
|
+
const timezoneOptions = useMemo(() => getTimezoneOptions(timezone, userLocalTimezone), [timezone, userLocalTimezone]);
|
|
186873
|
+
const errors = validateUserProgressSettings({
|
|
186874
|
+
frequency,
|
|
186875
|
+
executionTime,
|
|
186876
|
+
customIntervalDays,
|
|
186877
|
+
lookbackDays,
|
|
186878
|
+
});
|
|
186879
|
+
const executionTimeError = (_a = serverErrors === null || serverErrors === void 0 ? void 0 : serverErrors.user_progress_execution_time) !== null && _a !== void 0 ? _a : (errors.executionTime ? t('componentsUserProgressSettingsSection.executionTimeRequired') : '');
|
|
186880
|
+
const customIntervalError = (_b = serverErrors === null || serverErrors === void 0 ? void 0 : serverErrors.user_progress_custom_interval_days) !== null && _b !== void 0 ? _b : (errors.customIntervalDays === 'required'
|
|
186881
|
+
? t('componentsUserProgressSettingsSection.customIntervalRequired')
|
|
186882
|
+
: errors.customIntervalDays === 'range'
|
|
186883
|
+
? t('componentsUserProgressSettingsSection.dayRangeError')
|
|
186884
|
+
: '');
|
|
186885
|
+
const lookbackError = (_c = serverErrors === null || serverErrors === void 0 ? void 0 : serverErrors.user_progress_lookback_days) !== null && _c !== void 0 ? _c : (errors.lookbackDays === 'required'
|
|
186886
|
+
? t('componentsUserProgressSettingsSection.lookbackRequired')
|
|
186887
|
+
: errors.lookbackDays === 'range'
|
|
186888
|
+
? t('componentsUserProgressSettingsSection.dayRangeError')
|
|
186889
|
+
: '');
|
|
186890
|
+
const frequencyError = (_d = serverErrors === null || serverErrors === void 0 ? void 0 : serverErrors.user_progress_frequency) !== null && _d !== void 0 ? _d : '';
|
|
186891
|
+
const timezoneError = (_e = serverErrors === null || serverErrors === void 0 ? void 0 : serverErrors.user_progress_timezone) !== null && _e !== void 0 ? _e : '';
|
|
186892
|
+
const dataPointsError = (_f = serverErrors === null || serverErrors === void 0 ? void 0 : serverErrors.user_progress_enabled_data_points) !== null && _f !== void 0 ? _f : '';
|
|
186893
|
+
const showUseLocalTimezone = timezone !== userLocalTimezone;
|
|
186894
|
+
const cadenceNotice = (() => {
|
|
186895
|
+
switch (frequency) {
|
|
186896
|
+
case 'DAILY':
|
|
186897
|
+
return t('componentsUserProgressSettingsSection.cadenceDaily');
|
|
186898
|
+
case 'WEEKLY':
|
|
186899
|
+
return t('componentsUserProgressSettingsSection.cadenceWeekly');
|
|
186900
|
+
case 'MONTHLY':
|
|
186901
|
+
return t('componentsUserProgressSettingsSection.cadenceMonthly');
|
|
186902
|
+
case 'CUSTOM':
|
|
186903
|
+
return customIntervalDays && !errors.customIntervalDays
|
|
186904
|
+
? t('componentsUserProgressSettingsSection.cadenceCustom', { days: customIntervalDays })
|
|
186905
|
+
: t('componentsUserProgressSettingsSection.cadenceCustomUnset');
|
|
186906
|
+
default:
|
|
186907
|
+
return '';
|
|
186908
|
+
}
|
|
186909
|
+
})();
|
|
186910
|
+
const handleDataPointToggle = (dataPoint, checked) => {
|
|
186911
|
+
if (checked) {
|
|
186912
|
+
if (enabledDataPoints.includes(dataPoint)) {
|
|
186913
|
+
return;
|
|
186914
|
+
}
|
|
186915
|
+
// Keep the canonical order so the payload is stable across toggles.
|
|
186916
|
+
onEnabledDataPointsChange(USER_PROGRESS_DATA_POINTS.filter((key) => key === dataPoint || enabledDataPoints.includes(key)));
|
|
186917
|
+
return;
|
|
186918
|
+
}
|
|
186919
|
+
onEnabledDataPointsChange(enabledDataPoints.filter((key) => key !== dataPoint));
|
|
186920
|
+
};
|
|
186921
|
+
return (jsxs("div", { className: "space-y-4 border-t border-gray-200 pt-4", "data-testid": "user-progress-settings-section", children: [jsxs("div", { className: "space-y-1", children: [jsx("h3", { className: "text-sm font-semibold text-gray-900", children: t('componentsUserProgressSettingsSection.scheduleTitle') }), jsx("p", { className: "text-xs text-gray-500", children: t('componentsUserProgressSettingsSection.scheduleDescription') })] }), jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "user-progress-frequency", className: "text-sm font-medium text-gray-700", children: t('componentsUserProgressSettingsSection.frequencyLabel') }), jsxs(Select$1, { value: frequency, onValueChange: (value) => onFrequencyChange(value), disabled: isSaving, children: [jsx(SelectTrigger, { id: "user-progress-frequency", "aria-label": t('componentsUserProgressSettingsSection.selectFrequencyAriaLabel'), "aria-describedby": cadenceNoticeId, children: jsx(SelectValue, { placeholder: t('componentsUserProgressSettingsSection.selectFrequencyPlaceholder') }) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "DAILY", children: t('componentsUserProgressSettingsSection.daily') }), jsx(SelectItem, { value: "WEEKLY", children: t('componentsUserProgressSettingsSection.weekly') }), jsx(SelectItem, { value: "MONTHLY", children: t('componentsUserProgressSettingsSection.monthly') }), jsx(SelectItem, { value: "CUSTOM", children: t('componentsUserProgressSettingsSection.custom') })] })] }), jsx("p", { id: cadenceNoticeId, className: "text-xs text-gray-500", children: cadenceNotice }), frequencyError && (jsx("p", { className: "text-sm text-red-600", role: "alert", children: frequencyError }))] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "user-progress-execution-time", className: "text-sm font-medium text-gray-700", children: t('componentsUserProgressSettingsSection.executionTimeLabel') }), jsx(Input, { id: "user-progress-execution-time", type: "time", value: executionTime, onChange: (event) => onExecutionTimeChange(event.target.value), disabled: isSaving, required: true, "aria-required": "true", "aria-invalid": Boolean(executionTimeError), "aria-describedby": executionTimeError ? executionTimeErrorId : undefined }), executionTimeError && (jsx("p", { id: executionTimeErrorId, className: "text-sm text-red-600", role: "alert", children: executionTimeError }))] })] }), jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "user-progress-timezone", className: "text-sm font-medium text-gray-700", children: t('componentsUserProgressSettingsSection.timezoneLabel') }), jsxs(Select$1, { value: timezone, onValueChange: onTimezoneChange, disabled: isSaving, children: [jsx(SelectTrigger, { id: "user-progress-timezone", "aria-label": t('componentsUserProgressSettingsSection.selectTimezoneAriaLabel'), children: jsx(SelectValue, { placeholder: t('componentsUserProgressSettingsSection.selectTimezonePlaceholder') }) }), jsx(SelectContent, { children: timezoneOptions.map((zone) => (jsx(SelectItem, { value: zone, children: zone }, zone))) })] }), showUseLocalTimezone && (jsx(Button$1, { type: "button", variant: "link", size: "sm", className: "px-0", onClick: () => onTimezoneChange(userLocalTimezone), disabled: isSaving, children: t('componentsUserProgressSettingsSection.useLocalTimezone', {
|
|
186922
|
+
timezone: userLocalTimezone,
|
|
186923
|
+
}) })), timezoneError && (jsx("p", { className: "text-sm text-red-600", role: "alert", children: timezoneError }))] }), frequency === 'CUSTOM' && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "user-progress-custom-interval", className: "text-sm font-medium text-gray-700", children: t('componentsUserProgressSettingsSection.customIntervalLabel') }), jsx(Input, { id: "user-progress-custom-interval", type: "number", inputMode: "numeric", min: DAY_BOUNDS.min, max: DAY_BOUNDS.max, step: 1, value: customIntervalDays, onChange: (event) => onCustomIntervalDaysChange(event.target.value), disabled: isSaving, required: true, "aria-required": "true", "aria-invalid": Boolean(customIntervalError), "aria-describedby": customIntervalError ? customIntervalErrorId : undefined }), customIntervalError && (jsx("p", { id: customIntervalErrorId, className: "text-sm text-red-600", role: "alert", children: customIntervalError }))] }))] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "user-progress-lookback", className: "text-sm font-medium text-gray-700", children: t('componentsUserProgressSettingsSection.lookbackLabel') }), jsx("p", { id: lookbackHelpId, className: "text-xs text-gray-500", children: t('componentsUserProgressSettingsSection.lookbackHelp') }), jsx(Input, { id: "user-progress-lookback", type: "number", inputMode: "numeric", min: DAY_BOUNDS.min, max: DAY_BOUNDS.max, step: 1, value: lookbackDays, onChange: (event) => onLookbackDaysChange(event.target.value), disabled: isSaving, required: true, "aria-required": "true", "aria-invalid": Boolean(lookbackError), "aria-describedby": lookbackError ? `${lookbackHelpId} ${lookbackErrorId}` : lookbackHelpId, className: "md:max-w-[12rem]" }), lookbackError && (jsx("p", { id: lookbackErrorId, className: "text-sm text-red-600", role: "alert", children: lookbackError }))] }), jsxs("fieldset", { className: "space-y-2", disabled: isSaving, children: [jsx("legend", { className: "text-sm font-medium text-gray-700", children: t('componentsUserProgressSettingsSection.dataPointsLabel') }), jsx("p", { id: dataPointsHelpId, className: "text-xs text-gray-500", children: t('componentsUserProgressSettingsSection.dataPointsHelp') }), jsx("div", { className: "grid gap-2 sm:grid-cols-2", children: USER_PROGRESS_DATA_POINTS.map((dataPoint) => {
|
|
186924
|
+
const inputId = `user-progress-data-point-${dataPoint}`;
|
|
186925
|
+
return (jsxs("div", { className: "flex items-center gap-2", children: [jsx(Checkbox, { id: inputId, checked: enabledDataPoints.includes(dataPoint), onCheckedChange: (checked) => handleDataPointToggle(dataPoint, checked === true), disabled: isSaving, "aria-describedby": dataPointsHelpId }), jsx(Label$2, { htmlFor: inputId, className: "text-sm font-normal text-gray-700", children: t(`componentsUserProgressSettingsSection.${DATA_POINT_LABEL_KEYS[dataPoint]}`) })] }, dataPoint));
|
|
186926
|
+
}) }), !enabledDataPoints.length && (jsx("p", { className: "text-xs text-amber-700", role: "status", children: t('componentsUserProgressSettingsSection.noDataPointsWarning') })), dataPointsError && (jsx("p", { className: "text-sm text-red-600", role: "alert", children: dataPointsError }))] })] }));
|
|
186927
|
+
}
|
|
186928
|
+
|
|
186929
|
+
/**
|
|
186930
|
+
* Coerces the read-only `available_context` / `watcher_available_context` map
|
|
186931
|
+
* into `{ variable: description }` entries.
|
|
186932
|
+
*
|
|
186933
|
+
* The API documents an object, but some deployments serialize it as a JSON
|
|
186934
|
+
* string, so both are accepted. Anything else yields an empty list, which hides
|
|
186935
|
+
* the helper rather than rendering a broken one.
|
|
186936
|
+
*/
|
|
186937
|
+
const normalizeTemplateContext = (context) => {
|
|
186938
|
+
if (!context) {
|
|
186939
|
+
return [];
|
|
186940
|
+
}
|
|
186941
|
+
let source = context;
|
|
186942
|
+
if (typeof source === 'string') {
|
|
186943
|
+
try {
|
|
186944
|
+
source = JSON.parse(source);
|
|
186945
|
+
}
|
|
186946
|
+
catch (_a) {
|
|
186947
|
+
return [];
|
|
186948
|
+
}
|
|
186949
|
+
}
|
|
186950
|
+
if (!source || typeof source !== 'object' || Array.isArray(source)) {
|
|
186951
|
+
return [];
|
|
186952
|
+
}
|
|
186953
|
+
return Object.entries(source).map(([name, description]) => [
|
|
186954
|
+
name,
|
|
186955
|
+
typeof description === 'string' ? description : '',
|
|
186956
|
+
]);
|
|
186957
|
+
};
|
|
186958
|
+
/** Renders `name` as the Django template token an admin would paste. */
|
|
186959
|
+
const toTemplateToken = (name) => `{{ ${name} }}`;
|
|
186960
|
+
/**
|
|
186961
|
+
* Lists the template variables the API says are available, so the UI never
|
|
186962
|
+
* maintains a static copy of the list.
|
|
186963
|
+
*
|
|
186964
|
+
* Renders nothing when the context is empty or unparseable.
|
|
186965
|
+
*/
|
|
186966
|
+
function TemplateVariablesHelper({ context, onInsert, className, }) {
|
|
186967
|
+
const t = useT();
|
|
186968
|
+
const entries = useMemo(() => normalizeTemplateContext(context), [context]);
|
|
186969
|
+
if (!entries.length) {
|
|
186970
|
+
return null;
|
|
186971
|
+
}
|
|
186972
|
+
const handleActivate = async (name) => {
|
|
186973
|
+
const token = toTemplateToken(name);
|
|
186974
|
+
if (onInsert) {
|
|
186975
|
+
onInsert(token);
|
|
186976
|
+
return;
|
|
186977
|
+
}
|
|
186978
|
+
try {
|
|
186979
|
+
await navigator.clipboard.writeText(token);
|
|
186980
|
+
toast.success(t('componentsTemplateVariablesHelper.copiedToast', { token }));
|
|
186981
|
+
}
|
|
186982
|
+
catch (_a) {
|
|
186983
|
+
// Clipboard access can be denied or unavailable (insecure context); the
|
|
186984
|
+
// token is still readable on screen, so this is not worth an error toast.
|
|
186985
|
+
toast.message(t('componentsTemplateVariablesHelper.copyUnavailableToast', { token }));
|
|
186986
|
+
}
|
|
186987
|
+
};
|
|
186988
|
+
return (jsxs("div", { className: `rounded-md border border-gray-200 bg-gray-50 p-3 ${className !== null && className !== void 0 ? className : ''}`, "data-testid": "template-variables-helper", children: [jsx("p", { className: "text-xs font-medium text-gray-700", children: t('componentsTemplateVariablesHelper.title') }), jsx("p", { className: "text-xs text-gray-500", children: onInsert
|
|
186989
|
+
? t('componentsTemplateVariablesHelper.insertHint')
|
|
186990
|
+
: t('componentsTemplateVariablesHelper.copyHint') }), jsx("dl", { className: "mt-2 grid gap-x-4 gap-y-1 sm:grid-cols-2", children: entries.map(([name, description]) => (jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2", children: [jsx("dt", { children: jsx("button", { type: "button", onClick: () => void handleActivate(name), className: "rounded bg-white px-1.5 py-0.5 font-mono text-xs text-blue-700 ring-1 ring-inset ring-gray-200 hover:bg-blue-50 focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:outline-none", "aria-label": onInsert
|
|
186991
|
+
? t('componentsTemplateVariablesHelper.insertAriaLabel', { name })
|
|
186992
|
+
: t('componentsTemplateVariablesHelper.copyAriaLabel', { name }), children: toTemplateToken(name) }) }), description && jsx("dd", { className: "text-xs text-gray-500", children: description })] }, name))) })] }));
|
|
186993
|
+
}
|
|
186994
|
+
|
|
186995
|
+
/**
|
|
186996
|
+
* Editor for the watcher variant of the email — the copy sent to a learner's
|
|
186997
|
+
* watchers (a parent or manager).
|
|
186998
|
+
*
|
|
186999
|
+
* Both fields are independently nullable: leaving one empty falls back to the
|
|
187000
|
+
* matching learner field, and "use the learner email" clears both.
|
|
187001
|
+
*/
|
|
187002
|
+
function WatcherEmailSection({ isSaving, isCustomized, onCustomizedChange, subject, onSubjectChange, body, onBodyChange, context, serverErrors, }) {
|
|
187003
|
+
var _a, _b;
|
|
187004
|
+
const t = useT();
|
|
187005
|
+
const subjectHelperId = 'watcher-email-subject-helper';
|
|
187006
|
+
const subjectErrorId = 'watcher-email-subject-error';
|
|
187007
|
+
const bodyLabelId = 'watcher-email-body-label';
|
|
187008
|
+
const bodyHelperId = 'watcher-email-body-helper';
|
|
187009
|
+
const bodyErrorId = 'watcher-email-body-error';
|
|
187010
|
+
const subjectError = (_a = serverErrors === null || serverErrors === void 0 ? void 0 : serverErrors.watcher_email_subject) !== null && _a !== void 0 ? _a : '';
|
|
187011
|
+
const bodyError = (_b = serverErrors === null || serverErrors === void 0 ? void 0 : serverErrors.watcher_email_html_template) !== null && _b !== void 0 ? _b : '';
|
|
187012
|
+
return (jsxs("div", { className: "space-y-4 border-t border-gray-200 pt-4", "data-testid": "watcher-email-section", children: [jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [jsxs("div", { className: "space-y-1", children: [jsx("h3", { className: "text-sm font-semibold text-gray-900", children: t('componentsWatcherEmailSection.title') }), jsx("p", { className: "text-xs text-gray-500", children: t('componentsWatcherEmailSection.description') })] }), isCustomized && (jsx(Button$1, { type: "button", variant: "outline", size: "sm", onClick: () => onCustomizedChange(false), disabled: isSaving, children: t('componentsWatcherEmailSection.useLearnerEmail') }))] }), !isCustomized ? (jsxs("div", { className: "rounded-md border border-blue-100 bg-blue-50 p-3", children: [jsx("p", { className: "text-xs text-blue-900", role: "status", children: t('componentsWatcherEmailSection.fallbackNotice') }), jsx(Button$1, { type: "button", variant: "outline", size: "sm", className: "mt-2 bg-white", onClick: () => onCustomizedChange(true), disabled: isSaving, "data-testid": "watcher-email-customize", children: t('componentsWatcherEmailSection.customize') })] })) : (jsxs(Fragment$1, { children: [jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "watcher-email-subject", className: "text-sm font-medium text-gray-700", children: t('componentsWatcherEmailSection.subjectLabel') }), jsx("p", { id: subjectHelperId, className: "text-xs text-gray-500", children: subject.trim()
|
|
187013
|
+
? t('componentsWatcherEmailSection.subjectHelper')
|
|
187014
|
+
: t('componentsWatcherEmailSection.subjectFallbackHelper') }), jsx(Input, { id: "watcher-email-subject", value: subject, onChange: (event) => onSubjectChange(event.target.value), placeholder: t('componentsWatcherEmailSection.subjectPlaceholder'), disabled: isSaving, "aria-invalid": Boolean(subjectError), "aria-describedby": subjectError ? `${subjectHelperId} ${subjectErrorId}` : subjectHelperId }), subjectError && (jsx("p", { id: subjectErrorId, className: "text-sm text-red-600", role: "alert", children: subjectError }))] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "watcher-email-body", id: bodyLabelId, className: "text-sm font-medium text-gray-700", children: t('componentsWatcherEmailSection.bodyLabel') }), jsx("p", { id: bodyHelperId, className: "text-xs text-gray-500", children: body.trim()
|
|
187015
|
+
? t('componentsWatcherEmailSection.bodyHelper')
|
|
187016
|
+
: t('componentsWatcherEmailSection.bodyFallbackHelper') }), jsx(RichTextEditor, { value: body, onChange: onBodyChange, placeholder: t('componentsWatcherEmailSection.bodyPlaceholder'), exportFormat: "html", disabled: isSaving, id: "watcher-email-body", ariaLabelledBy: bodyLabelId, ariaDescribedBy: bodyError ? `${bodyHelperId} ${bodyErrorId}` : bodyHelperId, ariaInvalid: Boolean(bodyError) }), bodyError && (jsx("p", { id: bodyErrorId, className: "text-sm text-red-600", role: "alert", children: bodyError }))] }), jsx(TemplateVariablesHelper, { context: context })] }))] }));
|
|
187017
|
+
}
|
|
187018
|
+
|
|
187019
|
+
var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
|
|
187020
|
+
// @__NO_SIDE_EFFECTS__
|
|
187021
|
+
function createSlottable(ownerName) {
|
|
187022
|
+
const Slottable2 = ({ children }) => {
|
|
187023
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
187024
|
+
};
|
|
187025
|
+
Slottable2.displayName = `${ownerName}.Slottable`;
|
|
187026
|
+
Slottable2.__radixId = SLOTTABLE_IDENTIFIER;
|
|
187027
|
+
return Slottable2;
|
|
187028
|
+
}
|
|
187029
|
+
|
|
187030
|
+
var ROOT_NAME = "AlertDialog";
|
|
187031
|
+
var [createAlertDialogContext] = createContextScope$1(ROOT_NAME, [
|
|
187032
|
+
createDialogScope
|
|
187033
|
+
]);
|
|
187034
|
+
var useDialogScope = createDialogScope();
|
|
187035
|
+
var AlertDialog$1 = (props) => {
|
|
187036
|
+
const { __scopeAlertDialog, ...alertDialogProps } = props;
|
|
187037
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187038
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { ...dialogScope, ...alertDialogProps, modal: true });
|
|
187039
|
+
};
|
|
187040
|
+
AlertDialog$1.displayName = ROOT_NAME;
|
|
187041
|
+
var TRIGGER_NAME = "AlertDialogTrigger";
|
|
187042
|
+
var AlertDialogTrigger = React.forwardRef(
|
|
187043
|
+
(props, forwardedRef) => {
|
|
187044
|
+
const { __scopeAlertDialog, ...triggerProps } = props;
|
|
187045
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187046
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Trigger, { ...dialogScope, ...triggerProps, ref: forwardedRef });
|
|
187047
|
+
}
|
|
187048
|
+
);
|
|
187049
|
+
AlertDialogTrigger.displayName = TRIGGER_NAME;
|
|
187050
|
+
var PORTAL_NAME = "AlertDialogPortal";
|
|
187051
|
+
var AlertDialogPortal$1 = (props) => {
|
|
187052
|
+
const { __scopeAlertDialog, ...portalProps } = props;
|
|
187053
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187054
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { ...dialogScope, ...portalProps });
|
|
187055
|
+
};
|
|
187056
|
+
AlertDialogPortal$1.displayName = PORTAL_NAME;
|
|
187057
|
+
var OVERLAY_NAME = "AlertDialogOverlay";
|
|
187058
|
+
var AlertDialogOverlay$1 = React.forwardRef(
|
|
187059
|
+
(props, forwardedRef) => {
|
|
187060
|
+
const { __scopeAlertDialog, ...overlayProps } = props;
|
|
187061
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187062
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Overlay, { ...dialogScope, ...overlayProps, ref: forwardedRef });
|
|
187063
|
+
}
|
|
187064
|
+
);
|
|
187065
|
+
AlertDialogOverlay$1.displayName = OVERLAY_NAME;
|
|
187066
|
+
var CONTENT_NAME = "AlertDialogContent";
|
|
187067
|
+
var [AlertDialogContentProvider, useAlertDialogContentContext] = createAlertDialogContext(CONTENT_NAME);
|
|
187068
|
+
var Slottable = createSlottable("AlertDialogContent");
|
|
187069
|
+
var AlertDialogContent$1 = React.forwardRef(
|
|
187070
|
+
(props, forwardedRef) => {
|
|
187071
|
+
const { __scopeAlertDialog, children, ...contentProps } = props;
|
|
187072
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187073
|
+
const contentRef = React.useRef(null);
|
|
187074
|
+
const composedRefs = useComposedRefs$1(forwardedRef, contentRef);
|
|
187075
|
+
const cancelRef = React.useRef(null);
|
|
187076
|
+
return /* @__PURE__ */ jsx(
|
|
187077
|
+
DialogPrimitive.WarningProvider,
|
|
187078
|
+
{
|
|
187079
|
+
contentName: CONTENT_NAME,
|
|
187080
|
+
titleName: TITLE_NAME,
|
|
187081
|
+
docsSlug: "alert-dialog",
|
|
187082
|
+
children: /* @__PURE__ */ jsx(AlertDialogContentProvider, { scope: __scopeAlertDialog, cancelRef, children: /* @__PURE__ */ jsxs(
|
|
187083
|
+
DialogPrimitive.Content,
|
|
187084
|
+
{
|
|
187085
|
+
role: "alertdialog",
|
|
187086
|
+
...dialogScope,
|
|
187087
|
+
...contentProps,
|
|
187088
|
+
ref: composedRefs,
|
|
187089
|
+
onOpenAutoFocus: composeEventHandlers$2(contentProps.onOpenAutoFocus, (event) => {
|
|
187090
|
+
event.preventDefault();
|
|
187091
|
+
cancelRef.current?.focus({ preventScroll: true });
|
|
187092
|
+
}),
|
|
187093
|
+
onPointerDownOutside: (event) => event.preventDefault(),
|
|
187094
|
+
onInteractOutside: (event) => event.preventDefault(),
|
|
187095
|
+
children: [
|
|
187096
|
+
/* @__PURE__ */ jsx(Slottable, { children }),
|
|
187097
|
+
/* @__PURE__ */ jsx(DescriptionWarning, { contentRef })
|
|
187098
|
+
]
|
|
187099
|
+
}
|
|
187100
|
+
) })
|
|
187101
|
+
}
|
|
187102
|
+
);
|
|
187103
|
+
}
|
|
187104
|
+
);
|
|
187105
|
+
AlertDialogContent$1.displayName = CONTENT_NAME;
|
|
187106
|
+
var TITLE_NAME = "AlertDialogTitle";
|
|
187107
|
+
var AlertDialogTitle$1 = React.forwardRef(
|
|
187108
|
+
(props, forwardedRef) => {
|
|
187109
|
+
const { __scopeAlertDialog, ...titleProps } = props;
|
|
187110
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187111
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Title, { ...dialogScope, ...titleProps, ref: forwardedRef });
|
|
187112
|
+
}
|
|
187113
|
+
);
|
|
187114
|
+
AlertDialogTitle$1.displayName = TITLE_NAME;
|
|
187115
|
+
var DESCRIPTION_NAME = "AlertDialogDescription";
|
|
187116
|
+
var AlertDialogDescription$1 = React.forwardRef((props, forwardedRef) => {
|
|
187117
|
+
const { __scopeAlertDialog, ...descriptionProps } = props;
|
|
187118
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187119
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Description, { ...dialogScope, ...descriptionProps, ref: forwardedRef });
|
|
187120
|
+
});
|
|
187121
|
+
AlertDialogDescription$1.displayName = DESCRIPTION_NAME;
|
|
187122
|
+
var ACTION_NAME = "AlertDialogAction";
|
|
187123
|
+
var AlertDialogAction$1 = React.forwardRef(
|
|
187124
|
+
(props, forwardedRef) => {
|
|
187125
|
+
const { __scopeAlertDialog, ...actionProps } = props;
|
|
187126
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187127
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Close, { ...dialogScope, ...actionProps, ref: forwardedRef });
|
|
187128
|
+
}
|
|
187129
|
+
);
|
|
187130
|
+
AlertDialogAction$1.displayName = ACTION_NAME;
|
|
187131
|
+
var CANCEL_NAME = "AlertDialogCancel";
|
|
187132
|
+
var AlertDialogCancel$1 = React.forwardRef(
|
|
187133
|
+
(props, forwardedRef) => {
|
|
187134
|
+
const { __scopeAlertDialog, ...cancelProps } = props;
|
|
187135
|
+
const { cancelRef } = useAlertDialogContentContext(CANCEL_NAME, __scopeAlertDialog);
|
|
187136
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187137
|
+
const ref = useComposedRefs$1(forwardedRef, cancelRef);
|
|
187138
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Close, { ...dialogScope, ...cancelProps, ref });
|
|
187139
|
+
}
|
|
187140
|
+
);
|
|
187141
|
+
AlertDialogCancel$1.displayName = CANCEL_NAME;
|
|
187142
|
+
var DescriptionWarning = ({ contentRef }) => {
|
|
187143
|
+
const MESSAGE = `\`${CONTENT_NAME}\` requires a description for the component to be accessible for screen reader users.
|
|
187144
|
+
|
|
187145
|
+
You can add a description to the \`${CONTENT_NAME}\` by passing a \`${DESCRIPTION_NAME}\` component as a child, which also benefits sighted users by adding visible context to the dialog.
|
|
187146
|
+
|
|
187147
|
+
Alternatively, you can use your own component as a description by assigning it an \`id\` and passing the same value to the \`aria-describedby\` prop in \`${CONTENT_NAME}\`. If the description is confusing or duplicative for sighted users, you can use the \`@radix-ui/react-visually-hidden\` primitive as a wrapper around your description component.
|
|
187148
|
+
|
|
187149
|
+
For more information, see https://radix-ui.com/primitives/docs/components/alert-dialog`;
|
|
187150
|
+
React.useEffect(() => {
|
|
187151
|
+
const hasDescription = document.getElementById(
|
|
187152
|
+
contentRef.current?.getAttribute("aria-describedby")
|
|
187153
|
+
);
|
|
187154
|
+
if (!hasDescription) console.warn(MESSAGE);
|
|
187155
|
+
}, [MESSAGE, contentRef]);
|
|
187156
|
+
return null;
|
|
187157
|
+
};
|
|
187158
|
+
var Root2 = AlertDialog$1;
|
|
187159
|
+
var Portal2 = AlertDialogPortal$1;
|
|
187160
|
+
var Overlay2 = AlertDialogOverlay$1;
|
|
187161
|
+
var Content2 = AlertDialogContent$1;
|
|
187162
|
+
var Action = AlertDialogAction$1;
|
|
187163
|
+
var Cancel = AlertDialogCancel$1;
|
|
187164
|
+
var Title2 = AlertDialogTitle$1;
|
|
187165
|
+
var Description2 = AlertDialogDescription$1;
|
|
187166
|
+
|
|
187167
|
+
const AlertDialog = Root2;
|
|
187168
|
+
const AlertDialogPortal = Portal2;
|
|
187169
|
+
const AlertDialogOverlay = React.forwardRef(({ className, ...props }, ref) => (jsx(Overlay2, { className: cn('data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80', className), ...props, ref: ref })));
|
|
187170
|
+
AlertDialogOverlay.displayName = Overlay2.displayName;
|
|
187171
|
+
const AlertDialogContent = React.forwardRef(({ className, ...props }, ref) => (jsxs(AlertDialogPortal, { children: [jsx(AlertDialogOverlay, {}), jsx(Content2, { ref: ref, className: cn('bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg', className), ...props })] })));
|
|
187172
|
+
AlertDialogContent.displayName = Content2.displayName;
|
|
187173
|
+
const AlertDialogHeader = ({ className, ...props }) => (jsx("div", { className: cn('flex flex-col space-y-2 text-center sm:text-left', className), ...props }));
|
|
187174
|
+
AlertDialogHeader.displayName = 'AlertDialogHeader';
|
|
187175
|
+
const AlertDialogFooter = ({ className, ...props }) => (jsx("div", { className: cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className), ...props }));
|
|
187176
|
+
AlertDialogFooter.displayName = 'AlertDialogFooter';
|
|
187177
|
+
const AlertDialogTitle = React.forwardRef(({ className, ...props }, ref) => (jsx(Title2, { ref: ref, className: cn('text-lg font-semibold', className), ...props })));
|
|
187178
|
+
AlertDialogTitle.displayName = Title2.displayName;
|
|
187179
|
+
const AlertDialogDescription = React.forwardRef(({ className, ...props }, ref) => (jsx(Description2, { ref: ref, className: cn('text-muted-foreground text-sm', className), ...props })));
|
|
187180
|
+
AlertDialogDescription.displayName = Description2.displayName;
|
|
187181
|
+
const AlertDialogAction = React.forwardRef(({ className, ...props }, ref) => (jsx(Action, { ref: ref, className: cn(buttonVariants(), className), ...props })));
|
|
187182
|
+
AlertDialogAction.displayName = Action.displayName;
|
|
187183
|
+
const AlertDialogCancel = React.forwardRef(({ className, ...props }, ref) => (jsx(Cancel, { ref: ref, className: cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', className), ...props })));
|
|
187184
|
+
AlertDialogCancel.displayName = Cancel.displayName;
|
|
187185
|
+
|
|
187186
|
+
/** Rough client-side check; the server remains the authority. */
|
|
187187
|
+
const isProbableEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim());
|
|
187188
|
+
/**
|
|
187189
|
+
* "Reset to default" and "Send test email" actions for a notification template.
|
|
187190
|
+
*
|
|
187191
|
+
* Reset discards the platform-specific copy, so it is confirmed before firing.
|
|
187192
|
+
*/
|
|
187193
|
+
function TemplateActionsSection({ platformKey, notificationType, isSaving, onResetComplete, }) {
|
|
187194
|
+
const t = useT();
|
|
187195
|
+
const [testEmail, setTestEmail] = useState('');
|
|
187196
|
+
const [isResetConfirmOpen, setIsResetConfirmOpen] = useState(false);
|
|
187197
|
+
const [resetTemplate, { isLoading: isResetting }] = useResetTemplateMutation();
|
|
187198
|
+
const [sendTestEmail, { isLoading: isSendingTest }] = useSendTestTemplateEmailMutation();
|
|
187199
|
+
const testEmailHelperId = 'template-test-email-helper';
|
|
187200
|
+
const isTestEmailValid = isProbableEmail(testEmail);
|
|
187201
|
+
const isBusy = isSaving || isResetting || isSendingTest;
|
|
187202
|
+
const handleReset = async () => {
|
|
187203
|
+
try {
|
|
187204
|
+
await resetTemplate({ platformKey, notificationType }).unwrap();
|
|
187205
|
+
toast.success(t('componentsTemplateActionsSection.resetSuccessTitle'), {
|
|
187206
|
+
description: t('componentsTemplateActionsSection.resetSuccessDescription'),
|
|
187207
|
+
});
|
|
187208
|
+
onResetComplete === null || onResetComplete === void 0 ? void 0 : onResetComplete();
|
|
187209
|
+
}
|
|
187210
|
+
catch (error) {
|
|
187211
|
+
console.error('Error resetting notification template:', error);
|
|
187212
|
+
toast.error(t('componentsTemplateActionsSection.resetErrorTitle'), {
|
|
187213
|
+
description: t('componentsTemplateActionsSection.resetErrorDescription'),
|
|
187214
|
+
});
|
|
187215
|
+
}
|
|
187216
|
+
finally {
|
|
187217
|
+
setIsResetConfirmOpen(false);
|
|
187218
|
+
}
|
|
187219
|
+
};
|
|
187220
|
+
// Reachable only with a valid address: the button is disabled otherwise.
|
|
187221
|
+
const handleSendTest = async () => {
|
|
187222
|
+
try {
|
|
187223
|
+
await sendTestEmail({
|
|
187224
|
+
platformKey,
|
|
187225
|
+
notificationType,
|
|
187226
|
+
testEmail: testEmail.trim(),
|
|
187227
|
+
}).unwrap();
|
|
187228
|
+
toast.success(t('componentsTemplateActionsSection.testSuccessTitle'), {
|
|
187229
|
+
description: t('componentsTemplateActionsSection.testSuccessDescription', {
|
|
187230
|
+
email: testEmail.trim(),
|
|
187231
|
+
}),
|
|
187232
|
+
});
|
|
187233
|
+
}
|
|
187234
|
+
catch (error) {
|
|
187235
|
+
console.error('Error sending test notification email:', error);
|
|
187236
|
+
toast.error(t('componentsTemplateActionsSection.testErrorTitle'), {
|
|
187237
|
+
description: t('componentsTemplateActionsSection.testErrorDescription'),
|
|
187238
|
+
});
|
|
187239
|
+
}
|
|
187240
|
+
};
|
|
187241
|
+
return (jsxs("div", { className: "space-y-4 border-t border-gray-200 pt-4", "data-testid": "template-actions-section", children: [jsxs("div", { className: "space-y-1", children: [jsx("h3", { className: "text-sm font-semibold text-gray-900", children: t('componentsTemplateActionsSection.title') }), jsx("p", { className: "text-xs text-gray-500", children: t('componentsTemplateActionsSection.description') })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "template-test-email", className: "text-sm font-medium text-gray-700", children: t('componentsTemplateActionsSection.testEmailLabel') }), jsx("p", { id: testEmailHelperId, className: "text-xs text-gray-500", children: t('componentsTemplateActionsSection.testEmailHelper') }), jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [jsx(Input, { id: "template-test-email", type: "email", value: testEmail, onChange: (event) => setTestEmail(event.target.value), placeholder: t('componentsTemplateActionsSection.testEmailPlaceholder'), disabled: isBusy, "aria-describedby": testEmailHelperId, className: "sm:max-w-xs" }), jsx(Button$1, { type: "button", variant: "outline", onClick: () => void handleSendTest(), disabled: isBusy || !isTestEmailValid, "data-testid": "template-send-test-email", children: isSendingTest
|
|
187242
|
+
? t('componentsTemplateActionsSection.sendingTest')
|
|
187243
|
+
: t('componentsTemplateActionsSection.sendTest') })] })] }), jsxs("div", { className: "space-y-2", children: [jsx("p", { className: "text-sm font-medium text-gray-700", children: t('componentsTemplateActionsSection.resetLabel') }), jsx("p", { className: "text-xs text-gray-500", children: t('componentsTemplateActionsSection.resetHelper') }), jsx(Button$1, { type: "button", variant: "outline", className: "text-red-600 hover:text-red-700", onClick: () => setIsResetConfirmOpen(true), disabled: isBusy, "data-testid": "template-reset-to-default", children: isResetting
|
|
187244
|
+
? t('componentsTemplateActionsSection.resetting')
|
|
187245
|
+
: t('componentsTemplateActionsSection.reset') })] }), jsx(AlertDialog, { open: isResetConfirmOpen, onOpenChange: setIsResetConfirmOpen, children: jsxs(AlertDialogContent, { children: [jsxs(AlertDialogHeader, { children: [jsx(AlertDialogTitle, { children: t('componentsTemplateActionsSection.resetConfirmTitle') }), jsx(AlertDialogDescription, { children: t('componentsTemplateActionsSection.resetConfirmDescription') })] }), jsxs(AlertDialogFooter, { children: [jsx(AlertDialogCancel, { disabled: isResetting, children: t('componentsTemplateActionsSection.resetConfirmCancel') }), jsx(AlertDialogAction, { onClick: (event) => {
|
|
187246
|
+
// Keep the dialog mounted until the request settles.
|
|
187247
|
+
event.preventDefault();
|
|
187248
|
+
void handleReset();
|
|
187249
|
+
}, disabled: isResetting, className: "bg-red-600 hover:bg-red-700", children: t('componentsTemplateActionsSection.resetConfirmAction') })] })] }) })] }));
|
|
187250
|
+
}
|
|
187251
|
+
|
|
187252
|
+
/**
|
|
187253
|
+
* Removes HTML tags from `value`.
|
|
187254
|
+
*
|
|
187255
|
+
* A single pass of `/<[^>]*>/g` is unsafe: stripping the inner match of nested
|
|
187256
|
+
* markup such as `<<div>script>` re-forms a live `<script>` tag in the output.
|
|
187257
|
+
* Replacing until the string stops changing guarantees no tag can be
|
|
187258
|
+
* reconstructed by the removal itself.
|
|
187259
|
+
*/
|
|
187260
|
+
const stripHtmlTags = (value) => {
|
|
187261
|
+
let previous = value;
|
|
187262
|
+
let current = value.replace(/<[^>]*>/g, '');
|
|
187263
|
+
while (current !== previous) {
|
|
187264
|
+
previous = current;
|
|
187265
|
+
current = current.replace(/<[^>]*>/g, '');
|
|
187266
|
+
}
|
|
187267
|
+
return current;
|
|
187268
|
+
};
|
|
187269
|
+
|
|
187270
|
+
const DEFAULT_TIMEZONE = 'UTC';
|
|
187271
|
+
/** Normalizes an API time value to the `"HH:MM"` an `<input type="time">` wants. */
|
|
186342
187272
|
const toTimeString = (value) => {
|
|
186343
187273
|
if (!value) {
|
|
186344
187274
|
return '';
|
|
@@ -186352,7 +187282,6 @@ const toTimeString = (value) => {
|
|
|
186352
187282
|
}
|
|
186353
187283
|
return date.toISOString().slice(11, 16);
|
|
186354
187284
|
};
|
|
186355
|
-
const DEFAULT_TIMEZONE = 'UTC';
|
|
186356
187285
|
const isValidTimeZone$1 = (value) => {
|
|
186357
187286
|
if (!value) {
|
|
186358
187287
|
return false;
|
|
@@ -186365,6 +187294,10 @@ const isValidTimeZone$1 = (value) => {
|
|
|
186365
187294
|
return false;
|
|
186366
187295
|
}
|
|
186367
187296
|
};
|
|
187297
|
+
/**
|
|
187298
|
+
* Returns the first valid IANA zone among `candidates`, falling back to the
|
|
187299
|
+
* viewer's own zone and finally to UTC.
|
|
187300
|
+
*/
|
|
186368
187301
|
const resolveTimezone = (...candidates) => {
|
|
186369
187302
|
for (const candidate of candidates) {
|
|
186370
187303
|
if (isValidTimeZone$1(candidate)) {
|
|
@@ -186377,6 +187310,144 @@ const resolveTimezone = (...candidates) => {
|
|
|
186377
187310
|
}
|
|
186378
187311
|
return DEFAULT_TIMEZONE;
|
|
186379
187312
|
};
|
|
187313
|
+
/** First candidate that is neither `undefined` nor `null`. */
|
|
187314
|
+
const firstDefined = (...candidates) => {
|
|
187315
|
+
for (const candidate of candidates) {
|
|
187316
|
+
if (candidate !== undefined && candidate !== null) {
|
|
187317
|
+
return candidate;
|
|
187318
|
+
}
|
|
187319
|
+
}
|
|
187320
|
+
return undefined;
|
|
187321
|
+
};
|
|
187322
|
+
|
|
187323
|
+
const DEFAULT_USER_PROGRESS_LOOKBACK_DAYS = '7';
|
|
187324
|
+
const DEFAULT_USER_PROGRESS_FREQUENCY = 'WEEKLY';
|
|
187325
|
+
/**
|
|
187326
|
+
* Pulls a progress config out of `metadata`, which arrives as an object on
|
|
187327
|
+
* current backends and as a JSON string on older ones.
|
|
187328
|
+
*/
|
|
187329
|
+
const readMetadataConfig = (metadata) => {
|
|
187330
|
+
var _a;
|
|
187331
|
+
let source = metadata;
|
|
187332
|
+
if (typeof source === 'string') {
|
|
187333
|
+
try {
|
|
187334
|
+
source = JSON.parse(source);
|
|
187335
|
+
}
|
|
187336
|
+
catch (_b) {
|
|
187337
|
+
return undefined;
|
|
187338
|
+
}
|
|
187339
|
+
}
|
|
187340
|
+
if (!source || typeof source !== 'object' || Array.isArray(source)) {
|
|
187341
|
+
return undefined;
|
|
187342
|
+
}
|
|
187343
|
+
const container = source;
|
|
187344
|
+
const config = (_a = container.user_progress_config) !== null && _a !== void 0 ? _a : container.courses_progress_config;
|
|
187345
|
+
return config && typeof config === 'object'
|
|
187346
|
+
? config
|
|
187347
|
+
: undefined;
|
|
187348
|
+
};
|
|
187349
|
+
const toDayString = (value) => typeof value === 'number' && Number.isFinite(value) ? String(value) : '';
|
|
187350
|
+
/**
|
|
187351
|
+
* Reads the schedule, reporting window and data points out of a template
|
|
187352
|
+
* detail response.
|
|
187353
|
+
*
|
|
187354
|
+
* The same settings can arrive in five places, so every field is resolved
|
|
187355
|
+
* through this precedence:
|
|
187356
|
+
*
|
|
187357
|
+
* 1. flat `user_progress_*`
|
|
187358
|
+
* 2. nested `user_progress_config`
|
|
187359
|
+
* 3. flat `courses_progress_*` (deprecated)
|
|
187360
|
+
* 4. nested `courses_progress_config` (deprecated — what backends return today)
|
|
187361
|
+
* 5. `metadata.courses_progress_config`
|
|
187362
|
+
*
|
|
187363
|
+
* Resolving per field rather than picking one source means a partially
|
|
187364
|
+
* populated `user_progress_config` cannot mask a fully populated legacy one.
|
|
187365
|
+
*/
|
|
187366
|
+
const readUserProgressSettings = (detail) => {
|
|
187367
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
187368
|
+
const template = detail !== null && detail !== void 0 ? detail : {};
|
|
187369
|
+
const newConfig = template.user_progress_config;
|
|
187370
|
+
const legacyConfig = (_a = template.courses_progress_config) !== null && _a !== void 0 ? _a : undefined;
|
|
187371
|
+
const metadataConfig = readMetadataConfig(template.metadata);
|
|
187372
|
+
const frequency = firstDefined(template.user_progress_frequency, (_b = newConfig === null || newConfig === void 0 ? void 0 : newConfig.schedule) === null || _b === void 0 ? void 0 : _b.frequency, template.courses_progress_frequency, (_c = legacyConfig === null || legacyConfig === void 0 ? void 0 : legacyConfig.schedule) === null || _c === void 0 ? void 0 : _c.frequency, (_d = metadataConfig === null || metadataConfig === void 0 ? void 0 : metadataConfig.schedule) === null || _d === void 0 ? void 0 : _d.frequency);
|
|
187373
|
+
const executionTime = firstDefined(template.user_progress_execution_time, (_e = newConfig === null || newConfig === void 0 ? void 0 : newConfig.schedule) === null || _e === void 0 ? void 0 : _e.execution_time, template.courses_progress_execution_time, (_f = legacyConfig === null || legacyConfig === void 0 ? void 0 : legacyConfig.schedule) === null || _f === void 0 ? void 0 : _f.execution_time, (_g = metadataConfig === null || metadataConfig === void 0 ? void 0 : metadataConfig.schedule) === null || _g === void 0 ? void 0 : _g.execution_time);
|
|
187374
|
+
const timezone = firstDefined(template.user_progress_timezone, (_h = newConfig === null || newConfig === void 0 ? void 0 : newConfig.schedule) === null || _h === void 0 ? void 0 : _h.timezone, template.courses_progress_timezone, (_j = legacyConfig === null || legacyConfig === void 0 ? void 0 : legacyConfig.schedule) === null || _j === void 0 ? void 0 : _j.timezone, (_k = metadataConfig === null || metadataConfig === void 0 ? void 0 : metadataConfig.schedule) === null || _k === void 0 ? void 0 : _k.timezone);
|
|
187375
|
+
const customIntervalDays = firstDefined(template.user_progress_custom_interval_days, (_l = newConfig === null || newConfig === void 0 ? void 0 : newConfig.schedule) === null || _l === void 0 ? void 0 : _l.custom_interval_days, template.courses_progress_custom_interval_days, (_m = legacyConfig === null || legacyConfig === void 0 ? void 0 : legacyConfig.schedule) === null || _m === void 0 ? void 0 : _m.custom_interval_days, (_o = metadataConfig === null || metadataConfig === void 0 ? void 0 : metadataConfig.schedule) === null || _o === void 0 ? void 0 : _o.custom_interval_days);
|
|
187376
|
+
const lookbackDays = firstDefined(template.user_progress_lookback_days, newConfig === null || newConfig === void 0 ? void 0 : newConfig.lookback_days, template.courses_progress_lookback_days, legacyConfig === null || legacyConfig === void 0 ? void 0 : legacyConfig.lookback_days, metadataConfig === null || metadataConfig === void 0 ? void 0 : metadataConfig.lookback_days);
|
|
187377
|
+
const enabledDataPoints = firstDefined(template.user_progress_enabled_data_points, newConfig === null || newConfig === void 0 ? void 0 : newConfig.enabled_data_points, template.courses_progress_enabled_data_points, legacyConfig === null || legacyConfig === void 0 ? void 0 : legacyConfig.enabled_data_points, metadataConfig === null || metadataConfig === void 0 ? void 0 : metadataConfig.enabled_data_points);
|
|
187378
|
+
const selected = Array.isArray(enabledDataPoints) ? enabledDataPoints : [];
|
|
187379
|
+
return {
|
|
187380
|
+
frequency: frequency !== null && frequency !== void 0 ? frequency : DEFAULT_USER_PROGRESS_FREQUENCY,
|
|
187381
|
+
executionTime: toTimeString(executionTime),
|
|
187382
|
+
timezone: resolveTimezone(timezone),
|
|
187383
|
+
customIntervalDays: toDayString(customIntervalDays),
|
|
187384
|
+
lookbackDays: toDayString(lookbackDays) || DEFAULT_USER_PROGRESS_LOOKBACK_DAYS,
|
|
187385
|
+
// Drop unknown keys and normalize to the canonical order so the save diff
|
|
187386
|
+
// is order-insensitive.
|
|
187387
|
+
enabledDataPoints: USER_PROGRESS_DATA_POINTS.filter((dataPoint) => selected.includes(dataPoint)),
|
|
187388
|
+
};
|
|
187389
|
+
};
|
|
187390
|
+
/**
|
|
187391
|
+
* `true` when the template has a watcher variant.
|
|
187392
|
+
*
|
|
187393
|
+
* `watcher_available_context` is the documented signal, but backends that
|
|
187394
|
+
* predate it still mark the variant with an `audience:watcher` tag.
|
|
187395
|
+
*/
|
|
187396
|
+
const hasWatcherVariant = (detail, watcherContextEntryCount) => {
|
|
187397
|
+
var _a;
|
|
187398
|
+
if (watcherContextEntryCount > 0) {
|
|
187399
|
+
return true;
|
|
187400
|
+
}
|
|
187401
|
+
return Boolean((_a = detail === null || detail === void 0 ? void 0 : detail.tags) === null || _a === void 0 ? void 0 : _a.includes('audience:watcher'));
|
|
187402
|
+
};
|
|
187403
|
+
|
|
187404
|
+
const GENERAL_ERROR_KEYS = ['detail', 'non_field_errors', 'error', 'message'];
|
|
187405
|
+
const flattenMessage = (value) => {
|
|
187406
|
+
if (typeof value === 'string') {
|
|
187407
|
+
return value;
|
|
187408
|
+
}
|
|
187409
|
+
if (Array.isArray(value)) {
|
|
187410
|
+
return value.map(flattenMessage).filter(Boolean).join(' ');
|
|
187411
|
+
}
|
|
187412
|
+
if (value && typeof value === 'object') {
|
|
187413
|
+
return Object.values(value)
|
|
187414
|
+
.map(flattenMessage)
|
|
187415
|
+
.filter(Boolean)
|
|
187416
|
+
.join(' ');
|
|
187417
|
+
}
|
|
187418
|
+
return '';
|
|
187419
|
+
};
|
|
187420
|
+
/**
|
|
187421
|
+
* Maps a DRF `400` response onto per-field messages.
|
|
187422
|
+
*
|
|
187423
|
+
* `iblFetchBaseQuery` rejects with `{ status, data }`, where `data` is the DRF
|
|
187424
|
+
* body — usually `{ field: ["message"] }`, sometimes `{ detail: "message" }`.
|
|
187425
|
+
* Anything that doesn't match those shapes yields empty results so the caller
|
|
187426
|
+
* falls back to a generic toast.
|
|
187427
|
+
*/
|
|
187428
|
+
const parseTemplateFieldErrors = (error) => {
|
|
187429
|
+
const fieldErrors = {};
|
|
187430
|
+
let generalError;
|
|
187431
|
+
const data = error === null || error === void 0 ? void 0 : error.data;
|
|
187432
|
+
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
187433
|
+
return { fieldErrors, generalError };
|
|
187434
|
+
}
|
|
187435
|
+
for (const [key, value] of Object.entries(data)) {
|
|
187436
|
+
const message = flattenMessage(value);
|
|
187437
|
+
if (!message) {
|
|
187438
|
+
continue;
|
|
187439
|
+
}
|
|
187440
|
+
if (GENERAL_ERROR_KEYS.includes(key)) {
|
|
187441
|
+
generalError = generalError ? `${generalError} ${message}` : message;
|
|
187442
|
+
continue;
|
|
187443
|
+
}
|
|
187444
|
+
fieldErrors[key] = message;
|
|
187445
|
+
}
|
|
187446
|
+
return { fieldErrors, generalError };
|
|
187447
|
+
};
|
|
187448
|
+
/** `true` when the request failed validation rather than erroring some other way. */
|
|
187449
|
+
const isValidationError = (error) => (error === null || error === void 0 ? void 0 : error.status) === 400;
|
|
187450
|
+
|
|
186380
187451
|
const pickFirstNonEmpty = (...candidates) => {
|
|
186381
187452
|
for (const candidate of candidates) {
|
|
186382
187453
|
if (typeof candidate === 'string' && candidate.trim()) {
|
|
@@ -186385,8 +187456,23 @@ const pickFirstNonEmpty = (...candidates) => {
|
|
|
186385
187456
|
}
|
|
186386
187457
|
return '';
|
|
186387
187458
|
};
|
|
187459
|
+
/**
|
|
187460
|
+
* `true` when rich-text HTML carries actual content. An emptied editor still
|
|
187461
|
+
* emits markup such as `<p><br></p>`, which must be treated as "cleared" so the
|
|
187462
|
+
* watcher fields can revert to their learner fallback.
|
|
187463
|
+
*/
|
|
187464
|
+
const hasHtmlContent = (value) => {
|
|
187465
|
+
if (!value) {
|
|
187466
|
+
return false;
|
|
187467
|
+
}
|
|
187468
|
+
if (/<img\b/i.test(value)) {
|
|
187469
|
+
return true;
|
|
187470
|
+
}
|
|
187471
|
+
return stripHtmlTags(value).replace(/ /gi, ' ').trim().length > 0;
|
|
187472
|
+
};
|
|
187473
|
+
const areDataPointsEqual = (a, b) => a.length === b.length && a.every((value, index) => value === b[index]);
|
|
186388
187474
|
function EditAlertDialog({ open, onOpenChange, template, platformKey, templateType, onSave, }) {
|
|
186389
|
-
var _a;
|
|
187475
|
+
var _a, _b, _c, _d, _e;
|
|
186390
187476
|
const t = useT();
|
|
186391
187477
|
const [messageTitle, setMessageTitle] = useState('');
|
|
186392
187478
|
const [messageBody, setMessageBody] = useState('');
|
|
@@ -186403,14 +187489,29 @@ function EditAlertDialog({ open, onOpenChange, template, platformKey, templateTy
|
|
|
186403
187489
|
const [policyNotifyOnRemoval, setPolicyNotifyOnRemoval] = useState(true);
|
|
186404
187490
|
const [humanSupportRecipientMode, setHumanSupportRecipientMode] = useState('platform_admins_and_mentor_owner');
|
|
186405
187491
|
const [humanSupportCustomRecipients, setHumanSupportCustomRecipients] = useState([]);
|
|
187492
|
+
// User Progress Summary settings
|
|
187493
|
+
const [userProgressFrequency, setUserProgressFrequency] = useState(DEFAULT_USER_PROGRESS_FREQUENCY);
|
|
187494
|
+
const [userProgressExecutionTime, setUserProgressExecutionTime] = useState('');
|
|
187495
|
+
const [userProgressTimezone, setUserProgressTimezone] = useState(() => resolveTimezone());
|
|
187496
|
+
const [userProgressCustomIntervalDays, setUserProgressCustomIntervalDays] = useState('');
|
|
187497
|
+
const [userProgressLookbackDays, setUserProgressLookbackDays] = useState(DEFAULT_USER_PROGRESS_LOOKBACK_DAYS);
|
|
187498
|
+
const [userProgressDataPoints, setUserProgressDataPoints] = useState([]);
|
|
187499
|
+
const [watcherEmailSubject, setWatcherEmailSubject] = useState('');
|
|
187500
|
+
const [watcherEmailBody, setWatcherEmailBody] = useState('');
|
|
187501
|
+
const [isWatcherEmailCustomized, setIsWatcherEmailCustomized] = useState(false);
|
|
187502
|
+
/** Inline `400` messages keyed by API field name. */
|
|
187503
|
+
const [fieldErrors, setFieldErrors] = useState({});
|
|
186406
187504
|
const dialogDescriptionId = 'edit-alert-dialog-description';
|
|
186407
187505
|
const messageTitleHelperId = 'edit-alert-message-title-helper';
|
|
187506
|
+
const messageTitleErrorId = 'edit-alert-message-title-error';
|
|
186408
187507
|
const messageBodyLabelId = 'edit-alert-message-body-label';
|
|
186409
187508
|
const messageBodyHelperId = 'edit-alert-message-body-helper';
|
|
187509
|
+
const messageBodyErrorId = 'edit-alert-message-body-error';
|
|
186410
187510
|
const notificationType = (_a = templateType !== null && templateType !== void 0 ? templateType : template === null || template === void 0 ? void 0 : template.type) !== null && _a !== void 0 ? _a : null;
|
|
186411
187511
|
const isProactive = notificationType === 'PROACTIVE_LEARNER_NOTIFICATION';
|
|
186412
187512
|
const isPolicyAssignment = notificationType === 'POLICY_ASSIGNMENT';
|
|
186413
187513
|
const isHumanSupport = notificationType === 'HUMAN_SUPPORT_NOTIFICATION';
|
|
187514
|
+
const isUserProgress = notificationType === USER_PROGRESS_SUMMARY_TYPE;
|
|
186414
187515
|
const [updateTemplate, { isLoading: isSaving }] = useUpdateTemplateMutation();
|
|
186415
187516
|
const shouldFetchTemplateDetails = Boolean(open && platformKey && notificationType);
|
|
186416
187517
|
const userLocalTimezone = useMemo(() => resolveTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone), []);
|
|
@@ -186494,6 +187595,38 @@ function EditAlertDialog({ open, onOpenChange, template, platformKey, templateTy
|
|
|
186494
187595
|
customRecipients: (_b = humanSupportConfig === null || humanSupportConfig === void 0 ? void 0 : humanSupportConfig.custom_recipients) !== null && _b !== void 0 ? _b : [],
|
|
186495
187596
|
};
|
|
186496
187597
|
}, [currentTemplateDetail, isHumanSupport, template]);
|
|
187598
|
+
/**
|
|
187599
|
+
* Seeded values for the learner email. Doubles as the baseline the save diff
|
|
187600
|
+
* compares against, so an untouched field is never PATCHed.
|
|
187601
|
+
*/
|
|
187602
|
+
const learnerEmailSeed = useMemo(() => ({
|
|
187603
|
+
subject: pickFirstNonEmpty(currentTemplateDetail.email_subject, currentTemplateDetail.message_title, template === null || template === void 0 ? void 0 : template.email_subject, template === null || template === void 0 ? void 0 : template.message_title),
|
|
187604
|
+
body: pickFirstNonEmpty(currentTemplateDetail.email_html_template, currentTemplateDetail.message_body, template === null || template === void 0 ? void 0 : template.email_html_template),
|
|
187605
|
+
}), [currentTemplateDetail, template]);
|
|
187606
|
+
/**
|
|
187607
|
+
* Schedule / period / data points. The settings can arrive under several
|
|
187608
|
+
* different keys depending on the backend build, so the resolver walks them
|
|
187609
|
+
* all — see `readUserProgressSettings`.
|
|
187610
|
+
*/
|
|
187611
|
+
const userProgressSettings = useMemo(() => readUserProgressSettings(currentTemplateDetail), [currentTemplateDetail]);
|
|
187612
|
+
const watcherEmailSettings = useMemo(() => {
|
|
187613
|
+
var _a, _b;
|
|
187614
|
+
const subject = (_a = currentTemplateDetail.watcher_email_subject) !== null && _a !== void 0 ? _a : null;
|
|
187615
|
+
const body = (_b = currentTemplateDetail.watcher_email_html_template) !== null && _b !== void 0 ? _b : null;
|
|
187616
|
+
return {
|
|
187617
|
+
subject: subject !== null && subject !== void 0 ? subject : '',
|
|
187618
|
+
body: body !== null && body !== void 0 ? body : '',
|
|
187619
|
+
// Both `null` means watchers currently receive the learner email.
|
|
187620
|
+
isCustomized: Boolean(subject) || Boolean(body),
|
|
187621
|
+
};
|
|
187622
|
+
}, [currentTemplateDetail]);
|
|
187623
|
+
const watcherContext = useMemo(() => normalizeTemplateContext(currentTemplateDetail.watcher_available_context), [currentTemplateDetail]);
|
|
187624
|
+
/**
|
|
187625
|
+
* No watcher variant means the watcher editor is hidden entirely.
|
|
187626
|
+
* `watcher_available_context` is the documented signal; the `audience:watcher`
|
|
187627
|
+
* tag covers backends that don't return that field yet.
|
|
187628
|
+
*/
|
|
187629
|
+
const showWatcherEditor = useMemo(() => hasWatcherVariant(currentTemplateDetail, watcherContext.length), [currentTemplateDetail, watcherContext]);
|
|
186497
187630
|
useEffect(() => {
|
|
186498
187631
|
try {
|
|
186499
187632
|
const storedUserName = getUserName$1();
|
|
@@ -186526,8 +187659,30 @@ function EditAlertDialog({ open, onOpenChange, template, platformKey, templateTy
|
|
|
186526
187659
|
setHumanSupportCustomRecipients([]);
|
|
186527
187660
|
return;
|
|
186528
187661
|
}
|
|
186529
|
-
setMessageTitle(
|
|
186530
|
-
setMessageBody(
|
|
187662
|
+
setMessageTitle(learnerEmailSeed.subject);
|
|
187663
|
+
setMessageBody(learnerEmailSeed.body);
|
|
187664
|
+
if (isUserProgress) {
|
|
187665
|
+
setUserProgressFrequency(userProgressSettings.frequency);
|
|
187666
|
+
setUserProgressExecutionTime(userProgressSettings.executionTime);
|
|
187667
|
+
setUserProgressTimezone(userProgressSettings.timezone);
|
|
187668
|
+
setUserProgressCustomIntervalDays(userProgressSettings.customIntervalDays);
|
|
187669
|
+
setUserProgressLookbackDays(userProgressSettings.lookbackDays);
|
|
187670
|
+
setUserProgressDataPoints(userProgressSettings.enabledDataPoints);
|
|
187671
|
+
setWatcherEmailSubject(watcherEmailSettings.subject);
|
|
187672
|
+
setWatcherEmailBody(watcherEmailSettings.body);
|
|
187673
|
+
setIsWatcherEmailCustomized(watcherEmailSettings.isCustomized);
|
|
187674
|
+
}
|
|
187675
|
+
else {
|
|
187676
|
+
setUserProgressFrequency(DEFAULT_USER_PROGRESS_FREQUENCY);
|
|
187677
|
+
setUserProgressExecutionTime('');
|
|
187678
|
+
setUserProgressTimezone(userLocalTimezone);
|
|
187679
|
+
setUserProgressCustomIntervalDays('');
|
|
187680
|
+
setUserProgressLookbackDays(DEFAULT_USER_PROGRESS_LOOKBACK_DAYS);
|
|
187681
|
+
setUserProgressDataPoints([]);
|
|
187682
|
+
setWatcherEmailSubject('');
|
|
187683
|
+
setWatcherEmailBody('');
|
|
187684
|
+
setIsWatcherEmailCustomized(false);
|
|
187685
|
+
}
|
|
186531
187686
|
if (isProactive) {
|
|
186532
187687
|
setPeriodicLearnerScope(periodicSettings.learnerScope);
|
|
186533
187688
|
setPeriodicFrequency(periodicSettings.frequency);
|
|
@@ -186561,12 +187716,16 @@ function EditAlertDialog({ open, onOpenChange, template, platformKey, templateTy
|
|
|
186561
187716
|
open,
|
|
186562
187717
|
template,
|
|
186563
187718
|
currentTemplateDetail,
|
|
187719
|
+
learnerEmailSeed,
|
|
186564
187720
|
isProactive,
|
|
186565
187721
|
periodicSettings,
|
|
186566
187722
|
isPolicyAssignment,
|
|
186567
187723
|
policySettings,
|
|
186568
187724
|
isHumanSupport,
|
|
186569
187725
|
humanSupportSettings,
|
|
187726
|
+
isUserProgress,
|
|
187727
|
+
userProgressSettings,
|
|
187728
|
+
watcherEmailSettings,
|
|
186570
187729
|
userLocalTimezone,
|
|
186571
187730
|
]);
|
|
186572
187731
|
const handleMentorsChange = useCallback((mentors) => {
|
|
@@ -186579,19 +187738,80 @@ function EditAlertDialog({ open, onOpenChange, template, platformKey, templateTy
|
|
|
186579
187738
|
setHumanSupportCustomRecipients(recipients);
|
|
186580
187739
|
}, []);
|
|
186581
187740
|
const handleSave = async () => {
|
|
186582
|
-
var _a, _b, _c, _d;
|
|
187741
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
186583
187742
|
if (!template || !notificationType)
|
|
186584
187743
|
return;
|
|
187744
|
+
setFieldErrors({});
|
|
186585
187745
|
try {
|
|
186586
187746
|
const templateDetail = currentTemplateDetail;
|
|
186587
187747
|
const periodicConfig = templateDetail.periodic_config;
|
|
186588
187748
|
const timezoneToSave = resolveTimezone(periodicTimezone, templateDetail.periodic_timezone, periodicConfig === null || periodicConfig === void 0 ? void 0 : periodicConfig.timezone);
|
|
186589
187749
|
const executionTimeValue = toTimeString(periodicExecutionTime);
|
|
186590
|
-
const payload = {
|
|
186591
|
-
|
|
186592
|
-
|
|
186593
|
-
|
|
187750
|
+
const payload = {};
|
|
187751
|
+
/**
|
|
187752
|
+
* Writes a schedule field under both prefixes. Backends that understand
|
|
187753
|
+
* `user_progress_*` prefer it; older ones only read `courses_progress_*`,
|
|
187754
|
+
* and unknown keys are ignored either way.
|
|
187755
|
+
*/
|
|
187756
|
+
const writeUserProgressField = (field, value) => {
|
|
187757
|
+
payload[`user_progress_${field}`] = value;
|
|
187758
|
+
payload[`courses_progress_${field}`] = value;
|
|
186594
187759
|
};
|
|
187760
|
+
if (isUserProgress) {
|
|
187761
|
+
// Partial write: only send what the admin actually changed.
|
|
187762
|
+
if (messageTitle !== learnerEmailSeed.subject) {
|
|
187763
|
+
payload.message_title = messageTitle;
|
|
187764
|
+
payload.email_subject = messageTitle;
|
|
187765
|
+
}
|
|
187766
|
+
if (messageBody !== learnerEmailSeed.body) {
|
|
187767
|
+
payload.email_html_template = messageBody;
|
|
187768
|
+
}
|
|
187769
|
+
}
|
|
187770
|
+
else {
|
|
187771
|
+
payload.message_title = messageTitle;
|
|
187772
|
+
payload.email_subject = messageTitle;
|
|
187773
|
+
payload.email_html_template = messageBody;
|
|
187774
|
+
}
|
|
187775
|
+
if (isUserProgress) {
|
|
187776
|
+
if (userProgressFrequency !== userProgressSettings.frequency) {
|
|
187777
|
+
writeUserProgressField('frequency', userProgressFrequency);
|
|
187778
|
+
}
|
|
187779
|
+
const userProgressTime = toTimeString(userProgressExecutionTime);
|
|
187780
|
+
if (userProgressTime !== userProgressSettings.executionTime) {
|
|
187781
|
+
writeUserProgressField('execution_time', userProgressTime);
|
|
187782
|
+
}
|
|
187783
|
+
if (userProgressTimezone !== userProgressSettings.timezone) {
|
|
187784
|
+
writeUserProgressField('timezone', userProgressTimezone);
|
|
187785
|
+
}
|
|
187786
|
+
// Only honored for CUSTOM; the other frequencies use a fixed cadence.
|
|
187787
|
+
if (userProgressFrequency === 'CUSTOM' &&
|
|
187788
|
+
userProgressCustomIntervalDays !== userProgressSettings.customIntervalDays) {
|
|
187789
|
+
writeUserProgressField('custom_interval_days', Number(userProgressCustomIntervalDays));
|
|
187790
|
+
}
|
|
187791
|
+
if (userProgressLookbackDays !== userProgressSettings.lookbackDays) {
|
|
187792
|
+
writeUserProgressField('lookback_days', Number(userProgressLookbackDays));
|
|
187793
|
+
}
|
|
187794
|
+
if (!areDataPointsEqual(userProgressDataPoints, userProgressSettings.enabledDataPoints)) {
|
|
187795
|
+
writeUserProgressField('enabled_data_points', userProgressDataPoints);
|
|
187796
|
+
}
|
|
187797
|
+
if (showWatcherEditor) {
|
|
187798
|
+
// An empty field is sent as `null` so watchers fall back to the
|
|
187799
|
+
// matching learner field.
|
|
187800
|
+
const nextWatcherSubject = isWatcherEmailCustomized && watcherEmailSubject.trim() ? watcherEmailSubject : null;
|
|
187801
|
+
const nextWatcherBody = isWatcherEmailCustomized && hasHtmlContent(watcherEmailBody) ? watcherEmailBody : null;
|
|
187802
|
+
if (nextWatcherSubject !== ((_a = currentTemplateDetail.watcher_email_subject) !== null && _a !== void 0 ? _a : null)) {
|
|
187803
|
+
payload.watcher_email_subject = nextWatcherSubject;
|
|
187804
|
+
}
|
|
187805
|
+
if (nextWatcherBody !== ((_b = currentTemplateDetail.watcher_email_html_template) !== null && _b !== void 0 ? _b : null)) {
|
|
187806
|
+
payload.watcher_email_html_template = nextWatcherBody;
|
|
187807
|
+
}
|
|
187808
|
+
}
|
|
187809
|
+
if (!Object.keys(payload).length) {
|
|
187810
|
+
toast.message(t('notificationsEditAlertDialog.noChangesToast'));
|
|
187811
|
+
onOpenChange(false);
|
|
187812
|
+
return;
|
|
187813
|
+
}
|
|
187814
|
+
}
|
|
186595
187815
|
if (isPolicyAssignment) {
|
|
186596
187816
|
payload.policy_enabled_policies = policyConfigPayload;
|
|
186597
187817
|
payload.policy_notify_on_assignment = policyNotifyOnAssignment;
|
|
@@ -186622,7 +187842,7 @@ function EditAlertDialog({ open, onOpenChange, template, platformKey, templateTy
|
|
|
186622
187842
|
}
|
|
186623
187843
|
}
|
|
186624
187844
|
else {
|
|
186625
|
-
const existingReportPeriod = (
|
|
187845
|
+
const existingReportPeriod = (_c = templateDetail.periodic_report_period_days) !== null && _c !== void 0 ? _c : periodicConfig === null || periodicConfig === void 0 ? void 0 : periodicConfig.report_period_days;
|
|
186626
187846
|
if (typeof existingReportPeriod === 'number') {
|
|
186627
187847
|
payload.periodic_report_period_days = existingReportPeriod;
|
|
186628
187848
|
}
|
|
@@ -186644,7 +187864,7 @@ function EditAlertDialog({ open, onOpenChange, template, platformKey, templateTy
|
|
|
186644
187864
|
(periodicConfig === null || periodicConfig === void 0 ? void 0 : periodicConfig.execution_time));
|
|
186645
187865
|
const customIntervalNumber = periodicFrequency === 'CUSTOM' && periodicCustomIntervalDays
|
|
186646
187866
|
? Number(periodicCustomIntervalDays)
|
|
186647
|
-
: ((
|
|
187867
|
+
: ((_d = template.periodic_custom_interval_days) !== null && _d !== void 0 ? _d : templateDetail.periodic_custom_interval_days);
|
|
186648
187868
|
onSave({
|
|
186649
187869
|
...template,
|
|
186650
187870
|
message_title: messageTitle,
|
|
@@ -186656,7 +187876,7 @@ function EditAlertDialog({ open, onOpenChange, template, platformKey, templateTy
|
|
|
186656
187876
|
periodic_execution_time: executionTimeForTemplate,
|
|
186657
187877
|
periodic_report_period_days: periodicFrequency === 'CUSTOM' && periodicCustomIntervalDays
|
|
186658
187878
|
? Number(periodicCustomIntervalDays)
|
|
186659
|
-
: ((
|
|
187879
|
+
: ((_f = (_e = template.periodic_report_period_days) !== null && _e !== void 0 ? _e : templateDetail.periodic_report_period_days) !== null && _f !== void 0 ? _f : periodicConfig === null || periodicConfig === void 0 ? void 0 : periodicConfig.report_period_days),
|
|
186660
187880
|
periodic_timezone: timezoneToSave ||
|
|
186661
187881
|
template.periodic_timezone ||
|
|
186662
187882
|
templateDetail.periodic_timezone ||
|
|
@@ -186664,12 +187884,29 @@ function EditAlertDialog({ open, onOpenChange, template, platformKey, templateTy
|
|
|
186664
187884
|
resolveTimezone(),
|
|
186665
187885
|
periodic_mentors: mentorPayload,
|
|
186666
187886
|
}),
|
|
187887
|
+
...(isUserProgress && {
|
|
187888
|
+
user_progress_frequency: userProgressFrequency,
|
|
187889
|
+
user_progress_execution_time: toTimeString(userProgressExecutionTime),
|
|
187890
|
+
user_progress_timezone: userProgressTimezone,
|
|
187891
|
+
user_progress_lookback_days: Number(userProgressLookbackDays),
|
|
187892
|
+
user_progress_enabled_data_points: userProgressDataPoints,
|
|
187893
|
+
...(userProgressFrequency === 'CUSTOM' && {
|
|
187894
|
+
user_progress_custom_interval_days: Number(userProgressCustomIntervalDays),
|
|
187895
|
+
}),
|
|
187896
|
+
}),
|
|
186667
187897
|
});
|
|
186668
187898
|
}
|
|
186669
187899
|
onOpenChange(false);
|
|
186670
187900
|
}
|
|
186671
187901
|
catch (error) {
|
|
186672
187902
|
console.error('Error updating template:', error);
|
|
187903
|
+
if (isValidationError(error)) {
|
|
187904
|
+
const { fieldErrors: parsedFieldErrors, generalError } = parseTemplateFieldErrors(error);
|
|
187905
|
+
setFieldErrors(parsedFieldErrors);
|
|
187906
|
+
const description = (_g = generalError !== null && generalError !== void 0 ? generalError : Object.values(parsedFieldErrors)[0]) !== null && _g !== void 0 ? _g : t('notificationsEditAlertDialog.toastValidationDescription');
|
|
187907
|
+
toast.error(t('notificationsEditAlertDialog.toastValidationTitle'), { description });
|
|
187908
|
+
return;
|
|
187909
|
+
}
|
|
186673
187910
|
toast.error(t('notificationsEditAlertDialog.toastErrorTitle'), {
|
|
186674
187911
|
description: t('notificationsEditAlertDialog.toastErrorDescription'),
|
|
186675
187912
|
});
|
|
@@ -186689,17 +187926,57 @@ function EditAlertDialog({ open, onOpenChange, template, platformKey, templateTy
|
|
|
186689
187926
|
setPolicyNotifyOnRemoval(true);
|
|
186690
187927
|
setHumanSupportRecipientMode('platform_admins_and_mentor_owner');
|
|
186691
187928
|
setHumanSupportCustomRecipients([]);
|
|
187929
|
+
setUserProgressFrequency(DEFAULT_USER_PROGRESS_FREQUENCY);
|
|
187930
|
+
setUserProgressExecutionTime('');
|
|
187931
|
+
setUserProgressTimezone(userLocalTimezone);
|
|
187932
|
+
setUserProgressCustomIntervalDays('');
|
|
187933
|
+
setUserProgressLookbackDays(DEFAULT_USER_PROGRESS_LOOKBACK_DAYS);
|
|
187934
|
+
setUserProgressDataPoints([]);
|
|
187935
|
+
setWatcherEmailSubject('');
|
|
187936
|
+
setWatcherEmailBody('');
|
|
187937
|
+
setIsWatcherEmailCustomized(false);
|
|
187938
|
+
setFieldErrors({});
|
|
186692
187939
|
onOpenChange(false);
|
|
186693
187940
|
};
|
|
187941
|
+
/** Starts from the learner copy so admins have something to edit down. */
|
|
187942
|
+
const handleWatcherCustomizedChange = (customized) => {
|
|
187943
|
+
setIsWatcherEmailCustomized(customized);
|
|
187944
|
+
if (customized && !watcherEmailSubject.trim() && !hasHtmlContent(watcherEmailBody)) {
|
|
187945
|
+
setWatcherEmailSubject(messageTitle);
|
|
187946
|
+
setWatcherEmailBody(messageBody);
|
|
187947
|
+
}
|
|
187948
|
+
};
|
|
186694
187949
|
const isProactiveInvalid = isProactive &&
|
|
186695
187950
|
periodicFrequency === 'CUSTOM' &&
|
|
186696
187951
|
(!periodicCustomIntervalDays || !periodicExecutionTime.trim());
|
|
187952
|
+
const isUserProgressInvalid = isUserProgress &&
|
|
187953
|
+
Object.keys(validateUserProgressSettings({
|
|
187954
|
+
frequency: userProgressFrequency,
|
|
187955
|
+
executionTime: userProgressExecutionTime,
|
|
187956
|
+
customIntervalDays: userProgressCustomIntervalDays,
|
|
187957
|
+
lookbackDays: userProgressLookbackDays,
|
|
187958
|
+
})).length > 0;
|
|
186697
187959
|
const isSaveDisabled = isSaving ||
|
|
186698
187960
|
isTemplateDetailsLoading ||
|
|
186699
187961
|
!messageTitle.trim() ||
|
|
186700
187962
|
!messageBody.trim() ||
|
|
186701
|
-
isProactiveInvalid
|
|
186702
|
-
|
|
187963
|
+
isProactiveInvalid ||
|
|
187964
|
+
isUserProgressInvalid;
|
|
187965
|
+
const messageTitleError = (_c = (_b = fieldErrors.email_subject) !== null && _b !== void 0 ? _b : fieldErrors.message_title) !== null && _c !== void 0 ? _c : '';
|
|
187966
|
+
const messageBodyError = (_e = (_d = fieldErrors.email_html_template) !== null && _d !== void 0 ? _d : fieldErrors.message_body) !== null && _e !== void 0 ? _e : '';
|
|
187967
|
+
return (jsx(Dialog, { open: open, onOpenChange: handleClose, children: jsxs(DialogContent, { className: "max-w-3xl h-[85vh] flex flex-col p-0", "aria-describedby": dialogDescriptionId, children: [jsxs(DialogHeader, { className: "px-6 py-4 border-b border-gray-200", children: [jsx(DialogTitle, { className: "text-xl font-semibold", children: t('notificationsEditAlertDialog.dialogTitle') }), jsx(DialogDescription, { id: dialogDescriptionId, children: t('notificationsEditAlertDialog.dialogDescription') })] }), jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: jsx("div", { className: "h-full overflow-y-auto px-6 py-4", children: jsxs("div", { className: "space-y-6", children: [jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "template-name", className: "text-sm font-medium text-gray-700", children: t('notificationsEditAlertDialog.templateNameLabel') }), jsx(Input, { id: "template-name", value: (template === null || template === void 0 ? void 0 : template.description) || '', disabled: true, className: "bg-gray-50" })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "message-title", className: "text-sm font-medium text-gray-700", children: isUserProgress
|
|
187968
|
+
? t('notificationsEditAlertDialog.learnerEmailSubjectLabel')
|
|
187969
|
+
: t('notificationsEditAlertDialog.messageTitleLabel') }), jsx("p", { id: messageTitleHelperId, className: "text-xs text-gray-500", children: isUserProgress
|
|
187970
|
+
? t('notificationsEditAlertDialog.learnerEmailSubjectHelper')
|
|
187971
|
+
: t('notificationsEditAlertDialog.messageTitleHelper') }), jsx(Input, { id: "message-title", value: messageTitle, onChange: (e) => setMessageTitle(e.target.value), placeholder: t('notificationsEditAlertDialog.messageTitlePlaceholder'), className: "w-full", disabled: isSaving, required: true, "aria-required": "true", "aria-invalid": Boolean(messageTitleError), "aria-describedby": messageTitleError
|
|
187972
|
+
? `${messageTitleHelperId} ${messageTitleErrorId}`
|
|
187973
|
+
: messageTitleHelperId }), messageTitleError && (jsx("p", { id: messageTitleErrorId, className: "text-sm text-red-600", role: "alert", children: messageTitleError }))] }), jsxs("div", { className: "space-y-2", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx(Label$2, { htmlFor: "message-body", id: messageBodyLabelId, className: "text-sm font-medium text-gray-700", children: isUserProgress
|
|
187974
|
+
? t('notificationsEditAlertDialog.learnerEmailBodyLabel')
|
|
187975
|
+
: t('notificationsEditAlertDialog.messageBodyLabel') }), currentTemplateDetail.can_customize === false && (jsx("span", { className: "inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-600", children: t('notificationsEditAlertDialog.nonCustomizable') }))] }), jsx("p", { id: messageBodyHelperId, className: "text-xs text-gray-500", children: isUserProgress
|
|
187976
|
+
? t('notificationsEditAlertDialog.learnerEmailBodyHelper')
|
|
187977
|
+
: t('notificationsEditAlertDialog.messageBodyHelper') }), jsx(RichTextEditor, { value: messageBody, onChange: setMessageBody, placeholder: t('notificationsEditAlertDialog.messageBodyPlaceholder'), exportFormat: "html", disabled: isSaving || currentTemplateDetail.can_customize === false, id: "message-body", ariaLabelledBy: messageBodyLabelId, ariaDescribedBy: messageBodyError
|
|
187978
|
+
? `${messageBodyHelperId} ${messageBodyErrorId}`
|
|
187979
|
+
: messageBodyHelperId, ariaRequired: true, ariaInvalid: Boolean(messageBodyError) }), messageBodyError && (jsx("p", { id: messageBodyErrorId, className: "text-sm text-red-600", role: "alert", children: messageBodyError })), isUserProgress && (jsx(TemplateVariablesHelper, { context: currentTemplateDetail.available_context }))] }), isPolicyAssignment && (jsx(PolicyAssignmentSection, { platformKey: platformKey, isSaving: isSaving, notifyOnAssignment: policyNotifyOnAssignment, onNotifyOnAssignmentChange: setPolicyNotifyOnAssignment, notifyOnRemoval: policyNotifyOnRemoval, onNotifyOnRemovalChange: setPolicyNotifyOnRemoval, initialPolicyConfigurations: policySettings.enabledPolicies, onPolicyConfigurationsChange: handlePolicyConfigurationsChange })), isHumanSupport && (jsx(HumanSupportSection, { platformKey: platformKey, isSaving: isSaving, recipientMode: humanSupportRecipientMode, onRecipientModeChange: setHumanSupportRecipientMode, initialCustomRecipients: humanSupportSettings.customRecipients, onCustomRecipientsChange: handleHumanSupportRecipientsChange })), isProactive && (jsx(ProactiveSettingsSection, { platformKey: platformKey, username: username, isSaving: isSaving, userLocalTimezone: userLocalTimezone, periodicLearnerScope: periodicLearnerScope, onLearnerScopeChange: setPeriodicLearnerScope, periodicFrequency: periodicFrequency, onFrequencyChange: setPeriodicFrequency, periodicCustomIntervalDays: periodicCustomIntervalDays, onCustomIntervalChange: setPeriodicCustomIntervalDays, periodicExecutionTime: periodicExecutionTime, onExecutionTimeChange: setPeriodicExecutionTime, periodicTimezone: periodicTimezone, onTimezoneChange: setPeriodicTimezone, initialMentors: periodicSettings.mentors, onMentorsChange: handleMentorsChange })), isUserProgress && (jsxs(Fragment$1, { children: [showWatcherEditor && (jsx(WatcherEmailSection, { isSaving: isSaving, isCustomized: isWatcherEmailCustomized, onCustomizedChange: handleWatcherCustomizedChange, subject: watcherEmailSubject, onSubjectChange: setWatcherEmailSubject, body: watcherEmailBody, onBodyChange: setWatcherEmailBody, context: currentTemplateDetail.watcher_available_context, serverErrors: fieldErrors })), jsx(UserProgressSettingsSection, { isSaving: isSaving, userLocalTimezone: userLocalTimezone, frequency: userProgressFrequency, onFrequencyChange: setUserProgressFrequency, executionTime: userProgressExecutionTime, onExecutionTimeChange: setUserProgressExecutionTime, timezone: userProgressTimezone, onTimezoneChange: setUserProgressTimezone, customIntervalDays: userProgressCustomIntervalDays, onCustomIntervalDaysChange: setUserProgressCustomIntervalDays, lookbackDays: userProgressLookbackDays, onLookbackDaysChange: setUserProgressLookbackDays, enabledDataPoints: userProgressDataPoints, onEnabledDataPointsChange: setUserProgressDataPoints, serverErrors: fieldErrors }), notificationType && (jsx(TemplateActionsSection, { platformKey: platformKey, notificationType: notificationType, isSaving: isSaving, onResetComplete: () => setFieldErrors({}) }))] }))] }) }) }), jsxs("div", { className: "px-6 py-4 border-t border-gray-200 flex justify-end gap-3", children: [jsx(Button$1, { variant: "outline", onClick: handleClose, disabled: isSaving, children: t('notificationsEditAlertDialog.cancel') }), jsx(Button$1, { onClick: handleSave, disabled: isSaveDisabled, className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white", children: isSaving
|
|
186703
187980
|
? t('notificationsEditAlertDialog.saving')
|
|
186704
187981
|
: t('notificationsEditAlertDialog.saveChanges') })] })] }) }));
|
|
186705
187982
|
}
|
|
@@ -186841,8 +188118,9 @@ function NotificationDisplay({ org, userId, isAdmin = false, selectedNotificatio
|
|
|
186841
188118
|
// Helper function to strip HTML tags
|
|
186842
188119
|
const stripHtml = (html) => {
|
|
186843
188120
|
if (typeof window === 'undefined') {
|
|
186844
|
-
// Server-side fallback:
|
|
186845
|
-
|
|
188121
|
+
// Server-side fallback: regex strip repeated to a fixed point so nested
|
|
188122
|
+
// markup cannot re-form a tag after the first pass.
|
|
188123
|
+
return stripHtmlTags(html);
|
|
186846
188124
|
}
|
|
186847
188125
|
const doc = new DOMParser().parseFromString(html, 'text/html');
|
|
186848
188126
|
return doc.body.textContent || '';
|
|
@@ -187024,173 +188302,6 @@ function NotificationDisplay({ org, userId, isAdmin = false, selectedNotificatio
|
|
|
187024
188302
|
} }), jsx(Dialog, { open: isMobileModalOpen, onOpenChange: setIsMobileModalOpen, children: jsx(DialogContent, { className: "max-h-[85vh] overflow-y-auto max-w-[95vw]", children: selectedNotification && (jsxs(Fragment$1, { children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { className: "text-xl font-semibold text-gray-900 pr-6", children: selectedNotification.title }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-500 pt-2", children: [jsx(Clock, { className: "h-4 w-4", "aria-hidden": "true" }), jsx("time", { dateTime: selectedNotification.timestamp.toISOString(), children: format$1(selectedNotification.timestamp, "MMMM d, yyyy 'at' h:mm a") })] })] }), jsx("div", { className: "prose prose-sm max-w-none text-gray-700 mt-4", dangerouslySetInnerHTML: { __html: sanitizeHtml(selectedNotification.body) }, "aria-labelledby": "mobile-notification-title" })] })) }) })] }));
|
|
187025
188303
|
}
|
|
187026
188304
|
|
|
187027
|
-
var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
|
|
187028
|
-
// @__NO_SIDE_EFFECTS__
|
|
187029
|
-
function createSlottable(ownerName) {
|
|
187030
|
-
const Slottable2 = ({ children }) => {
|
|
187031
|
-
return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
187032
|
-
};
|
|
187033
|
-
Slottable2.displayName = `${ownerName}.Slottable`;
|
|
187034
|
-
Slottable2.__radixId = SLOTTABLE_IDENTIFIER;
|
|
187035
|
-
return Slottable2;
|
|
187036
|
-
}
|
|
187037
|
-
|
|
187038
|
-
var ROOT_NAME = "AlertDialog";
|
|
187039
|
-
var [createAlertDialogContext] = createContextScope$1(ROOT_NAME, [
|
|
187040
|
-
createDialogScope
|
|
187041
|
-
]);
|
|
187042
|
-
var useDialogScope = createDialogScope();
|
|
187043
|
-
var AlertDialog$1 = (props) => {
|
|
187044
|
-
const { __scopeAlertDialog, ...alertDialogProps } = props;
|
|
187045
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187046
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { ...dialogScope, ...alertDialogProps, modal: true });
|
|
187047
|
-
};
|
|
187048
|
-
AlertDialog$1.displayName = ROOT_NAME;
|
|
187049
|
-
var TRIGGER_NAME = "AlertDialogTrigger";
|
|
187050
|
-
var AlertDialogTrigger = React.forwardRef(
|
|
187051
|
-
(props, forwardedRef) => {
|
|
187052
|
-
const { __scopeAlertDialog, ...triggerProps } = props;
|
|
187053
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187054
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Trigger, { ...dialogScope, ...triggerProps, ref: forwardedRef });
|
|
187055
|
-
}
|
|
187056
|
-
);
|
|
187057
|
-
AlertDialogTrigger.displayName = TRIGGER_NAME;
|
|
187058
|
-
var PORTAL_NAME = "AlertDialogPortal";
|
|
187059
|
-
var AlertDialogPortal$1 = (props) => {
|
|
187060
|
-
const { __scopeAlertDialog, ...portalProps } = props;
|
|
187061
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187062
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { ...dialogScope, ...portalProps });
|
|
187063
|
-
};
|
|
187064
|
-
AlertDialogPortal$1.displayName = PORTAL_NAME;
|
|
187065
|
-
var OVERLAY_NAME = "AlertDialogOverlay";
|
|
187066
|
-
var AlertDialogOverlay$1 = React.forwardRef(
|
|
187067
|
-
(props, forwardedRef) => {
|
|
187068
|
-
const { __scopeAlertDialog, ...overlayProps } = props;
|
|
187069
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187070
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Overlay, { ...dialogScope, ...overlayProps, ref: forwardedRef });
|
|
187071
|
-
}
|
|
187072
|
-
);
|
|
187073
|
-
AlertDialogOverlay$1.displayName = OVERLAY_NAME;
|
|
187074
|
-
var CONTENT_NAME = "AlertDialogContent";
|
|
187075
|
-
var [AlertDialogContentProvider, useAlertDialogContentContext] = createAlertDialogContext(CONTENT_NAME);
|
|
187076
|
-
var Slottable = createSlottable("AlertDialogContent");
|
|
187077
|
-
var AlertDialogContent$1 = React.forwardRef(
|
|
187078
|
-
(props, forwardedRef) => {
|
|
187079
|
-
const { __scopeAlertDialog, children, ...contentProps } = props;
|
|
187080
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187081
|
-
const contentRef = React.useRef(null);
|
|
187082
|
-
const composedRefs = useComposedRefs$1(forwardedRef, contentRef);
|
|
187083
|
-
const cancelRef = React.useRef(null);
|
|
187084
|
-
return /* @__PURE__ */ jsx(
|
|
187085
|
-
DialogPrimitive.WarningProvider,
|
|
187086
|
-
{
|
|
187087
|
-
contentName: CONTENT_NAME,
|
|
187088
|
-
titleName: TITLE_NAME,
|
|
187089
|
-
docsSlug: "alert-dialog",
|
|
187090
|
-
children: /* @__PURE__ */ jsx(AlertDialogContentProvider, { scope: __scopeAlertDialog, cancelRef, children: /* @__PURE__ */ jsxs(
|
|
187091
|
-
DialogPrimitive.Content,
|
|
187092
|
-
{
|
|
187093
|
-
role: "alertdialog",
|
|
187094
|
-
...dialogScope,
|
|
187095
|
-
...contentProps,
|
|
187096
|
-
ref: composedRefs,
|
|
187097
|
-
onOpenAutoFocus: composeEventHandlers$2(contentProps.onOpenAutoFocus, (event) => {
|
|
187098
|
-
event.preventDefault();
|
|
187099
|
-
cancelRef.current?.focus({ preventScroll: true });
|
|
187100
|
-
}),
|
|
187101
|
-
onPointerDownOutside: (event) => event.preventDefault(),
|
|
187102
|
-
onInteractOutside: (event) => event.preventDefault(),
|
|
187103
|
-
children: [
|
|
187104
|
-
/* @__PURE__ */ jsx(Slottable, { children }),
|
|
187105
|
-
/* @__PURE__ */ jsx(DescriptionWarning, { contentRef })
|
|
187106
|
-
]
|
|
187107
|
-
}
|
|
187108
|
-
) })
|
|
187109
|
-
}
|
|
187110
|
-
);
|
|
187111
|
-
}
|
|
187112
|
-
);
|
|
187113
|
-
AlertDialogContent$1.displayName = CONTENT_NAME;
|
|
187114
|
-
var TITLE_NAME = "AlertDialogTitle";
|
|
187115
|
-
var AlertDialogTitle$1 = React.forwardRef(
|
|
187116
|
-
(props, forwardedRef) => {
|
|
187117
|
-
const { __scopeAlertDialog, ...titleProps } = props;
|
|
187118
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187119
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Title, { ...dialogScope, ...titleProps, ref: forwardedRef });
|
|
187120
|
-
}
|
|
187121
|
-
);
|
|
187122
|
-
AlertDialogTitle$1.displayName = TITLE_NAME;
|
|
187123
|
-
var DESCRIPTION_NAME = "AlertDialogDescription";
|
|
187124
|
-
var AlertDialogDescription$1 = React.forwardRef((props, forwardedRef) => {
|
|
187125
|
-
const { __scopeAlertDialog, ...descriptionProps } = props;
|
|
187126
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187127
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Description, { ...dialogScope, ...descriptionProps, ref: forwardedRef });
|
|
187128
|
-
});
|
|
187129
|
-
AlertDialogDescription$1.displayName = DESCRIPTION_NAME;
|
|
187130
|
-
var ACTION_NAME = "AlertDialogAction";
|
|
187131
|
-
var AlertDialogAction$1 = React.forwardRef(
|
|
187132
|
-
(props, forwardedRef) => {
|
|
187133
|
-
const { __scopeAlertDialog, ...actionProps } = props;
|
|
187134
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187135
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Close, { ...dialogScope, ...actionProps, ref: forwardedRef });
|
|
187136
|
-
}
|
|
187137
|
-
);
|
|
187138
|
-
AlertDialogAction$1.displayName = ACTION_NAME;
|
|
187139
|
-
var CANCEL_NAME = "AlertDialogCancel";
|
|
187140
|
-
var AlertDialogCancel$1 = React.forwardRef(
|
|
187141
|
-
(props, forwardedRef) => {
|
|
187142
|
-
const { __scopeAlertDialog, ...cancelProps } = props;
|
|
187143
|
-
const { cancelRef } = useAlertDialogContentContext(CANCEL_NAME, __scopeAlertDialog);
|
|
187144
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
187145
|
-
const ref = useComposedRefs$1(forwardedRef, cancelRef);
|
|
187146
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Close, { ...dialogScope, ...cancelProps, ref });
|
|
187147
|
-
}
|
|
187148
|
-
);
|
|
187149
|
-
AlertDialogCancel$1.displayName = CANCEL_NAME;
|
|
187150
|
-
var DescriptionWarning = ({ contentRef }) => {
|
|
187151
|
-
const MESSAGE = `\`${CONTENT_NAME}\` requires a description for the component to be accessible for screen reader users.
|
|
187152
|
-
|
|
187153
|
-
You can add a description to the \`${CONTENT_NAME}\` by passing a \`${DESCRIPTION_NAME}\` component as a child, which also benefits sighted users by adding visible context to the dialog.
|
|
187154
|
-
|
|
187155
|
-
Alternatively, you can use your own component as a description by assigning it an \`id\` and passing the same value to the \`aria-describedby\` prop in \`${CONTENT_NAME}\`. If the description is confusing or duplicative for sighted users, you can use the \`@radix-ui/react-visually-hidden\` primitive as a wrapper around your description component.
|
|
187156
|
-
|
|
187157
|
-
For more information, see https://radix-ui.com/primitives/docs/components/alert-dialog`;
|
|
187158
|
-
React.useEffect(() => {
|
|
187159
|
-
const hasDescription = document.getElementById(
|
|
187160
|
-
contentRef.current?.getAttribute("aria-describedby")
|
|
187161
|
-
);
|
|
187162
|
-
if (!hasDescription) console.warn(MESSAGE);
|
|
187163
|
-
}, [MESSAGE, contentRef]);
|
|
187164
|
-
return null;
|
|
187165
|
-
};
|
|
187166
|
-
var Root2 = AlertDialog$1;
|
|
187167
|
-
var Portal2 = AlertDialogPortal$1;
|
|
187168
|
-
var Overlay2 = AlertDialogOverlay$1;
|
|
187169
|
-
var Content2 = AlertDialogContent$1;
|
|
187170
|
-
var Action = AlertDialogAction$1;
|
|
187171
|
-
var Cancel = AlertDialogCancel$1;
|
|
187172
|
-
var Title2 = AlertDialogTitle$1;
|
|
187173
|
-
var Description2 = AlertDialogDescription$1;
|
|
187174
|
-
|
|
187175
|
-
const AlertDialog = Root2;
|
|
187176
|
-
const AlertDialogPortal = Portal2;
|
|
187177
|
-
const AlertDialogOverlay = React.forwardRef(({ className, ...props }, ref) => (jsx(Overlay2, { className: cn('data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80', className), ...props, ref: ref })));
|
|
187178
|
-
AlertDialogOverlay.displayName = Overlay2.displayName;
|
|
187179
|
-
const AlertDialogContent = React.forwardRef(({ className, ...props }, ref) => (jsxs(AlertDialogPortal, { children: [jsx(AlertDialogOverlay, {}), jsx(Content2, { ref: ref, className: cn('bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg', className), ...props })] })));
|
|
187180
|
-
AlertDialogContent.displayName = Content2.displayName;
|
|
187181
|
-
const AlertDialogHeader = ({ className, ...props }) => (jsx("div", { className: cn('flex flex-col space-y-2 text-center sm:text-left', className), ...props }));
|
|
187182
|
-
AlertDialogHeader.displayName = 'AlertDialogHeader';
|
|
187183
|
-
const AlertDialogFooter = ({ className, ...props }) => (jsx("div", { className: cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className), ...props }));
|
|
187184
|
-
AlertDialogFooter.displayName = 'AlertDialogFooter';
|
|
187185
|
-
const AlertDialogTitle = React.forwardRef(({ className, ...props }, ref) => (jsx(Title2, { ref: ref, className: cn('text-lg font-semibold', className), ...props })));
|
|
187186
|
-
AlertDialogTitle.displayName = Title2.displayName;
|
|
187187
|
-
const AlertDialogDescription = React.forwardRef(({ className, ...props }, ref) => (jsx(Description2, { ref: ref, className: cn('text-muted-foreground text-sm', className), ...props })));
|
|
187188
|
-
AlertDialogDescription.displayName = Description2.displayName;
|
|
187189
|
-
const AlertDialogAction = React.forwardRef(({ className, ...props }, ref) => (jsx(Action, { ref: ref, className: cn(buttonVariants(), className), ...props })));
|
|
187190
|
-
AlertDialogAction.displayName = Action.displayName;
|
|
187191
|
-
const AlertDialogCancel = React.forwardRef(({ className, ...props }, ref) => (jsx(Cancel, { ref: ref, className: cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', className), ...props })));
|
|
187192
|
-
AlertDialogCancel.displayName = Cancel.displayName;
|
|
187193
|
-
|
|
187194
188305
|
/**
|
|
187195
188306
|
* **Private mode** toggle for the platform nav-bar. A single pill that
|
|
187196
188307
|
* collapses to an icon-only chip when off, and expands with a cool
|