@oneuptime/common 14.0.9 → 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/AutoRemediationSuggestion.ts +60 -0
- package/Models/DatabaseModels/CephCluster.ts +225 -0
- package/Models/DatabaseModels/CloudResource.ts +12 -0
- package/Models/DatabaseModels/DatabaseServer.ts +225 -0
- package/Models/DatabaseModels/DockerHost.ts +225 -0
- package/Models/DatabaseModels/DockerSwarmCluster.ts +225 -0
- package/Models/DatabaseModels/GlobalConfig.ts +1 -1
- 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 +225 -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 +16 -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 +225 -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 +225 -0
- package/Models/DatabaseModels/ResourceAiAgent.ts +419 -0
- package/Models/DatabaseModels/RumApplication.ts +12 -0
- package/Models/DatabaseModels/RunnerJob.ts +144 -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 +225 -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/AutoRemediationAPI.ts +392 -1
- package/Server/API/IncidentFormAPI.ts +376 -0
- package/Server/API/ProjectOIDC.ts +16 -25
- package/Server/API/ProjectSSO.ts +16 -24
- package/Server/API/ResourceAiAccessAPI.ts +1669 -0
- 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/1796300000000-AddResourceAiAgents.ts +423 -0
- 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 +10 -0
- package/Server/Infrastructure/Semaphore.ts +22 -0
- package/Server/Middleware/IncidentFormRateLimit.ts +847 -0
- package/Server/Middleware/TelemetryIngest.ts +15 -5
- package/Server/Middleware/UserAuthorization.ts +16 -38
- package/Server/Services/AIService.ts +10 -13
- package/Server/Services/AnalyticsDatabaseService.ts +45 -1
- package/Server/Services/AutoRemediationRuleEngineService.ts +940 -112
- package/Server/Services/CephClusterService.ts +109 -1
- package/Server/Services/DatabaseServerService.ts +116 -1
- package/Server/Services/DockerHostService.ts +109 -1
- package/Server/Services/DockerSwarmClusterService.ts +113 -1
- package/Server/Services/HostService.ts +126 -4
- 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/MetricRecordingRuleService.ts +47 -0
- package/Server/Services/OpenTelemetryIngestService.ts +37 -4
- package/Server/Services/PodmanHostService.ts +109 -1
- package/Server/Services/ProjectService.ts +0 -59
- package/Server/Services/ProxmoxClusterService.ts +110 -1
- package/Server/Services/ResourceAiAccessService.ts +1439 -0
- package/Server/Services/ResourceAiAgentJobService.ts +202 -0
- package/Server/Services/ResourceAiAgentService.ts +2432 -0
- package/Server/Services/RunnerJobService.ts +611 -4
- package/Server/Services/StatusPagePrivateUserService.ts +1 -4
- package/Server/Services/StatusPageService.ts +1 -51
- package/Server/Services/TeamComplianceSettingService.ts +163 -42
- package/Server/Services/TelemetryUsageBillingService.ts +28 -0
- package/Server/Services/TraceRecordingRuleService.ts +33 -0
- package/Server/Services/UserNotificationRuleService.ts +8 -1
- package/Server/Services/VMwareVCenterService.ts +110 -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 +1442 -34
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +968 -34
- package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +25 -1
- package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +622 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessContext.ts +271 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.ts +45 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.ts +964 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.ts +333 -0
- package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +882 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +125 -12
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +99 -15
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +99 -15
- 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/AutoRemediation/CommandPlanExecutor.ts +396 -13
- package/Server/Utils/AutoRemediation/RemediationVerifier.ts +35 -2
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +9 -1
- 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/SessionReplay/SessionReplayBudgetMetrics.ts +920 -0
- package/Server/Utils/SessionReplay/SessionReplayUsage.ts +84 -6
- 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/Alert.ts +35 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +33 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +21 -1
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +301 -225
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +38 -16
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +389 -175
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +376 -144
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.ts +163 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.ts +396 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.ts +418 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.ts +152 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.ts +251 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.ts +214 -0
- 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 +267 -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 +23 -6
- 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/InvestigationInfrastructureTools.test.tsx +506 -0
- 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/RemediationSuggestionCardDescription.test.tsx +209 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardResource.test.tsx +317 -0
- package/Tests/App/Dashboard/ResourceAiAccessSettingsUtil.test.ts +921 -0
- package/Tests/App/Dashboard/ResourceAiAgentAttentionServerParity.test.ts +555 -0
- package/Tests/App/Dashboard/ResourceAiAgentInstall.test.ts +860 -0
- package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +2010 -0
- package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +1455 -0
- package/Tests/App/Dashboard/ResourceAiInsightsPage.test.tsx +931 -0
- package/Tests/App/Dashboard/ResourceAiNavigation.test.tsx +575 -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/RunbookStepTypeMaps.test.ts +38 -7
- 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 +61 -10
- package/Tests/Models/DatabaseModels/IncidentFormModel.test.ts +1250 -0
- package/Tests/Models/DatabaseModels/MessageQueueModels.test.ts +1983 -0
- package/Tests/Models/DatabaseModels/ResourceAiAccessColumns.test.ts +738 -0
- package/Tests/Models/DatabaseModels/ResourceAiAgentModel.test.ts +842 -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/AutoRemediationApproveResourceRound.test.ts +835 -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/ResourceAiAccessAPI.test.ts +2730 -0
- 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/AddDatabaseServerTablesMigration.test.ts +60 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentFormsMigration.test.ts +438 -0
- package/Tests/Server/Infrastructure/Postgres/AddResourceAiAgentsMigration.test.ts +659 -0
- package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleNotificationChannelsMigration.test.ts +255 -0
- package/Tests/Server/Infrastructure/Postgres/MessageQueueTablesMigration.test.ts +637 -0
- package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +31 -0
- package/Tests/Server/Middleware/IncidentFormRateLimit.test.ts +1630 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +63 -5
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +103 -5
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +19 -1
- 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/AutoRemediationResourceRuleEngine.test.ts +1279 -0
- package/Tests/Server/Services/DatabaseServerService.test.ts +55 -0
- package/Tests/Server/Services/GroupTelemetryUsageExcludeNames.test.ts +299 -0
- package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +44 -0
- 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/MonitorProbeServiceIntervalScheduling.test.ts +45 -6
- 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/RecordingRuleReservedMetricName.test.ts +171 -0
- package/Tests/Server/Services/ResourceAiAccessChangeAuthorization.test.ts +256 -0
- package/Tests/Server/Services/ResourceAiAccessService.test.ts +1373 -0
- package/Tests/Server/Services/ResourceAiAgentJobService.test.ts +375 -0
- package/Tests/Server/Services/ResourceAiAgentServiceHelpers.test.ts +1114 -0
- package/Tests/Server/Services/ResourceAiAgentServiceLifecycle.test.ts +1050 -0
- package/Tests/Server/Services/ResourceAiAgentServiceRegister.test.ts +2251 -0
- package/Tests/Server/Services/ResourceAiSettingsCreate.test.ts +373 -0
- package/Tests/Server/Services/ResourceAiSettingsPermission.test.ts +1042 -0
- package/Tests/Server/Services/ResourceServiceDeleteCleansUpAi.test.ts +319 -0
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +56 -6
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -1
- package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +105 -0
- package/Tests/Server/Services/RunnerJobEnqueueResourceCommand.test.ts +986 -0
- package/Tests/Server/Services/RunnerJobResourceCommandLane.test.ts +211 -0
- package/Tests/Server/Services/RunnerJobResourceCommandTimeoutAndRedaction.test.ts +352 -0
- 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/Services/TelemetryUsageBillingSloExclusion.test.ts +218 -0
- package/Tests/Server/TestingUtils/Services/FakeRunnerJobCount.ts +145 -0
- 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 +694 -0
- package/Tests/Server/Utils/AI/InvestigationInfrastructureReport.test.ts +721 -0
- 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/RemediationCommandTools.test.ts +94 -1
- package/Tests/Server/Utils/AI/RemediationCommandToolsResource.test.ts +1530 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +14 -25
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +1251 -0
- package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +117 -0
- package/Tests/Server/Utils/AI/RemediationResourceCopyParity.test.ts +463 -0
- package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +1004 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAccessContext.test.ts +266 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.test.ts +1220 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.test.ts +569 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +834 -0
- 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/AutoRemediation/CommandPlanExecutorResource.test.ts +717 -0
- package/Tests/Server/Utils/AutoRemediation/RemediationVerifierResourceFollowUp.test.ts +338 -0
- package/Tests/Server/Utils/EditionEnforcement.test.ts +107 -147
- package/Tests/Server/Utils/Monitor/Criteria/SessionReplayBudgetTemplateCriteria.test.ts +422 -0
- 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/SessionReplay/SessionReplayBudgetMetrics.test.ts +1647 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayUsage.test.ts +143 -1
- 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/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +33 -3
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsAccountNotLinked.test.ts +1093 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.test.ts +1049 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.test.ts +1676 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCards.test.ts +2884 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.test.ts +2490 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmit.test.ts +2293 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmitServerTimezone.test.ts +386 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.test.ts +1477 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.test.ts +1967 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsStripHtmlTags.test.ts +92 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsSubmittedFormRemoval.test.ts +1819 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.test.ts +1033 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezoneServerZone.test.ts +610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsBotMessageHandling.test.ts +2610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsCreateCommandsEndToEnd.test.ts +4672 -0
- package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +190 -65
- package/Tests/Types/AI/AIAgentRunLimits.test.ts +255 -0
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +10 -4
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlanResourceCommand.test.ts +305 -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/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +277 -13
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +113 -0
- package/Tests/Types/Monitor/RumAlertTemplates.test.ts +773 -2
- package/Tests/Types/ResourceAiAgent/AiResourceType.test.ts +419 -0
- package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +519 -0
- package/Tests/Types/Runbook/RunbookStepType.test.ts +147 -8
- 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/Rum/RecordingHealthDashboard.test.tsx +769 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +81 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +17 -0
- package/Tests/Utils/AiRemediation/Resource/CephCommandPolicy.test.ts +1653 -0
- package/Tests/Utils/AiRemediation/Resource/CephOutputRedaction.test.ts +204 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseCommandPolicy.test.ts +1077 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.test.ts +558 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseQueryRedactor.test.ts +834 -0
- package/Tests/Utils/AiRemediation/Resource/DockerCliGrammar.test.ts +747 -0
- package/Tests/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.test.ts +1259 -0
- package/Tests/Utils/AiRemediation/Resource/DockerOutputRedaction.test.ts +386 -0
- package/Tests/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.test.ts +782 -0
- package/Tests/Utils/AiRemediation/Resource/GovcCommandPolicy.test.ts +2259 -0
- package/Tests/Utils/AiRemediation/Resource/HostCommandPolicy.test.ts +2019 -0
- package/Tests/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.test.ts +2497 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicy.test.ts +1305 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.test.ts +585 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactor.test.ts +334 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactorCopyParity.test.ts +98 -0
- package/Tests/Utils/AiRemediation/Resource/ResourcePolicyImportClosure.test.ts +391 -0
- package/Tests/Utils/AiRemediation/ResourceAiAgentPolicyCopyParity.test.ts +497 -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/Tests/Utils/SessionReplay/SessionReplayBudgetMetricType.test.ts +383 -0
- package/Types/AI/AIAgentRunLimits.ts +146 -0
- package/Types/AI/ResourceAiAccessApi.ts +140 -0
- package/Types/AI/ResourceAiAccessPermissions.ts +126 -0
- package/Types/AutoRemediation/AiRemediationCommandPlan.ts +183 -2
- 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/Monitor/Recommendation/MonitorRecommendationCatalog.ts +55 -22
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +35 -3
- package/Types/Monitor/RumAlertTemplates.ts +351 -4
- package/Types/Permission.ts +310 -0
- package/Types/ResourceAiAgent/AiResourceType.ts +310 -0
- package/Types/ResourceAiAgent/ResourceAiAccess.ts +580 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
- package/Types/Rules/RuleRun.ts +4 -0
- package/Types/Rum/SessionReplayBudgetMetricType.ts +47 -0
- package/Types/Runbook/RunbookStepType.ts +29 -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/Telemetry/TelemetryIngestSurface.ts +14 -2
- 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/AI/InvestigationReport.ts +121 -15
- package/Utils/AiRemediation/Resource/CephCommandPolicy.ts +1936 -0
- package/Utils/AiRemediation/Resource/DatabaseCommandPolicy.ts +166 -0
- package/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.ts +1532 -0
- package/Utils/AiRemediation/Resource/DatabaseQueryRedactor.ts +1394 -0
- package/Utils/AiRemediation/Resource/DockerCliGrammar.ts +1839 -0
- package/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.ts +490 -0
- package/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.ts +687 -0
- package/Utils/AiRemediation/Resource/GovcCommandPolicy.ts +2096 -0
- package/Utils/AiRemediation/Resource/HostCommandPolicy.ts +2982 -0
- package/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.ts +1679 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicy.ts +851 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.ts +593 -0
- package/Utils/AiRemediation/Resource/ResourceOutputRedactor.ts +2812 -0
- 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/SessionReplay/SessionReplayBudgetMetricType.ts +184 -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/AutoRemediationSuggestion.js +62 -0
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +231 -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 +231 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +231 -0
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +231 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.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 +231 -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 +16 -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 +231 -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 +231 -0
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js +439 -0
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/RumApplication.js +12 -0
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunnerJob.js +145 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.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 +231 -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/AutoRemediationAPI.js +231 -1
- package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
- 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/ResourceAiAccessAPI.js +1119 -0
- package/build/dist/Server/API/ResourceAiAccessAPI.js.map +1 -0
- 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/1796300000000-AddResourceAiAgents.js +168 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js.map +1 -0
- 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 +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +6 -0
- package/build/dist/Server/Infrastructure/Semaphore.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/TelemetryIngest.js +12 -5
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- 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/AnalyticsDatabaseService.js +26 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +601 -3
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +104 -0
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseServerService.js +99 -0
- package/build/dist/Server/Services/DatabaseServerService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +104 -0
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +104 -0
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +114 -2
- package/build/dist/Server/Services/HostService.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/MetricRecordingRuleService.js +46 -0
- package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +25 -4
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +104 -0
- package/build/dist/Server/Services/PodmanHostService.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/ProxmoxClusterService.js +104 -0
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/ResourceAiAccessService.js +1028 -0
- package/build/dist/Server/Services/ResourceAiAccessService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js +173 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js +1687 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js.map +1 -0
- package/build/dist/Server/Services/RunnerJobService.js +344 -5
- package/build/dist/Server/Services/RunnerJobService.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/TelemetryUsageBillingService.js +26 -0
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/TraceRecordingRuleService.js +37 -0
- package/build/dist/Server/Services/TraceRecordingRuleService.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/VMwareVCenterService.js +104 -0
- package/build/dist/Server/Services/VMwareVCenterService.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 +1036 -32
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +661 -41
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +21 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +354 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js +160 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js +33 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js +640 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js +226 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +602 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +90 -14
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +73 -10
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +73 -10
- 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/AutoRemediation/CommandPlanExecutor.js +290 -13
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +29 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +9 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.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/SessionReplay/SessionReplayBudgetMetrics.js +627 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +60 -5
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -1
- 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/Alert.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +17 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +186 -210
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +22 -16
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +233 -167
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +273 -111
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js +129 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js +266 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js +258 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js +104 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js +183 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js +123 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js.map +1 -0
- package/build/dist/Types/AI/AIAgentRunLimits.js +91 -0
- package/build/dist/Types/AI/AIAgentRunLimits.js.map +1 -0
- package/build/dist/Types/AI/ResourceAiAccessApi.js +30 -0
- package/build/dist/Types/AI/ResourceAiAccessApi.js.map +1 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js +98 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js.map +1 -0
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +116 -29
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
- 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/Monitor/Recommendation/MonitorRecommendationCatalog.js +47 -21
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +5 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/RumAlertTemplates.js +199 -3
- package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
- package/build/dist/Types/Permission.js +274 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js +242 -0
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js.map +1 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +281 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -0
- 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/Rum/SessionReplayBudgetMetricType.js +45 -0
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookStepType.js +27 -0
- package/build/dist/Types/Runbook/RunbookStepType.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/Telemetry/TelemetryIngestSurface.js +13 -2
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.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/AI/InvestigationReport.js +71 -11
- package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js +1462 -0
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js +122 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js +1139 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js +1060 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js +1301 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js +370 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js +498 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js +1565 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js +2206 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js +1129 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js +565 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js +408 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js +1910 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js.map +1 -0
- 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/SessionReplay/SessionReplayBudgetMetricType.js +160 -0
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.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,6 +4,7 @@ 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 HTTPResponse from "../../../Types/API/HTTPResponse";
|
|
@@ -11,12 +12,32 @@ import MimeType from "../../../Types/File/MimeType";
|
|
|
11
12
|
import FileModel from "../../../Models/DatabaseModels/File";
|
|
12
13
|
import DOMPurify from "dompurify";
|
|
13
14
|
import { htmlToMarkdown, markdownToHtml } from "./MarkdownConverters";
|
|
15
|
+
import {
|
|
16
|
+
indentMarkdownLines,
|
|
17
|
+
isInFencedCodeBlock,
|
|
18
|
+
liftListItems,
|
|
19
|
+
MarkdownListKind,
|
|
20
|
+
MarkdownTextEdit,
|
|
21
|
+
outdentMarkdownLines,
|
|
22
|
+
sinkListItems,
|
|
23
|
+
stripTextListMarkers,
|
|
24
|
+
toggleMarkdownList,
|
|
25
|
+
} from "./MarkdownListEditing";
|
|
26
|
+
import MarkdownEditorHistory from "./MarkdownEditorHistory";
|
|
27
|
+
import { clipboardToMarkdown } from "./MarkdownPaste";
|
|
28
|
+
import {
|
|
29
|
+
deleteSelectionForInsert,
|
|
30
|
+
insertBlocksAtCaret,
|
|
31
|
+
isCaretOnEmptyLine,
|
|
32
|
+
moveCaretIntoEmptyListAhead,
|
|
33
|
+
} from "./MarkdownVisualEditing";
|
|
14
34
|
import React, {
|
|
15
35
|
FunctionComponent,
|
|
16
36
|
ReactElement,
|
|
17
37
|
useState,
|
|
18
38
|
useRef,
|
|
19
39
|
useEffect,
|
|
40
|
+
useId,
|
|
20
41
|
} from "react";
|
|
21
42
|
|
|
22
43
|
export interface ComponentProps {
|
|
@@ -32,6 +53,13 @@ export interface ComponentProps {
|
|
|
32
53
|
disableSpellCheck?: boolean | undefined;
|
|
33
54
|
dataTestId?: string | undefined;
|
|
34
55
|
ariaLabelledby?: string | undefined;
|
|
56
|
+
/*
|
|
57
|
+
* Default: true. Inline images upload to the File API, which needs a
|
|
58
|
+
* signed-in user, so a form open to anyone (no OneUptime account) sets
|
|
59
|
+
* this to false: the Image button is hidden and pasted or dropped image
|
|
60
|
+
* files are ignored rather than failing to upload.
|
|
61
|
+
*/
|
|
62
|
+
allowImageUpload?: boolean | undefined;
|
|
35
63
|
}
|
|
36
64
|
|
|
37
65
|
type EditorMode = "wysiwyg" | "markdown";
|
|
@@ -77,6 +105,175 @@ const sanitizeHtml: (html: string) => string = (html: string): string => {
|
|
|
77
105
|
});
|
|
78
106
|
};
|
|
79
107
|
|
|
108
|
+
const RE_SINGLE_PARAGRAPH: RegExp = /^<p>([\s\S]*)<\/p>$/;
|
|
109
|
+
const RE_LINE_BREAKS: RegExp = /\r\n?/g;
|
|
110
|
+
const RE_SHOWN_CHARACTER: RegExp = /\S/;
|
|
111
|
+
const RE_BLANKS_AT_END: RegExp = /[ \t]*$/;
|
|
112
|
+
const RE_BLANKS_AT_START: RegExp = /^[ \t]*/;
|
|
113
|
+
// A list item's line, up to its marker: its indentation is group 1.
|
|
114
|
+
const RE_LIST_ITEM_LINE: RegExp = /^([ \t]*)(?:[-*+]|\d{1,9}[.)])(?=[ \t]|$)/;
|
|
115
|
+
// A list item's line holding nothing but its marker (and a task's box).
|
|
116
|
+
const RE_BARE_LIST_MARKER_LINE: RegExp =
|
|
117
|
+
/^[ \t]*(?:[-*+]|\d{1,9}[.)])(?:[ \t]+\[[ xX]\])?[ \t]*$/;
|
|
118
|
+
const RE_STARTS_WITH_LIST_ITEM: RegExp = /^(?:[-*+]|\d{1,9}[.)])[ \t]/;
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
* The inside of `html` when it is exactly one paragraph -- which is what
|
|
122
|
+
* markdownToHtml makes of a word, a sentence or an image -- and null for
|
|
123
|
+
* anything else.
|
|
124
|
+
*/
|
|
125
|
+
const singleParagraphContents: (html: string) => string | null = (
|
|
126
|
+
html: string,
|
|
127
|
+
): string | null => {
|
|
128
|
+
const inner: string | undefined = html.match(RE_SINGLE_PARAGRAPH)?.[1];
|
|
129
|
+
if (inner === undefined || inner.includes("</p>")) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
return inner;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/*
|
|
136
|
+
* Markdown made of blocks -- a fenced code block, a list, a heading, more
|
|
137
|
+
* than one paragraph -- pasted into the middle of a line of the markdown
|
|
138
|
+
* source goes on lines of its own, with a blank line between it and the
|
|
139
|
+
* text either side of it on that line: the split the visual editor makes
|
|
140
|
+
* for a block. Put in the middle of the line as it was, a code block's
|
|
141
|
+
* closing fence had the rest of the line after it, which made it an opening
|
|
142
|
+
* fence instead -- the block never closed, and everything after it in the
|
|
143
|
+
* note rendered as code. The spaces at the split go, as in the visual
|
|
144
|
+
* editor. Returns the text to insert, having widened the textarea's
|
|
145
|
+
* selection over those spaces.
|
|
146
|
+
*/
|
|
147
|
+
const onLinesOfItsOwn: (
|
|
148
|
+
textarea: HTMLTextAreaElement,
|
|
149
|
+
markdown: string,
|
|
150
|
+
) => string = (textarea: HTMLTextAreaElement, markdown: string): string => {
|
|
151
|
+
if (
|
|
152
|
+
!RE_SHOWN_CHARACTER.test(markdown) ||
|
|
153
|
+
singleParagraphContents(markdownToHtml(markdown)) !== null
|
|
154
|
+
) {
|
|
155
|
+
return markdown;
|
|
156
|
+
}
|
|
157
|
+
const value: string = textarea.value;
|
|
158
|
+
const start: number = textarea.selectionStart;
|
|
159
|
+
const end: number = textarea.selectionEnd;
|
|
160
|
+
const lineStart: number = value.lastIndexOf("\n", start - 1) + 1;
|
|
161
|
+
const lineEndAt: number = value.indexOf("\n", end);
|
|
162
|
+
const lineEnd: number = lineEndAt === -1 ? value.length : lineEndAt;
|
|
163
|
+
const before: string = value.slice(lineStart, start);
|
|
164
|
+
const after: string = value.slice(end, lineEnd);
|
|
165
|
+
const textBefore: boolean = RE_SHOWN_CHARACTER.test(before);
|
|
166
|
+
const textAfter: boolean = RE_SHOWN_CHARACTER.test(after);
|
|
167
|
+
if (!textBefore && !textAfter) {
|
|
168
|
+
return markdown;
|
|
169
|
+
}
|
|
170
|
+
const spacesBefore: number = textBefore
|
|
171
|
+
? (before.match(RE_BLANKS_AT_END)?.[0] || "").length
|
|
172
|
+
: 0;
|
|
173
|
+
const spacesAfter: number = textAfter
|
|
174
|
+
? (after.match(RE_BLANKS_AT_START)?.[0] || "").length
|
|
175
|
+
: 0;
|
|
176
|
+
const itemLine: RegExpMatchArray | null = before.match(RE_LIST_ITEM_LINE);
|
|
177
|
+
if (itemLine && RE_STARTS_WITH_LIST_ITEM.test(markdown)) {
|
|
178
|
+
/*
|
|
179
|
+
* A list pasted on the line of a list item joins that item's list, as
|
|
180
|
+
* in the visual editor: its items go on the lines after the item, at
|
|
181
|
+
* its indentation -- or in its place when the caret sits after nothing
|
|
182
|
+
* but its marker, a "- " typed to start the list. After a blank line
|
|
183
|
+
* they were a list of their own; after the bare marker, a list nested
|
|
184
|
+
* in an empty item: "- - a", two bullets.
|
|
185
|
+
*/
|
|
186
|
+
const indent: string = itemLine[1] || "";
|
|
187
|
+
const items: string = markdown
|
|
188
|
+
.split("\n")
|
|
189
|
+
.map((line: string): string => {
|
|
190
|
+
return line ? `${indent}${line}` : line;
|
|
191
|
+
})
|
|
192
|
+
.join("\n");
|
|
193
|
+
if (RE_BARE_LIST_MARKER_LINE.test(before)) {
|
|
194
|
+
/*
|
|
195
|
+
* Only the item's marker (and task box) is before the caret. An empty
|
|
196
|
+
* item is replaced by the pasted items; an item with text keeps its
|
|
197
|
+
* own marker and task box, and the pasted items go in before it, as in
|
|
198
|
+
* the visual editor. Deciding on what is before the caret alone turned
|
|
199
|
+
* "- [x] |rolled back deploy" into a paragraph: the marker and the tick
|
|
200
|
+
* went, and the item's text was left on a line of its own.
|
|
201
|
+
*/
|
|
202
|
+
textarea.setSelectionRange(lineStart, end + spacesAfter);
|
|
203
|
+
return textAfter ? `${items}\n${before}` : items;
|
|
204
|
+
}
|
|
205
|
+
textarea.setSelectionRange(start - spacesBefore, end + spacesAfter);
|
|
206
|
+
return `\n${items}${textAfter ? "\n\n" : ""}`;
|
|
207
|
+
}
|
|
208
|
+
textarea.setSelectionRange(start - spacesBefore, end + spacesAfter);
|
|
209
|
+
return `${textBefore ? "\n\n" : ""}${markdown}${textAfter ? "\n\n" : ""}`;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const RE_MARKUP: RegExp = /<[a-z!/]/i;
|
|
213
|
+
|
|
214
|
+
// The text of `html` when it holds no markup at all, else null.
|
|
215
|
+
const textOfMarkupFreeHtml: (html: string) => string | null = (
|
|
216
|
+
html: string,
|
|
217
|
+
): string | null => {
|
|
218
|
+
if (RE_MARKUP.test(html)) {
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
// Only entities to decode; a <template> parses them without running anything.
|
|
222
|
+
const template: HTMLTemplateElement = document.createElement("template");
|
|
223
|
+
template.innerHTML = html;
|
|
224
|
+
return template.content.textContent || "";
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/*
|
|
228
|
+
* Tab and Shift+Tab without other modifiers indent and outdent list items.
|
|
229
|
+
* A keypress that is still composing (an IME) is left alone.
|
|
230
|
+
*/
|
|
231
|
+
const isListIndentKey: (event: React.KeyboardEvent<HTMLElement>) => boolean = (
|
|
232
|
+
event: React.KeyboardEvent<HTMLElement>,
|
|
233
|
+
): boolean => {
|
|
234
|
+
return (
|
|
235
|
+
event.key === "Tab" &&
|
|
236
|
+
!event.ctrlKey &&
|
|
237
|
+
!event.metaKey &&
|
|
238
|
+
!event.altKey &&
|
|
239
|
+
!event.nativeEvent.isComposing
|
|
240
|
+
);
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
type HistoryStep = "undo" | "redo";
|
|
244
|
+
|
|
245
|
+
/*
|
|
246
|
+
* Ctrl+Z (Cmd+Z on a Mac) is undo; Ctrl+Shift+Z, Cmd+Shift+Z and Ctrl+Y are
|
|
247
|
+
* redo. A keypress that is still composing is left alone.
|
|
248
|
+
*/
|
|
249
|
+
const historyStepOfKey: (
|
|
250
|
+
event: React.KeyboardEvent<HTMLElement>,
|
|
251
|
+
) => HistoryStep | null = (
|
|
252
|
+
event: React.KeyboardEvent<HTMLElement>,
|
|
253
|
+
): HistoryStep | null => {
|
|
254
|
+
if (
|
|
255
|
+
!(event.ctrlKey || event.metaKey) ||
|
|
256
|
+
event.altKey ||
|
|
257
|
+
event.nativeEvent.isComposing
|
|
258
|
+
) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const key: string = event.key.toLowerCase();
|
|
262
|
+
if (key === "z") {
|
|
263
|
+
return event.shiftKey ? "redo" : "undo";
|
|
264
|
+
}
|
|
265
|
+
if (key === "y" && !event.shiftKey) {
|
|
266
|
+
return "redo";
|
|
267
|
+
}
|
|
268
|
+
return null;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
type MarkdownTextEditor = (
|
|
272
|
+
text: string,
|
|
273
|
+
selectionStart: number,
|
|
274
|
+
selectionEnd: number,
|
|
275
|
+
) => MarkdownTextEdit | null;
|
|
276
|
+
|
|
80
277
|
interface ToolbarButtonProps {
|
|
81
278
|
icon: IconProp;
|
|
82
279
|
title: string;
|
|
@@ -116,6 +313,33 @@ const ToolbarButton: FunctionComponent<ToolbarButtonProps> = ({
|
|
|
116
313
|
const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
117
314
|
props: ComponentProps,
|
|
118
315
|
): ReactElement => {
|
|
316
|
+
const allowImageUpload: boolean = props.allowImageUpload !== false;
|
|
317
|
+
/*
|
|
318
|
+
* The error message is tied to the field -- in either mode -- and
|
|
319
|
+
* announced when it appears, as Input's and TextArea's are. It was a bare
|
|
320
|
+
* paragraph: a required description left empty was neither announced nor
|
|
321
|
+
* tied to the editor, so to a screen reader the form did nothing.
|
|
322
|
+
*/
|
|
323
|
+
const errorId: string = `markdown-editor-error-${useId()}`;
|
|
324
|
+
/*
|
|
325
|
+
* The words the editor always shows of its own -- an empty field's
|
|
326
|
+
* placeholder and the heading of its formatting help -- are looked up in
|
|
327
|
+
* the page's locale, as FieldLabel's "(Optional)" is: on the public
|
|
328
|
+
* incident form, translated all round, they were the only English left.
|
|
329
|
+
* The English text is the key, and an app whose locale has no entry for
|
|
330
|
+
* it shows the English.
|
|
331
|
+
*/
|
|
332
|
+
const { translateString } = useTranslateValue();
|
|
333
|
+
const visualPlaceholder: string =
|
|
334
|
+
props.placeholder ||
|
|
335
|
+
(translateString("Type your content here...") ??
|
|
336
|
+
"Type your content here...");
|
|
337
|
+
const sourcePlaceholder: string =
|
|
338
|
+
props.placeholder ||
|
|
339
|
+
(translateString("Type your markdown here...") ??
|
|
340
|
+
"Type your markdown here...");
|
|
341
|
+
const helpTitle: string =
|
|
342
|
+
translateString("Formatting help") ?? "Formatting help";
|
|
119
343
|
const [text, setText] = useState<string>(props.initialValue || "");
|
|
120
344
|
const [mode, setMode] = useState<EditorMode>("wysiwyg");
|
|
121
345
|
const [isDraggingOver, setIsDraggingOver] = useState<boolean>(false);
|
|
@@ -134,6 +358,16 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
134
358
|
const textRef: React.MutableRefObject<string> = useRef<string>(
|
|
135
359
|
props.initialValue || "",
|
|
136
360
|
);
|
|
361
|
+
/*
|
|
362
|
+
* The visual editor's own edits -- list moves, inserts made by hand --
|
|
363
|
+
* which the browser's undo stack never hears of (see
|
|
364
|
+
* MarkdownEditorHistory).
|
|
365
|
+
*/
|
|
366
|
+
const [history] = useState<MarkdownEditorHistory>(
|
|
367
|
+
(): MarkdownEditorHistory => {
|
|
368
|
+
return new MarkdownEditorHistory();
|
|
369
|
+
},
|
|
370
|
+
);
|
|
137
371
|
|
|
138
372
|
useEffect(() => {
|
|
139
373
|
if (
|
|
@@ -145,6 +379,11 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
145
379
|
}
|
|
146
380
|
}, [props.initialValue]);
|
|
147
381
|
|
|
382
|
+
// A new editable in each mode: records about the old one's nodes are no use.
|
|
383
|
+
useEffect(() => {
|
|
384
|
+
history.clear();
|
|
385
|
+
}, [mode]);
|
|
386
|
+
|
|
148
387
|
/*
|
|
149
388
|
* Sync markdown -> contenteditable when entering WYSIWYG, when text
|
|
150
389
|
* changes from outside, or after async image-upload swaps. Skip when
|
|
@@ -168,6 +407,7 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
168
407
|
const html: string = sanitizeHtml(markdownToHtml(text));
|
|
169
408
|
if (editable.innerHTML !== html) {
|
|
170
409
|
editable.innerHTML = html;
|
|
410
|
+
history.clear();
|
|
171
411
|
}
|
|
172
412
|
}, [mode, text]);
|
|
173
413
|
|
|
@@ -191,6 +431,92 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
191
431
|
}
|
|
192
432
|
};
|
|
193
433
|
|
|
434
|
+
/*
|
|
435
|
+
* An edit the visual editor makes to its DOM itself, recorded so that
|
|
436
|
+
* Ctrl+Z takes it back. Returns what `edit` returns: whether it changed
|
|
437
|
+
* anything.
|
|
438
|
+
*/
|
|
439
|
+
const editEditableByHand: (
|
|
440
|
+
edit: (editable: HTMLDivElement) => boolean,
|
|
441
|
+
) => boolean = (edit: (editable: HTMLDivElement) => boolean): boolean => {
|
|
442
|
+
const editable: HTMLDivElement | null = editableRef.current;
|
|
443
|
+
if (!editable) {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
return history.record(editable, (): boolean => {
|
|
447
|
+
return edit(editable);
|
|
448
|
+
});
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
/*
|
|
452
|
+
* Undo or redo of the editor's own edits; false (and nothing done) when
|
|
453
|
+
* the last thing to undo is the browser's -- typing, say -- so the
|
|
454
|
+
* browser does it.
|
|
455
|
+
*/
|
|
456
|
+
const stepEditableHistory: (step: HistoryStep) => boolean = (
|
|
457
|
+
step: HistoryStep,
|
|
458
|
+
): boolean => {
|
|
459
|
+
const editable: HTMLDivElement | null = editableRef.current;
|
|
460
|
+
if (!editable) {
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
const stepped: boolean =
|
|
464
|
+
step === "undo" ? history.undo(editable) : history.redo(editable);
|
|
465
|
+
if (stepped) {
|
|
466
|
+
syncFromEditable();
|
|
467
|
+
}
|
|
468
|
+
return stepped;
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
/*
|
|
472
|
+
* Typing, a paste the browser makes, an execCommand: each is newer
|
|
473
|
+
* history in the browser's own undo stack. The editor's own records wait
|
|
474
|
+
* behind it -- each applies again once the browser's undo has put the
|
|
475
|
+
* editor back as that edit left it -- but what they would redo is gone,
|
|
476
|
+
* as the browser's own redo is. The browser's undo and redo themselves
|
|
477
|
+
* leave both be.
|
|
478
|
+
*/
|
|
479
|
+
const handleEditableInput: (
|
|
480
|
+
event: React.FormEvent<HTMLDivElement>,
|
|
481
|
+
) => void = (event: React.FormEvent<HTMLDivElement>): void => {
|
|
482
|
+
const inputType: string =
|
|
483
|
+
(event.nativeEvent as InputEvent | undefined)?.inputType || "";
|
|
484
|
+
if (inputType !== "historyUndo" && inputType !== "historyRedo") {
|
|
485
|
+
history.clearRedo();
|
|
486
|
+
}
|
|
487
|
+
syncFromEditable();
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
/*
|
|
491
|
+
* Undo and redo from the browser's Edit menu or context menu arrive with
|
|
492
|
+
* no key press, as a native beforeinput event -- which React's
|
|
493
|
+
* onBeforeInput is not -- so it is listened for on the element itself.
|
|
494
|
+
* The ref keeps the listener on the latest render's handlers.
|
|
495
|
+
*/
|
|
496
|
+
const beforeInputRef: React.MutableRefObject<(event: InputEvent) => void> =
|
|
497
|
+
useRef<(event: InputEvent) => void>((): void => {});
|
|
498
|
+
beforeInputRef.current = (event: InputEvent): void => {
|
|
499
|
+
if (
|
|
500
|
+
(event.inputType === "historyUndo" && stepEditableHistory("undo")) ||
|
|
501
|
+
(event.inputType === "historyRedo" && stepEditableHistory("redo"))
|
|
502
|
+
) {
|
|
503
|
+
event.preventDefault();
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
useEffect(() => {
|
|
507
|
+
const editable: HTMLDivElement | null = editableRef.current;
|
|
508
|
+
if (mode !== "wysiwyg" || !editable) {
|
|
509
|
+
return undefined;
|
|
510
|
+
}
|
|
511
|
+
const listener: (event: Event) => void = (event: Event): void => {
|
|
512
|
+
beforeInputRef.current(event as InputEvent);
|
|
513
|
+
};
|
|
514
|
+
editable.addEventListener("beforeinput", listener);
|
|
515
|
+
return () => {
|
|
516
|
+
editable.removeEventListener("beforeinput", listener);
|
|
517
|
+
};
|
|
518
|
+
}, [mode]);
|
|
519
|
+
|
|
194
520
|
const insertTextAtCursor: (textToInsert: string) => void = (
|
|
195
521
|
textToInsert: string,
|
|
196
522
|
): void => {
|
|
@@ -235,17 +561,79 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
235
561
|
syncFromEditable();
|
|
236
562
|
return;
|
|
237
563
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const lastNode: ChildNode | null = fragment.lastChild;
|
|
241
|
-
range.insertNode(fragment);
|
|
242
|
-
if (lastNode) {
|
|
243
|
-
const newRange: Range = document.createRange();
|
|
244
|
-
newRange.setStartAfter(lastNode);
|
|
245
|
-
newRange.collapse(true);
|
|
564
|
+
// Chromium's caret just before a list it has just made goes into its item.
|
|
565
|
+
if (moveCaretIntoEmptyListAhead(editable, range)) {
|
|
246
566
|
selection.removeAllRanges();
|
|
247
|
-
selection.addRange(
|
|
567
|
+
selection.addRange(range);
|
|
248
568
|
}
|
|
569
|
+
/*
|
|
570
|
+
* A single paragraph goes in as its contents, so text pasted into the
|
|
571
|
+
* middle of a line joins that line. Inserted whole, the <p> landed
|
|
572
|
+
* inside the paragraph the caret was in and the serializer wrote it out
|
|
573
|
+
* as three: pasting "big " into "hello world" saved
|
|
574
|
+
* "hello \n\nbig \n\nworld", and an uploading image's placeholder split
|
|
575
|
+
* its line the same way. Straight into the editor itself -- empty, or
|
|
576
|
+
* between two blocks -- the paragraph is kept.
|
|
577
|
+
*/
|
|
578
|
+
const contents: string =
|
|
579
|
+
range.startContainer === editable
|
|
580
|
+
? html
|
|
581
|
+
: singleParagraphContents(html) ?? html;
|
|
582
|
+
/*
|
|
583
|
+
* execCommand puts the insert on the browser's undo stack. Plain words
|
|
584
|
+
* go in with insertText, as if typed. Blocks go in with insertHTML only
|
|
585
|
+
* onto an empty line: anywhere else in a line, Chromium and Safari fold
|
|
586
|
+
* the first block into that line -- a <pre> became a monospace <span> of
|
|
587
|
+
* the paragraph, and a code block pasted after "Run:" saved as
|
|
588
|
+
* "Run:npm install" -- so there the line is split at the caret by hand
|
|
589
|
+
* and the blocks go in between its halves. Words with formatting go in
|
|
590
|
+
* by hand too: Chromium's and Firefox's insertHTML turn the spaces around
|
|
591
|
+
* an inline insert into non-breaking ones, which then ended up in the
|
|
592
|
+
* saved markdown. jsdom has no execCommand and a browser may refuse the
|
|
593
|
+
* command, so the insert by hand is the fallback as well.
|
|
594
|
+
*/
|
|
595
|
+
const inline: boolean = contents !== html;
|
|
596
|
+
const plainText: string | null = inline
|
|
597
|
+
? textOfMarkupFreeHtml(contents)
|
|
598
|
+
: null;
|
|
599
|
+
let command: string | null = null;
|
|
600
|
+
if (plainText !== null) {
|
|
601
|
+
command = "insertText";
|
|
602
|
+
} else if (!inline && isCaretOnEmptyLine(editable, range)) {
|
|
603
|
+
command = "insertHTML";
|
|
604
|
+
}
|
|
605
|
+
if (command && typeof document.execCommand === "function") {
|
|
606
|
+
try {
|
|
607
|
+
if (document.execCommand(command, false, plainText ?? contents)) {
|
|
608
|
+
syncFromEditable();
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
} catch {
|
|
612
|
+
// Fall through to the insert by hand.
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
editEditableByHand((): boolean => {
|
|
616
|
+
deleteSelectionForInsert(editable, range);
|
|
617
|
+
const fragment: DocumentFragment =
|
|
618
|
+
range.createContextualFragment(contents);
|
|
619
|
+
let caret: Range | null = null;
|
|
620
|
+
if (inline) {
|
|
621
|
+
const lastNode: ChildNode | null = fragment.lastChild;
|
|
622
|
+
range.insertNode(fragment);
|
|
623
|
+
if (lastNode) {
|
|
624
|
+
caret = document.createRange();
|
|
625
|
+
caret.setStartAfter(lastNode);
|
|
626
|
+
caret.collapse(true);
|
|
627
|
+
}
|
|
628
|
+
} else {
|
|
629
|
+
caret = insertBlocksAtCaret(editable, range, fragment);
|
|
630
|
+
}
|
|
631
|
+
if (caret) {
|
|
632
|
+
selection.removeAllRanges();
|
|
633
|
+
selection.addRange(caret);
|
|
634
|
+
}
|
|
635
|
+
return true;
|
|
636
|
+
});
|
|
249
637
|
syncFromEditable();
|
|
250
638
|
};
|
|
251
639
|
|
|
@@ -406,39 +794,158 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
406
794
|
return files;
|
|
407
795
|
};
|
|
408
796
|
|
|
797
|
+
/*
|
|
798
|
+
* Text for the source textarea. execCommand("insertText") types it the
|
|
799
|
+
* way a native paste would, so Ctrl+Z undoes it; where the browser has no
|
|
800
|
+
* such command (jsdom) it is spliced into the value instead.
|
|
801
|
+
*/
|
|
802
|
+
const insertTextInTextarea: (textToInsert: string) => void = (
|
|
803
|
+
textToInsert: string,
|
|
804
|
+
): void => {
|
|
805
|
+
const textarea: HTMLTextAreaElement | null = textareaRef.current;
|
|
806
|
+
if (textarea && typeof document.execCommand === "function") {
|
|
807
|
+
textarea.focus();
|
|
808
|
+
try {
|
|
809
|
+
if (document.execCommand("insertText", false, textToInsert)) {
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
} catch {
|
|
813
|
+
// Fall back to splicing the value.
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
insertTextAtCursor(textToInsert);
|
|
817
|
+
};
|
|
818
|
+
|
|
819
|
+
/*
|
|
820
|
+
* Markdown mode. Rich clipboard content (a Word list, a copied note) is
|
|
821
|
+
* converted to markdown source, and a file on the clipboard uploads as
|
|
822
|
+
* before. When the conversion gives back exactly the plain text, the
|
|
823
|
+
* browser's own paste inserts the same thing, so it is left to it.
|
|
824
|
+
*/
|
|
409
825
|
const handleTextareaPaste: (
|
|
410
826
|
e: React.ClipboardEvent<HTMLTextAreaElement>,
|
|
411
827
|
) => void = (e: React.ClipboardEvent<HTMLTextAreaElement>): void => {
|
|
412
|
-
const
|
|
413
|
-
|
|
828
|
+
const clipboardData: DataTransfer | null = e.clipboardData;
|
|
829
|
+
if (!clipboardData) {
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
/*
|
|
833
|
+
* Inside a fenced code block the text goes in as it is, the browser's
|
|
834
|
+
* own paste (which keeps it on the undo stack) -- as in the visual
|
|
835
|
+
* editor's code blocks. Converted there, a command copied from a docs
|
|
836
|
+
* page came in as its own ``` fence, which closed the block around it,
|
|
837
|
+
* and CLI output had its "1)" and "•" lines rewritten as list items. A
|
|
838
|
+
* clipboard with no text, only an image, still uploads below.
|
|
839
|
+
*/
|
|
840
|
+
const textarea: HTMLTextAreaElement = e.currentTarget;
|
|
841
|
+
if (
|
|
842
|
+
clipboardData.getData("text/plain") &&
|
|
843
|
+
isInFencedCodeBlock(textarea.value, textarea.selectionStart)
|
|
844
|
+
) {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
const images: Array<File> = allowImageUpload
|
|
848
|
+
? extractImagesFromClipboard(clipboardData.items || null)
|
|
849
|
+
: [];
|
|
850
|
+
const markdown: string | null = clipboardToMarkdown(clipboardData, {
|
|
851
|
+
hasImageFiles: images.length > 0,
|
|
852
|
+
});
|
|
853
|
+
if (markdown === null) {
|
|
854
|
+
if (images.length > 0) {
|
|
855
|
+
e.preventDefault();
|
|
856
|
+
void handleImageFiles(images);
|
|
857
|
+
}
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
const plain: string = (clipboardData.getData("text/plain") || "").replace(
|
|
861
|
+
RE_LINE_BREAKS,
|
|
862
|
+
"\n",
|
|
414
863
|
);
|
|
415
|
-
if (
|
|
864
|
+
if (markdown === plain) {
|
|
416
865
|
return;
|
|
417
866
|
}
|
|
418
867
|
e.preventDefault();
|
|
419
|
-
|
|
868
|
+
insertTextInTextarea(onLinesOfItsOwn(textarea, markdown));
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
// The code block the caret is in, if it is in one.
|
|
872
|
+
const codeBlockAtSelection: () => HTMLElement | null =
|
|
873
|
+
(): HTMLElement | null => {
|
|
874
|
+
const editable: HTMLDivElement | null = editableRef.current;
|
|
875
|
+
const selection: Selection | null = window.getSelection();
|
|
876
|
+
if (!editable || !selection || selection.rangeCount === 0) {
|
|
877
|
+
return null;
|
|
878
|
+
}
|
|
879
|
+
let node: Node | null = selection.getRangeAt(0).startContainer;
|
|
880
|
+
while (node && node !== editable) {
|
|
881
|
+
if (node.nodeName.toLowerCase() === "pre") {
|
|
882
|
+
return node as HTMLElement;
|
|
883
|
+
}
|
|
884
|
+
node = node.parentNode;
|
|
885
|
+
}
|
|
886
|
+
return null;
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
const insertPlainTextInEditable: (value: string) => void = (
|
|
890
|
+
value: string,
|
|
891
|
+
): void => {
|
|
892
|
+
const editable: HTMLDivElement | null = editableRef.current;
|
|
893
|
+
const selection: Selection | null = window.getSelection();
|
|
894
|
+
if (!editable || !selection || selection.rangeCount === 0) {
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
const range: Range = selection.getRangeAt(0);
|
|
898
|
+
editEditableByHand((): boolean => {
|
|
899
|
+
deleteSelectionForInsert(editable, range);
|
|
900
|
+
const textNode: Text = document.createTextNode(value);
|
|
901
|
+
range.insertNode(textNode);
|
|
902
|
+
const after: Range = document.createRange();
|
|
903
|
+
after.setStartAfter(textNode);
|
|
904
|
+
after.collapse(true);
|
|
905
|
+
selection.removeAllRanges();
|
|
906
|
+
selection.addRange(after);
|
|
907
|
+
return true;
|
|
908
|
+
});
|
|
909
|
+
syncFromEditable();
|
|
420
910
|
};
|
|
421
911
|
|
|
912
|
+
/*
|
|
913
|
+
* Visual mode. The browser's own paste would bring the source's markup in
|
|
914
|
+
* with it -- styles, classes, elements markdown cannot hold -- so the paste
|
|
915
|
+
* is always handled here: converted to markdown (the clipboard's HTML
|
|
916
|
+
* first, so a Word or Outlook list keeps its nesting, then its plain text)
|
|
917
|
+
* and rendered back. Image files upload when there is no text to paste.
|
|
918
|
+
* Inside a code block the plain text goes in as it is.
|
|
919
|
+
*/
|
|
422
920
|
const handleEditablePaste: (
|
|
423
921
|
e: React.ClipboardEvent<HTMLDivElement>,
|
|
424
922
|
) => void = (e: React.ClipboardEvent<HTMLDivElement>): void => {
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
);
|
|
428
|
-
if (images.length > 0) {
|
|
429
|
-
e.preventDefault();
|
|
430
|
-
void handleImageFiles(images);
|
|
923
|
+
const clipboardData: DataTransfer | null = e.clipboardData;
|
|
924
|
+
if (!clipboardData) {
|
|
431
925
|
return;
|
|
432
926
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
927
|
+
e.preventDefault();
|
|
928
|
+
if (codeBlockAtSelection()) {
|
|
929
|
+
const plain: string = clipboardData.getData("text/plain") || "";
|
|
930
|
+
if (plain) {
|
|
931
|
+
insertPlainTextInEditable(plain.replace(RE_LINE_BREAKS, "\n"));
|
|
932
|
+
}
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
const images: Array<File> = allowImageUpload
|
|
936
|
+
? extractImagesFromClipboard(clipboardData.items || null)
|
|
937
|
+
: [];
|
|
938
|
+
const markdown: string | null = clipboardToMarkdown(clipboardData, {
|
|
939
|
+
hasImageFiles: images.length > 0,
|
|
940
|
+
});
|
|
941
|
+
if (markdown !== null) {
|
|
942
|
+
if (markdown) {
|
|
943
|
+
insertMarkdownAtCursor(markdown);
|
|
944
|
+
}
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
if (images.length > 0) {
|
|
948
|
+
void handleImageFiles(images);
|
|
442
949
|
}
|
|
443
950
|
};
|
|
444
951
|
|
|
@@ -463,6 +970,17 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
463
970
|
return;
|
|
464
971
|
}
|
|
465
972
|
e.preventDefault();
|
|
973
|
+
if (!allowImageUpload) {
|
|
974
|
+
/*
|
|
975
|
+
* Refuse the drop outright. Left to itself the browser would drop the
|
|
976
|
+
* file in anyway -- Firefox inlines an image as a data: URL -- or
|
|
977
|
+
* navigate away to it.
|
|
978
|
+
*/
|
|
979
|
+
if (e.dataTransfer) {
|
|
980
|
+
e.dataTransfer.dropEffect = "none";
|
|
981
|
+
}
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
466
984
|
if (!isDraggingOver) {
|
|
467
985
|
setIsDraggingOver(true);
|
|
468
986
|
}
|
|
@@ -482,6 +1000,9 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
482
1000
|
}
|
|
483
1001
|
e.preventDefault();
|
|
484
1002
|
setIsDraggingOver(false);
|
|
1003
|
+
if (!allowImageUpload) {
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
485
1006
|
const fileList: FileList | null = e.dataTransfer?.files || null;
|
|
486
1007
|
if (!fileList || fileList.length === 0) {
|
|
487
1008
|
return;
|
|
@@ -491,6 +1012,9 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
491
1012
|
};
|
|
492
1013
|
|
|
493
1014
|
const handleImageButtonClick: () => void = (): void => {
|
|
1015
|
+
if (!allowImageUpload) {
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
494
1018
|
fileInputRef.current?.click();
|
|
495
1019
|
};
|
|
496
1020
|
|
|
@@ -627,10 +1151,120 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
627
1151
|
}
|
|
628
1152
|
};
|
|
629
1153
|
|
|
1154
|
+
/*
|
|
1155
|
+
* Puts an edit into the source textarea, selection included. Only the
|
|
1156
|
+
* stretch that changed is replaced, with execCommand("insertText") where
|
|
1157
|
+
* the browser has it, so Ctrl+Z undoes an indent like any typing; without
|
|
1158
|
+
* it (jsdom) the value is set directly.
|
|
1159
|
+
*/
|
|
1160
|
+
const applyTextareaEdit: (edit: MarkdownTextEdit) => void = (
|
|
1161
|
+
edit: MarkdownTextEdit,
|
|
1162
|
+
): void => {
|
|
1163
|
+
const textarea: HTMLTextAreaElement | null = textareaRef.current;
|
|
1164
|
+
if (!textarea) {
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
const current: string = textarea.value;
|
|
1168
|
+
let start: number = 0;
|
|
1169
|
+
while (
|
|
1170
|
+
start < current.length &&
|
|
1171
|
+
start < edit.text.length &&
|
|
1172
|
+
current.charAt(start) === edit.text.charAt(start)
|
|
1173
|
+
) {
|
|
1174
|
+
start++;
|
|
1175
|
+
}
|
|
1176
|
+
let oldEnd: number = current.length;
|
|
1177
|
+
let newEnd: number = edit.text.length;
|
|
1178
|
+
while (
|
|
1179
|
+
oldEnd > start &&
|
|
1180
|
+
newEnd > start &&
|
|
1181
|
+
current.charAt(oldEnd - 1) === edit.text.charAt(newEnd - 1)
|
|
1182
|
+
) {
|
|
1183
|
+
oldEnd--;
|
|
1184
|
+
newEnd--;
|
|
1185
|
+
}
|
|
1186
|
+
textarea.focus();
|
|
1187
|
+
let applied: boolean = false;
|
|
1188
|
+
if (typeof document.execCommand === "function") {
|
|
1189
|
+
textarea.setSelectionRange(start, oldEnd);
|
|
1190
|
+
try {
|
|
1191
|
+
applied = document.execCommand(
|
|
1192
|
+
"insertText",
|
|
1193
|
+
false,
|
|
1194
|
+
edit.text.slice(start, newEnd),
|
|
1195
|
+
);
|
|
1196
|
+
} catch {
|
|
1197
|
+
applied = false;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
if (!applied || textarea.value !== edit.text) {
|
|
1201
|
+
textarea.value = edit.text;
|
|
1202
|
+
}
|
|
1203
|
+
if (textRef.current !== edit.text) {
|
|
1204
|
+
handleChange(edit.text);
|
|
1205
|
+
}
|
|
1206
|
+
textarea.setSelectionRange(edit.selectionStart, edit.selectionEnd);
|
|
1207
|
+
};
|
|
1208
|
+
|
|
1209
|
+
// Runs a source edit on the textarea's text and selection; false if it changed nothing.
|
|
1210
|
+
const editTextarea: (editor: MarkdownTextEditor) => boolean = (
|
|
1211
|
+
editor: MarkdownTextEditor,
|
|
1212
|
+
): boolean => {
|
|
1213
|
+
const textarea: HTMLTextAreaElement | null = textareaRef.current;
|
|
1214
|
+
if (!textarea) {
|
|
1215
|
+
return false;
|
|
1216
|
+
}
|
|
1217
|
+
const edit: MarkdownTextEdit | null = editor(
|
|
1218
|
+
textarea.value,
|
|
1219
|
+
textarea.selectionStart,
|
|
1220
|
+
textarea.selectionEnd,
|
|
1221
|
+
);
|
|
1222
|
+
if (!edit) {
|
|
1223
|
+
return false;
|
|
1224
|
+
}
|
|
1225
|
+
applyTextareaEdit(edit);
|
|
1226
|
+
return true;
|
|
1227
|
+
};
|
|
1228
|
+
|
|
1229
|
+
const toggleListInTextarea: (kind: MarkdownListKind) => void = (
|
|
1230
|
+
kind: MarkdownListKind,
|
|
1231
|
+
): void => {
|
|
1232
|
+
editTextarea(
|
|
1233
|
+
(source: string, selectionStart: number, selectionEnd: number) => {
|
|
1234
|
+
return toggleMarkdownList(source, selectionStart, selectionEnd, kind);
|
|
1235
|
+
},
|
|
1236
|
+
);
|
|
1237
|
+
};
|
|
1238
|
+
|
|
1239
|
+
/*
|
|
1240
|
+
* Indent or outdent the list items at the selection in the visual editor;
|
|
1241
|
+
* false (and nothing changed) when the selection is not on an item that
|
|
1242
|
+
* can move. The items are moved by hand, so the move is recorded for
|
|
1243
|
+
* Ctrl+Z: it undid the typing before an indent and left the indent.
|
|
1244
|
+
*/
|
|
1245
|
+
const shiftListItemsInEditable: (outdent: boolean) => boolean = (
|
|
1246
|
+
outdent: boolean,
|
|
1247
|
+
): boolean => {
|
|
1248
|
+
const changed: boolean = editEditableByHand(
|
|
1249
|
+
(editable: HTMLDivElement): boolean => {
|
|
1250
|
+
return outdent ? liftListItems(editable) : sinkListItems(editable);
|
|
1251
|
+
},
|
|
1252
|
+
);
|
|
1253
|
+
if (changed) {
|
|
1254
|
+
syncFromEditable();
|
|
1255
|
+
}
|
|
1256
|
+
return changed;
|
|
1257
|
+
};
|
|
1258
|
+
|
|
630
1259
|
// WYSIWYG-mode toolbar helpers (operate on the contenteditable DOM).
|
|
631
|
-
const execEditable: (
|
|
1260
|
+
const execEditable: (
|
|
632
1261
|
command: string,
|
|
633
1262
|
value?: string,
|
|
1263
|
+
afterCommand?: (editable: HTMLDivElement) => void,
|
|
1264
|
+
) => void = (
|
|
1265
|
+
command: string,
|
|
1266
|
+
value?: string,
|
|
1267
|
+
afterCommand?: (editable: HTMLDivElement) => void,
|
|
634
1268
|
): void => {
|
|
635
1269
|
const editable: HTMLDivElement | null = editableRef.current;
|
|
636
1270
|
if (!editable) {
|
|
@@ -647,9 +1281,26 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
647
1281
|
} catch {
|
|
648
1282
|
// Ignore — older command names occasionally throw in some browsers.
|
|
649
1283
|
}
|
|
1284
|
+
if (afterCommand) {
|
|
1285
|
+
afterCommand(editable);
|
|
1286
|
+
}
|
|
650
1287
|
syncFromEditable();
|
|
651
1288
|
};
|
|
652
1289
|
|
|
1290
|
+
/*
|
|
1291
|
+
* The list buttons. execCommand turns the selected lines into items but
|
|
1292
|
+
* keeps whatever text they started with, so a line pasted from Word as
|
|
1293
|
+
* "•\tService down" showed the list's bullet and its own; the leftover
|
|
1294
|
+
* markers are stripped from the items it made.
|
|
1295
|
+
*/
|
|
1296
|
+
const makeListInEditable: (command: string) => void = (
|
|
1297
|
+
command: string,
|
|
1298
|
+
): void => {
|
|
1299
|
+
execEditable(command, undefined, (editable: HTMLDivElement): void => {
|
|
1300
|
+
stripTextListMarkers(editable);
|
|
1301
|
+
});
|
|
1302
|
+
};
|
|
1303
|
+
|
|
653
1304
|
const wrapSelectionInEditable: (
|
|
654
1305
|
tagName: string,
|
|
655
1306
|
fallbackText: string,
|
|
@@ -668,12 +1319,15 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
668
1319
|
const selected: string = selection.toString() || fallbackText;
|
|
669
1320
|
const wrapper: HTMLElement = document.createElement(tagName);
|
|
670
1321
|
wrapper.textContent = selected;
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
1322
|
+
editEditableByHand((): boolean => {
|
|
1323
|
+
deleteSelectionForInsert(editable, range);
|
|
1324
|
+
range.insertNode(wrapper);
|
|
1325
|
+
const newRange: Range = document.createRange();
|
|
1326
|
+
newRange.selectNodeContents(wrapper);
|
|
1327
|
+
selection.removeAllRanges();
|
|
1328
|
+
selection.addRange(newRange);
|
|
1329
|
+
return true;
|
|
1330
|
+
});
|
|
677
1331
|
syncFromEditable();
|
|
678
1332
|
};
|
|
679
1333
|
|
|
@@ -703,14 +1357,52 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
703
1357
|
if (hasSelection) {
|
|
704
1358
|
execEditable("createLink", url);
|
|
705
1359
|
} else {
|
|
1360
|
+
/*
|
|
1361
|
+
* Wrapped in a paragraph, so a link put into a line goes in as that
|
|
1362
|
+
* line's own inline content (insertHtmlAtCursorInEditable unwraps a
|
|
1363
|
+
* single paragraph). A bare <a> was taken for a block: it split the
|
|
1364
|
+
* line, and "See " plus the link saved as two paragraphs. Into the
|
|
1365
|
+
* empty editor the paragraph goes in whole.
|
|
1366
|
+
*/
|
|
706
1367
|
insertHtmlAtCursorInEditable(
|
|
707
|
-
`<a href="${url.replace(/"/g, """)}">${url.replace(/</g, "<")}</a>`,
|
|
1368
|
+
`<p><a href="${url.replace(/"/g, """)}">${url.replace(/</g, "<")}</a></p>`,
|
|
708
1369
|
);
|
|
709
1370
|
}
|
|
710
1371
|
};
|
|
711
1372
|
|
|
1373
|
+
/*
|
|
1374
|
+
* The Code Block button. As in the markdown source, the new block's
|
|
1375
|
+
* placeholder is selected, so what is typed next replaces it inside the
|
|
1376
|
+
* block. Left to themselves, browsers put the caret at the end of the
|
|
1377
|
+
* placeholder (Chromium, Safari) or on the line below the block (Firefox).
|
|
1378
|
+
* The empty line after the block (a <br> keeps it a line a caret can sit
|
|
1379
|
+
* on) is where writing carries on below it.
|
|
1380
|
+
*/
|
|
712
1381
|
const insertWysiwygCodeBlock: () => void = (): void => {
|
|
713
|
-
|
|
1382
|
+
const editable: HTMLDivElement | null = editableRef.current;
|
|
1383
|
+
if (!editable) {
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
const existing: Set<Element> = new Set<Element>(
|
|
1387
|
+
Array.from(editable.querySelectorAll("pre")),
|
|
1388
|
+
);
|
|
1389
|
+
insertHtmlAtCursorInEditable(
|
|
1390
|
+
"<pre><code>code block</code></pre><p><br></p>",
|
|
1391
|
+
);
|
|
1392
|
+
const added: Array<Element> = Array.from(
|
|
1393
|
+
editable.querySelectorAll("pre"),
|
|
1394
|
+
).filter((pre: Element): boolean => {
|
|
1395
|
+
return !existing.has(pre);
|
|
1396
|
+
});
|
|
1397
|
+
const block: Element | undefined = added[added.length - 1];
|
|
1398
|
+
const selection: Selection | null = window.getSelection();
|
|
1399
|
+
if (!block || !selection) {
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
const placeholder: Range = document.createRange();
|
|
1403
|
+
placeholder.selectNodeContents(block.querySelector("code") || block);
|
|
1404
|
+
selection.removeAllRanges();
|
|
1405
|
+
selection.addRange(placeholder);
|
|
714
1406
|
};
|
|
715
1407
|
|
|
716
1408
|
const insertWysiwygTable: () => void = (): void => {
|
|
@@ -719,7 +1411,7 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
719
1411
|
"<tbody>" +
|
|
720
1412
|
"<tr><td>Cell 1</td><td>Cell 2</td><td>Cell 3</td></tr>" +
|
|
721
1413
|
"<tr><td>Cell 4</td><td>Cell 5</td><td>Cell 6</td></tr>" +
|
|
722
|
-
"</tbody></table><p></p>";
|
|
1414
|
+
"</tbody></table><p><br></p>";
|
|
723
1415
|
insertHtmlAtCursorInEditable(html);
|
|
724
1416
|
};
|
|
725
1417
|
|
|
@@ -734,6 +1426,8 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
734
1426
|
unorderedList: () => void;
|
|
735
1427
|
orderedList: () => void;
|
|
736
1428
|
taskList: () => void;
|
|
1429
|
+
indent: () => void;
|
|
1430
|
+
outdent: () => void;
|
|
737
1431
|
link: () => void;
|
|
738
1432
|
image: () => void;
|
|
739
1433
|
code: () => void;
|
|
@@ -786,21 +1480,37 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
786
1480
|
},
|
|
787
1481
|
unorderedList: () => {
|
|
788
1482
|
if (mode === "wysiwyg") {
|
|
789
|
-
return
|
|
1483
|
+
return makeListInEditable("insertUnorderedList");
|
|
790
1484
|
}
|
|
791
|
-
return
|
|
1485
|
+
return toggleListInTextarea("bullet");
|
|
792
1486
|
},
|
|
793
1487
|
orderedList: () => {
|
|
794
1488
|
if (mode === "wysiwyg") {
|
|
795
|
-
return
|
|
1489
|
+
return makeListInEditable("insertOrderedList");
|
|
796
1490
|
}
|
|
797
|
-
return
|
|
1491
|
+
return toggleListInTextarea("ordered");
|
|
798
1492
|
},
|
|
799
1493
|
taskList: () => {
|
|
800
1494
|
if (mode === "wysiwyg") {
|
|
801
1495
|
return insertWysiwygTaskList();
|
|
802
1496
|
}
|
|
803
|
-
return
|
|
1497
|
+
return toggleListInTextarea("task");
|
|
1498
|
+
},
|
|
1499
|
+
indent: () => {
|
|
1500
|
+
if (mode === "wysiwyg") {
|
|
1501
|
+
editableRef.current?.focus();
|
|
1502
|
+
shiftListItemsInEditable(false);
|
|
1503
|
+
return;
|
|
1504
|
+
}
|
|
1505
|
+
editTextarea(indentMarkdownLines);
|
|
1506
|
+
},
|
|
1507
|
+
outdent: () => {
|
|
1508
|
+
if (mode === "wysiwyg") {
|
|
1509
|
+
editableRef.current?.focus();
|
|
1510
|
+
shiftListItemsInEditable(true);
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
editTextarea(outdentMarkdownLines);
|
|
804
1514
|
},
|
|
805
1515
|
link: () => {
|
|
806
1516
|
if (mode === "wysiwyg") {
|
|
@@ -873,6 +1583,16 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
873
1583
|
const handleEditableKeyDown: (
|
|
874
1584
|
e: React.KeyboardEvent<HTMLDivElement>,
|
|
875
1585
|
) => void = (e: React.KeyboardEvent<HTMLDivElement>): void => {
|
|
1586
|
+
/*
|
|
1587
|
+
* Ctrl+Z right after an edit the editor made itself -- a list move, an
|
|
1588
|
+
* insert made by hand -- takes that edit back, and Ctrl+Shift+Z makes
|
|
1589
|
+
* it again. Otherwise the key is the browser's, as always.
|
|
1590
|
+
*/
|
|
1591
|
+
const historyStep: HistoryStep | null = historyStepOfKey(e);
|
|
1592
|
+
if (historyStep && stepEditableHistory(historyStep)) {
|
|
1593
|
+
e.preventDefault();
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
876
1596
|
if (e.ctrlKey || e.metaKey) {
|
|
877
1597
|
switch (e.key) {
|
|
878
1598
|
case "b":
|
|
@@ -887,6 +1607,41 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
887
1607
|
break;
|
|
888
1608
|
}
|
|
889
1609
|
}
|
|
1610
|
+
/*
|
|
1611
|
+
* Tab indents a list item and Shift+Tab outdents it -- but the key is
|
|
1612
|
+
* only taken when that actually moved something. On a list's first
|
|
1613
|
+
* item, a top-level item, or outside a list, Tab keeps moving focus to
|
|
1614
|
+
* the next field (and Shift+Tab to the previous one), so the editor is
|
|
1615
|
+
* never a keyboard trap. The event is not stopped either: the note
|
|
1616
|
+
* composer handles its own keys where they bubble to.
|
|
1617
|
+
*/
|
|
1618
|
+
if (isListIndentKey(e) && shiftListItemsInEditable(e.shiftKey)) {
|
|
1619
|
+
e.preventDefault();
|
|
1620
|
+
}
|
|
1621
|
+
};
|
|
1622
|
+
|
|
1623
|
+
const handleTextareaKeyDown: (
|
|
1624
|
+
e: React.KeyboardEvent<HTMLTextAreaElement>,
|
|
1625
|
+
) => void = (e: React.KeyboardEvent<HTMLTextAreaElement>): void => {
|
|
1626
|
+
if (e.ctrlKey || e.metaKey) {
|
|
1627
|
+
switch (e.key) {
|
|
1628
|
+
case "b":
|
|
1629
|
+
e.preventDefault();
|
|
1630
|
+
formatActions.bold();
|
|
1631
|
+
break;
|
|
1632
|
+
case "i":
|
|
1633
|
+
e.preventDefault();
|
|
1634
|
+
formatActions.italic();
|
|
1635
|
+
break;
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
// The same Tab rule as the visual editor's, on the markdown lines.
|
|
1639
|
+
if (
|
|
1640
|
+
isListIndentKey(e) &&
|
|
1641
|
+
editTextarea(e.shiftKey ? outdentMarkdownLines : indentMarkdownLines)
|
|
1642
|
+
) {
|
|
1643
|
+
e.preventDefault();
|
|
1644
|
+
}
|
|
890
1645
|
};
|
|
891
1646
|
|
|
892
1647
|
return (
|
|
@@ -899,6 +1654,9 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
899
1654
|
.oneuptime-wysiwyg p { margin: 0.5rem 0; }
|
|
900
1655
|
.oneuptime-wysiwyg ul, .oneuptime-wysiwyg ol { margin: 0.5rem 0 0.5rem 1.5rem; }
|
|
901
1656
|
.oneuptime-wysiwyg ul { list-style-type: disc; }
|
|
1657
|
+
/* Nested bullets step through circle and square, as MarkdownViewer draws them. */
|
|
1658
|
+
.oneuptime-wysiwyg ul ul, .oneuptime-wysiwyg ol ul { list-style-type: circle; }
|
|
1659
|
+
.oneuptime-wysiwyg ul ul ul, .oneuptime-wysiwyg ul ol ul, .oneuptime-wysiwyg ol ul ul, .oneuptime-wysiwyg ol ol ul { list-style-type: square; }
|
|
902
1660
|
.oneuptime-wysiwyg ol { list-style-type: decimal; }
|
|
903
1661
|
.oneuptime-wysiwyg ul.task-list, .oneuptime-wysiwyg ul.task-list li { list-style: none; margin-left: 0; }
|
|
904
1662
|
.oneuptime-wysiwyg ul.task-list li { padding-left: 0; }
|
|
@@ -1006,6 +1764,21 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
1006
1764
|
title="Task List"
|
|
1007
1765
|
onClick={formatActions.taskList}
|
|
1008
1766
|
/>
|
|
1767
|
+
<ToolbarButton
|
|
1768
|
+
icon={IconProp.Indent}
|
|
1769
|
+
title={`Indent (${KeyboardKeyUtil.getDisplayLabel([
|
|
1770
|
+
KeyboardKey.Tab,
|
|
1771
|
+
])})`}
|
|
1772
|
+
onClick={formatActions.indent}
|
|
1773
|
+
/>
|
|
1774
|
+
<ToolbarButton
|
|
1775
|
+
icon={IconProp.Outdent}
|
|
1776
|
+
title={`Outdent (${KeyboardKeyUtil.getDisplayLabel([
|
|
1777
|
+
KeyboardKey.Shift,
|
|
1778
|
+
KeyboardKey.Tab,
|
|
1779
|
+
])})`}
|
|
1780
|
+
onClick={formatActions.outdent}
|
|
1781
|
+
/>
|
|
1009
1782
|
</div>
|
|
1010
1783
|
|
|
1011
1784
|
<div className="w-px h-6 bg-gray-300" />
|
|
@@ -1017,11 +1790,13 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
1017
1790
|
title="Link"
|
|
1018
1791
|
onClick={formatActions.link}
|
|
1019
1792
|
/>
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1793
|
+
{allowImageUpload && (
|
|
1794
|
+
<ToolbarButton
|
|
1795
|
+
icon={IconProp.Image}
|
|
1796
|
+
title="Image"
|
|
1797
|
+
onClick={formatActions.image}
|
|
1798
|
+
/>
|
|
1799
|
+
)}
|
|
1025
1800
|
<ToolbarButton
|
|
1026
1801
|
icon={IconProp.Code}
|
|
1027
1802
|
title="Code"
|
|
@@ -1106,14 +1881,16 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
1106
1881
|
|
|
1107
1882
|
{/* Editor Area */}
|
|
1108
1883
|
<div className="relative">
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1884
|
+
{allowImageUpload && (
|
|
1885
|
+
<input
|
|
1886
|
+
ref={fileInputRef}
|
|
1887
|
+
type="file"
|
|
1888
|
+
accept="image/*"
|
|
1889
|
+
multiple
|
|
1890
|
+
className="hidden"
|
|
1891
|
+
onChange={handleFileInputChange}
|
|
1892
|
+
/>
|
|
1893
|
+
)}
|
|
1117
1894
|
{mode === "wysiwyg" ? (
|
|
1118
1895
|
<>
|
|
1119
1896
|
<div
|
|
@@ -1121,15 +1898,15 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
1121
1898
|
role="textbox"
|
|
1122
1899
|
aria-multiline="true"
|
|
1123
1900
|
aria-labelledby={props.ariaLabelledby}
|
|
1901
|
+
aria-invalid={props.error ? "true" : undefined}
|
|
1902
|
+
aria-describedby={props.error ? errorId : undefined}
|
|
1124
1903
|
contentEditable
|
|
1125
1904
|
suppressContentEditableWarning
|
|
1126
1905
|
spellCheck={props.disableSpellCheck !== true}
|
|
1127
|
-
data-placeholder={
|
|
1128
|
-
props.placeholder || "Type your content here..."
|
|
1129
|
-
}
|
|
1906
|
+
data-placeholder={visualPlaceholder}
|
|
1130
1907
|
tabIndex={props.tabIndex}
|
|
1131
1908
|
className={wysiwygClassName}
|
|
1132
|
-
onInput={
|
|
1909
|
+
onInput={handleEditableInput}
|
|
1133
1910
|
onPaste={handleEditablePaste}
|
|
1134
1911
|
onDragOver={handleDragOver}
|
|
1135
1912
|
onDragEnter={handleDragOver}
|
|
@@ -1169,7 +1946,9 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
1169
1946
|
ref={textareaRef}
|
|
1170
1947
|
autoFocus={false}
|
|
1171
1948
|
aria-labelledby={props.ariaLabelledby}
|
|
1172
|
-
|
|
1949
|
+
aria-invalid={props.error ? "true" : undefined}
|
|
1950
|
+
aria-describedby={props.error ? errorId : undefined}
|
|
1951
|
+
placeholder={sourcePlaceholder}
|
|
1173
1952
|
className={`${className} rounded-t-none min-h-32 ${
|
|
1174
1953
|
isDraggingOver
|
|
1175
1954
|
? "ring-2 ring-indigo-400 ring-offset-1 border-indigo-400"
|
|
@@ -1195,20 +1974,7 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
1195
1974
|
props.onBlur();
|
|
1196
1975
|
}
|
|
1197
1976
|
}}
|
|
1198
|
-
onKeyDown={
|
|
1199
|
-
if (e.ctrlKey || e.metaKey) {
|
|
1200
|
-
switch (e.key) {
|
|
1201
|
-
case "b":
|
|
1202
|
-
e.preventDefault();
|
|
1203
|
-
formatActions.bold();
|
|
1204
|
-
break;
|
|
1205
|
-
case "i":
|
|
1206
|
-
e.preventDefault();
|
|
1207
|
-
formatActions.italic();
|
|
1208
|
-
break;
|
|
1209
|
-
}
|
|
1210
|
-
}
|
|
1211
|
-
}}
|
|
1977
|
+
onKeyDown={handleTextareaKeyDown}
|
|
1212
1978
|
tabIndex={props.tabIndex}
|
|
1213
1979
|
rows={10}
|
|
1214
1980
|
/>
|
|
@@ -1233,11 +1999,13 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
1233
1999
|
|
|
1234
2000
|
{/* Error Message */}
|
|
1235
2001
|
{props.error && (
|
|
1236
|
-
<p className="mt-1 text-sm text-red-400">
|
|
2002
|
+
<p id={errorId} role="alert" className="mt-1 text-sm text-red-400">
|
|
2003
|
+
{props.error}
|
|
2004
|
+
</p>
|
|
1237
2005
|
)}
|
|
1238
2006
|
|
|
1239
2007
|
{/* Help Text */}
|
|
1240
|
-
<TinyFormDocumentation title=
|
|
2008
|
+
<TinyFormDocumentation title={helpTitle}>
|
|
1241
2009
|
<>
|
|
1242
2010
|
<div>
|
|
1243
2011
|
Type directly in the visual editor — use the toolbar to format.
|
|
@@ -1246,9 +2014,39 @@ const MarkdownEditor: FunctionComponent<ComponentProps> = (
|
|
|
1246
2014
|
Switch to <strong>Markdown</strong> to view or edit the raw source.
|
|
1247
2015
|
</div>
|
|
1248
2016
|
<div>
|
|
1249
|
-
|
|
1250
|
-
|
|
2017
|
+
In a list, press{" "}
|
|
2018
|
+
<strong>
|
|
2019
|
+
{KeyboardKeyUtil.getDisplayLabel([KeyboardKey.Tab])}
|
|
2020
|
+
</strong>{" "}
|
|
2021
|
+
to indent an item and{" "}
|
|
2022
|
+
<strong>
|
|
2023
|
+
{KeyboardKeyUtil.getDisplayLabel([
|
|
2024
|
+
KeyboardKey.Shift,
|
|
2025
|
+
KeyboardKey.Tab,
|
|
2026
|
+
])}
|
|
2027
|
+
</strong>{" "}
|
|
2028
|
+
to outdent it, or use the Indent and Outdent buttons. Outside a
|
|
2029
|
+
list, {KeyboardKeyUtil.getDisplayLabel([KeyboardKey.Tab])} moves to
|
|
2030
|
+
the next field.
|
|
2031
|
+
</div>
|
|
2032
|
+
<div>
|
|
2033
|
+
Pasting keeps lists, links and formatting from Word, Outlook, web
|
|
2034
|
+
pages and other notes. To paste plain text instead, press{" "}
|
|
2035
|
+
<strong>
|
|
2036
|
+
{KeyboardKeyUtil.getDisplayLabel([
|
|
2037
|
+
KeyboardKey.Mod,
|
|
2038
|
+
KeyboardKey.Shift,
|
|
2039
|
+
"V",
|
|
2040
|
+
])}
|
|
2041
|
+
</strong>
|
|
2042
|
+
.
|
|
1251
2043
|
</div>
|
|
2044
|
+
{allowImageUpload && (
|
|
2045
|
+
<div>
|
|
2046
|
+
Tip: paste, drag & drop, or click the image button to upload
|
|
2047
|
+
screenshots inline.
|
|
2048
|
+
</div>
|
|
2049
|
+
)}
|
|
1252
2050
|
</>
|
|
1253
2051
|
</TinyFormDocumentation>
|
|
1254
2052
|
</div>
|