@oneuptime/common 14.0.10 → 14.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/AIConversation.ts +127 -1
- package/Models/DatabaseModels/CephCluster.ts +12 -0
- package/Models/DatabaseModels/CloudResource.ts +12 -0
- package/Models/DatabaseModels/DatabaseServer.ts +12 -0
- package/Models/DatabaseModels/DockerHost.ts +12 -0
- package/Models/DatabaseModels/DockerSwarmCluster.ts +12 -0
- package/Models/DatabaseModels/GlobalOidc.ts +0 -4
- package/Models/DatabaseModels/GlobalOidcProject.ts +0 -4
- package/Models/DatabaseModels/GlobalSso.ts +0 -4
- package/Models/DatabaseModels/GlobalSsoProject.ts +0 -4
- package/Models/DatabaseModels/Host.ts +12 -0
- package/Models/DatabaseModels/IncidentForm.ts +594 -0
- package/Models/DatabaseModels/IncidentFormSubmission.ts +283 -0
- package/Models/DatabaseModels/IncidentTemplate.ts +59 -0
- package/Models/DatabaseModels/Index.ts +14 -0
- package/Models/DatabaseModels/IoTFleet.ts +12 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +12 -0
- package/Models/DatabaseModels/MessageQueue.ts +1102 -0
- package/Models/DatabaseModels/MessageQueueLabelRule.ts +553 -0
- package/Models/DatabaseModels/MessageQueueOwnerRule.ts +633 -0
- package/Models/DatabaseModels/MessageQueueOwnerTeam.ts +491 -0
- package/Models/DatabaseModels/MessageQueueOwnerUser.ts +490 -0
- package/Models/DatabaseModels/PodmanHost.ts +12 -0
- package/Models/DatabaseModels/Project.ts +59 -0
- package/Models/DatabaseModels/ProjectOidc.ts +0 -4
- package/Models/DatabaseModels/ProjectSso.ts +0 -4
- package/Models/DatabaseModels/ProxmoxCluster.ts +12 -0
- package/Models/DatabaseModels/RumApplication.ts +12 -0
- package/Models/DatabaseModels/ServerlessFunction.ts +12 -0
- package/Models/DatabaseModels/Service.ts +12 -0
- package/Models/DatabaseModels/StatusPageOidc.ts +0 -4
- package/Models/DatabaseModels/StatusPageSso.ts +0 -4
- package/Models/DatabaseModels/TeamComplianceSetting.ts +47 -2
- package/Models/DatabaseModels/VMwareVCenter.ts +12 -0
- package/Server/API/AIChatAPI.ts +13 -114
- package/Server/API/AIInvestigationAPI.ts +3 -3
- package/Server/API/AIInvestigationConversationAPI.ts +266 -0
- package/Server/API/IncidentFormAPI.ts +376 -0
- package/Server/API/ProjectOIDC.ts +16 -25
- package/Server/API/ProjectSSO.ts +16 -24
- package/Server/API/StatusPageAPI.ts +42 -77
- package/Server/Enterprise/EnterpriseEdition.ts +93 -28
- package/Server/Enterprise/EnterpriseFeature.ts +25 -3
- package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +1 -1
- package/Server/Enterprise/EnterpriseServerModule.ts +4 -1
- package/Server/EnvironmentConfig.ts +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.ts +129 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.ts +52 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.ts +75 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.ts +477 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
- package/Server/Middleware/IncidentFormRateLimit.ts +847 -0
- package/Server/Middleware/UserAuthorization.ts +16 -38
- package/Server/Services/AIService.ts +10 -13
- package/Server/Services/IncidentCustomFieldService.ts +112 -2
- package/Server/Services/IncidentEpisodeMemberService.ts +24 -4
- package/Server/Services/IncidentEpisodeService.ts +10 -1
- package/Server/Services/IncidentFormService.ts +1566 -0
- package/Server/Services/IncidentFormSubmissionService.ts +97 -0
- package/Server/Services/IncidentGroupingEngineService.ts +45 -8
- package/Server/Services/IncidentService.ts +123 -5
- package/Server/Services/IncidentTemplateService.ts +22 -0
- package/Server/Services/Index.ts +14 -0
- package/Server/Services/MessageQueueLabelRuleEngineService.ts +321 -0
- package/Server/Services/MessageQueueLabelRuleService.ts +14 -0
- package/Server/Services/MessageQueueOwnerRuleEngineService.ts +412 -0
- package/Server/Services/MessageQueueOwnerRuleService.ts +14 -0
- package/Server/Services/MessageQueueOwnerTeamService.ts +62 -0
- package/Server/Services/MessageQueueOwnerUserService.ts +62 -0
- package/Server/Services/MessageQueueService.ts +1463 -0
- package/Server/Services/OpenTelemetryIngestService.ts +37 -4
- package/Server/Services/ProjectService.ts +0 -59
- package/Server/Services/StatusPagePrivateUserService.ts +1 -4
- package/Server/Services/StatusPageService.ts +1 -51
- package/Server/Services/TeamComplianceSettingService.ts +163 -42
- package/Server/Services/UserNotificationRuleService.ts +8 -1
- package/Server/Services/WorkspaceNotificationSummaryService.ts +12 -3
- package/Server/Types/Database/Permissions/CreatePermission.ts +17 -3
- package/Server/Types/Database/Permissions/EditionPermission.ts +140 -38
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +16 -0
- package/Server/Types/Database/Permissions/TablePermission.ts +3 -3
- package/Server/Types/Database/Permissions/UpdatePermission.ts +20 -6
- package/Server/Utils/AI/Chat/AgentContextCompactor.ts +200 -0
- package/Server/Utils/AI/Chat/ChatAgentRunner.ts +307 -48
- package/Server/Utils/AI/Chat/ChatRunCancellation.ts +156 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +78 -18
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
- package/Server/Utils/AI/Chat/ToolOutputPager.ts +322 -0
- package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +88 -30
- package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +13 -1
- package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +0 -32
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +27 -25
- package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +7 -1
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +34 -14
- package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +69 -24
- package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +9 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +53 -10
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +27 -10
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +27 -10
- package/Server/Utils/AI/SRE/InvestigationQueue.ts +16 -19
- package/Server/Utils/AI/SRE/InvestigationThread.ts +646 -0
- package/Server/Utils/AI/SRE/InvestigationThreadService.ts +715 -0
- package/Server/Utils/AI/Toolbox/Serializer.ts +10 -3
- package/Server/Utils/EditionEnforcement.ts +19 -202
- package/Server/Utils/LLM/LLMService.ts +259 -63
- package/Server/Utils/RelaxedScimTeamLocksReport.ts +245 -0
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
- package/Server/Utils/SameOriginRequest.ts +203 -0
- package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +4 -1
- package/Server/Utils/Telemetry/MessageQueueDiscovery.ts +1402 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +4 -1
- package/Server/Utils/VendorAssets.ts +3 -3
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +3 -1
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +3 -1
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +10 -1
- package/Tests/App/Accounts/IncidentFormPage.test.tsx +2036 -0
- package/Tests/App/Accounts/IncidentFormServerMessages.test.ts +119 -0
- package/Tests/App/Accounts/IncidentFormUtils.test.ts +1157 -0
- package/Tests/App/Accounts/LoginPasskey.test.tsx +6 -4
- package/Tests/App/Accounts/LoginSso.test.tsx +724 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationRequireSso.test.tsx +338 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoCardLocales.test.tsx +331 -0
- package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +47 -33
- package/Tests/App/AdminDashboard/GlobalSsoOidcPages.test.tsx +1021 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +876 -78
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +20 -3
- package/Tests/App/Dashboard/CephProxmoxVMwareDocumentationCards.test.tsx +359 -0
- package/Tests/App/Dashboard/CephSetupGuide.test.ts +961 -0
- package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +381 -95
- package/Tests/App/Dashboard/CloudSetupGuide.test.ts +1463 -0
- package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +174 -12
- package/Tests/App/Dashboard/ContainerSetupGuideCards.test.tsx +345 -0
- package/Tests/App/Dashboard/CoreListEmptyStates.test.tsx +501 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +0 -1
- package/Tests/App/Dashboard/DatabaseDocumentationCard.test.tsx +400 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +5 -0
- package/Tests/App/Dashboard/DatabaseSetupGuide.test.ts +1869 -0
- package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +44 -0
- package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +50 -9
- package/Tests/App/Dashboard/DockerSetupGuide.test.ts +899 -0
- package/Tests/App/Dashboard/DockerSwarmSetupGuide.test.ts +964 -0
- package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +141 -7
- package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +52 -39
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +7 -1
- package/Tests/App/Dashboard/GettingStartedTaskRoutes.test.tsx +331 -0
- package/Tests/App/Dashboard/HomeOverviewStatsFirstRun.test.tsx +925 -0
- package/Tests/App/Dashboard/HostDocumentationCard.test.tsx +225 -0
- package/Tests/App/Dashboard/HostSetupGuide.test.ts +1183 -0
- package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +69 -45
- package/Tests/App/Dashboard/IncidentCreateTemplateCustomFieldSettings.test.tsx +745 -0
- package/Tests/App/Dashboard/IncidentCreateTemplateOwners.test.tsx +414 -0
- package/Tests/App/Dashboard/IncidentCustomFieldCreateSettingsForm.test.ts +1042 -0
- package/Tests/App/Dashboard/IncidentCustomFieldSettingsCard.test.tsx +1816 -0
- package/Tests/App/Dashboard/IncidentFormPlan.test.ts +89 -0
- package/Tests/App/Dashboard/IncidentFormShareLinkCard.test.tsx +846 -0
- package/Tests/App/Dashboard/IncidentFormsPages.test.tsx +1324 -0
- package/Tests/App/Dashboard/IncidentTemplateCustomFieldSettings.test.tsx +630 -0
- package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +13 -0
- package/Tests/App/Dashboard/IncomingEmailMonitorLinkVerifyHint.test.tsx +104 -0
- package/Tests/App/Dashboard/InvestigationConversation.test.tsx +1107 -0
- package/Tests/App/Dashboard/InvestigationConversationData.test.ts +546 -0
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +170 -5
- package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +207 -2
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +729 -34
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +9 -21
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +274 -37
- package/Tests/App/Dashboard/InvestigationStatusBadge.test.tsx +130 -0
- package/Tests/App/Dashboard/IoTDocumentationCard.test.tsx +218 -0
- package/Tests/App/Dashboard/IoTSetupGuide.test.ts +1124 -0
- package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +20 -6
- package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +107 -83
- package/Tests/App/Dashboard/KubernetesSetupGuide.test.ts +787 -0
- package/Tests/App/Dashboard/MessageQueueBreadcrumbs.test.tsx +228 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealth.test.tsx +1538 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealthMetricChart.test.tsx +969 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealthReads.test.ts +889 -0
- package/Tests/App/Dashboard/MessageQueueBrokerMetricsReach.test.ts +236 -0
- package/Tests/App/Dashboard/MessageQueueDocumentationCard.test.tsx +479 -0
- package/Tests/App/Dashboard/MessageQueueListPages.test.tsx +1232 -0
- package/Tests/App/Dashboard/MessageQueueMetricDescriptions.test.ts +244 -0
- package/Tests/App/Dashboard/MessageQueueMonitorLink.test.ts +952 -0
- package/Tests/App/Dashboard/MessageQueueMonitorLinkMonitorCreate.test.tsx +859 -0
- package/Tests/App/Dashboard/MessageQueueOverview.test.tsx +1773 -0
- package/Tests/App/Dashboard/MessageQueueOverviewPresentation.test.ts +196 -0
- package/Tests/App/Dashboard/MessageQueuePresentation.test.ts +799 -0
- package/Tests/App/Dashboard/MessageQueueProducersConsumers.test.tsx +680 -0
- package/Tests/App/Dashboard/MessageQueueRoutes.test.tsx +383 -0
- package/Tests/App/Dashboard/MessageQueueRulePages.test.tsx +278 -0
- package/Tests/App/Dashboard/MessageQueueSetupGuide.test.ts +2778 -0
- package/Tests/App/Dashboard/MessageQueueSideMenus.test.tsx +273 -0
- package/Tests/App/Dashboard/MessageQueueSpanPopulations.test.ts +930 -0
- package/Tests/App/Dashboard/MessageQueueSpanStore.ts +351 -0
- package/Tests/App/Dashboard/MessageQueueTelemetryScope.test.ts +375 -0
- package/Tests/App/Dashboard/MessageQueueTelemetryScopeTabs.test.tsx +668 -0
- package/Tests/App/Dashboard/MessageQueueViewPages.test.tsx +685 -0
- package/Tests/App/Dashboard/MonitorAndHomeNotOperationalMenus.test.tsx +342 -0
- package/Tests/App/Dashboard/MonitorCreateFirstRunDefaults.test.tsx +623 -0
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +442 -0
- package/Tests/App/Dashboard/MonitorLogsPageViewSummary.test.tsx +814 -0
- package/Tests/App/Dashboard/MonitorSetupCardBodies.test.tsx +246 -0
- package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +8 -0
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +27 -12
- package/Tests/App/Dashboard/PlanGatedPage.test.tsx +292 -0
- package/Tests/App/Dashboard/PodmanSetupGuide.test.ts +948 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +5 -4
- package/Tests/App/Dashboard/ProductSettingsSectionCollapsed.test.tsx +266 -0
- package/Tests/App/Dashboard/ProxmoxSetupGuide.test.ts +1318 -0
- package/Tests/App/Dashboard/ResourceAiAgentAttentionServerParity.test.ts +555 -0
- package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +298 -9
- package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +453 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +16 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideCard.test.tsx +444 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsInfra.test.tsx +798 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsPlatforms.test.tsx +717 -0
- package/Tests/App/Dashboard/ResourceConnectionGuides.test.ts +981 -0
- package/Tests/App/Dashboard/ResourceConnectionState.test.ts +132 -0
- package/Tests/App/Dashboard/RumDocumentationCard.test.tsx +293 -0
- package/Tests/App/Dashboard/RumSessionReplayRetentionSettings.test.tsx +467 -0
- package/Tests/App/Dashboard/RumSetupGuide.test.ts +758 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +25 -0
- package/Tests/App/Dashboard/ServerlessDocumentationCard.test.tsx +254 -0
- package/Tests/App/Dashboard/ServerlessSetupGuide.test.ts +1074 -0
- package/Tests/App/Dashboard/SetupGuide.test.ts +246 -0
- package/Tests/App/Dashboard/SetupGuideCard.test.tsx +756 -0
- package/Tests/App/Dashboard/SloListSideMenu.test.tsx +120 -0
- package/Tests/App/Dashboard/SsoPages.test.tsx +833 -0
- package/Tests/App/Dashboard/TelemetryDocumentation.test.tsx +253 -0
- package/Tests/App/Dashboard/TelemetryRetentionShells.test.tsx +730 -0
- package/Tests/App/Dashboard/VMwareSetupGuide.test.ts +1033 -0
- package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +87 -7
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +28 -9
- package/Tests/Models/DatabaseModels/IncidentFormModel.test.ts +1250 -0
- package/Tests/Models/DatabaseModels/MessageQueueModels.test.ts +1983 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +190 -14
- package/Tests/Models/IncidentTemplateCustomFieldSettingsColumn.test.ts +291 -0
- package/Tests/Server/API/AIInvestigationConversationAPI.test.ts +412 -0
- package/Tests/Server/API/GlobalConfigLicense.test.ts +38 -9
- package/Tests/Server/API/IncidentFormAPI.test.ts +942 -0
- package/Tests/Server/API/IncidentFormPublicRoutes.test.ts +1653 -0
- package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -1
- package/Tests/Server/API/{SsoProviderListingsEdition.test.ts → SsoProviderListings.test.ts} +164 -110
- package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +76 -54
- package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +125 -42
- package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +36 -10
- package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +51 -9
- package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +13 -8
- package/Tests/Server/Enterprise/SsoInCommunityEdition.test.ts +540 -0
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentFormsMigration.test.ts +438 -0
- package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleNotificationChannelsMigration.test.ts +255 -0
- package/Tests/Server/Infrastructure/Postgres/MessageQueueTablesMigration.test.ts +637 -0
- package/Tests/Server/Middleware/IncidentFormRateLimit.test.ts +1630 -0
- package/Tests/Server/Middleware/UserAuthorization.test.ts +16 -17
- package/Tests/Server/Middleware/UserAuthorizationSsoEnforcement.test.ts +544 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +37 -8
- package/Tests/Server/Services/IncidentCreatedFeedTitle.test.ts +212 -0
- package/Tests/Server/Services/IncidentCustomFieldDeleteFormQuestions.test.ts +297 -0
- package/Tests/Server/Services/IncidentFormOwnersCreatedNotification.test.ts +497 -0
- package/Tests/Server/Services/IncidentFormPostgres.test.ts +958 -0
- package/Tests/Server/Services/IncidentFormPublicForm.test.ts +1260 -0
- package/Tests/Server/Services/IncidentFormPublicSubmission.test.ts +2520 -0
- package/Tests/Server/Services/IncidentFormRegistration.test.ts +159 -0
- package/Tests/Server/Services/IncidentFormService.test.ts +663 -0
- package/Tests/Server/Services/IncidentFormSubmissionService.test.ts +430 -0
- package/Tests/Server/Services/IncidentFormSubmissionTemplateBranch.test.ts +473 -0
- package/Tests/Server/Services/IncidentGroupingTemplateSubstitution.test.ts +81 -0
- package/Tests/Server/Services/IncidentTemplateCustomFieldSettings.test.ts +262 -0
- package/Tests/Server/Services/IncidentTemplateOwnersOnDeclare.test.ts +566 -0
- package/Tests/Server/Services/IncidentTitleMarkdownSinks.test.ts +640 -0
- package/Tests/Server/Services/LlmLogServiceTokenAggregateParams.test.ts +3 -3
- package/Tests/Server/Services/MessageQueueOwnerServices.test.ts +440 -0
- package/Tests/Server/Services/MessageQueueRegistries.test.ts +577 -0
- package/Tests/Server/Services/MessageQueueRuleEngines.test.ts +900 -0
- package/Tests/Server/Services/MessageQueueService.test.ts +2210 -0
- package/Tests/Server/Services/MessageQueueSqlPostgres.test.ts +1271 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
- package/Tests/Server/Services/OpenTelemetryRetentionOverrideEdition.test.ts +474 -0
- package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +21 -0
- package/Tests/Server/Services/OwnerRowUniqueness.test.ts +3 -0
- package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +0 -1
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +56 -6
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -1
- package/Tests/Server/Services/SsoRequirementReads.test.ts +454 -0
- package/Tests/Server/Services/SsoRequirementWrites.test.ts +529 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
- package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +107 -89
- package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +1068 -176
- package/Tests/Server/Services/TeamComplianceSettingService.test.ts +1962 -200
- package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +654 -297
- package/Tests/Server/Types/Database/Permissions/RetentionOverrideColumns.test.ts +784 -0
- package/Tests/Server/Types/Database/Permissions/SsoScalePlanGate.test.ts +418 -0
- package/Tests/Server/Utils/AI/AIAlertGating.test.ts +0 -1
- package/Tests/Server/Utils/AI/AIInvestigationEngineRunLimits.test.ts +136 -0
- package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +15 -14
- package/Tests/Server/Utils/AI/AgentContextCompactor.test.ts +351 -0
- package/Tests/Server/Utils/AI/ChatAgentRunnerSharedThread.test.ts +842 -0
- package/Tests/Server/Utils/AI/ChatRunCancellation.test.ts +195 -0
- package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +10 -57
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +20 -24
- package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +7 -30
- package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +225 -29
- package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +266 -25
- package/Tests/Server/Utils/AI/InvestigationThread.test.ts +580 -0
- package/Tests/Server/Utils/AI/InvestigationThreadService.test.ts +801 -0
- package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +525 -43
- package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +4 -2
- package/Tests/Server/Utils/AI/LLMServiceUnreachableProvider.test.ts +435 -0
- package/Tests/Server/Utils/AI/ObservabilityAssistantLimits.test.ts +462 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +14 -25
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +2 -0
- package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +297 -15
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +10 -6
- package/Tests/Server/Utils/AI/ToolOutputPager.test.ts +382 -0
- package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +23 -4
- package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +25 -6
- package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +14 -3
- package/Tests/Server/Utils/EditionEnforcement.test.ts +107 -147
- package/Tests/Server/Utils/{CommunityEditionSsoReport.test.ts → RelaxedScimTeamLocksReport.test.ts} +212 -208
- package/Tests/Server/Utils/SameOriginRequest.test.ts +372 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +20 -0
- package/Tests/Server/Utils/Telemetry/MessageQueueDiscovery.test.ts +2590 -0
- package/Tests/Server/Utils/Telemetry/MessageQueueSpanQueryTwin.ts +246 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +23 -0
- package/Tests/Types/AI/AIAgentRunLimits.test.ts +255 -0
- package/Tests/Types/Code/JsonSyntax.test.ts +1300 -0
- package/Tests/Types/CustomField/CustomFieldCreateSettings.test.ts +1113 -0
- package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +91 -0
- package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +30 -0
- package/Tests/Types/Incident/IncidentFormIpAllowlist.test.ts +227 -0
- package/Tests/Types/Incident/IncidentFormPublic.test.ts +1916 -0
- package/Tests/Types/MessageQueue/MessageQueueEntityKey.test.ts +916 -0
- package/Tests/Types/MessageQueue/MessageQueueIdentity.test.ts +567 -0
- package/Tests/Types/MessageQueue/MessageQueueManualIdentity.test.ts +686 -0
- package/Tests/Types/MessageQueue/MessageQueueMetricCatalog.test.ts +1726 -0
- package/Tests/Types/MessageQueue/MessageQueueMetricResolution.test.ts +1758 -0
- package/Tests/Types/MessageQueue/MessagingInstrumentationFixtures.test.ts +4686 -0
- package/Tests/Types/MessageQueue/MessagingSystem.test.ts +840 -0
- package/Tests/Types/MessageQueue/MessagingTelemetryFixtures.ts +3287 -0
- package/Tests/Types/MessageQueue/MessagingTelemetryResolver.test.ts +2966 -0
- package/Tests/Types/Monitor/MessageQueueAlertTemplates.test.ts +5401 -0
- package/Tests/Types/Monitor/MetricEngineFold.ts +154 -0
- package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +5 -3
- package/Tests/Types/Team/ComplianceRule.test.ts +588 -37
- package/Tests/Types/Team/TeamComplianceStatus.test.ts +64 -11
- package/Tests/Types/XML.test.ts +51 -0
- package/Tests/UI/Components/CodeEditor/CodeEditor.test.tsx +2362 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorCommands.test.ts +810 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorHighlight.test.ts +338 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorLanguages.test.ts +222 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorStyles.test.ts +807 -0
- package/Tests/UI/Components/CodeEditor/NoMonaco.test.ts +245 -0
- package/Tests/UI/Components/CodeEditor/YamlEditor.test.tsx +729 -0
- package/Tests/UI/Components/CopyTextButton.test.tsx +76 -0
- package/Tests/UI/Components/EditionLabelLapseCopy.ts +51 -14
- package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +131 -23
- package/Tests/UI/Components/ErrorMessageAction.test.tsx +142 -0
- package/Tests/UI/Components/FacetSidebarInScope.test.tsx +459 -0
- package/Tests/UI/Components/FacetValuesInScope.test.ts +270 -0
- package/Tests/UI/Components/Forms/FormFieldCodeEditors.test.tsx +294 -0
- package/Tests/UI/Components/Forms/FormFieldMarkdown.test.tsx +126 -0
- package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +22 -75
- package/Tests/UI/Components/Forms/ModelFormOnBeforeCreateMiscData.test.tsx +254 -0
- package/Tests/UI/Components/Icon.test.tsx +32 -0
- package/Tests/UI/Components/Input.test.tsx +31 -0
- package/Tests/UI/Components/LockedFilterChipScope.test.tsx +501 -0
- package/Tests/UI/Components/MarkdownConverters.test.ts +253 -1
- package/Tests/UI/Components/MarkdownEditor.test.tsx +2785 -2
- package/Tests/UI/Components/MarkdownEditorHistory.test.ts +243 -0
- package/Tests/UI/Components/MarkdownListEditing.test.ts +1118 -0
- package/Tests/UI/Components/MarkdownPaste.test.ts +1180 -0
- package/Tests/UI/Components/MarkdownViewerCopy.test.tsx +466 -0
- package/Tests/UI/Components/MarkdownVisualEditing.test.ts +1089 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableEmptyStateAction.test.tsx +623 -0
- package/Tests/UI/Components/ResetObjectID.test.tsx +282 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/Table/EmptyTableMessage.test.ts +439 -0
- package/Tests/UI/Components/Table/TableEmptyState.test.tsx +352 -0
- package/Tests/UI/Components/TableRowMobileTitles.test.tsx +78 -0
- package/Tests/UI/Components/TextArea.test.tsx +19 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditor.render.test.tsx +12 -29
- package/Tests/UI/Components/fixtures/MarkdownPasteFixtures.ts +460 -0
- package/Tests/UI/EsbuildConfig.test.ts +115 -39
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +4 -4
- package/Tests/UI/Monitor/MonitorLogSummaryRender.test.tsx +377 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +81 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +17 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
- package/Tests/Utils/Markdown/DashboardMarkdownRenderer.ts +81 -0
- package/Tests/Utils/Markdown/UntrustedMarkdown.test.ts +1339 -0
- package/Tests/Utils/Monitor/MonitorLogSummaryUtil.test.ts +862 -0
- package/Types/AI/AIAgentRunLimits.ts +146 -0
- package/Types/Code/CodeType.ts +2 -0
- package/Types/Code/JsonSyntax.ts +923 -0
- package/Types/CustomField/CustomFieldCreateSettings.ts +549 -0
- package/Types/CustomField/CustomFieldMappingCatalog.ts +77 -0
- package/Types/CustomField/CustomFieldValueValidator.ts +10 -7
- package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +1 -1
- package/Types/Icon/IconProp.ts +2 -0
- package/Types/Incident/IncidentFormIpAllowlist.ts +206 -0
- package/Types/Incident/IncidentFormPublic.ts +1145 -0
- package/Types/Kubernetes/KubernetesClusterAiAccess.ts +10 -3
- package/Types/MessageQueue/MessageQueueIdentity.ts +256 -0
- package/Types/MessageQueue/MessageQueueManualIdentity.ts +325 -0
- package/Types/MessageQueue/MessageQueueMetricCatalog.ts +1357 -0
- package/Types/MessageQueue/MessagingSystem.ts +518 -0
- package/Types/MessageQueue/MessagingTelemetryResolver.ts +2311 -0
- package/Types/Monitor/MessageQueueAlertTemplates.ts +2128 -0
- package/Types/Permission.ts +310 -0
- package/Types/ResourceAiAgent/ResourceAiAccess.ts +10 -4
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
- package/Types/Rules/RuleRun.ts +4 -0
- package/Types/Team/ComplianceNotificationChannel.ts +4 -3
- package/Types/Team/ComplianceRule.ts +71 -18
- package/Types/Team/ComplianceRuleType.ts +2 -2
- package/Types/Team/TeamComplianceStatus.ts +6 -2
- package/Types/Telemetry/EntityType.ts +16 -0
- package/Types/Telemetry/LockedFilterDetail.ts +22 -0
- package/Types/XML.ts +26 -0
- package/UI/Components/CodeEditor/CodeEditor.css +379 -0
- package/UI/Components/CodeEditor/CodeEditor.tsx +1128 -294
- package/UI/Components/CodeEditor/CodeEditorCommands.ts +774 -0
- package/UI/Components/CodeEditor/CodeEditorHighlight.ts +106 -0
- package/UI/Components/CodeEditor/CodeEditorLanguages.ts +164 -0
- package/UI/Components/CodeEditor/YamlEditor.tsx +28 -326
- package/UI/Components/CopyTextButton/CopyTextButton.tsx +5 -1
- package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +6 -25
- package/UI/Components/EditionLabel/EditionLabel.tsx +14 -13
- package/UI/Components/ErrorMessage/ErrorMessage.tsx +11 -1
- package/UI/Components/Forms/Fields/FormField.tsx +8 -0
- package/UI/Components/Forms/Types/Field.ts +8 -0
- package/UI/Components/Icon/Icon.tsx +18 -0
- package/UI/Components/Input/Input.tsx +11 -4
- package/UI/Components/LogsViewer/LogsViewer.tsx +4 -0
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +21 -3
- package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
- package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +877 -79
- package/UI/Components/Markdown.tsx/MarkdownEditorHistory.ts +284 -0
- package/UI/Components/Markdown.tsx/MarkdownListEditing.ts +1362 -0
- package/UI/Components/Markdown.tsx/MarkdownPaste.ts +1326 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +106 -10
- package/UI/Components/Markdown.tsx/MarkdownVisualEditing.ts +1032 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +85 -7
- package/UI/Components/ResetObjectID/ResetObjectID.tsx +35 -9
- package/UI/Components/Table/EmptyTableMessage.ts +81 -0
- package/UI/Components/Table/Table.tsx +50 -21
- package/UI/Components/Table/TableRow.tsx +9 -1
- package/UI/Components/TelemetryViewer/FacetVisibility.ts +97 -2
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +13 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +214 -7
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +21 -3
- package/UI/Components/TextArea/TextArea.tsx +9 -2
- package/UI/Components/Workflow/ModelFieldPicker.tsx +10 -12
- package/UI/Styles/Theme.css +8 -0
- package/UI/esbuild-config.js +2 -32
- package/Utils/LabelRuleImportExport.ts +2 -0
- package/Utils/Markdown/UntrustedMarkdown.ts +1513 -0
- package/Utils/Monitor/IncomingEmailMonitorRequestUtil.ts +41 -0
- package/Utils/Monitor/MonitorLogSummaryUtil.ts +212 -0
- package/Utils/Telemetry/EntityKey.ts +48 -0
- package/build/dist/Models/DatabaseModels/AIConversation.js +125 -1
- package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +12 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResource.js +12 -0
- package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +12 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +12 -0
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +12 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSso.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +12 -0
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentForm.js +605 -0
- package/build/dist/Models/DatabaseModels/IncidentForm.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js +299 -0
- package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +60 -0
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +14 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleet.js +12 -0
- package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +12 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MessageQueue.js +1106 -0
- package/build/dist/Models/DatabaseModels/MessageQueue.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js +562 -0
- package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js +643 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js +506 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js +505 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js +12 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +61 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/ProjectOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectSso.js +0 -4
- package/build/dist/Models/DatabaseModels/ProjectSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +12 -0
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +12 -0
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunction.js +12 -0
- package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Service.js +12 -0
- package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSso.js +0 -4
- package/build/dist/Models/DatabaseModels/StatusPageSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +49 -3
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js +12 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +9 -103
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +3 -3
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationConversationAPI.js +162 -0
- package/build/dist/Server/API/AIInvestigationConversationAPI.js.map +1 -0
- package/build/dist/Server/API/IncidentFormAPI.js +245 -0
- package/build/dist/Server/API/IncidentFormAPI.js.map +1 -0
- package/build/dist/Server/API/ProjectOIDC.js +16 -24
- package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
- package/build/dist/Server/API/ProjectSSO.js +16 -24
- package/build/dist/Server/API/ProjectSSO.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +42 -75
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseEdition.js +79 -25
- package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseFeature.js +24 -3
- package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +1 -1
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js +63 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js +183 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/IncidentFormRateLimit.js +559 -0
- package/build/dist/Server/Middleware/IncidentFormRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/UserAuthorization.js +11 -30
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +10 -13
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/IncidentCustomFieldService.js +83 -0
- package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js +8 -4
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +10 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentFormService.js +1202 -0
- package/build/dist/Server/Services/IncidentFormService.js.map +1 -0
- package/build/dist/Server/Services/IncidentFormSubmissionService.js +91 -0
- package/build/dist/Server/Services/IncidentFormSubmissionService.js.map +1 -0
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +20 -8
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +106 -4
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +18 -0
- package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +14 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js +262 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleService.js +13 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js +334 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerTeamService.js +62 -0
- package/build/dist/Server/Services/MessageQueueOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerUserService.js +62 -0
- package/build/dist/Server/Services/MessageQueueOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueService.js +1140 -0
- package/build/dist/Server/Services/MessageQueueService.js.map +1 -0
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +25 -4
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +0 -54
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -4
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +0 -46
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceSettingService.js +120 -31
- package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +8 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +12 -3
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +6 -3
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +109 -37
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +16 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js +3 -3
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +9 -6
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js +128 -0
- package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js.map +1 -0
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +192 -50
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js +133 -0
- package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js.map +1 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +53 -13
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
- package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js +206 -0
- package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js.map +1 -0
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +53 -26
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +4 -2
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +1 -29
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +24 -24
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +7 -2
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +29 -14
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +38 -14
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -1
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +2 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +40 -10
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +19 -7
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +19 -7
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +15 -18
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js +412 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js +495 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js +10 -3
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -1
- package/build/dist/Server/Utils/EditionEnforcement.js +20 -158
- package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +193 -54
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js +160 -0
- package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/SameOriginRequest.js +151 -0
- package/build/dist/Server/Utils/SameOriginRequest.js.map +1 -0
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js +1015 -0
- package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +4 -1
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +3 -3
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +3 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +3 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +10 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/AI/AIAgentRunLimits.js +91 -0
- package/build/dist/Types/AI/AIAgentRunLimits.js.map +1 -0
- package/build/dist/Types/Code/CodeType.js +2 -0
- package/build/dist/Types/Code/CodeType.js.map +1 -1
- package/build/dist/Types/Code/JsonSyntax.js +604 -0
- package/build/dist/Types/Code/JsonSyntax.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldCreateSettings.js +310 -0
- package/build/dist/Types/CustomField/CustomFieldCreateSettings.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +38 -0
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js +10 -7
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +1 -1
- package/build/dist/Types/Icon/IconProp.js +2 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/Incident/IncidentFormIpAllowlist.js +119 -0
- package/build/dist/Types/Incident/IncidentFormIpAllowlist.js.map +1 -0
- package/build/dist/Types/Incident/IncidentFormPublic.js +678 -0
- package/build/dist/Types/Incident/IncidentFormPublic.js.map +1 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +10 -3
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
- package/build/dist/Types/MessageQueue/MessageQueueIdentity.js +184 -0
- package/build/dist/Types/MessageQueue/MessageQueueIdentity.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js +190 -0
- package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js +1057 -0
- package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessagingSystem.js +394 -0
- package/build/dist/Types/MessageQueue/MessagingSystem.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js +1768 -0
- package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js.map +1 -0
- package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js +1207 -0
- package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js.map +1 -0
- package/build/dist/Types/Permission.js +274 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +10 -4
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +12 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -1
- package/build/dist/Types/Team/ComplianceNotificationChannel.js +4 -3
- package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -1
- package/build/dist/Types/Team/ComplianceRule.js +48 -14
- package/build/dist/Types/Team/ComplianceRule.js.map +1 -1
- package/build/dist/Types/Team/ComplianceRuleType.js +2 -2
- package/build/dist/Types/Telemetry/EntityType.js +16 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/XML.js +23 -0
- package/build/dist/Types/XML.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +641 -266
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js +464 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js +69 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js +108 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js +14 -186
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +5 -14
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +14 -13
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +1 -1
- package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +8 -3
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +8 -0
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +11 -3
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +2 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +14 -4
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +710 -65
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js +238 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js +1028 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js +1088 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +70 -10
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js +887 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +57 -6
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js +7 -5
- package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js.map +1 -1
- package/build/dist/UI/Components/Table/EmptyTableMessage.js +51 -0
- package/build/dist/UI/Components/Table/EmptyTableMessage.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +30 -11
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +9 -2
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +63 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +4 -2
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +91 -10
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +14 -4
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TextArea/TextArea.js +9 -3
- package/build/dist/UI/Components/TextArea/TextArea.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ModelFieldPicker.js +1 -2
- package/build/dist/UI/Components/Workflow/ModelFieldPicker.js.map +1 -1
- package/build/dist/Utils/LabelRuleImportExport.js +2 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/Markdown/UntrustedMarkdown.js +988 -0
- package/build/dist/Utils/Markdown/UntrustedMarkdown.js.map +1 -0
- package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js +34 -0
- package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js +148 -0
- package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +36 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/package.json +1 -3
- package/Server/Utils/CommunityEditionSsoReport.ts +0 -361
- package/Tests/App/Accounts/LoginSsoEdition.test.tsx +0 -616
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +0 -217
- package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +0 -271
- package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +0 -215
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +0 -784
- package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +0 -518
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +0 -419
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +0 -769
- package/Tests/UI/Components/CodeEditor.test.tsx +0 -638
- package/Tests/UI/Components/MonacoLoader.test.ts +0 -67
- package/Tests/UI/Components/MonacoRuntime.test.ts +0 -121
- package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +0 -329
- package/Tests/UI/Components/YamlEditor.test.tsx +0 -847
- package/UI/Components/CodeEditor/MonacoLoader.ts +0 -36
- package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +0 -319
- package/UI/Components/Telemetry/TelemetryRetentionConfigSummary.tsx +0 -223
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js +0 -223
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +0 -1
- package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +0 -34
- package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +0 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +0 -171
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +0 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js +0 -119
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js.map +0 -1
|
@@ -4,13 +4,18 @@ import IconProp from "../../../Types/Icon/IconProp";
|
|
|
4
4
|
import TinyFormDocumentation from "../TinyFormDocumentation/TinyFormDocumentation";
|
|
5
5
|
import { FILE_URL } from "../../Config";
|
|
6
6
|
import API from "../../Utils/API/API";
|
|
7
|
+
import useTranslateValue from "../../Utils/Translation";
|
|
7
8
|
import ModelAPI from "../../Utils/ModelAPI/ModelAPI";
|
|
8
9
|
import CommonURL from "../../../Types/API/URL";
|
|
9
10
|
import MimeType from "../../../Types/File/MimeType";
|
|
10
11
|
import FileModel from "../../../Models/DatabaseModels/File";
|
|
11
12
|
import DOMPurify from "dompurify";
|
|
12
13
|
import { htmlToMarkdown, markdownToHtml } from "./MarkdownConverters";
|
|
13
|
-
import
|
|
14
|
+
import { indentMarkdownLines, isInFencedCodeBlock, liftListItems, outdentMarkdownLines, sinkListItems, stripTextListMarkers, toggleMarkdownList, } from "./MarkdownListEditing";
|
|
15
|
+
import MarkdownEditorHistory from "./MarkdownEditorHistory";
|
|
16
|
+
import { clipboardToMarkdown } from "./MarkdownPaste";
|
|
17
|
+
import { deleteSelectionForInsert, insertBlocksAtCaret, isCaretOnEmptyLine, moveCaretIntoEmptyListAhead, } from "./MarkdownVisualEditing";
|
|
18
|
+
import React, { useState, useRef, useEffect, useId, } from "react";
|
|
14
19
|
const MAX_IMAGE_SIZE_BYTES = 10 * 1024 * 1024; // 10MB
|
|
15
20
|
const IMAGE_MIME_BY_EXTENSION = {
|
|
16
21
|
png: MimeType.png,
|
|
@@ -46,6 +51,142 @@ const sanitizeHtml = (html) => {
|
|
|
46
51
|
ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|tel|ftp|data|placeholder|oneuptime-uploading):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i,
|
|
47
52
|
});
|
|
48
53
|
};
|
|
54
|
+
const RE_SINGLE_PARAGRAPH = /^<p>([\s\S]*)<\/p>$/;
|
|
55
|
+
const RE_LINE_BREAKS = /\r\n?/g;
|
|
56
|
+
const RE_SHOWN_CHARACTER = /\S/;
|
|
57
|
+
const RE_BLANKS_AT_END = /[ \t]*$/;
|
|
58
|
+
const RE_BLANKS_AT_START = /^[ \t]*/;
|
|
59
|
+
// A list item's line, up to its marker: its indentation is group 1.
|
|
60
|
+
const RE_LIST_ITEM_LINE = /^([ \t]*)(?:[-*+]|\d{1,9}[.)])(?=[ \t]|$)/;
|
|
61
|
+
// A list item's line holding nothing but its marker (and a task's box).
|
|
62
|
+
const RE_BARE_LIST_MARKER_LINE = /^[ \t]*(?:[-*+]|\d{1,9}[.)])(?:[ \t]+\[[ xX]\])?[ \t]*$/;
|
|
63
|
+
const RE_STARTS_WITH_LIST_ITEM = /^(?:[-*+]|\d{1,9}[.)])[ \t]/;
|
|
64
|
+
/*
|
|
65
|
+
* The inside of `html` when it is exactly one paragraph -- which is what
|
|
66
|
+
* markdownToHtml makes of a word, a sentence or an image -- and null for
|
|
67
|
+
* anything else.
|
|
68
|
+
*/
|
|
69
|
+
const singleParagraphContents = (html) => {
|
|
70
|
+
var _a;
|
|
71
|
+
const inner = (_a = html.match(RE_SINGLE_PARAGRAPH)) === null || _a === void 0 ? void 0 : _a[1];
|
|
72
|
+
if (inner === undefined || inner.includes("</p>")) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
return inner;
|
|
76
|
+
};
|
|
77
|
+
/*
|
|
78
|
+
* Markdown made of blocks -- a fenced code block, a list, a heading, more
|
|
79
|
+
* than one paragraph -- pasted into the middle of a line of the markdown
|
|
80
|
+
* source goes on lines of its own, with a blank line between it and the
|
|
81
|
+
* text either side of it on that line: the split the visual editor makes
|
|
82
|
+
* for a block. Put in the middle of the line as it was, a code block's
|
|
83
|
+
* closing fence had the rest of the line after it, which made it an opening
|
|
84
|
+
* fence instead -- the block never closed, and everything after it in the
|
|
85
|
+
* note rendered as code. The spaces at the split go, as in the visual
|
|
86
|
+
* editor. Returns the text to insert, having widened the textarea's
|
|
87
|
+
* selection over those spaces.
|
|
88
|
+
*/
|
|
89
|
+
const onLinesOfItsOwn = (textarea, markdown) => {
|
|
90
|
+
var _a, _b;
|
|
91
|
+
if (!RE_SHOWN_CHARACTER.test(markdown) ||
|
|
92
|
+
singleParagraphContents(markdownToHtml(markdown)) !== null) {
|
|
93
|
+
return markdown;
|
|
94
|
+
}
|
|
95
|
+
const value = textarea.value;
|
|
96
|
+
const start = textarea.selectionStart;
|
|
97
|
+
const end = textarea.selectionEnd;
|
|
98
|
+
const lineStart = value.lastIndexOf("\n", start - 1) + 1;
|
|
99
|
+
const lineEndAt = value.indexOf("\n", end);
|
|
100
|
+
const lineEnd = lineEndAt === -1 ? value.length : lineEndAt;
|
|
101
|
+
const before = value.slice(lineStart, start);
|
|
102
|
+
const after = value.slice(end, lineEnd);
|
|
103
|
+
const textBefore = RE_SHOWN_CHARACTER.test(before);
|
|
104
|
+
const textAfter = RE_SHOWN_CHARACTER.test(after);
|
|
105
|
+
if (!textBefore && !textAfter) {
|
|
106
|
+
return markdown;
|
|
107
|
+
}
|
|
108
|
+
const spacesBefore = textBefore
|
|
109
|
+
? (((_a = before.match(RE_BLANKS_AT_END)) === null || _a === void 0 ? void 0 : _a[0]) || "").length
|
|
110
|
+
: 0;
|
|
111
|
+
const spacesAfter = textAfter
|
|
112
|
+
? (((_b = after.match(RE_BLANKS_AT_START)) === null || _b === void 0 ? void 0 : _b[0]) || "").length
|
|
113
|
+
: 0;
|
|
114
|
+
const itemLine = before.match(RE_LIST_ITEM_LINE);
|
|
115
|
+
if (itemLine && RE_STARTS_WITH_LIST_ITEM.test(markdown)) {
|
|
116
|
+
/*
|
|
117
|
+
* A list pasted on the line of a list item joins that item's list, as
|
|
118
|
+
* in the visual editor: its items go on the lines after the item, at
|
|
119
|
+
* its indentation -- or in its place when the caret sits after nothing
|
|
120
|
+
* but its marker, a "- " typed to start the list. After a blank line
|
|
121
|
+
* they were a list of their own; after the bare marker, a list nested
|
|
122
|
+
* in an empty item: "- - a", two bullets.
|
|
123
|
+
*/
|
|
124
|
+
const indent = itemLine[1] || "";
|
|
125
|
+
const items = markdown
|
|
126
|
+
.split("\n")
|
|
127
|
+
.map((line) => {
|
|
128
|
+
return line ? `${indent}${line}` : line;
|
|
129
|
+
})
|
|
130
|
+
.join("\n");
|
|
131
|
+
if (RE_BARE_LIST_MARKER_LINE.test(before)) {
|
|
132
|
+
/*
|
|
133
|
+
* Only the item's marker (and task box) is before the caret. An empty
|
|
134
|
+
* item is replaced by the pasted items; an item with text keeps its
|
|
135
|
+
* own marker and task box, and the pasted items go in before it, as in
|
|
136
|
+
* the visual editor. Deciding on what is before the caret alone turned
|
|
137
|
+
* "- [x] |rolled back deploy" into a paragraph: the marker and the tick
|
|
138
|
+
* went, and the item's text was left on a line of its own.
|
|
139
|
+
*/
|
|
140
|
+
textarea.setSelectionRange(lineStart, end + spacesAfter);
|
|
141
|
+
return textAfter ? `${items}\n${before}` : items;
|
|
142
|
+
}
|
|
143
|
+
textarea.setSelectionRange(start - spacesBefore, end + spacesAfter);
|
|
144
|
+
return `\n${items}${textAfter ? "\n\n" : ""}`;
|
|
145
|
+
}
|
|
146
|
+
textarea.setSelectionRange(start - spacesBefore, end + spacesAfter);
|
|
147
|
+
return `${textBefore ? "\n\n" : ""}${markdown}${textAfter ? "\n\n" : ""}`;
|
|
148
|
+
};
|
|
149
|
+
const RE_MARKUP = /<[a-z!/]/i;
|
|
150
|
+
// The text of `html` when it holds no markup at all, else null.
|
|
151
|
+
const textOfMarkupFreeHtml = (html) => {
|
|
152
|
+
if (RE_MARKUP.test(html)) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
// Only entities to decode; a <template> parses them without running anything.
|
|
156
|
+
const template = document.createElement("template");
|
|
157
|
+
template.innerHTML = html;
|
|
158
|
+
return template.content.textContent || "";
|
|
159
|
+
};
|
|
160
|
+
/*
|
|
161
|
+
* Tab and Shift+Tab without other modifiers indent and outdent list items.
|
|
162
|
+
* A keypress that is still composing (an IME) is left alone.
|
|
163
|
+
*/
|
|
164
|
+
const isListIndentKey = (event) => {
|
|
165
|
+
return (event.key === "Tab" &&
|
|
166
|
+
!event.ctrlKey &&
|
|
167
|
+
!event.metaKey &&
|
|
168
|
+
!event.altKey &&
|
|
169
|
+
!event.nativeEvent.isComposing);
|
|
170
|
+
};
|
|
171
|
+
/*
|
|
172
|
+
* Ctrl+Z (Cmd+Z on a Mac) is undo; Ctrl+Shift+Z, Cmd+Shift+Z and Ctrl+Y are
|
|
173
|
+
* redo. A keypress that is still composing is left alone.
|
|
174
|
+
*/
|
|
175
|
+
const historyStepOfKey = (event) => {
|
|
176
|
+
if (!(event.ctrlKey || event.metaKey) ||
|
|
177
|
+
event.altKey ||
|
|
178
|
+
event.nativeEvent.isComposing) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
const key = event.key.toLowerCase();
|
|
182
|
+
if (key === "z") {
|
|
183
|
+
return event.shiftKey ? "redo" : "undo";
|
|
184
|
+
}
|
|
185
|
+
if (key === "y" && !event.shiftKey) {
|
|
186
|
+
return "redo";
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
};
|
|
49
190
|
const ToolbarButton = ({ icon, title, onClick, isActive = false, }) => {
|
|
50
191
|
return (React.createElement("button", { type: "button", onMouseDown: (e) => {
|
|
51
192
|
/*
|
|
@@ -59,6 +200,29 @@ const ToolbarButton = ({ icon, title, onClick, isActive = false, }) => {
|
|
|
59
200
|
React.createElement(Icon, { icon: icon, className: "h-4 w-4" })));
|
|
60
201
|
};
|
|
61
202
|
const MarkdownEditor = (props) => {
|
|
203
|
+
var _a, _b, _c;
|
|
204
|
+
const allowImageUpload = props.allowImageUpload !== false;
|
|
205
|
+
/*
|
|
206
|
+
* The error message is tied to the field -- in either mode -- and
|
|
207
|
+
* announced when it appears, as Input's and TextArea's are. It was a bare
|
|
208
|
+
* paragraph: a required description left empty was neither announced nor
|
|
209
|
+
* tied to the editor, so to a screen reader the form did nothing.
|
|
210
|
+
*/
|
|
211
|
+
const errorId = `markdown-editor-error-${useId()}`;
|
|
212
|
+
/*
|
|
213
|
+
* The words the editor always shows of its own -- an empty field's
|
|
214
|
+
* placeholder and the heading of its formatting help -- are looked up in
|
|
215
|
+
* the page's locale, as FieldLabel's "(Optional)" is: on the public
|
|
216
|
+
* incident form, translated all round, they were the only English left.
|
|
217
|
+
* The English text is the key, and an app whose locale has no entry for
|
|
218
|
+
* it shows the English.
|
|
219
|
+
*/
|
|
220
|
+
const { translateString } = useTranslateValue();
|
|
221
|
+
const visualPlaceholder = props.placeholder ||
|
|
222
|
+
((_a = translateString("Type your content here...")) !== null && _a !== void 0 ? _a : "Type your content here...");
|
|
223
|
+
const sourcePlaceholder = props.placeholder ||
|
|
224
|
+
((_b = translateString("Type your markdown here...")) !== null && _b !== void 0 ? _b : "Type your markdown here...");
|
|
225
|
+
const helpTitle = (_c = translateString("Formatting help")) !== null && _c !== void 0 ? _c : "Formatting help";
|
|
62
226
|
const [text, setText] = useState(props.initialValue || "");
|
|
63
227
|
const [mode, setMode] = useState("wysiwyg");
|
|
64
228
|
const [isDraggingOver, setIsDraggingOver] = useState(false);
|
|
@@ -72,6 +236,14 @@ const MarkdownEditor = (props) => {
|
|
|
72
236
|
* quick succession or the user keeps typing while uploading.
|
|
73
237
|
*/
|
|
74
238
|
const textRef = useRef(props.initialValue || "");
|
|
239
|
+
/*
|
|
240
|
+
* The visual editor's own edits -- list moves, inserts made by hand --
|
|
241
|
+
* which the browser's undo stack never hears of (see
|
|
242
|
+
* MarkdownEditorHistory).
|
|
243
|
+
*/
|
|
244
|
+
const [history] = useState(() => {
|
|
245
|
+
return new MarkdownEditorHistory();
|
|
246
|
+
});
|
|
75
247
|
useEffect(() => {
|
|
76
248
|
if (props.initialValue !== undefined &&
|
|
77
249
|
props.initialValue !== textRef.current) {
|
|
@@ -79,6 +251,10 @@ const MarkdownEditor = (props) => {
|
|
|
79
251
|
textRef.current = props.initialValue;
|
|
80
252
|
}
|
|
81
253
|
}, [props.initialValue]);
|
|
254
|
+
// A new editable in each mode: records about the old one's nodes are no use.
|
|
255
|
+
useEffect(() => {
|
|
256
|
+
history.clear();
|
|
257
|
+
}, [mode]);
|
|
82
258
|
/*
|
|
83
259
|
* Sync markdown -> contenteditable when entering WYSIWYG, when text
|
|
84
260
|
* changes from outside, or after async image-upload swaps. Skip when
|
|
@@ -100,6 +276,7 @@ const MarkdownEditor = (props) => {
|
|
|
100
276
|
const html = sanitizeHtml(markdownToHtml(text));
|
|
101
277
|
if (editable.innerHTML !== html) {
|
|
102
278
|
editable.innerHTML = html;
|
|
279
|
+
history.clear();
|
|
103
280
|
}
|
|
104
281
|
}, [mode, text]);
|
|
105
282
|
const handleChange = (value) => {
|
|
@@ -120,6 +297,78 @@ const MarkdownEditor = (props) => {
|
|
|
120
297
|
handleChange(md);
|
|
121
298
|
}
|
|
122
299
|
};
|
|
300
|
+
/*
|
|
301
|
+
* An edit the visual editor makes to its DOM itself, recorded so that
|
|
302
|
+
* Ctrl+Z takes it back. Returns what `edit` returns: whether it changed
|
|
303
|
+
* anything.
|
|
304
|
+
*/
|
|
305
|
+
const editEditableByHand = (edit) => {
|
|
306
|
+
const editable = editableRef.current;
|
|
307
|
+
if (!editable) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
return history.record(editable, () => {
|
|
311
|
+
return edit(editable);
|
|
312
|
+
});
|
|
313
|
+
};
|
|
314
|
+
/*
|
|
315
|
+
* Undo or redo of the editor's own edits; false (and nothing done) when
|
|
316
|
+
* the last thing to undo is the browser's -- typing, say -- so the
|
|
317
|
+
* browser does it.
|
|
318
|
+
*/
|
|
319
|
+
const stepEditableHistory = (step) => {
|
|
320
|
+
const editable = editableRef.current;
|
|
321
|
+
if (!editable) {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
const stepped = step === "undo" ? history.undo(editable) : history.redo(editable);
|
|
325
|
+
if (stepped) {
|
|
326
|
+
syncFromEditable();
|
|
327
|
+
}
|
|
328
|
+
return stepped;
|
|
329
|
+
};
|
|
330
|
+
/*
|
|
331
|
+
* Typing, a paste the browser makes, an execCommand: each is newer
|
|
332
|
+
* history in the browser's own undo stack. The editor's own records wait
|
|
333
|
+
* behind it -- each applies again once the browser's undo has put the
|
|
334
|
+
* editor back as that edit left it -- but what they would redo is gone,
|
|
335
|
+
* as the browser's own redo is. The browser's undo and redo themselves
|
|
336
|
+
* leave both be.
|
|
337
|
+
*/
|
|
338
|
+
const handleEditableInput = (event) => {
|
|
339
|
+
var _a;
|
|
340
|
+
const inputType = ((_a = event.nativeEvent) === null || _a === void 0 ? void 0 : _a.inputType) || "";
|
|
341
|
+
if (inputType !== "historyUndo" && inputType !== "historyRedo") {
|
|
342
|
+
history.clearRedo();
|
|
343
|
+
}
|
|
344
|
+
syncFromEditable();
|
|
345
|
+
};
|
|
346
|
+
/*
|
|
347
|
+
* Undo and redo from the browser's Edit menu or context menu arrive with
|
|
348
|
+
* no key press, as a native beforeinput event -- which React's
|
|
349
|
+
* onBeforeInput is not -- so it is listened for on the element itself.
|
|
350
|
+
* The ref keeps the listener on the latest render's handlers.
|
|
351
|
+
*/
|
|
352
|
+
const beforeInputRef = useRef(() => { });
|
|
353
|
+
beforeInputRef.current = (event) => {
|
|
354
|
+
if ((event.inputType === "historyUndo" && stepEditableHistory("undo")) ||
|
|
355
|
+
(event.inputType === "historyRedo" && stepEditableHistory("redo"))) {
|
|
356
|
+
event.preventDefault();
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
useEffect(() => {
|
|
360
|
+
const editable = editableRef.current;
|
|
361
|
+
if (mode !== "wysiwyg" || !editable) {
|
|
362
|
+
return undefined;
|
|
363
|
+
}
|
|
364
|
+
const listener = (event) => {
|
|
365
|
+
beforeInputRef.current(event);
|
|
366
|
+
};
|
|
367
|
+
editable.addEventListener("beforeinput", listener);
|
|
368
|
+
return () => {
|
|
369
|
+
editable.removeEventListener("beforeinput", listener);
|
|
370
|
+
};
|
|
371
|
+
}, [mode]);
|
|
123
372
|
const insertTextAtCursor = (textToInsert) => {
|
|
124
373
|
const textarea = textareaRef.current;
|
|
125
374
|
const currentText = textRef.current;
|
|
@@ -140,6 +389,7 @@ const MarkdownEditor = (props) => {
|
|
|
140
389
|
}, 0);
|
|
141
390
|
};
|
|
142
391
|
const insertHtmlAtCursorInEditable = (html) => {
|
|
392
|
+
var _a;
|
|
143
393
|
const editable = editableRef.current;
|
|
144
394
|
if (!editable) {
|
|
145
395
|
return;
|
|
@@ -158,17 +408,80 @@ const MarkdownEditor = (props) => {
|
|
|
158
408
|
syncFromEditable();
|
|
159
409
|
return;
|
|
160
410
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const lastNode = fragment.lastChild;
|
|
164
|
-
range.insertNode(fragment);
|
|
165
|
-
if (lastNode) {
|
|
166
|
-
const newRange = document.createRange();
|
|
167
|
-
newRange.setStartAfter(lastNode);
|
|
168
|
-
newRange.collapse(true);
|
|
411
|
+
// Chromium's caret just before a list it has just made goes into its item.
|
|
412
|
+
if (moveCaretIntoEmptyListAhead(editable, range)) {
|
|
169
413
|
selection.removeAllRanges();
|
|
170
|
-
selection.addRange(
|
|
414
|
+
selection.addRange(range);
|
|
415
|
+
}
|
|
416
|
+
/*
|
|
417
|
+
* A single paragraph goes in as its contents, so text pasted into the
|
|
418
|
+
* middle of a line joins that line. Inserted whole, the <p> landed
|
|
419
|
+
* inside the paragraph the caret was in and the serializer wrote it out
|
|
420
|
+
* as three: pasting "big " into "hello world" saved
|
|
421
|
+
* "hello \n\nbig \n\nworld", and an uploading image's placeholder split
|
|
422
|
+
* its line the same way. Straight into the editor itself -- empty, or
|
|
423
|
+
* between two blocks -- the paragraph is kept.
|
|
424
|
+
*/
|
|
425
|
+
const contents = range.startContainer === editable
|
|
426
|
+
? html
|
|
427
|
+
: (_a = singleParagraphContents(html)) !== null && _a !== void 0 ? _a : html;
|
|
428
|
+
/*
|
|
429
|
+
* execCommand puts the insert on the browser's undo stack. Plain words
|
|
430
|
+
* go in with insertText, as if typed. Blocks go in with insertHTML only
|
|
431
|
+
* onto an empty line: anywhere else in a line, Chromium and Safari fold
|
|
432
|
+
* the first block into that line -- a <pre> became a monospace <span> of
|
|
433
|
+
* the paragraph, and a code block pasted after "Run:" saved as
|
|
434
|
+
* "Run:npm install" -- so there the line is split at the caret by hand
|
|
435
|
+
* and the blocks go in between its halves. Words with formatting go in
|
|
436
|
+
* by hand too: Chromium's and Firefox's insertHTML turn the spaces around
|
|
437
|
+
* an inline insert into non-breaking ones, which then ended up in the
|
|
438
|
+
* saved markdown. jsdom has no execCommand and a browser may refuse the
|
|
439
|
+
* command, so the insert by hand is the fallback as well.
|
|
440
|
+
*/
|
|
441
|
+
const inline = contents !== html;
|
|
442
|
+
const plainText = inline
|
|
443
|
+
? textOfMarkupFreeHtml(contents)
|
|
444
|
+
: null;
|
|
445
|
+
let command = null;
|
|
446
|
+
if (plainText !== null) {
|
|
447
|
+
command = "insertText";
|
|
448
|
+
}
|
|
449
|
+
else if (!inline && isCaretOnEmptyLine(editable, range)) {
|
|
450
|
+
command = "insertHTML";
|
|
451
|
+
}
|
|
452
|
+
if (command && typeof document.execCommand === "function") {
|
|
453
|
+
try {
|
|
454
|
+
if (document.execCommand(command, false, plainText !== null && plainText !== void 0 ? plainText : contents)) {
|
|
455
|
+
syncFromEditable();
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
catch (_b) {
|
|
460
|
+
// Fall through to the insert by hand.
|
|
461
|
+
}
|
|
171
462
|
}
|
|
463
|
+
editEditableByHand(() => {
|
|
464
|
+
deleteSelectionForInsert(editable, range);
|
|
465
|
+
const fragment = range.createContextualFragment(contents);
|
|
466
|
+
let caret = null;
|
|
467
|
+
if (inline) {
|
|
468
|
+
const lastNode = fragment.lastChild;
|
|
469
|
+
range.insertNode(fragment);
|
|
470
|
+
if (lastNode) {
|
|
471
|
+
caret = document.createRange();
|
|
472
|
+
caret.setStartAfter(lastNode);
|
|
473
|
+
caret.collapse(true);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
caret = insertBlocksAtCaret(editable, range, fragment);
|
|
478
|
+
}
|
|
479
|
+
if (caret) {
|
|
480
|
+
selection.removeAllRanges();
|
|
481
|
+
selection.addRange(caret);
|
|
482
|
+
}
|
|
483
|
+
return true;
|
|
484
|
+
});
|
|
172
485
|
syncFromEditable();
|
|
173
486
|
};
|
|
174
487
|
const insertMarkdownAtCursor = (md) => {
|
|
@@ -294,32 +607,141 @@ const MarkdownEditor = (props) => {
|
|
|
294
607
|
}
|
|
295
608
|
return files;
|
|
296
609
|
};
|
|
610
|
+
/*
|
|
611
|
+
* Text for the source textarea. execCommand("insertText") types it the
|
|
612
|
+
* way a native paste would, so Ctrl+Z undoes it; where the browser has no
|
|
613
|
+
* such command (jsdom) it is spliced into the value instead.
|
|
614
|
+
*/
|
|
615
|
+
const insertTextInTextarea = (textToInsert) => {
|
|
616
|
+
const textarea = textareaRef.current;
|
|
617
|
+
if (textarea && typeof document.execCommand === "function") {
|
|
618
|
+
textarea.focus();
|
|
619
|
+
try {
|
|
620
|
+
if (document.execCommand("insertText", false, textToInsert)) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
catch (_a) {
|
|
625
|
+
// Fall back to splicing the value.
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
insertTextAtCursor(textToInsert);
|
|
629
|
+
};
|
|
630
|
+
/*
|
|
631
|
+
* Markdown mode. Rich clipboard content (a Word list, a copied note) is
|
|
632
|
+
* converted to markdown source, and a file on the clipboard uploads as
|
|
633
|
+
* before. When the conversion gives back exactly the plain text, the
|
|
634
|
+
* browser's own paste inserts the same thing, so it is left to it.
|
|
635
|
+
*/
|
|
297
636
|
const handleTextareaPaste = (e) => {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
637
|
+
const clipboardData = e.clipboardData;
|
|
638
|
+
if (!clipboardData) {
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
/*
|
|
642
|
+
* Inside a fenced code block the text goes in as it is, the browser's
|
|
643
|
+
* own paste (which keeps it on the undo stack) -- as in the visual
|
|
644
|
+
* editor's code blocks. Converted there, a command copied from a docs
|
|
645
|
+
* page came in as its own ``` fence, which closed the block around it,
|
|
646
|
+
* and CLI output had its "1)" and "•" lines rewritten as list items. A
|
|
647
|
+
* clipboard with no text, only an image, still uploads below.
|
|
648
|
+
*/
|
|
649
|
+
const textarea = e.currentTarget;
|
|
650
|
+
if (clipboardData.getData("text/plain") &&
|
|
651
|
+
isInFencedCodeBlock(textarea.value, textarea.selectionStart)) {
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
const images = allowImageUpload
|
|
655
|
+
? extractImagesFromClipboard(clipboardData.items || null)
|
|
656
|
+
: [];
|
|
657
|
+
const markdown = clipboardToMarkdown(clipboardData, {
|
|
658
|
+
hasImageFiles: images.length > 0,
|
|
659
|
+
});
|
|
660
|
+
if (markdown === null) {
|
|
661
|
+
if (images.length > 0) {
|
|
662
|
+
e.preventDefault();
|
|
663
|
+
void handleImageFiles(images);
|
|
664
|
+
}
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
const plain = (clipboardData.getData("text/plain") || "").replace(RE_LINE_BREAKS, "\n");
|
|
668
|
+
if (markdown === plain) {
|
|
301
669
|
return;
|
|
302
670
|
}
|
|
303
671
|
e.preventDefault();
|
|
304
|
-
|
|
672
|
+
insertTextInTextarea(onLinesOfItsOwn(textarea, markdown));
|
|
673
|
+
};
|
|
674
|
+
// The code block the caret is in, if it is in one.
|
|
675
|
+
const codeBlockAtSelection = () => {
|
|
676
|
+
const editable = editableRef.current;
|
|
677
|
+
const selection = window.getSelection();
|
|
678
|
+
if (!editable || !selection || selection.rangeCount === 0) {
|
|
679
|
+
return null;
|
|
680
|
+
}
|
|
681
|
+
let node = selection.getRangeAt(0).startContainer;
|
|
682
|
+
while (node && node !== editable) {
|
|
683
|
+
if (node.nodeName.toLowerCase() === "pre") {
|
|
684
|
+
return node;
|
|
685
|
+
}
|
|
686
|
+
node = node.parentNode;
|
|
687
|
+
}
|
|
688
|
+
return null;
|
|
689
|
+
};
|
|
690
|
+
const insertPlainTextInEditable = (value) => {
|
|
691
|
+
const editable = editableRef.current;
|
|
692
|
+
const selection = window.getSelection();
|
|
693
|
+
if (!editable || !selection || selection.rangeCount === 0) {
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
const range = selection.getRangeAt(0);
|
|
697
|
+
editEditableByHand(() => {
|
|
698
|
+
deleteSelectionForInsert(editable, range);
|
|
699
|
+
const textNode = document.createTextNode(value);
|
|
700
|
+
range.insertNode(textNode);
|
|
701
|
+
const after = document.createRange();
|
|
702
|
+
after.setStartAfter(textNode);
|
|
703
|
+
after.collapse(true);
|
|
704
|
+
selection.removeAllRanges();
|
|
705
|
+
selection.addRange(after);
|
|
706
|
+
return true;
|
|
707
|
+
});
|
|
708
|
+
syncFromEditable();
|
|
305
709
|
};
|
|
710
|
+
/*
|
|
711
|
+
* Visual mode. The browser's own paste would bring the source's markup in
|
|
712
|
+
* with it -- styles, classes, elements markdown cannot hold -- so the paste
|
|
713
|
+
* is always handled here: converted to markdown (the clipboard's HTML
|
|
714
|
+
* first, so a Word or Outlook list keeps its nesting, then its plain text)
|
|
715
|
+
* and rendered back. Image files upload when there is no text to paste.
|
|
716
|
+
* Inside a code block the plain text goes in as it is.
|
|
717
|
+
*/
|
|
306
718
|
const handleEditablePaste = (e) => {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (images.length > 0) {
|
|
310
|
-
e.preventDefault();
|
|
311
|
-
void handleImageFiles(images);
|
|
719
|
+
const clipboardData = e.clipboardData;
|
|
720
|
+
if (!clipboardData) {
|
|
312
721
|
return;
|
|
313
722
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
723
|
+
e.preventDefault();
|
|
724
|
+
if (codeBlockAtSelection()) {
|
|
725
|
+
const plain = clipboardData.getData("text/plain") || "";
|
|
726
|
+
if (plain) {
|
|
727
|
+
insertPlainTextInEditable(plain.replace(RE_LINE_BREAKS, "\n"));
|
|
728
|
+
}
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
const images = allowImageUpload
|
|
732
|
+
? extractImagesFromClipboard(clipboardData.items || null)
|
|
733
|
+
: [];
|
|
734
|
+
const markdown = clipboardToMarkdown(clipboardData, {
|
|
735
|
+
hasImageFiles: images.length > 0,
|
|
736
|
+
});
|
|
737
|
+
if (markdown !== null) {
|
|
738
|
+
if (markdown) {
|
|
739
|
+
insertMarkdownAtCursor(markdown);
|
|
740
|
+
}
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
if (images.length > 0) {
|
|
744
|
+
void handleImageFiles(images);
|
|
323
745
|
}
|
|
324
746
|
};
|
|
325
747
|
const dragHasFiles = (types) => {
|
|
@@ -339,6 +761,17 @@ const MarkdownEditor = (props) => {
|
|
|
339
761
|
return;
|
|
340
762
|
}
|
|
341
763
|
e.preventDefault();
|
|
764
|
+
if (!allowImageUpload) {
|
|
765
|
+
/*
|
|
766
|
+
* Refuse the drop outright. Left to itself the browser would drop the
|
|
767
|
+
* file in anyway -- Firefox inlines an image as a data: URL -- or
|
|
768
|
+
* navigate away to it.
|
|
769
|
+
*/
|
|
770
|
+
if (e.dataTransfer) {
|
|
771
|
+
e.dataTransfer.dropEffect = "none";
|
|
772
|
+
}
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
342
775
|
if (!isDraggingOver) {
|
|
343
776
|
setIsDraggingOver(true);
|
|
344
777
|
}
|
|
@@ -353,6 +786,9 @@ const MarkdownEditor = (props) => {
|
|
|
353
786
|
}
|
|
354
787
|
e.preventDefault();
|
|
355
788
|
setIsDraggingOver(false);
|
|
789
|
+
if (!allowImageUpload) {
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
356
792
|
const fileList = ((_b = e.dataTransfer) === null || _b === void 0 ? void 0 : _b.files) || null;
|
|
357
793
|
if (!fileList || fileList.length === 0) {
|
|
358
794
|
return;
|
|
@@ -362,6 +798,9 @@ const MarkdownEditor = (props) => {
|
|
|
362
798
|
};
|
|
363
799
|
const handleImageButtonClick = () => {
|
|
364
800
|
var _a;
|
|
801
|
+
if (!allowImageUpload) {
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
365
804
|
(_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
|
|
366
805
|
};
|
|
367
806
|
const handleFileInputChange = (e) => {
|
|
@@ -457,8 +896,86 @@ const MarkdownEditor = (props) => {
|
|
|
457
896
|
}, 0);
|
|
458
897
|
}
|
|
459
898
|
};
|
|
899
|
+
/*
|
|
900
|
+
* Puts an edit into the source textarea, selection included. Only the
|
|
901
|
+
* stretch that changed is replaced, with execCommand("insertText") where
|
|
902
|
+
* the browser has it, so Ctrl+Z undoes an indent like any typing; without
|
|
903
|
+
* it (jsdom) the value is set directly.
|
|
904
|
+
*/
|
|
905
|
+
const applyTextareaEdit = (edit) => {
|
|
906
|
+
const textarea = textareaRef.current;
|
|
907
|
+
if (!textarea) {
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
const current = textarea.value;
|
|
911
|
+
let start = 0;
|
|
912
|
+
while (start < current.length &&
|
|
913
|
+
start < edit.text.length &&
|
|
914
|
+
current.charAt(start) === edit.text.charAt(start)) {
|
|
915
|
+
start++;
|
|
916
|
+
}
|
|
917
|
+
let oldEnd = current.length;
|
|
918
|
+
let newEnd = edit.text.length;
|
|
919
|
+
while (oldEnd > start &&
|
|
920
|
+
newEnd > start &&
|
|
921
|
+
current.charAt(oldEnd - 1) === edit.text.charAt(newEnd - 1)) {
|
|
922
|
+
oldEnd--;
|
|
923
|
+
newEnd--;
|
|
924
|
+
}
|
|
925
|
+
textarea.focus();
|
|
926
|
+
let applied = false;
|
|
927
|
+
if (typeof document.execCommand === "function") {
|
|
928
|
+
textarea.setSelectionRange(start, oldEnd);
|
|
929
|
+
try {
|
|
930
|
+
applied = document.execCommand("insertText", false, edit.text.slice(start, newEnd));
|
|
931
|
+
}
|
|
932
|
+
catch (_a) {
|
|
933
|
+
applied = false;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
if (!applied || textarea.value !== edit.text) {
|
|
937
|
+
textarea.value = edit.text;
|
|
938
|
+
}
|
|
939
|
+
if (textRef.current !== edit.text) {
|
|
940
|
+
handleChange(edit.text);
|
|
941
|
+
}
|
|
942
|
+
textarea.setSelectionRange(edit.selectionStart, edit.selectionEnd);
|
|
943
|
+
};
|
|
944
|
+
// Runs a source edit on the textarea's text and selection; false if it changed nothing.
|
|
945
|
+
const editTextarea = (editor) => {
|
|
946
|
+
const textarea = textareaRef.current;
|
|
947
|
+
if (!textarea) {
|
|
948
|
+
return false;
|
|
949
|
+
}
|
|
950
|
+
const edit = editor(textarea.value, textarea.selectionStart, textarea.selectionEnd);
|
|
951
|
+
if (!edit) {
|
|
952
|
+
return false;
|
|
953
|
+
}
|
|
954
|
+
applyTextareaEdit(edit);
|
|
955
|
+
return true;
|
|
956
|
+
};
|
|
957
|
+
const toggleListInTextarea = (kind) => {
|
|
958
|
+
editTextarea((source, selectionStart, selectionEnd) => {
|
|
959
|
+
return toggleMarkdownList(source, selectionStart, selectionEnd, kind);
|
|
960
|
+
});
|
|
961
|
+
};
|
|
962
|
+
/*
|
|
963
|
+
* Indent or outdent the list items at the selection in the visual editor;
|
|
964
|
+
* false (and nothing changed) when the selection is not on an item that
|
|
965
|
+
* can move. The items are moved by hand, so the move is recorded for
|
|
966
|
+
* Ctrl+Z: it undid the typing before an indent and left the indent.
|
|
967
|
+
*/
|
|
968
|
+
const shiftListItemsInEditable = (outdent) => {
|
|
969
|
+
const changed = editEditableByHand((editable) => {
|
|
970
|
+
return outdent ? liftListItems(editable) : sinkListItems(editable);
|
|
971
|
+
});
|
|
972
|
+
if (changed) {
|
|
973
|
+
syncFromEditable();
|
|
974
|
+
}
|
|
975
|
+
return changed;
|
|
976
|
+
};
|
|
460
977
|
// WYSIWYG-mode toolbar helpers (operate on the contenteditable DOM).
|
|
461
|
-
const execEditable = (command, value) => {
|
|
978
|
+
const execEditable = (command, value, afterCommand) => {
|
|
462
979
|
const editable = editableRef.current;
|
|
463
980
|
if (!editable) {
|
|
464
981
|
return;
|
|
@@ -475,8 +992,22 @@ const MarkdownEditor = (props) => {
|
|
|
475
992
|
catch (_a) {
|
|
476
993
|
// Ignore — older command names occasionally throw in some browsers.
|
|
477
994
|
}
|
|
995
|
+
if (afterCommand) {
|
|
996
|
+
afterCommand(editable);
|
|
997
|
+
}
|
|
478
998
|
syncFromEditable();
|
|
479
999
|
};
|
|
1000
|
+
/*
|
|
1001
|
+
* The list buttons. execCommand turns the selected lines into items but
|
|
1002
|
+
* keeps whatever text they started with, so a line pasted from Word as
|
|
1003
|
+
* "•\tService down" showed the list's bullet and its own; the leftover
|
|
1004
|
+
* markers are stripped from the items it made.
|
|
1005
|
+
*/
|
|
1006
|
+
const makeListInEditable = (command) => {
|
|
1007
|
+
execEditable(command, undefined, (editable) => {
|
|
1008
|
+
stripTextListMarkers(editable);
|
|
1009
|
+
});
|
|
1010
|
+
};
|
|
480
1011
|
const wrapSelectionInEditable = (tagName, fallbackText) => {
|
|
481
1012
|
const editable = editableRef.current;
|
|
482
1013
|
if (!editable) {
|
|
@@ -492,12 +1023,15 @@ const MarkdownEditor = (props) => {
|
|
|
492
1023
|
const selected = selection.toString() || fallbackText;
|
|
493
1024
|
const wrapper = document.createElement(tagName);
|
|
494
1025
|
wrapper.textContent = selected;
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
1026
|
+
editEditableByHand(() => {
|
|
1027
|
+
deleteSelectionForInsert(editable, range);
|
|
1028
|
+
range.insertNode(wrapper);
|
|
1029
|
+
const newRange = document.createRange();
|
|
1030
|
+
newRange.selectNodeContents(wrapper);
|
|
1031
|
+
selection.removeAllRanges();
|
|
1032
|
+
selection.addRange(newRange);
|
|
1033
|
+
return true;
|
|
1034
|
+
});
|
|
501
1035
|
syncFromEditable();
|
|
502
1036
|
};
|
|
503
1037
|
const insertWysiwygTaskList = () => {
|
|
@@ -523,18 +1057,50 @@ const MarkdownEditor = (props) => {
|
|
|
523
1057
|
execEditable("createLink", url);
|
|
524
1058
|
}
|
|
525
1059
|
else {
|
|
526
|
-
|
|
1060
|
+
/*
|
|
1061
|
+
* Wrapped in a paragraph, so a link put into a line goes in as that
|
|
1062
|
+
* line's own inline content (insertHtmlAtCursorInEditable unwraps a
|
|
1063
|
+
* single paragraph). A bare <a> was taken for a block: it split the
|
|
1064
|
+
* line, and "See " plus the link saved as two paragraphs. Into the
|
|
1065
|
+
* empty editor the paragraph goes in whole.
|
|
1066
|
+
*/
|
|
1067
|
+
insertHtmlAtCursorInEditable(`<p><a href="${url.replace(/"/g, """)}">${url.replace(/</g, "<")}</a></p>`);
|
|
527
1068
|
}
|
|
528
1069
|
};
|
|
1070
|
+
/*
|
|
1071
|
+
* The Code Block button. As in the markdown source, the new block's
|
|
1072
|
+
* placeholder is selected, so what is typed next replaces it inside the
|
|
1073
|
+
* block. Left to themselves, browsers put the caret at the end of the
|
|
1074
|
+
* placeholder (Chromium, Safari) or on the line below the block (Firefox).
|
|
1075
|
+
* The empty line after the block (a <br> keeps it a line a caret can sit
|
|
1076
|
+
* on) is where writing carries on below it.
|
|
1077
|
+
*/
|
|
529
1078
|
const insertWysiwygCodeBlock = () => {
|
|
530
|
-
|
|
1079
|
+
const editable = editableRef.current;
|
|
1080
|
+
if (!editable) {
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
const existing = new Set(Array.from(editable.querySelectorAll("pre")));
|
|
1084
|
+
insertHtmlAtCursorInEditable("<pre><code>code block</code></pre><p><br></p>");
|
|
1085
|
+
const added = Array.from(editable.querySelectorAll("pre")).filter((pre) => {
|
|
1086
|
+
return !existing.has(pre);
|
|
1087
|
+
});
|
|
1088
|
+
const block = added[added.length - 1];
|
|
1089
|
+
const selection = window.getSelection();
|
|
1090
|
+
if (!block || !selection) {
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
const placeholder = document.createRange();
|
|
1094
|
+
placeholder.selectNodeContents(block.querySelector("code") || block);
|
|
1095
|
+
selection.removeAllRanges();
|
|
1096
|
+
selection.addRange(placeholder);
|
|
531
1097
|
};
|
|
532
1098
|
const insertWysiwygTable = () => {
|
|
533
1099
|
const html = "<table><thead><tr><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr></thead>" +
|
|
534
1100
|
"<tbody>" +
|
|
535
1101
|
"<tr><td>Cell 1</td><td>Cell 2</td><td>Cell 3</td></tr>" +
|
|
536
1102
|
"<tr><td>Cell 4</td><td>Cell 5</td><td>Cell 6</td></tr>" +
|
|
537
|
-
"</tbody></table><p></p>";
|
|
1103
|
+
"</tbody></table><p><br></p>";
|
|
538
1104
|
insertHtmlAtCursorInEditable(html);
|
|
539
1105
|
};
|
|
540
1106
|
const formatActions = {
|
|
@@ -582,21 +1148,39 @@ const MarkdownEditor = (props) => {
|
|
|
582
1148
|
},
|
|
583
1149
|
unorderedList: () => {
|
|
584
1150
|
if (mode === "wysiwyg") {
|
|
585
|
-
return
|
|
1151
|
+
return makeListInEditable("insertUnorderedList");
|
|
586
1152
|
}
|
|
587
|
-
return
|
|
1153
|
+
return toggleListInTextarea("bullet");
|
|
588
1154
|
},
|
|
589
1155
|
orderedList: () => {
|
|
590
1156
|
if (mode === "wysiwyg") {
|
|
591
|
-
return
|
|
1157
|
+
return makeListInEditable("insertOrderedList");
|
|
592
1158
|
}
|
|
593
|
-
return
|
|
1159
|
+
return toggleListInTextarea("ordered");
|
|
594
1160
|
},
|
|
595
1161
|
taskList: () => {
|
|
596
1162
|
if (mode === "wysiwyg") {
|
|
597
1163
|
return insertWysiwygTaskList();
|
|
598
1164
|
}
|
|
599
|
-
return
|
|
1165
|
+
return toggleListInTextarea("task");
|
|
1166
|
+
},
|
|
1167
|
+
indent: () => {
|
|
1168
|
+
var _a;
|
|
1169
|
+
if (mode === "wysiwyg") {
|
|
1170
|
+
(_a = editableRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
1171
|
+
shiftListItemsInEditable(false);
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
editTextarea(indentMarkdownLines);
|
|
1175
|
+
},
|
|
1176
|
+
outdent: () => {
|
|
1177
|
+
var _a;
|
|
1178
|
+
if (mode === "wysiwyg") {
|
|
1179
|
+
(_a = editableRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
1180
|
+
shiftListItemsInEditable(true);
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
editTextarea(outdentMarkdownLines);
|
|
600
1184
|
},
|
|
601
1185
|
link: () => {
|
|
602
1186
|
if (mode === "wysiwyg") {
|
|
@@ -656,6 +1240,16 @@ const MarkdownEditor = (props) => {
|
|
|
656
1240
|
? "ring-2 ring-indigo-400 ring-offset-1 border-indigo-400"
|
|
657
1241
|
: ""}`;
|
|
658
1242
|
const handleEditableKeyDown = (e) => {
|
|
1243
|
+
/*
|
|
1244
|
+
* Ctrl+Z right after an edit the editor made itself -- a list move, an
|
|
1245
|
+
* insert made by hand -- takes that edit back, and Ctrl+Shift+Z makes
|
|
1246
|
+
* it again. Otherwise the key is the browser's, as always.
|
|
1247
|
+
*/
|
|
1248
|
+
const historyStep = historyStepOfKey(e);
|
|
1249
|
+
if (historyStep && stepEditableHistory(historyStep)) {
|
|
1250
|
+
e.preventDefault();
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
659
1253
|
if (e.ctrlKey || e.metaKey) {
|
|
660
1254
|
switch (e.key) {
|
|
661
1255
|
case "b":
|
|
@@ -670,6 +1264,36 @@ const MarkdownEditor = (props) => {
|
|
|
670
1264
|
break;
|
|
671
1265
|
}
|
|
672
1266
|
}
|
|
1267
|
+
/*
|
|
1268
|
+
* Tab indents a list item and Shift+Tab outdents it -- but the key is
|
|
1269
|
+
* only taken when that actually moved something. On a list's first
|
|
1270
|
+
* item, a top-level item, or outside a list, Tab keeps moving focus to
|
|
1271
|
+
* the next field (and Shift+Tab to the previous one), so the editor is
|
|
1272
|
+
* never a keyboard trap. The event is not stopped either: the note
|
|
1273
|
+
* composer handles its own keys where they bubble to.
|
|
1274
|
+
*/
|
|
1275
|
+
if (isListIndentKey(e) && shiftListItemsInEditable(e.shiftKey)) {
|
|
1276
|
+
e.preventDefault();
|
|
1277
|
+
}
|
|
1278
|
+
};
|
|
1279
|
+
const handleTextareaKeyDown = (e) => {
|
|
1280
|
+
if (e.ctrlKey || e.metaKey) {
|
|
1281
|
+
switch (e.key) {
|
|
1282
|
+
case "b":
|
|
1283
|
+
e.preventDefault();
|
|
1284
|
+
formatActions.bold();
|
|
1285
|
+
break;
|
|
1286
|
+
case "i":
|
|
1287
|
+
e.preventDefault();
|
|
1288
|
+
formatActions.italic();
|
|
1289
|
+
break;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
// The same Tab rule as the visual editor's, on the markdown lines.
|
|
1293
|
+
if (isListIndentKey(e) &&
|
|
1294
|
+
editTextarea(e.shiftKey ? outdentMarkdownLines : indentMarkdownLines)) {
|
|
1295
|
+
e.preventDefault();
|
|
1296
|
+
}
|
|
673
1297
|
};
|
|
674
1298
|
return (React.createElement("div", { className: "relative", "data-testid": props.dataTestId },
|
|
675
1299
|
React.createElement("style", null, `
|
|
@@ -679,6 +1303,9 @@ const MarkdownEditor = (props) => {
|
|
|
679
1303
|
.oneuptime-wysiwyg p { margin: 0.5rem 0; }
|
|
680
1304
|
.oneuptime-wysiwyg ul, .oneuptime-wysiwyg ol { margin: 0.5rem 0 0.5rem 1.5rem; }
|
|
681
1305
|
.oneuptime-wysiwyg ul { list-style-type: disc; }
|
|
1306
|
+
/* Nested bullets step through circle and square, as MarkdownViewer draws them. */
|
|
1307
|
+
.oneuptime-wysiwyg ul ul, .oneuptime-wysiwyg ol ul { list-style-type: circle; }
|
|
1308
|
+
.oneuptime-wysiwyg ul ul ul, .oneuptime-wysiwyg ul ol ul, .oneuptime-wysiwyg ol ul ul, .oneuptime-wysiwyg ol ol ul { list-style-type: square; }
|
|
682
1309
|
.oneuptime-wysiwyg ol { list-style-type: decimal; }
|
|
683
1310
|
.oneuptime-wysiwyg ul.task-list, .oneuptime-wysiwyg ul.task-list li { list-style: none; margin-left: 0; }
|
|
684
1311
|
.oneuptime-wysiwyg ul.task-list li { padding-left: 0; }
|
|
@@ -725,11 +1352,18 @@ const MarkdownEditor = (props) => {
|
|
|
725
1352
|
React.createElement("div", { className: "flex items-center gap-1" },
|
|
726
1353
|
React.createElement(ToolbarButton, { icon: IconProp.ListBullet, title: "Bullet List", onClick: formatActions.unorderedList }),
|
|
727
1354
|
React.createElement(ToolbarButton, { icon: IconProp.List, title: "Numbered List", onClick: formatActions.orderedList }),
|
|
728
|
-
React.createElement(ToolbarButton, { icon: IconProp.Check, title: "Task List", onClick: formatActions.taskList })
|
|
1355
|
+
React.createElement(ToolbarButton, { icon: IconProp.Check, title: "Task List", onClick: formatActions.taskList }),
|
|
1356
|
+
React.createElement(ToolbarButton, { icon: IconProp.Indent, title: `Indent (${KeyboardKeyUtil.getDisplayLabel([
|
|
1357
|
+
KeyboardKey.Tab,
|
|
1358
|
+
])})`, onClick: formatActions.indent }),
|
|
1359
|
+
React.createElement(ToolbarButton, { icon: IconProp.Outdent, title: `Outdent (${KeyboardKeyUtil.getDisplayLabel([
|
|
1360
|
+
KeyboardKey.Shift,
|
|
1361
|
+
KeyboardKey.Tab,
|
|
1362
|
+
])})`, onClick: formatActions.outdent })),
|
|
729
1363
|
React.createElement("div", { className: "w-px h-6 bg-gray-300" }),
|
|
730
1364
|
React.createElement("div", { className: "flex items-center gap-1" },
|
|
731
1365
|
React.createElement(ToolbarButton, { icon: IconProp.Link, title: "Link", onClick: formatActions.link }),
|
|
732
|
-
React.createElement(ToolbarButton, { icon: IconProp.Image, title: "Image", onClick: formatActions.image }),
|
|
1366
|
+
allowImageUpload && (React.createElement(ToolbarButton, { icon: IconProp.Image, title: "Image", onClick: formatActions.image })),
|
|
733
1367
|
React.createElement(ToolbarButton, { icon: IconProp.Code, title: "Code", onClick: formatActions.code })),
|
|
734
1368
|
React.createElement("div", { className: "w-px h-6 bg-gray-300" }),
|
|
735
1369
|
React.createElement("div", { className: "flex items-center gap-1" },
|
|
@@ -760,9 +1394,9 @@ const MarkdownEditor = (props) => {
|
|
|
760
1394
|
? "Switch to markdown source"
|
|
761
1395
|
: "Switch to visual editor" }, mode === "wysiwyg" ? "Markdown" : "Visual")))),
|
|
762
1396
|
React.createElement("div", { className: "relative" },
|
|
763
|
-
React.createElement("input", { ref: fileInputRef, type: "file", accept: "image/*", multiple: true, className: "hidden", onChange: handleFileInputChange }),
|
|
1397
|
+
allowImageUpload && (React.createElement("input", { ref: fileInputRef, type: "file", accept: "image/*", multiple: true, className: "hidden", onChange: handleFileInputChange })),
|
|
764
1398
|
mode === "wysiwyg" ? (React.createElement(React.Fragment, null,
|
|
765
|
-
React.createElement("div", { ref: editableRef, role: "textbox", "aria-multiline": "true", "aria-labelledby": props.ariaLabelledby, contentEditable: true, suppressContentEditableWarning: true, spellCheck: props.disableSpellCheck !== true, "data-placeholder":
|
|
1399
|
+
React.createElement("div", { ref: editableRef, role: "textbox", "aria-multiline": "true", "aria-labelledby": props.ariaLabelledby, "aria-invalid": props.error ? "true" : undefined, "aria-describedby": props.error ? errorId : undefined, contentEditable: true, suppressContentEditableWarning: true, spellCheck: props.disableSpellCheck !== true, "data-placeholder": visualPlaceholder, tabIndex: props.tabIndex, className: wysiwygClassName, onInput: handleEditableInput, onPaste: handleEditablePaste, onDragOver: handleDragOver, onDragEnter: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onKeyDown: handleEditableKeyDown, onFocus: () => {
|
|
766
1400
|
if (props.onFocus) {
|
|
767
1401
|
props.onFocus();
|
|
768
1402
|
}
|
|
@@ -775,7 +1409,7 @@ const MarkdownEditor = (props) => {
|
|
|
775
1409
|
React.createElement("span", { className: "rounded-full bg-white px-3 py-1 text-sm font-medium text-indigo-700 shadow-sm" }, "Drop image to upload"))),
|
|
776
1410
|
props.error && (React.createElement("div", { className: "pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3" },
|
|
777
1411
|
React.createElement(Icon, { icon: IconProp.ErrorSolid, className: "h-5 w-5 text-red-500" }))))) : (React.createElement(React.Fragment, null,
|
|
778
|
-
React.createElement("textarea", { ref: textareaRef, autoFocus: false, "aria-labelledby": props.ariaLabelledby,
|
|
1412
|
+
React.createElement("textarea", { ref: textareaRef, autoFocus: false, "aria-labelledby": props.ariaLabelledby, "aria-invalid": props.error ? "true" : undefined, "aria-describedby": props.error ? errorId : undefined, placeholder: sourcePlaceholder, className: `${className} rounded-t-none min-h-32 ${isDraggingOver
|
|
779
1413
|
? "ring-2 ring-indigo-400 ring-offset-1 border-indigo-400"
|
|
780
1414
|
: ""}`, value: text, spellCheck: props.disableSpellCheck !== true, onChange: (e) => {
|
|
781
1415
|
handleChange(e.target.value);
|
|
@@ -787,33 +1421,44 @@ const MarkdownEditor = (props) => {
|
|
|
787
1421
|
if (props.onBlur) {
|
|
788
1422
|
props.onBlur();
|
|
789
1423
|
}
|
|
790
|
-
}, onKeyDown:
|
|
791
|
-
if (e.ctrlKey || e.metaKey) {
|
|
792
|
-
switch (e.key) {
|
|
793
|
-
case "b":
|
|
794
|
-
e.preventDefault();
|
|
795
|
-
formatActions.bold();
|
|
796
|
-
break;
|
|
797
|
-
case "i":
|
|
798
|
-
e.preventDefault();
|
|
799
|
-
formatActions.italic();
|
|
800
|
-
break;
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
}, tabIndex: props.tabIndex, rows: 10 }),
|
|
1424
|
+
}, onKeyDown: handleTextareaKeyDown, tabIndex: props.tabIndex, rows: 10 }),
|
|
804
1425
|
isDraggingOver && (React.createElement("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center rounded-b-md bg-indigo-50/70" },
|
|
805
1426
|
React.createElement("span", { className: "rounded-full bg-white px-3 py-1 text-sm font-medium text-indigo-700 shadow-sm" }, "Drop image to upload"))),
|
|
806
1427
|
props.error && (React.createElement("div", { className: "pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3" },
|
|
807
1428
|
React.createElement(Icon, { icon: IconProp.ErrorSolid, className: "h-5 w-5 text-red-500" })))))),
|
|
808
|
-
props.error && (React.createElement("p", { className: "mt-1 text-sm text-red-400" }, props.error)),
|
|
809
|
-
React.createElement(TinyFormDocumentation, { title:
|
|
1429
|
+
props.error && (React.createElement("p", { id: errorId, role: "alert", className: "mt-1 text-sm text-red-400" }, props.error)),
|
|
1430
|
+
React.createElement(TinyFormDocumentation, { title: helpTitle },
|
|
810
1431
|
React.createElement(React.Fragment, null,
|
|
811
1432
|
React.createElement("div", null, "Type directly in the visual editor \u2014 use the toolbar to format."),
|
|
812
1433
|
React.createElement("div", null,
|
|
813
1434
|
"Switch to ",
|
|
814
1435
|
React.createElement("strong", null, "Markdown"),
|
|
815
1436
|
" to view or edit the raw source."),
|
|
816
|
-
React.createElement("div", null,
|
|
1437
|
+
React.createElement("div", null,
|
|
1438
|
+
"In a list, press",
|
|
1439
|
+
" ",
|
|
1440
|
+
React.createElement("strong", null, KeyboardKeyUtil.getDisplayLabel([KeyboardKey.Tab])),
|
|
1441
|
+
" ",
|
|
1442
|
+
"to indent an item and",
|
|
1443
|
+
" ",
|
|
1444
|
+
React.createElement("strong", null, KeyboardKeyUtil.getDisplayLabel([
|
|
1445
|
+
KeyboardKey.Shift,
|
|
1446
|
+
KeyboardKey.Tab,
|
|
1447
|
+
])),
|
|
1448
|
+
" ",
|
|
1449
|
+
"to outdent it, or use the Indent and Outdent buttons. Outside a list, ",
|
|
1450
|
+
KeyboardKeyUtil.getDisplayLabel([KeyboardKey.Tab]),
|
|
1451
|
+
" moves to the next field."),
|
|
1452
|
+
React.createElement("div", null,
|
|
1453
|
+
"Pasting keeps lists, links and formatting from Word, Outlook, web pages and other notes. To paste plain text instead, press",
|
|
1454
|
+
" ",
|
|
1455
|
+
React.createElement("strong", null, KeyboardKeyUtil.getDisplayLabel([
|
|
1456
|
+
KeyboardKey.Mod,
|
|
1457
|
+
KeyboardKey.Shift,
|
|
1458
|
+
"V",
|
|
1459
|
+
])),
|
|
1460
|
+
"."),
|
|
1461
|
+
allowImageUpload && (React.createElement("div", null, "Tip: paste, drag & drop, or click the image button to upload screenshots inline."))))));
|
|
817
1462
|
};
|
|
818
1463
|
export default MarkdownEditor;
|
|
819
1464
|
//# sourceMappingURL=MarkdownEditor.js.map
|