@oneuptime/common 12.0.6 → 12.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/AIInsight.ts +1 -1
- package/Models/DatabaseModels/DatabaseBaseModel/FileModel.ts +2 -3
- package/Models/DatabaseModels/DeletedProject.ts +595 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/Monitor.ts +111 -0
- package/Models/DatabaseModels/Project.ts +3 -3
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -1
- package/Server/API/FileAPI.ts +15 -2
- package/Server/API/MicrosoftTeamsAPI.ts +6 -1
- package/Server/API/ProjectAPI.ts +214 -0
- package/Server/API/StatusPageAPI.ts +39 -6
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.ts +50 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.ts +67 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.ts +39 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Services/AIAgentService.ts +20 -0
- package/Server/Services/DashboardDomainService.ts +73 -28
- package/Server/Services/DatabaseService.ts +1 -0
- package/Server/Services/DeletedProjectService.ts +138 -0
- package/Server/Services/FileService.ts +61 -0
- package/Server/Services/IncidentEpisodePublicNoteService.ts +18 -0
- package/Server/Services/IncidentPublicNoteService.ts +18 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/MonitorService.ts +311 -0
- package/Server/Services/ProbeService.ts +20 -0
- package/Server/Services/ProjectService.ts +297 -1
- package/Server/Services/PushNotificationService.ts +71 -0
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +18 -0
- package/Server/Services/StatusPageAnnouncementService.ts +53 -0
- package/Server/Services/StatusPageDomainService.ts +73 -28
- package/Server/Services/TeamMemberService.ts +117 -12
- package/Server/Services/TelemetryIngestionKeyService.ts +1 -0
- package/Server/Services/UserWebhookService.ts +34 -109
- package/Server/Services/WorkspaceNotificationRuleService.ts +69 -0
- package/Server/Services/WorkspaceProjectAuthTokenService.ts +37 -1
- package/Server/Types/Database/DeleteById.ts +2 -0
- package/Server/Types/Database/DeleteOneBy.ts +6 -0
- package/Server/Types/Domain.ts +41 -0
- package/Server/Types/Workflow/Components/API/Delete.ts +2 -1
- package/Server/Types/Workflow/Components/API/Get.ts +2 -1
- package/Server/Types/Workflow/Components/API/Patch.ts +2 -1
- package/Server/Types/Workflow/Components/API/Post.ts +2 -1
- package/Server/Types/Workflow/Components/API/Put.ts +2 -1
- package/Server/Types/Workflow/Components/API/Utils.ts +41 -2
- package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +25 -19
- package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +6 -5
- package/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.ts +32 -14
- package/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts +31 -13
- package/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts +29 -20
- package/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts +28 -21
- package/Server/Types/Workflow/Components/BaseModel/LogComponentError.ts +89 -0
- package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +208 -0
- package/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts +11 -0
- package/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts +41 -18
- package/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts +45 -19
- package/Server/Types/Workflow/Components/Discord/SendMessageToChannel.ts +16 -9
- package/Server/Types/Workflow/Components/IncomingWebhookUtils.ts +66 -0
- package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +15 -9
- package/Server/Types/Workflow/Components/Slack/SendMessageToChannel.ts +17 -0
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
- package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +171 -0
- package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +3 -3
- package/Server/Utils/AI/SRE/Insights/FixRouting.ts +3 -2
- package/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.ts +1 -1
- package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +6 -6
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +43 -5
- package/Server/Utils/DataSource/EgressGuard.ts +176 -16
- package/Server/Utils/DataSource/HttpFetch.ts +6 -45
- package/Server/Utils/Execute.ts +8 -0
- package/Server/Utils/InlineImageAccessTokenSync.ts +23 -0
- package/Server/Utils/LLM/LLMService.ts +57 -12
- package/Server/Utils/Monitor/MonitorAlert.ts +40 -0
- package/Server/Utils/Monitor/MonitorDependencySuppression.ts +192 -0
- package/Server/Utils/Monitor/MonitorIncident.ts +40 -0
- package/Server/Utils/Monitor/MonitorResource.ts +36 -0
- package/Server/Utils/Response.ts +142 -6
- package/Server/Utils/SSRFProtection.ts +273 -60
- package/Server/Utils/StartServer.ts +8 -0
- package/Server/Utils/VM/VMRunner.ts +88 -1
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +555 -49
- package/Server/Utils/Workspace/Slack/Slack.ts +25 -2
- package/Server/Utils/Workspace/WorkspaceBase.ts +6 -0
- package/Tests/App/Dashboard/DangerZone.test.tsx +334 -0
- package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +539 -0
- package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +678 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +706 -0
- package/Tests/App/Dashboard/DashboardVariablesModal.test.tsx +508 -0
- package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +470 -0
- package/Tests/App/StatusPage/StatusPageDetailPagesNotFound.test.tsx +308 -0
- package/Tests/Models/DatabaseModels/DeletedProjectModel.test.ts +251 -0
- package/Tests/Models/DatabaseModels/SavedViewJSONColumnTuples.test.ts +115 -0
- package/Tests/Server/API/FileAPIAccessControl.test.ts +316 -0
- package/Tests/Server/API/ProjectAPI.test.ts +299 -1
- package/Tests/Server/API/ProjectAPIAdjustBalance.test.ts +459 -0
- package/Tests/Server/API/ProjectAPIAdjustBalanceBillingDisabled.test.ts +177 -0
- package/Tests/Server/Services/DatabaseServiceDeletionReason.test.ts +123 -0
- package/Tests/Server/Services/DeletedProjectService.test.ts +415 -0
- package/Tests/Server/Services/DeletedProjectServiceSelfHosted.test.ts +70 -0
- package/Tests/Server/Services/DomainSubdomainHooks.test.ts +94 -0
- package/Tests/Server/Services/FileIsPublicBooleanMigration.test.ts +244 -0
- package/Tests/Server/Services/FileServiceMimeType.test.ts +89 -0
- package/Tests/Server/Services/MonitorServiceDependencyValidation.test.ts +702 -0
- package/Tests/Server/Services/ProjectServiceAdjustBalance.test.ts +615 -0
- package/Tests/Server/Services/ProjectServiceDeleteAudit.test.ts +406 -0
- package/Tests/Server/Services/PublishTimeImageVisibility.test.ts +450 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +669 -0
- package/Tests/Server/Services/UserWebhookSSRF.test.ts +174 -0
- package/Tests/Server/Services/WebPushEndpointAllowlist.test.ts +133 -0
- package/Tests/Server/Services/WorkspaceProjectAuthTokenRepoint.test.ts +618 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +26 -1
- package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +215 -0
- package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +742 -0
- package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +256 -0
- package/Tests/Server/Types/Workflow/Components/ModelArguments.test.ts +371 -0
- package/Tests/Server/Utils/AI/CodeAgentCommandGuard.test.ts +204 -0
- package/Tests/Server/Utils/AI/CodeAgentWriteLimits.test.ts +213 -0
- package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +52 -5
- package/Tests/Server/Utils/AI/LLMServiceBaseUrl.test.ts +3 -0
- package/Tests/Server/Utils/AI/LLMServiceEgressGuard.test.ts +315 -0
- package/Tests/Server/Utils/AI/LLMServiceModelCompatibility.test.ts +3 -0
- package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +17 -5
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +14 -1
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +35 -0
- package/Tests/Server/Utils/AI/StubLLMEgressGuard.ts +25 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +62 -7
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +69 -0
- package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +330 -0
- package/Tests/Server/Utils/GitHubCreatePullRequestWithToken.test.ts +393 -0
- package/Tests/Server/Utils/InlineImageAccessTokenSync.test.ts +202 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppression.test.ts +811 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +604 -0
- package/Tests/Server/Utils/ResponseSendFileResponse.test.ts +192 -0
- package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +406 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +1169 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +2 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +1605 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTenantResolution.test.ts +1218 -0
- package/Tests/Types/AI/AIChatMessageStatus.test.ts +79 -0
- package/Tests/Types/AI/AIInsightStatus.test.ts +40 -0
- package/Tests/Types/API/HostnameAuthorityParsing.test.ts +157 -0
- package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +27 -0
- package/Tests/Types/DataSource/DataSourceLimits.test.ts +71 -0
- package/Tests/Types/DataSource/DataSourceType.test.ts +181 -0
- package/Tests/Types/DomainSubdomainValidation.test.ts +90 -0
- package/Tests/Types/JSONFunctions.test.ts +252 -1
- package/Tests/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.test.ts +61 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.test.ts +62 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.test.ts +68 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpVersion.test.ts +51 -0
- package/Tests/UI/Components/404.test.tsx +1 -1
- package/Tests/UI/Components/Alert.test.tsx +1 -1
- package/Tests/UI/Components/Badge.test.tsx +1 -1
- package/Tests/UI/Components/BasicForm.test.tsx +39 -10
- package/Tests/UI/Components/Button.test.tsx +1 -1
- package/Tests/UI/Components/Card.test.tsx +1 -1
- package/Tests/UI/Components/Charts/AxisTickColor.test.tsx +1 -1
- package/Tests/UI/Components/ColorViewer.test.tsx +1 -1
- package/Tests/UI/Components/ComponentsModal.test.tsx +7 -1
- package/Tests/UI/Components/DictionaryOfStrings.test.tsx +1 -1
- package/Tests/UI/Components/Dropdown.test.tsx +1 -1
- package/Tests/UI/Components/FilePicker.test.tsx +1 -1
- package/Tests/UI/Components/HiddenText.test.tsx +1 -1
- package/Tests/UI/Components/Input.test.tsx +1 -1
- package/Tests/UI/Components/Loader.test.tsx +1 -1
- package/Tests/UI/Components/LogTimeRangePicker.test.tsx +1 -1
- package/Tests/UI/Components/MasterPage.test.tsx +1 -1
- package/Tests/UI/Components/ModalPortalDismissal.test.tsx +489 -0
- package/Tests/UI/Components/ModelDelete.test.tsx +214 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1 -1
- package/Tests/UI/Components/NavBar.test.tsx +1 -1
- package/Tests/UI/Components/OperatorSelectorKeyboard.test.tsx +1 -1
- package/Tests/UI/Components/Pagination.test.tsx +1 -1
- package/Tests/UI/Components/Pill.test.tsx +1 -1
- package/Tests/UI/Components/Probe.test.tsx +1 -1
- package/Tests/UI/Components/ProgressBar.test.tsx +1 -1
- package/Tests/UI/Components/RadioButtons.test.tsx +1 -1
- package/Tests/UI/Components/SideMenuItem.test.tsx +1 -1
- package/Tests/UI/Components/SideOver.test.tsx +500 -6
- package/Tests/UI/Components/Tabs.test.tsx +1 -1
- package/Tests/UI/Components/TelemetrySearchBar.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +1 -1
- package/Tests/UI/Components/TextArea.test.tsx +1 -1
- package/Tests/UI/Components/Toast.test.tsx +1 -1
- package/Tests/UI/Components/Toggle.test.tsx +1 -1
- package/Tests/UI/Components/TopSection.test.tsx +1 -1
- package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +1 -1
- package/Tests/UI/Rum/ReplayScrubber.test.tsx +1 -1
- package/Tests/UI/Rum/ReplayStage.test.tsx +1 -1
- package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +1 -1
- package/Tests/UI/Utils/LocalStorageArrayRoundTrip.test.ts +72 -0
- package/Tests/Utils/Dashboard/HtmlWidgetDocument.test.ts +19 -2
- package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +44 -0
- package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +288 -5
- package/Tests/Utils/Dashboard/VariableUrlState.test.ts +42 -0
- package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +27 -0
- package/Tests/Utils/LegacySerializedArray.test.ts +139 -0
- package/Tests/Utils/Monitor/MonitorDependencyRule.test.ts +190 -0
- package/Tests/Utils/Realtime.test.ts +78 -0
- package/Tests/Utils/Telemetry/SavedViewFilters.test.ts +246 -0
- package/Tests/__mocks__/i18next-browser-languagedetector.js +21 -0
- package/Types/AI/FixPullRequestCiStatus.ts +1 -1
- package/Types/AI/FixVerificationStatus.ts +2 -2
- package/Types/API/Hostname.ts +92 -4
- package/Types/API/URL.ts +43 -25
- package/Types/Billing/BalanceAdjustmentType.ts +14 -0
- package/Types/Billing/ProjectBalanceType.ts +13 -0
- package/Types/Domain.ts +26 -0
- package/Types/File/MimeType.ts +11 -0
- package/Types/JSONFunctions.ts +15 -0
- package/Types/Telemetry/TelemetrySavedViewState.ts +9 -1
- package/Types/Workflow/Components/BaseModel.ts +92 -28
- package/Typings/Index.d.ts +12 -0
- package/UI/Components/GanttChart/ChartContainer.tsx +4 -3
- package/UI/Components/Modal/ConfirmModal.tsx +10 -5
- package/UI/Components/Modal/Modal.tsx +27 -47
- package/UI/Components/ModelDelete/ModelDelete.tsx +23 -6
- package/UI/Components/SideOver/SideOver.tsx +195 -68
- package/UI/Utils/PageScrollLock.ts +66 -0
- package/Utils/Dashboard/HtmlWidgetDocument.ts +4 -2
- package/Utils/Dashboard/VariableInterpolation.ts +19 -1
- package/Utils/LegacySerializedArray.ts +60 -0
- package/Utils/Monitor/MonitorDependencyRule.ts +88 -0
- package/Utils/Telemetry/SavedViewFilters.ts +88 -0
- package/build/dist/Models/DatabaseModels/AIInsight.js +1 -1
- package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js +2 -3
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DeletedProject.js +640 -0
- package/build/dist/Models/DatabaseModels/DeletedProject.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +106 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +3 -3
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/FileAPI.js +14 -2
- package/build/dist/Server/API/FileAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +6 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectAPI.js +157 -4
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +27 -3
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIAgentService.js +17 -0
- package/build/dist/Server/Services/AIAgentService.js.map +1 -1
- package/build/dist/Server/Services/DashboardDomainService.js +55 -18
- package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +1 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DeletedProjectService.js +124 -0
- package/build/dist/Server/Services/DeletedProjectService.js.map +1 -0
- package/build/dist/Server/Services/FileService.js +52 -0
- package/build/dist/Server/Services/FileService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +10 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +10 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +232 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/ProbeService.js +17 -0
- package/build/dist/Server/Services/ProbeService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +228 -6
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/PushNotificationService.js +56 -0
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +10 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageAnnouncementService.js +54 -0
- package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageDomainService.js +55 -18
- package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +97 -6
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js +1 -0
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
- package/build/dist/Server/Services/UserWebhookService.js +31 -87
- package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +65 -0
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +23 -0
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
- package/build/dist/Server/Types/Domain.js +37 -0
- package/build/dist/Server/Types/Domain.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js +35 -2
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +15 -11
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +2 -3
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js +21 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js +21 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js +18 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js +18 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js +43 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +116 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js +7 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js +24 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js +27 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js +14 -6
- package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js +42 -0
- package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +15 -6
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js +10 -2
- package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +141 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +6 -6
- package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +39 -5
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +94 -10
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +1 -19
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/Execute.js +2 -2
- package/build/dist/Server/Utils/Execute.js.map +1 -1
- package/build/dist/Server/Utils/InlineImageAccessTokenSync.js +13 -0
- package/build/dist/Server/Utils/InlineImageAccessTokenSync.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +43 -12
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +44 -24
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js +158 -0
- package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +50 -30
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +32 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Response.js +112 -5
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +219 -53
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +7 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +73 -1
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +445 -43
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +18 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
- package/build/dist/Types/AI/FixPullRequestCiStatus.js +1 -1
- package/build/dist/Types/AI/FixVerificationStatus.js +2 -2
- package/build/dist/Types/API/Hostname.js +73 -4
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/API/URL.js +42 -24
- package/build/dist/Types/API/URL.js.map +1 -1
- package/build/dist/Types/Billing/BalanceAdjustmentType.js +15 -0
- package/build/dist/Types/Billing/BalanceAdjustmentType.js.map +1 -0
- package/build/dist/Types/Billing/ProjectBalanceType.js +14 -0
- package/build/dist/Types/Billing/ProjectBalanceType.js.map +1 -0
- package/build/dist/Types/Domain.js +22 -0
- package/build/dist/Types/Domain.js.map +1 -1
- package/build/dist/Types/File/MimeType.js +11 -0
- package/build/dist/Types/File/MimeType.js.map +1 -1
- package/build/dist/Types/JSONFunctions.js +14 -0
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/Workflow/Components/BaseModel.js +83 -28
- package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
- package/build/dist/UI/Components/GanttChart/ChartContainer.js +4 -3
- package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js +3 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +24 -34
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/ModelDelete/ModelDelete.js +11 -6
- package/build/dist/UI/Components/ModelDelete/ModelDelete.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +105 -30
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Utils/PageScrollLock.js +52 -0
- package/build/dist/UI/Utils/PageScrollLock.js.map +1 -0
- package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js +4 -2
- package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js.map +1 -1
- package/build/dist/Utils/Dashboard/VariableInterpolation.js +19 -1
- package/build/dist/Utils/Dashboard/VariableInterpolation.js.map +1 -1
- package/build/dist/Utils/LegacySerializedArray.js +51 -0
- package/build/dist/Utils/LegacySerializedArray.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorDependencyRule.js +47 -0
- package/build/dist/Utils/Monitor/MonitorDependencyRule.js.map +1 -0
- package/build/dist/Utils/Telemetry/SavedViewFilters.js +52 -0
- package/build/dist/Utils/Telemetry/SavedViewFilters.js.map +1 -0
- package/jest.config.json +3 -0
- package/package.json +1 -1
- package/tsconfig.json +3 -1
|
@@ -7,6 +7,7 @@ import ModalFooter from "./ModalFooter";
|
|
|
7
7
|
import { VeryLightGray } from "../../../Types/BrandColors";
|
|
8
8
|
import IconProp from "../../../Types/Icon/IconProp";
|
|
9
9
|
import useTranslateValue from "../../Utils/Translation";
|
|
10
|
+
import { lockPageScroll, unlockPageScroll } from "../../Utils/PageScrollLock";
|
|
10
11
|
import React, {
|
|
11
12
|
FunctionComponent,
|
|
12
13
|
ReactElement,
|
|
@@ -23,52 +24,6 @@ export enum ModalWidth {
|
|
|
23
24
|
Large,
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
/*
|
|
27
|
-
* The page behind a modal must not scroll, and nested modals share a single
|
|
28
|
-
* lock: a counter, rather than a boolean, is what stops the inner modal from
|
|
29
|
-
* handing scrolling back while its parent is still open.
|
|
30
|
-
*/
|
|
31
|
-
let openModalCount: number = 0;
|
|
32
|
-
let bodyOverflowBeforeLock: string = "";
|
|
33
|
-
let bodyPaddingRightBeforeLock: string = "";
|
|
34
|
-
|
|
35
|
-
type PageScrollLockFunction = () => void;
|
|
36
|
-
|
|
37
|
-
const lockPageScroll: PageScrollLockFunction = (): void => {
|
|
38
|
-
openModalCount++;
|
|
39
|
-
|
|
40
|
-
if (openModalCount > 1 || typeof document === "undefined") {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
bodyOverflowBeforeLock = document.body.style.overflow;
|
|
45
|
-
bodyPaddingRightBeforeLock = document.body.style.paddingRight;
|
|
46
|
-
|
|
47
|
-
/*
|
|
48
|
-
* Hiding the scrollbar reclaims its width, so the page underneath would
|
|
49
|
-
* jump sideways by exactly that much. Pad it back to hold everything still.
|
|
50
|
-
*/
|
|
51
|
-
const scrollbarWidth: number =
|
|
52
|
-
window.innerWidth - document.documentElement.clientWidth;
|
|
53
|
-
|
|
54
|
-
if (scrollbarWidth > 0) {
|
|
55
|
-
document.body.style.paddingRight = `${scrollbarWidth}px`;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
document.body.style.overflow = "hidden";
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const unlockPageScroll: PageScrollLockFunction = (): void => {
|
|
62
|
-
openModalCount = Math.max(0, openModalCount - 1);
|
|
63
|
-
|
|
64
|
-
if (openModalCount > 0 || typeof document === "undefined") {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
document.body.style.overflow = bodyOverflowBeforeLock;
|
|
69
|
-
document.body.style.paddingRight = bodyPaddingRightBeforeLock;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
27
|
export interface ComponentProps {
|
|
73
28
|
title: string;
|
|
74
29
|
description?: string | undefined;
|
|
@@ -346,7 +301,32 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
346
301
|
): boolean => {
|
|
347
302
|
const modal: HTMLDivElement | null = modalRef.current;
|
|
348
303
|
|
|
349
|
-
|
|
304
|
+
if (modal === null) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const target: Node = event.target as Node;
|
|
309
|
+
|
|
310
|
+
/*
|
|
311
|
+
* Dropdown menus inside the body (AutocompleteTextInput, OperatorSelector,
|
|
312
|
+
* ColorPicker, IconPicker, react-select) portal themselves to document.body
|
|
313
|
+
* so a scroll container cannot clip them. React dispatches events through
|
|
314
|
+
* the *React* tree rather than the DOM tree, so picking one of those
|
|
315
|
+
* options still bubbles into this handler even though the pointer never
|
|
316
|
+
* touched the backdrop — and because the option is not a DOM descendant of
|
|
317
|
+
* the panel, the containment check below read it as a click outside and
|
|
318
|
+
* dismissed the dialog, discarding whatever the user had filled in.
|
|
319
|
+
*
|
|
320
|
+
* A press only counts as a backdrop press when it physically landed inside
|
|
321
|
+
* the backdrop element this handler is attached to. That is a DOM question,
|
|
322
|
+
* and `contains` is true of the element itself, so a press directly on this
|
|
323
|
+
* layer or on the flex box it centres the panel in still dismisses.
|
|
324
|
+
*/
|
|
325
|
+
if (!event.currentTarget.contains(target)) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return !modal.contains(target);
|
|
350
330
|
};
|
|
351
331
|
|
|
352
332
|
const onBackdropMouseDown: BackdropPressHandler = (
|
|
@@ -14,6 +14,17 @@ export interface ComponentProps<TBaseModel extends BaseModel> {
|
|
|
14
14
|
modelId: ObjectID;
|
|
15
15
|
modelAPI?: typeof ModelAPI | undefined;
|
|
16
16
|
onDeleteSuccess: () => void;
|
|
17
|
+
/*
|
|
18
|
+
* Extra content for the confirmation modal - a field to fill in before
|
|
19
|
+
* confirming, for example. State for it belongs to the caller.
|
|
20
|
+
*/
|
|
21
|
+
confirmationContent?: ReactElement | undefined;
|
|
22
|
+
/*
|
|
23
|
+
* Replaces the delete request itself, for models whose delete needs more
|
|
24
|
+
* than an id (see confirmationContent). Throwing surfaces the error in the
|
|
25
|
+
* same dialog the default request uses.
|
|
26
|
+
*/
|
|
27
|
+
onDelete?: (() => Promise<void>) | undefined;
|
|
17
28
|
}
|
|
18
29
|
|
|
19
30
|
const ModelDelete: <TBaseModel extends BaseModel>(
|
|
@@ -30,12 +41,16 @@ const ModelDelete: <TBaseModel extends BaseModel>(
|
|
|
30
41
|
const deleteItem: PromiseVoidFunction = async (): Promise<void> => {
|
|
31
42
|
setIsLoading(true);
|
|
32
43
|
try {
|
|
33
|
-
|
|
44
|
+
if (props.onDelete) {
|
|
45
|
+
await props.onDelete();
|
|
46
|
+
} else {
|
|
47
|
+
const modelAPI: typeof ModelAPI = props.modelAPI || ModelAPI;
|
|
34
48
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
49
|
+
await modelAPI.deleteItem<TBaseModel>({
|
|
50
|
+
modelType: props.modelType,
|
|
51
|
+
id: props.modelId,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
39
54
|
props.onDeleteSuccess?.();
|
|
40
55
|
} catch (err) {
|
|
41
56
|
setError(API.getFriendlyMessage(err));
|
|
@@ -76,7 +91,9 @@ const ModelDelete: <TBaseModel extends BaseModel>(
|
|
|
76
91
|
}}
|
|
77
92
|
submitButtonText={`Delete ${model.singularName}`}
|
|
78
93
|
submitButtonType={ButtonStyleType.DANGER}
|
|
79
|
-
|
|
94
|
+
>
|
|
95
|
+
{props.confirmationContent}
|
|
96
|
+
</ConfirmModal>
|
|
80
97
|
) : (
|
|
81
98
|
<></>
|
|
82
99
|
)}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import Button, { ButtonStyleType } from "../Button/Button";
|
|
2
2
|
import Icon from "../Icon/Icon";
|
|
3
3
|
import IconProp from "../../../Types/Icon/IconProp";
|
|
4
|
-
import
|
|
4
|
+
import { lockPageScroll, unlockPageScroll } from "../../Utils/PageScrollLock";
|
|
5
|
+
import React, {
|
|
6
|
+
FunctionComponent,
|
|
7
|
+
ReactElement,
|
|
8
|
+
useEffect,
|
|
9
|
+
useId,
|
|
10
|
+
useLayoutEffect,
|
|
11
|
+
useState,
|
|
12
|
+
} from "react";
|
|
13
|
+
import { createPortal } from "react-dom";
|
|
5
14
|
|
|
6
15
|
export enum SideOverSize {
|
|
7
16
|
Small = "Small",
|
|
@@ -19,8 +28,42 @@ export interface ComponentProps {
|
|
|
19
28
|
submitButtonText?: string | undefined;
|
|
20
29
|
leftFooterElement?: ReactElement | undefined;
|
|
21
30
|
size?: SideOverSize | undefined;
|
|
31
|
+
/*
|
|
32
|
+
* Opt out of hiding the page's scrollbar while the panel is open. Only worth
|
|
33
|
+
* setting for a panel that is a permanent part of its page rather than a
|
|
34
|
+
* transient drawer — every current caller wants the lock.
|
|
35
|
+
*/
|
|
36
|
+
disablePageScrollLock?: boolean | undefined;
|
|
22
37
|
}
|
|
23
38
|
|
|
39
|
+
type PortalTargetFunction = () => HTMLElement | null;
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
* Where the panel is appended in the DOM, not where it appears on screen — it
|
|
43
|
+
* is `position: fixed` either way.
|
|
44
|
+
*
|
|
45
|
+
* Two reasons it cannot simply stay where the caller rendered it. First, any
|
|
46
|
+
* ancestor with a z-index traps the panel in that ancestor's stacking context,
|
|
47
|
+
* which is how a map's zoom toolbar (z-20) ended up painting on top of an open
|
|
48
|
+
* device panel. Second, and unfixable by z-index at all: only the fullscreen
|
|
49
|
+
* element's own subtree reaches the browser's top layer, so a panel appended to
|
|
50
|
+
* <body> while a chart or map is fullscreen is not painted anywhere. Following
|
|
51
|
+
* document.fullscreenElement keeps the panel visible in both modes.
|
|
52
|
+
*/
|
|
53
|
+
const getPortalTarget: PortalTargetFunction = (): HTMLElement | null => {
|
|
54
|
+
if (typeof document === "undefined") {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const fullscreenElement: Element | null = document.fullscreenElement;
|
|
59
|
+
|
|
60
|
+
if (fullscreenElement instanceof HTMLElement) {
|
|
61
|
+
return fullscreenElement;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return document.body;
|
|
65
|
+
};
|
|
66
|
+
|
|
24
67
|
const SideOver: FunctionComponent<ComponentProps> = (
|
|
25
68
|
props: ComponentProps,
|
|
26
69
|
): ReactElement => {
|
|
@@ -34,85 +77,169 @@ const SideOver: FunctionComponent<ComponentProps> = (
|
|
|
34
77
|
widthClass = "max-w-7xl";
|
|
35
78
|
}
|
|
36
79
|
|
|
37
|
-
|
|
80
|
+
const titleId: string = useId();
|
|
81
|
+
const descriptionId: string = useId();
|
|
82
|
+
|
|
83
|
+
const [portalTarget, setPortalTarget] = useState<HTMLElement | null>(
|
|
84
|
+
getPortalTarget,
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
const syncPortalTarget: () => void = (): void => {
|
|
89
|
+
setPortalTarget(getPortalTarget());
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/*
|
|
93
|
+
* Re-read once on mount as well: the first render happens before the
|
|
94
|
+
* browser has necessarily settled document.fullscreenElement.
|
|
95
|
+
*/
|
|
96
|
+
syncPortalTarget();
|
|
97
|
+
document.addEventListener("fullscreenchange", syncPortalTarget);
|
|
98
|
+
|
|
99
|
+
return () => {
|
|
100
|
+
document.removeEventListener("fullscreenchange", syncPortalTarget);
|
|
101
|
+
};
|
|
102
|
+
}, []);
|
|
103
|
+
|
|
104
|
+
/*
|
|
105
|
+
* A layout effect, not an ordinary one. Hiding the page scrollbar widens the
|
|
106
|
+
* viewport that `right: 0` resolves against, so a panel that painted before
|
|
107
|
+
* the lock landed would visibly jump sideways by the scrollbar's width on
|
|
108
|
+
* every platform that draws a classic scrollbar. Locking before paint means
|
|
109
|
+
* the panel is only ever drawn in its final position.
|
|
110
|
+
*/
|
|
111
|
+
useLayoutEffect(() => {
|
|
112
|
+
if (props.disablePageScrollLock) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
lockPageScroll();
|
|
117
|
+
|
|
118
|
+
return () => {
|
|
119
|
+
unlockPageScroll();
|
|
120
|
+
};
|
|
121
|
+
}, [props.disablePageScrollLock]);
|
|
122
|
+
|
|
123
|
+
const sideOver: ReactElement = (
|
|
124
|
+
/*
|
|
125
|
+
* z-30 clears every tier of page chrome (sticky headers and table headers
|
|
126
|
+
* at z-10/z-20, map and log-viewer toolbars at z-20) while staying under
|
|
127
|
+
* the app-wide overlays that must remain visible over a panel: Toast and
|
|
128
|
+
* the AI chat panel at z-40, Modal at z-50, portalled dropdown menus at
|
|
129
|
+
* z-60. Deliberately NOT z-40 — Toast and AIChatPanel are mounted ahead of
|
|
130
|
+
* the routed page in App.tsx, so an equal z-index would be broken in this
|
|
131
|
+
* panel's favour by document order and toasts would disappear behind it.
|
|
132
|
+
*
|
|
133
|
+
* role="dialog" without aria-modal, because the panel genuinely is not
|
|
134
|
+
* modal: everything outside it stays clickable by design (both topology
|
|
135
|
+
* maps let you click straight from one node's panel to the next). Claiming
|
|
136
|
+
* aria-modal also made this panel the last entry in Modal's dialog stack,
|
|
137
|
+
* which silently disabled Escape, backdrop-dismissal and initial focus on
|
|
138
|
+
* any Modal that was already open.
|
|
139
|
+
*/
|
|
38
140
|
<div
|
|
39
|
-
className="relative z-
|
|
40
|
-
aria-labelledby=
|
|
141
|
+
className="relative z-30"
|
|
142
|
+
aria-labelledby={titleId}
|
|
143
|
+
aria-describedby={props.description ? descriptionId : undefined}
|
|
41
144
|
role="dialog"
|
|
42
|
-
|
|
145
|
+
data-testid="side-over"
|
|
43
146
|
>
|
|
44
|
-
<div
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
props.onClose();
|
|
68
|
-
}}
|
|
69
|
-
type="button"
|
|
70
|
-
className="text-gray-400 hover:text-gray-500"
|
|
71
|
-
>
|
|
72
|
-
<span className="sr-only">Close panel</span>
|
|
73
|
-
|
|
74
|
-
<Icon className="h-6 w-6" icon={IconProp.Close} />
|
|
75
|
-
</button>
|
|
76
|
-
</div>
|
|
77
|
-
</div>
|
|
78
|
-
</div>
|
|
79
|
-
<div className="h-full overflow-y-scroll">
|
|
80
|
-
<div className="space-y-6 py-6 sm:space-y-0 sm:divide-y sm:divide-gray-200 sm:py-0 p-5">
|
|
81
|
-
{props.children}
|
|
82
|
-
</div>
|
|
147
|
+
<div
|
|
148
|
+
className="pointer-events-none fixed inset-0 flex justify-end"
|
|
149
|
+
data-testid="side-over-layer"
|
|
150
|
+
>
|
|
151
|
+
<div className={`pointer-events-auto w-full ${widthClass}`}>
|
|
152
|
+
<div className="flex h-full flex-col bg-white shadow-xl">
|
|
153
|
+
<div className="flex-shrink-0 flex flex-col bg-gray-50 px-4 py-6 sm:px-6">
|
|
154
|
+
<div className="flex items-start justify-between space-x-3">
|
|
155
|
+
<div className="space-y-1">
|
|
156
|
+
<h2
|
|
157
|
+
className="text-lg font-medium text-gray-900"
|
|
158
|
+
id={titleId}
|
|
159
|
+
data-testid="side-over-title"
|
|
160
|
+
>
|
|
161
|
+
{props.title}
|
|
162
|
+
</h2>
|
|
163
|
+
<p
|
|
164
|
+
className="text-sm text-gray-500"
|
|
165
|
+
id={descriptionId}
|
|
166
|
+
data-testid="side-over-description"
|
|
167
|
+
>
|
|
168
|
+
{props.description}
|
|
169
|
+
</p>
|
|
83
170
|
</div>
|
|
84
|
-
<div className="flex
|
|
85
|
-
<
|
|
86
|
-
{
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<Button
|
|
99
|
-
title={props.submitButtonText || "Save"}
|
|
100
|
-
disabled={props.submitButtonDisabled}
|
|
101
|
-
onClick={() => {
|
|
102
|
-
props.onSubmit!();
|
|
103
|
-
}}
|
|
104
|
-
buttonStyle={ButtonStyleType.PRIMARY}
|
|
105
|
-
/>
|
|
106
|
-
)}
|
|
107
|
-
</div>
|
|
171
|
+
<div className="flex h-7 items-center">
|
|
172
|
+
<button
|
|
173
|
+
onClick={() => {
|
|
174
|
+
props.onClose();
|
|
175
|
+
}}
|
|
176
|
+
type="button"
|
|
177
|
+
title="Close panel"
|
|
178
|
+
data-testid="close-button"
|
|
179
|
+
className="text-gray-400 hover:text-gray-500"
|
|
180
|
+
>
|
|
181
|
+
<span className="sr-only">Close panel</span>
|
|
182
|
+
|
|
183
|
+
<Icon className="h-6 w-6" icon={IconProp.Close} />
|
|
184
|
+
</button>
|
|
108
185
|
</div>
|
|
109
186
|
</div>
|
|
110
187
|
</div>
|
|
188
|
+
{/*
|
|
189
|
+
* overflow-y-auto, not overflow-y-scroll: `scroll` paints a dead
|
|
190
|
+
* track down the panel's right edge even when the content fits,
|
|
191
|
+
* immediately beside the page's own scrollbar, which reads as the
|
|
192
|
+
* page scrollbar bleeding through the panel. overscroll-contain
|
|
193
|
+
* stops a wheel past the end of the panel from scrolling the page
|
|
194
|
+
* out from under it.
|
|
195
|
+
*/}
|
|
196
|
+
<div
|
|
197
|
+
className="min-h-0 flex-1 overflow-y-auto overscroll-contain"
|
|
198
|
+
data-testid="side-over-content"
|
|
199
|
+
>
|
|
200
|
+
<div className="space-y-6 py-6 sm:space-y-0 sm:divide-y sm:divide-gray-200 sm:py-0 p-5">
|
|
201
|
+
{props.children}
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
<div
|
|
205
|
+
className="flex-shrink-0 border-t border-gray-200 px-4 py-5 sm:px-6 flex justify-between"
|
|
206
|
+
data-testid="side-over-footer"
|
|
207
|
+
>
|
|
208
|
+
<div className="flex justify-start space-x-3">
|
|
209
|
+
{props.leftFooterElement}
|
|
210
|
+
</div>
|
|
211
|
+
<div className="flex justify-end space-x-3">
|
|
212
|
+
<Button
|
|
213
|
+
title="Close"
|
|
214
|
+
onClick={() => {
|
|
215
|
+
props.onClose();
|
|
216
|
+
}}
|
|
217
|
+
buttonStyle={ButtonStyleType.NORMAL}
|
|
218
|
+
/>
|
|
219
|
+
|
|
220
|
+
{props.onSubmit && (
|
|
221
|
+
<Button
|
|
222
|
+
title={props.submitButtonText || "Save"}
|
|
223
|
+
disabled={props.submitButtonDisabled}
|
|
224
|
+
onClick={() => {
|
|
225
|
+
props.onSubmit!();
|
|
226
|
+
}}
|
|
227
|
+
buttonStyle={ButtonStyleType.PRIMARY}
|
|
228
|
+
/>
|
|
229
|
+
)}
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
111
232
|
</div>
|
|
112
233
|
</div>
|
|
113
234
|
</div>
|
|
114
235
|
</div>
|
|
115
236
|
);
|
|
237
|
+
|
|
238
|
+
if (!portalTarget) {
|
|
239
|
+
return sideOver;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return createPortal(sideOver, portalTarget);
|
|
116
243
|
};
|
|
117
244
|
|
|
118
245
|
export default SideOver;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The page behind an open dialog surface must not scroll, and nested surfaces
|
|
3
|
+
* share a single lock: a counter, rather than a boolean, is what stops an inner
|
|
4
|
+
* dialog from handing scrolling back while the surface that opened it is still
|
|
5
|
+
* up.
|
|
6
|
+
*
|
|
7
|
+
* This lives outside any one component on purpose. Modal and SideOver nest
|
|
8
|
+
* inside each other in shipped code — Workflow's "Run Workflow" panel is a
|
|
9
|
+
* SideOver that opens a ConfirmModal — and two private counters would race over
|
|
10
|
+
* document.body.style. Whichever surface unmounted first would restore the
|
|
11
|
+
* snapshot the other had already overwritten, leaving the page either scrolling
|
|
12
|
+
* under a dialog that is still open or locked forever with no dialog on screen.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
let openDialogCount: number = 0;
|
|
16
|
+
let bodyOverflowBeforeLock: string = "";
|
|
17
|
+
let bodyPaddingRightBeforeLock: string = "";
|
|
18
|
+
|
|
19
|
+
export type PageScrollLockFunction = () => void;
|
|
20
|
+
|
|
21
|
+
export const lockPageScroll: PageScrollLockFunction = (): void => {
|
|
22
|
+
openDialogCount++;
|
|
23
|
+
|
|
24
|
+
if (openDialogCount > 1 || typeof document === "undefined") {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
bodyOverflowBeforeLock = document.body.style.overflow;
|
|
29
|
+
bodyPaddingRightBeforeLock = document.body.style.paddingRight;
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
* Hiding the scrollbar reclaims its width, so the page underneath would
|
|
33
|
+
* jump sideways by exactly that much. Pad it back to hold everything still.
|
|
34
|
+
*/
|
|
35
|
+
const scrollbarWidth: number =
|
|
36
|
+
window.innerWidth - document.documentElement.clientWidth;
|
|
37
|
+
|
|
38
|
+
if (scrollbarWidth > 0) {
|
|
39
|
+
document.body.style.paddingRight = `${scrollbarWidth}px`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
document.body.style.overflow = "hidden";
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const unlockPageScroll: PageScrollLockFunction = (): void => {
|
|
46
|
+
openDialogCount = Math.max(0, openDialogCount - 1);
|
|
47
|
+
|
|
48
|
+
if (openDialogCount > 0 || typeof document === "undefined") {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
document.body.style.overflow = bodyOverflowBeforeLock;
|
|
53
|
+
document.body.style.paddingRight = bodyPaddingRightBeforeLock;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* Test-only escape hatch. The counter is module state that survives between
|
|
58
|
+
* cases in the same jest file, so a suite that asserts on the FIRST lock needs
|
|
59
|
+
* a way back to a known zero.
|
|
60
|
+
*/
|
|
61
|
+
export const resetPageScrollLockForTesting: PageScrollLockFunction =
|
|
62
|
+
(): void => {
|
|
63
|
+
openDialogCount = 0;
|
|
64
|
+
bodyOverflowBeforeLock = "";
|
|
65
|
+
bodyPaddingRightBeforeLock = "";
|
|
66
|
+
};
|
|
@@ -128,8 +128,10 @@ export default class HtmlWidgetDocument {
|
|
|
128
128
|
*
|
|
129
129
|
* Resolution is delegated to DashboardVariableInterpolation so this widget
|
|
130
130
|
* agrees with every query-driven widget about what a variable currently
|
|
131
|
-
* means
|
|
132
|
-
*
|
|
131
|
+
* means: a single-select is its selected value, else its default, else
|
|
132
|
+
* nothing; a multi-select is its picks, and no picks is "All" — which
|
|
133
|
+
* lands here as "" rather than the default. Multi-select joins with ","
|
|
134
|
+
* because that is the form an author would paste into a filter.
|
|
133
135
|
*/
|
|
134
136
|
public static resolveVariables(
|
|
135
137
|
variables: Array<DashboardVariable> | undefined,
|
|
@@ -31,6 +31,23 @@ export interface ResolvedVariableValue {
|
|
|
31
31
|
* key so the server's WHERE-builder produces `attributes[key] IN (...)`.
|
|
32
32
|
*/
|
|
33
33
|
export default class DashboardVariableInterpolation {
|
|
34
|
+
/*
|
|
35
|
+
* The one place that decides what a variable currently *means*. Every
|
|
36
|
+
* widget and every selector defers to it, so the rules have to be
|
|
37
|
+
* stated rather than inferred:
|
|
38
|
+
*
|
|
39
|
+
* - A multi-select variable's `selectedValues` is its sole source of
|
|
40
|
+
* truth. Empty or unset is the "All" state and produces no
|
|
41
|
+
* predicate. `defaultValue` deliberately does NOT apply here: the
|
|
42
|
+
* selector shows "All" whenever the list is empty and cannot show
|
|
43
|
+
* anything else, so honouring a default would filter widgets behind
|
|
44
|
+
* a control that reads "unfiltered". A default that only holds one
|
|
45
|
+
* value also cannot express what a multi-select is for.
|
|
46
|
+
* - A single-select variable falls back to `defaultValue` only when
|
|
47
|
+
* `selectedValue` is absent. An empty string is a real choice — the
|
|
48
|
+
* "All" option — and must not be overwritten by the default, which
|
|
49
|
+
* is why this uses `??` rather than `||`.
|
|
50
|
+
*/
|
|
34
51
|
public static resolveValue(
|
|
35
52
|
variable: DashboardVariable,
|
|
36
53
|
): ResolvedVariableValue | undefined {
|
|
@@ -43,7 +60,8 @@ export default class DashboardVariableInterpolation {
|
|
|
43
60
|
if (values.length > 0) {
|
|
44
61
|
return { multi: values };
|
|
45
62
|
}
|
|
46
|
-
// No
|
|
63
|
+
// No picks: "All". Never falls back to the single-select default.
|
|
64
|
+
return undefined;
|
|
47
65
|
}
|
|
48
66
|
|
|
49
67
|
const v: string | undefined =
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* JSONFunctions.serializeValue had no Array.isArray branch. Arrays are
|
|
3
|
+
* typeof "object", so any array that reached it directly was walked by key and
|
|
4
|
+
* written out as { "0": ..., "1": ... }. Two shapes hit that path:
|
|
5
|
+
*
|
|
6
|
+
* - an array nested directly inside another array, e.g. the
|
|
7
|
+
* [facetKey, value] filter tuples of a telemetry saved view;
|
|
8
|
+
* - a top-level array handed to LocalStorage/SessionStorage/Cookie, which
|
|
9
|
+
* call serializeValue on the value itself rather than on a wrapper object.
|
|
10
|
+
*
|
|
11
|
+
* (An array under an object key was always safe, at any depth, because
|
|
12
|
+
* serialize() special-cases array-valued keys.)
|
|
13
|
+
*
|
|
14
|
+
* The serializer is fixed, but values written before the fix are still in
|
|
15
|
+
* databases and in browser storage. readLegacySerializedArray reads either
|
|
16
|
+
* shape, so those values load instead of being thrown away — or, worse,
|
|
17
|
+
* destructured and taking the page down with them.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export function readLegacySerializedArray(
|
|
21
|
+
value: unknown,
|
|
22
|
+
): Array<unknown> | null {
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!value || typeof value !== "object") {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const record: Record<string, unknown> = value as Record<string, unknown>;
|
|
32
|
+
const keys: Array<string> = Object.keys(record);
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* An empty object is what an empty array serialized to, and in every place
|
|
36
|
+
* this is used an empty collection is the sensible reading.
|
|
37
|
+
*/
|
|
38
|
+
if (keys.length === 0) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
* Only a complete run of indices 0..n-1 could have come from an array. A
|
|
44
|
+
* genuine object that merely happens to have a "0" key keeps its own shape
|
|
45
|
+
* and is rejected here.
|
|
46
|
+
*/
|
|
47
|
+
for (let index: number = 0; index < keys.length; index++) {
|
|
48
|
+
if (!Object.prototype.hasOwnProperty.call(record, String(index))) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const restored: Array<unknown> = [];
|
|
54
|
+
|
|
55
|
+
for (let index: number = 0; index < keys.length; index++) {
|
|
56
|
+
restored.push(record[String(index)]);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return restored;
|
|
60
|
+
}
|