@oneuptime/common 11.7.2 → 11.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/KubernetesCostAllocation.ts +103 -0
- package/Models/DatabaseModels/AlertEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/AlertStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
- package/Models/DatabaseModels/Index.ts +5 -0
- package/Models/DatabaseModels/LogDropFilter.ts +89 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +13 -3
- package/Models/DatabaseModels/RecommendationDismissal.ts +463 -0
- package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
- package/Models/DatabaseModels/StatusPageGroup.ts +95 -0
- package/Models/DatabaseModels/TableView.ts +40 -0
- package/Models/DatabaseModels/TraceDropFilter.ts +89 -0
- package/Models/DatabaseModels/WorkflowVariable.ts +5 -1
- package/Server/API/AlertAPI.ts +32 -17
- package/Server/API/BaseAPI.ts +31 -2
- package/Server/API/BaseAnalyticsAPI.ts +36 -2
- package/Server/API/CommonAPI.ts +57 -0
- package/Server/API/IncidentAPI.ts +60 -33
- package/Server/API/IncidentEpisodeAPI.ts +31 -16
- package/Server/API/MonitorAPI.ts +30 -0
- package/Server/API/MonitorTemplateAPI.ts +8 -0
- package/Server/API/ProbeAPI.ts +196 -15
- package/Server/API/ProjectAPI.ts +79 -1
- package/Server/API/ScheduledMaintenanceAPI.ts +33 -18
- package/Server/API/StatusPageAPI.ts +74 -37
- package/Server/API/WorkspaceNotificationRuleAPI.ts +34 -4
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.ts +13 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.ts +527 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.ts +55 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.ts +53 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Services/AlertEpisodeService.ts +47 -0
- package/Server/Services/AlertService.ts +125 -0
- package/Server/Services/BillingService.ts +98 -0
- package/Server/Services/DatabaseService.ts +184 -20
- package/Server/Services/IncidentEpisodeService.ts +47 -0
- package/Server/Services/IncidentService.ts +123 -0
- package/Server/Services/IncidentTemplateService.ts +123 -1
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/LogDropFilterService.ts +133 -0
- package/Server/Services/MonitorProbeService.ts +94 -4
- package/Server/Services/MonitorService.ts +48 -43
- package/Server/Services/NetworkDeviceDiscoveryScanService.ts +70 -0
- package/Server/Services/ProbeService.ts +66 -0
- package/Server/Services/ProjectService.ts +131 -7
- package/Server/Services/RecommendationDismissalService.ts +52 -0
- package/Server/Services/RunbookAgentJobService.ts +68 -7
- package/Server/Services/ScheduledMaintenanceService.ts +103 -0
- package/Server/Services/ScheduledMaintenanceTemplateService.ts +90 -0
- package/Server/Services/StatusPageGroupService.ts +186 -0
- package/Server/Services/TraceDropFilterService.ts +133 -0
- package/Server/Types/Workflow/Components/API/Delete.ts +12 -0
- package/Server/Types/Workflow/Components/API/Get.ts +12 -0
- package/Server/Types/Workflow/Components/API/Patch.ts +12 -0
- package/Server/Types/Workflow/Components/API/Post.ts +12 -0
- package/Server/Types/Workflow/Components/API/Put.ts +13 -0
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +212 -0
- package/Server/Utils/DropFilterValidation.ts +127 -0
- package/Server/Utils/Errors.ts +5 -0
- package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
- package/Server/Utils/Monitor/MonitorIncident.ts +31 -2
- package/Server/Utils/Telemetry/AppMetrics.ts +31 -0
- package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +16 -0
- package/Tests/Models/DatabaseModels/MonitorProbeColumnAccessControl.test.ts +196 -0
- package/Tests/Models/RecommendationDismissalModel.test.ts +269 -0
- package/Tests/Server/API/BaseAPIUpdatePayloadValidation.test.ts +320 -0
- package/Tests/Server/API/BaseAnalyticsAPIUpdatePayloadValidation.test.ts +293 -0
- package/Tests/Server/API/CommonAPIAuthGuard.test.ts +164 -0
- package/Tests/Server/API/ProbeAPI.test.ts +422 -53
- package/Tests/Server/API/ProjectAPI.test.ts +180 -0
- package/Tests/Server/API/ProjectAPIExtendTrialBillingDisabled.test.ts +138 -0
- package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +458 -0
- package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +359 -0
- package/Tests/Server/Infrastructure/ProcessSignalDelivery.test.ts +427 -0
- package/Tests/Server/Services/BillingServiceExtendTrial.test.ts +439 -0
- package/Tests/Server/Services/CrossProjectReferenceWriteGuard.test.ts +810 -0
- package/Tests/Server/Services/DatabaseServiceAtomicAddToColumns.test.ts +269 -0
- package/Tests/Server/Services/DatabaseServiceEmptyUpdate.test.ts +277 -0
- package/Tests/Server/Services/DatabaseServiceSortColumnSelect.test.ts +201 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +81 -23
- package/Tests/Server/Services/DropFilterSaveValidation.test.ts +398 -0
- package/Tests/Server/Services/MonitorProbeDeleteHooks.test.ts +280 -0
- package/Tests/Server/Services/MonitorProbeServiceProbeTenancy.test.ts +304 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +262 -0
- package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +614 -0
- package/Tests/Server/Services/RecommendationDismissalService.test.ts +306 -0
- package/Tests/Server/Services/RepairCrossProjectIncidentReferencesMigration.test.ts +528 -0
- package/Tests/Server/Services/StatusPageGroupNesting.test.ts +395 -0
- package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +26 -21
- package/Tests/Server/Types/Database/Permissions/WorkflowVariableColumnPermission.test.ts +227 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +285 -0
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +463 -0
- package/Tests/Server/Utils/DropFilterValidation.test.ts +269 -0
- package/Tests/Server/Utils/Telemetry/SpanUtil.test.ts +94 -0
- package/Tests/Types/DateUserTimezone.test.ts +52 -0
- package/Tests/Types/JSONFunctions.test.ts +103 -1
- package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +177 -9
- package/Tests/Types/Monitor/MonitorStepDnsMonitor.test.ts +105 -0
- package/Tests/Types/Monitor/MonitorStepDnssecMonitor.test.ts +131 -0
- package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +60 -0
- package/Tests/Types/Monitor/MonitorStepExternalStatusPageMonitor.test.ts +82 -0
- package/Tests/Types/Monitor/MonitorStepInfrastructureMonitors.test.ts +268 -0
- package/Tests/Types/Monitor/MonitorStepMetricMonitor.test.ts +386 -0
- package/Tests/Types/Monitor/MonitorStepProfileMonitor.test.ts +185 -0
- package/Tests/Types/Monitor/MonitorStepSnmpMonitor.test.ts +156 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +371 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +901 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +607 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +754 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +960 -0
- package/Tests/Types/RollingTime/RollingTimeUtil.test.ts +186 -0
- package/Tests/Types/Runbook/RunbookStepTimeout.test.ts +410 -0
- package/Tests/Types/Telemetry/DropFilterSampling.test.ts +241 -0
- package/Tests/Types/Workspace/NotificationRuleConditionUtil.test.ts +353 -0
- package/Tests/Types/Workspace/NotificationRuleUtil.test.ts +566 -0
- package/Tests/UI/Components/CodeEditor.test.tsx +174 -0
- package/Tests/UI/Components/ErrorBoundary.test.tsx +555 -24
- package/Tests/UI/Components/InfoCard.test.tsx +358 -0
- package/Tests/UI/Components/LogTimeRangePicker.test.tsx +138 -0
- package/Tests/UI/Components/Modal.test.tsx +43 -5
- package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +679 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +397 -0
- package/Tests/UI/Components/ModelTable/ColumnCustomizationModal.test.tsx +999 -0
- package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +1678 -0
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1094 -0
- package/Tests/UI/Components/Runbook/StepTimeoutInput.test.tsx +386 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +671 -0
- package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +404 -0
- package/Tests/UI/Utils/DropdownAlignment.test.ts +306 -0
- package/Tests/UI/Utils/TableFilterUrlState.test.ts +292 -0
- package/Tests/Utils/Monitor/MonitorSummaryProbeUtil.test.ts +263 -0
- package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +583 -0
- package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +1072 -0
- package/Tests/Utils/StatusPage/GroupTree.test.ts +583 -0
- package/Tests/Utils/StatusPage/ResourceUptime.test.ts +411 -0
- package/Tests/Utils/UserPreferences.test.ts +563 -0
- package/Types/Date.ts +15 -6
- package/Types/JSONFunctions.ts +7 -2
- package/Types/Kubernetes/KubernetesCostIngest.ts +37 -1
- package/Types/Monitor/KubernetesAlertTemplates.ts +205 -0
- package/Types/Monitor/MonitorStep.ts +10 -1
- package/Types/Monitor/MonitorStepMetricMonitor.ts +46 -1
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +413 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +168 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +175 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +743 -0
- package/Types/Permission.ts +45 -0
- package/Types/Recommendation/RecommendationType.ts +20 -0
- package/Types/Runbook/RunbookExecutionDeadline.ts +129 -0
- package/Types/Runbook/RunbookStepTimeout.ts +202 -0
- package/Types/Telemetry/DropFilterSampling.ts +92 -0
- package/UI/Components/AI/GenerateFromAIModal.tsx +0 -2
- package/UI/Components/Accordion/Accordion.tsx +10 -2
- package/UI/Components/BulkUpdate/BulkLabelActions.tsx +0 -1
- package/UI/Components/CodeEditor/CodeEditor.tsx +34 -20
- package/UI/Components/Date/RangeStartAndEndDateView.tsx +0 -1
- package/UI/Components/EditionLabel/EditionLabel.tsx +1 -27
- package/UI/Components/Error/PageError.tsx +0 -4
- package/UI/Components/ErrorBoundary.tsx +252 -15
- package/UI/Components/InfoCard/InfoCard.tsx +58 -1
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +34 -1
- package/UI/Components/MasterPage/MasterPage.tsx +65 -0
- package/UI/Components/Modal/Modal.tsx +16 -60
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +0 -8
- package/UI/Components/ModelTable/BaseModelTable.tsx +503 -71
- package/UI/Components/ModelTable/Column.ts +17 -0
- package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +523 -0
- package/UI/Components/ModelTable/ColumnPreference.ts +482 -0
- package/UI/Components/ModelTable/CustomFieldColumns.tsx +326 -0
- package/UI/Components/ModelTable/TableView.tsx +24 -2
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +150 -0
- package/UI/Components/Runbook/StepTimeoutInput.tsx +173 -0
- package/UI/Components/SideMenu/SideMenu.tsx +24 -4
- package/UI/Components/StatusPage/ResourceGroupSection.tsx +231 -0
- package/UI/Components/Table/Table.tsx +14 -1
- package/UI/Components/Table/TableRow.tsx +180 -175
- package/UI/Components/Table/Types/Column.ts +2 -0
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +34 -1
- package/UI/Utils/DropdownAlignment.ts +162 -0
- package/UI/Utils/TableFilterUrlState.ts +59 -20
- package/Utils/API.ts +106 -2
- package/Utils/Monitor/MonitorSummaryProbeUtil.ts +130 -0
- package/Utils/NetworkDiscovery/ScanTargetUtil.ts +434 -0
- package/Utils/StatusPage/GroupNestingLayout.ts +343 -0
- package/Utils/StatusPage/GroupTree.ts +307 -0
- package/Utils/StatusPage/ResourceUptime.ts +90 -17
- package/Utils/UserPreferences.ts +53 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +86 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/AlertStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogDropFilter.js +91 -0
- package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +14 -4
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RecommendationDismissal.js +484 -0
- package/build/dist/Models/DatabaseModels/RecommendationDismissal.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageGroup.js +94 -0
- package/build/dist/Models/DatabaseModels/StatusPageGroup.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TableView.js +40 -0
- package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js +91 -0
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js +5 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
- package/build/dist/Server/API/AlertAPI.js +22 -13
- package/build/dist/Server/API/AlertAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +22 -1
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAnalyticsAPI.js +24 -1
- package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
- package/build/dist/Server/API/CommonAPI.js +42 -0
- package/build/dist/Server/API/CommonAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +43 -26
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js +21 -12
- package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
- package/build/dist/Server/API/MonitorAPI.js +23 -0
- package/build/dist/Server/API/MonitorAPI.js.map +1 -1
- package/build/dist/Server/API/MonitorTemplateAPI.js +4 -0
- package/build/dist/Server/API/MonitorTemplateAPI.js.map +1 -1
- package/build/dist/Server/API/ProbeAPI.js +131 -15
- package/build/dist/Server/API/ProbeAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectAPI.js +62 -3
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js +23 -14
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +61 -33
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js +26 -2
- package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js +397 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.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/Services/AlertEpisodeService.js +39 -0
- package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +95 -0
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +71 -0
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +140 -17
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +39 -0
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +100 -0
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +97 -0
- package/build/dist/Server/Services/IncidentTemplateService.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/LogDropFilterService.js +93 -0
- package/build/dist/Server/Services/LogDropFilterService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +73 -5
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +34 -39
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +71 -0
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
- package/build/dist/Server/Services/ProbeService.js +64 -0
- package/build/dist/Server/Services/ProbeService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +103 -7
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RecommendationDismissalService.js +50 -0
- package/build/dist/Server/Services/RecommendationDismissalService.js.map +1 -0
- package/build/dist/Server/Services/RunbookAgentJobService.js +63 -5
- package/build/dist/Server/Services/RunbookAgentJobService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +83 -0
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +65 -0
- package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageGroupService.js +136 -0
- package/build/dist/Server/Services/StatusPageGroupService.js.map +1 -1
- package/build/dist/Server/Services/TraceDropFilterService.js +93 -0
- package/build/dist/Server/Services/TraceDropFilterService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js +12 -0
- package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +132 -0
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -0
- package/build/dist/Server/Utils/DropFilterValidation.js +80 -0
- package/build/dist/Server/Utils/DropFilterValidation.js.map +1 -0
- package/build/dist/Server/Utils/Errors.js +3 -0
- package/build/dist/Server/Utils/Errors.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +30 -12
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +38 -18
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/AppMetrics.js +26 -0
- package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
- package/build/dist/Types/Date.js +14 -4
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/JSONFunctions.js +8 -3
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +192 -0
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +6 -1
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js +32 -1
- package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +294 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +110 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +58 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +451 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -0
- package/build/dist/Types/Permission.js +40 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Recommendation/RecommendationType.js +21 -0
- package/build/dist/Types/Recommendation/RecommendationType.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookExecutionDeadline.js +93 -0
- package/build/dist/Types/Runbook/RunbookExecutionDeadline.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookStepTimeout.js +142 -0
- package/build/dist/Types/Runbook/RunbookStepTimeout.js.map +1 -0
- package/build/dist/Types/Telemetry/DropFilterSampling.js +75 -0
- package/build/dist/Types/Telemetry/DropFilterSampling.js.map +1 -0
- package/build/dist/UI/Components/AI/GenerateFromAIModal.js +1 -2
- package/build/dist/UI/Components/AI/GenerateFromAIModal.js.map +1 -1
- package/build/dist/UI/Components/Accordion/Accordion.js +9 -2
- package/build/dist/UI/Components/Accordion/Accordion.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +27 -14
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js +1 -1
- package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +2 -20
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Error/PageError.js +1 -3
- package/build/dist/UI/Components/Error/PageError.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +145 -11
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js +28 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +13 -2
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.js +50 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +4 -32
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +308 -40
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +230 -0
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js +258 -0
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +168 -0
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/TableView.js +13 -2
- package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +84 -0
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -0
- package/build/dist/UI/Components/Runbook/StepTimeoutInput.js +101 -0
- package/build/dist/UI/Components/Runbook/StepTimeoutInput.js.map +1 -0
- package/build/dist/UI/Components/SideMenu/SideMenu.js +15 -5
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js +73 -0
- package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +15 -2
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +11 -6
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +13 -2
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Utils/DropdownAlignment.js +98 -0
- package/build/dist/UI/Utils/DropdownAlignment.js.map +1 -0
- package/build/dist/UI/Utils/TableFilterUrlState.js +48 -15
- package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
- package/build/dist/Utils/API.js +39 -2
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js +97 -0
- package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +330 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -0
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js +280 -0
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -0
- package/build/dist/Utils/StatusPage/GroupTree.js +214 -0
- package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -0
- package/build/dist/Utils/StatusPage/ResourceUptime.js +60 -16
- package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
- package/build/dist/Utils/UserPreferences.js +33 -0
- package/build/dist/Utils/UserPreferences.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import StatusPageGroup from "../../Models/DatabaseModels/StatusPageGroup";
|
|
2
|
+
import StatusPageResource from "../../Models/DatabaseModels/StatusPageResource";
|
|
3
|
+
import StatusPageGroupViewMode from "../../Types/StatusPage/StatusPageGroupViewMode";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* Status page groups nest (Corporate Unit -> Region -> Market -> Site) and the
|
|
7
|
+
* overview page draws that nesting.
|
|
8
|
+
*
|
|
9
|
+
* Drawing each level as a card inside a card inside a card is what it used to
|
|
10
|
+
* do, and it does not survive contact with a real hierarchy: four borders end
|
|
11
|
+
* up wrapped around one uptime bar, every level eats horizontal room the bars
|
|
12
|
+
* need, and a leaf resource ends up rendered larger than the group that
|
|
13
|
+
* contains it. Below the top level a group is therefore drawn as a row hanging
|
|
14
|
+
* off a tree rail - one hairline down the left, one indent step, no extra card.
|
|
15
|
+
*
|
|
16
|
+
* The numbers live here rather than inline in the page because they are the
|
|
17
|
+
* part that has to hold at depth 1 and still hold at depth 12, and that is
|
|
18
|
+
* worth pinning down in tests.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/* What a group header shows on its right hand side, if anything. */
|
|
22
|
+
export enum StatusPageGroupRollupKind {
|
|
23
|
+
UptimePercent = "UptimePercent",
|
|
24
|
+
CurrentStatus = "CurrentStatus",
|
|
25
|
+
None = "None",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default class StatusPageGroupNestingLayoutUtil {
|
|
29
|
+
/*
|
|
30
|
+
* Beyond this depth the indent step shrinks instead of growing. Nesting is
|
|
31
|
+
* capped on write at StatusPageGroupTreeUtil.MaxNestingDepth, but rows
|
|
32
|
+
* written straight to the database are not, so the layout is not allowed to
|
|
33
|
+
* assume any particular ceiling.
|
|
34
|
+
*/
|
|
35
|
+
public static readonly MaxIndentedDepth: number = 4;
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* A depth that is not a whole number >= 0 is treated as the top level. The
|
|
39
|
+
* page derives depth from a recursive render, but nothing stops a caller (or
|
|
40
|
+
* a future refactor) from handing over -1 or NaN, and a broken indent is not
|
|
41
|
+
* worth a broken page.
|
|
42
|
+
*/
|
|
43
|
+
public static getVisualDepth(data: { depth: number }): number {
|
|
44
|
+
if (!Number.isFinite(data.depth)) {
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const depth: number = Math.floor(data.depth);
|
|
49
|
+
|
|
50
|
+
if (depth <= 0) {
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return Math.min(depth, this.MaxIndentedDepth);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public static isRootLevel(data: { depth: number }): boolean {
|
|
58
|
+
return this.getVisualDepth({ depth: data.depth }) === 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/*
|
|
62
|
+
* Nesting is expressed with the rail, so the title only ever steps down once
|
|
63
|
+
* - and never below the size a resource name renders at. That inversion, a
|
|
64
|
+
* text-sm group heading over a text-lg resource, is what made the old nesting
|
|
65
|
+
* read upside down.
|
|
66
|
+
*/
|
|
67
|
+
/*
|
|
68
|
+
* Truncates at every width, including on a phone. Wrapping was tried and is
|
|
69
|
+
* worse: the title is the only shrinkable item in the header row, so next to a
|
|
70
|
+
* sub group badge and a rollup it collapses to a ~30px column and breaks a
|
|
71
|
+
* name one character per line. An ellipsis with the full name in `title` is the
|
|
72
|
+
* lesser evil.
|
|
73
|
+
*/
|
|
74
|
+
public static getTitleClassName(data: { depth: number }): string {
|
|
75
|
+
const base: string = "min-w-0 truncate font-semibold text-gray-900";
|
|
76
|
+
|
|
77
|
+
if (this.isRootLevel(data)) {
|
|
78
|
+
return `${base} text-base sm:text-lg tracking-tight`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return `${base} text-base tracking-tight`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/*
|
|
85
|
+
* A resource name, as rendered by MonitorOverview. It lives here so the floor
|
|
86
|
+
* a group title has to clear is the same string the resource actually renders
|
|
87
|
+
* with, rather than a number written down next to it.
|
|
88
|
+
*/
|
|
89
|
+
public static getResourceTitleClassName(): string {
|
|
90
|
+
return "text-base font-medium";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* The chevron box and the gap after it are what set where a title starts, and
|
|
95
|
+
* a sub group's contents and a group description are both aligned to that. All
|
|
96
|
+
* three are derived from these two, so moving the chevron moves them with it.
|
|
97
|
+
*/
|
|
98
|
+
public static getChevronBoxClassName(): string {
|
|
99
|
+
return "flex-shrink-0 flex items-center justify-center w-6 h-6 rounded-md transition-colors";
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public static getHeaderRowClassName(): string {
|
|
103
|
+
return "flex min-w-0 flex-1 items-center gap-2.5";
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* A nested group is not a card. It is a block in the parent's body, so all it
|
|
108
|
+
* gets is the vertical rhythm that separates it from its siblings.
|
|
109
|
+
*/
|
|
110
|
+
public static getContainerClassName(data: { depth: number }): string {
|
|
111
|
+
if (this.isRootLevel(data)) {
|
|
112
|
+
return "bg-white rounded-xl shadow px-4 py-3 sm:px-6 sm:py-4";
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return "";
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/*
|
|
119
|
+
* Resources that belong to no group at all get their own card at the top of
|
|
120
|
+
* the page. It is the same surface as a top level group, minus the header.
|
|
121
|
+
*/
|
|
122
|
+
public static getUngroupedResourcesCardClassName(): string {
|
|
123
|
+
return "bg-white rounded-xl shadow px-4 py-4 sm:px-6 sm:py-5";
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Vertical rhythm between the resources of one group. */
|
|
127
|
+
public static getResourceListClassName(): string {
|
|
128
|
+
return "space-y-4 sm:space-y-5";
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
* Quieter than the per-resource labels it replaces. It is a scale, not a
|
|
133
|
+
* reading, and it is what made a nested block look shouty when it appeared
|
|
134
|
+
* three times in one screen.
|
|
135
|
+
*/
|
|
136
|
+
public static getTimeAxisClassName(): string {
|
|
137
|
+
return "flex justify-between text-[11px] text-gray-400";
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/*
|
|
141
|
+
* The rolled up reading on the right of a group header. Sized to match the
|
|
142
|
+
* per-resource readings below it: a rollup and a resource reading are the same
|
|
143
|
+
* kind of number, and the status dot is what tells them apart.
|
|
144
|
+
*/
|
|
145
|
+
public static getRollupClassName(): string {
|
|
146
|
+
return "flex-shrink-0 text-sm sm:text-base font-medium";
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public static getHeaderClassName(data: { depth: number }): string {
|
|
150
|
+
/*
|
|
151
|
+
* The whole row is the disclosure control, so it carries the hover state.
|
|
152
|
+
* Negative horizontal margin with matching padding lets that hover reach the
|
|
153
|
+
* edge of the content column while the row's contents stay aligned with the
|
|
154
|
+
* resources below it.
|
|
155
|
+
*
|
|
156
|
+
* The width has to pay for both margins explicitly. A button shrink wraps
|
|
157
|
+
* even as a flex container, so it needs a width; but `w-full` with both
|
|
158
|
+
* negative margins over-constrains the box, and the browser resolves that by
|
|
159
|
+
* dropping margin-right (CSS 2.1 10.3.3) - which leaves every rollup 16px
|
|
160
|
+
* short of the card edge the resource readings below it sit on. 100% + 1rem
|
|
161
|
+
* satisfies the equation exactly, so nothing is dropped.
|
|
162
|
+
*/
|
|
163
|
+
const base: string =
|
|
164
|
+
"flex w-[calc(100%+1rem)] items-center justify-between gap-3 text-left rounded-lg -mx-2 px-2 transition-colors hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-300";
|
|
165
|
+
|
|
166
|
+
return this.isRootLevel(data) ? `${base} py-2` : `${base} py-1.5`;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/*
|
|
170
|
+
* The rail and the indent that carry one nesting step.
|
|
171
|
+
*
|
|
172
|
+
* `ml` moves the rail under its parent's chevron and `pl` pushes the contents
|
|
173
|
+
* clear of it, so the two together land a sub group's contents at the parent's
|
|
174
|
+
* title. Past MaxIndentedDepth the step tightens rather than stops: the rails
|
|
175
|
+
* have to stay distinguishable, but a deep tree still has to leave room for
|
|
176
|
+
* the uptime bars on a phone.
|
|
177
|
+
*/
|
|
178
|
+
private static getIndentClassName(data: { depth: number }): string {
|
|
179
|
+
const visualDepth: number = this.getVisualDepth(data);
|
|
180
|
+
|
|
181
|
+
if (visualDepth === 0) {
|
|
182
|
+
return "";
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (visualDepth < this.MaxIndentedDepth) {
|
|
186
|
+
return "ml-2.5 sm:ml-3 pl-4 sm:pl-5";
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return "ml-1.5 pl-3";
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/*
|
|
193
|
+
* Everything a group contains - its own resources and then its sub groups -
|
|
194
|
+
* lives in one body so a single rail covers all of it.
|
|
195
|
+
*/
|
|
196
|
+
public static getBodyClassName(data: { depth: number }): string {
|
|
197
|
+
if (this.isRootLevel(data)) {
|
|
198
|
+
// The card's own padding is the boundary at the top level; no rail.
|
|
199
|
+
return "mt-3 space-y-4";
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return `mt-2.5 space-y-3.5 border-l border-gray-200 ${this.getIndentClassName(
|
|
203
|
+
data,
|
|
204
|
+
)}`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public static showRail(data: { depth: number }): boolean {
|
|
208
|
+
return !this.isRootLevel(data);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public static getSubGroupListClassName(data: { depth: number }): string {
|
|
212
|
+
return this.isRootLevel(data) ? "space-y-3" : "space-y-2.5";
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/*
|
|
216
|
+
* A group with resources of its own *and* sub groups needs a line between the
|
|
217
|
+
* two, otherwise its last resource reads as belonging to the first sub group.
|
|
218
|
+
*/
|
|
219
|
+
public static shouldShowSubGroupDivider(data: {
|
|
220
|
+
hasOwnResources: boolean;
|
|
221
|
+
subGroupCount: number;
|
|
222
|
+
}): boolean {
|
|
223
|
+
return data.hasOwnResources && data.subGroupCount > 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public static getSubGroupDividerClassName(): string {
|
|
227
|
+
return "border-t border-gray-100 pt-3.5";
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/*
|
|
231
|
+
* The group description hangs under the title, indented past the chevron so
|
|
232
|
+
* it lines up with the name rather than with the disclosure control. It sits
|
|
233
|
+
* outside the header button on purpose: a description is markdown and may
|
|
234
|
+
* contain links, which cannot live inside a button.
|
|
235
|
+
*
|
|
236
|
+
* The indent is 34px: the 24px chevron box (w-6, see getChevronBoxClassName)
|
|
237
|
+
* plus the 10px gap after it (gap-2.5, see getHeaderRowClassName).
|
|
238
|
+
*
|
|
239
|
+
* Alignment only. Type and vertical rhythm are MarkdownViewer's - it sets
|
|
240
|
+
* them on the paragraph it renders, which beats anything inherited from here,
|
|
241
|
+
* so declaring a size or a colour on this wrapper would just be a comment that
|
|
242
|
+
* looks like code.
|
|
243
|
+
*/
|
|
244
|
+
public static getDescriptionClassName(): string {
|
|
245
|
+
return "pl-[34px] pr-2";
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
public static getSubGroupCountBadgeClassName(): string {
|
|
249
|
+
return "flex-shrink-0 inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-[11px] font-medium text-gray-500 tabular-nums";
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* The status dot that marks a reading as a rollup rather than a resource's own. */
|
|
253
|
+
public static getRollupDotClassName(): string {
|
|
254
|
+
return "h-1.5 w-1.5 flex-shrink-0 rounded-full";
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
public static getRollupLabelClassName(): string {
|
|
258
|
+
return "font-semibold tabular-nums";
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/*
|
|
262
|
+
* A group that only exists to hold sub groups has no resources of its own,
|
|
263
|
+
* and telling the visitor it is empty would be wrong - the sub groups below
|
|
264
|
+
* it are its content. A group with neither still renders its (empty) resource
|
|
265
|
+
* list, because that is where the "no resources" message belongs.
|
|
266
|
+
*/
|
|
267
|
+
public static shouldRenderOwnResources(data: {
|
|
268
|
+
ownResourceCount: number;
|
|
269
|
+
subGroupCount: number;
|
|
270
|
+
}): boolean {
|
|
271
|
+
return data.ownResourceCount > 0 || data.subGroupCount === 0;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/*
|
|
275
|
+
* Whether a group draws the time axis under its own resource list.
|
|
276
|
+
*
|
|
277
|
+
* Once per resource list rather than once per resource: every bar in one list
|
|
278
|
+
* is drawn over the same window and sits in the same column, so one axis
|
|
279
|
+
* describes all of them. It deliberately does not cover sub groups - their
|
|
280
|
+
* bars are indented past this one, and they may be collapsed, so an axis up
|
|
281
|
+
* here would be labelling a column that is not there.
|
|
282
|
+
*
|
|
283
|
+
* A group in grid view draws a matrix of cells instead of bars, so its
|
|
284
|
+
* resources are not something a time axis describes.
|
|
285
|
+
*/
|
|
286
|
+
public static shouldRenderTimeAxis(data: {
|
|
287
|
+
statusPageGroup: StatusPageGroup | null;
|
|
288
|
+
statusPageResources: Array<StatusPageResource>;
|
|
289
|
+
}): boolean {
|
|
290
|
+
if (data.statusPageGroup?.viewMode === StatusPageGroupViewMode.Grid) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const groupId: string | null =
|
|
295
|
+
data.statusPageGroup?._id?.toString() || null;
|
|
296
|
+
|
|
297
|
+
return (
|
|
298
|
+
data.statusPageResources.find((resource: StatusPageResource) => {
|
|
299
|
+
if (!resource.showStatusHistoryChart) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/*
|
|
304
|
+
* Skipped for the same reason the page skips them - a resource that
|
|
305
|
+
* resolves to neither a monitor nor a monitor group draws nothing.
|
|
306
|
+
*/
|
|
307
|
+
if (!resource.monitor && !resource.monitorGroupId) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const resourceGroupId: string | null =
|
|
312
|
+
resource.statusPageGroupId?.toString() || null;
|
|
313
|
+
|
|
314
|
+
return resourceGroupId === groupId;
|
|
315
|
+
}) !== undefined
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/*
|
|
320
|
+
* Which rolled up reading a group header shows.
|
|
321
|
+
*
|
|
322
|
+
* A group that is currently down shows its status rather than an uptime
|
|
323
|
+
* percent - "99.9% uptime" next to a red group is not the thing a visitor came
|
|
324
|
+
* to read - and a group whose uptime cannot be worked out (no resources under
|
|
325
|
+
* it at all) shows nothing rather than a zero.
|
|
326
|
+
*/
|
|
327
|
+
public static getRollupKind(data: {
|
|
328
|
+
showUptimePercent: boolean;
|
|
329
|
+
showCurrentStatus: boolean;
|
|
330
|
+
isCurrentlyDown: boolean;
|
|
331
|
+
uptimePercent: number | null;
|
|
332
|
+
}): StatusPageGroupRollupKind {
|
|
333
|
+
if (data.showUptimePercent && !data.isCurrentlyDown) {
|
|
334
|
+
return data.uptimePercent === null
|
|
335
|
+
? StatusPageGroupRollupKind.None
|
|
336
|
+
: StatusPageGroupRollupKind.UptimePercent;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return data.showCurrentStatus
|
|
340
|
+
? StatusPageGroupRollupKind.CurrentStatus
|
|
341
|
+
: StatusPageGroupRollupKind.None;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import StatusPageGroup from "../../Models/DatabaseModels/StatusPageGroup";
|
|
2
|
+
|
|
3
|
+
export interface StatusPageGroupTreeNode {
|
|
4
|
+
group: StatusPageGroup;
|
|
5
|
+
depth: number;
|
|
6
|
+
children: Array<StatusPageGroupTreeNode>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* Status page groups form a tree: a group may be nested under another group
|
|
11
|
+
* (Corporate Unit -> Region -> Market -> Site), and each level rolls up the
|
|
12
|
+
* status and uptime of everything below it.
|
|
13
|
+
*
|
|
14
|
+
* Everything here is defensive about the shape of the data it is handed. The
|
|
15
|
+
* parent pointer lives in a plain nullable column, so rows written directly to
|
|
16
|
+
* the database (or a group whose parent the caller did not fetch) can point at
|
|
17
|
+
* a missing parent, at themselves, or around a cycle. None of those may make a
|
|
18
|
+
* group disappear from the status page or hang the render, so every walk is
|
|
19
|
+
* bounded by a visited set and every group ends up in the tree exactly once.
|
|
20
|
+
*/
|
|
21
|
+
export default class StatusPageGroupTreeUtil {
|
|
22
|
+
/*
|
|
23
|
+
* How deep a group may be nested. Enforced on write (see
|
|
24
|
+
* StatusPageGroupService) - reads never drop levels beyond it, they only
|
|
25
|
+
* refuse to loop.
|
|
26
|
+
*/
|
|
27
|
+
public static readonly MaxNestingDepth: number = 10;
|
|
28
|
+
|
|
29
|
+
public static getParentId(statusPageGroup: StatusPageGroup): string | null {
|
|
30
|
+
const parentId: string | null =
|
|
31
|
+
statusPageGroup.parentStatusPageGroupId?.toString() || null;
|
|
32
|
+
|
|
33
|
+
if (!parentId) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// a group that points at itself is a root, not an infinite loop.
|
|
38
|
+
if (parentId === statusPageGroup._id?.toString()) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return parentId;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public static getChildGroups(data: {
|
|
46
|
+
statusPageGroupId: string | null;
|
|
47
|
+
statusPageGroups: Array<StatusPageGroup>;
|
|
48
|
+
}): Array<StatusPageGroup> {
|
|
49
|
+
const children: Array<StatusPageGroup> = data.statusPageGroups.filter(
|
|
50
|
+
(group: StatusPageGroup) => {
|
|
51
|
+
return this.getParentId(group) === data.statusPageGroupId;
|
|
52
|
+
},
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return this.sortByOrder(children);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
* Top level groups: no parent, or a parent that is not part of the supplied
|
|
60
|
+
* list (an orphan still has to render somewhere).
|
|
61
|
+
*/
|
|
62
|
+
public static getRootGroups(data: {
|
|
63
|
+
statusPageGroups: Array<StatusPageGroup>;
|
|
64
|
+
}): Array<StatusPageGroup> {
|
|
65
|
+
const idsInList: Set<string> = this.getIdSet(data.statusPageGroups);
|
|
66
|
+
|
|
67
|
+
const roots: Array<StatusPageGroup> = data.statusPageGroups.filter(
|
|
68
|
+
(group: StatusPageGroup) => {
|
|
69
|
+
const parentId: string | null = this.getParentId(group);
|
|
70
|
+
return !parentId || !idsInList.has(parentId);
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return this.sortByOrder(roots);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/*
|
|
78
|
+
* The full tree, in render order. Every supplied group appears exactly once:
|
|
79
|
+
* orphans are promoted to roots, and groups that are only reachable through a
|
|
80
|
+
* cycle are promoted too (rather than being silently dropped).
|
|
81
|
+
*/
|
|
82
|
+
public static buildTree(data: {
|
|
83
|
+
statusPageGroups: Array<StatusPageGroup>;
|
|
84
|
+
}): Array<StatusPageGroupTreeNode> {
|
|
85
|
+
const visited: Set<string> = new Set<string>();
|
|
86
|
+
|
|
87
|
+
const buildNode: (
|
|
88
|
+
group: StatusPageGroup,
|
|
89
|
+
depth: number,
|
|
90
|
+
) => StatusPageGroupTreeNode = (
|
|
91
|
+
group: StatusPageGroup,
|
|
92
|
+
depth: number,
|
|
93
|
+
): StatusPageGroupTreeNode => {
|
|
94
|
+
const groupId: string = group._id?.toString() || "";
|
|
95
|
+
visited.add(groupId);
|
|
96
|
+
|
|
97
|
+
const children: Array<StatusPageGroupTreeNode> = this.getChildGroups({
|
|
98
|
+
statusPageGroupId: groupId,
|
|
99
|
+
statusPageGroups: data.statusPageGroups,
|
|
100
|
+
})
|
|
101
|
+
.filter((child: StatusPageGroup) => {
|
|
102
|
+
return !visited.has(child._id?.toString() || "");
|
|
103
|
+
})
|
|
104
|
+
.map((child: StatusPageGroup) => {
|
|
105
|
+
return buildNode(child, depth + 1);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
group: group,
|
|
110
|
+
depth: depth,
|
|
111
|
+
children: children,
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const tree: Array<StatusPageGroupTreeNode> = this.getRootGroups({
|
|
116
|
+
statusPageGroups: data.statusPageGroups,
|
|
117
|
+
}).map((root: StatusPageGroup) => {
|
|
118
|
+
return buildNode(root, 0);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
/*
|
|
122
|
+
* Anything left unvisited is inside a cycle that no root points into. Pull
|
|
123
|
+
* each one up to the top level so the page still shows it.
|
|
124
|
+
*/
|
|
125
|
+
for (const group of this.sortByOrder(data.statusPageGroups)) {
|
|
126
|
+
if (!visited.has(group._id?.toString() || "")) {
|
|
127
|
+
tree.push(buildNode(group, 0));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return tree;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/*
|
|
135
|
+
* Every group below this one, at any depth. Excludes the group itself.
|
|
136
|
+
*/
|
|
137
|
+
public static getDescendantGroups(data: {
|
|
138
|
+
statusPageGroup: StatusPageGroup;
|
|
139
|
+
statusPageGroups: Array<StatusPageGroup>;
|
|
140
|
+
}): Array<StatusPageGroup> {
|
|
141
|
+
const descendants: Array<StatusPageGroup> = [];
|
|
142
|
+
const visited: Set<string> = new Set<string>([
|
|
143
|
+
data.statusPageGroup._id?.toString() || "",
|
|
144
|
+
]);
|
|
145
|
+
|
|
146
|
+
let frontier: Array<StatusPageGroup> = this.getChildGroups({
|
|
147
|
+
statusPageGroupId: data.statusPageGroup._id?.toString() || "",
|
|
148
|
+
statusPageGroups: data.statusPageGroups,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
while (frontier.length > 0) {
|
|
152
|
+
const nextFrontier: Array<StatusPageGroup> = [];
|
|
153
|
+
|
|
154
|
+
for (const group of frontier) {
|
|
155
|
+
const groupId: string = group._id?.toString() || "";
|
|
156
|
+
|
|
157
|
+
if (visited.has(groupId)) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
visited.add(groupId);
|
|
162
|
+
descendants.push(group);
|
|
163
|
+
|
|
164
|
+
nextFrontier.push(
|
|
165
|
+
...this.getChildGroups({
|
|
166
|
+
statusPageGroupId: groupId,
|
|
167
|
+
statusPageGroups: data.statusPageGroups,
|
|
168
|
+
}),
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
frontier = nextFrontier;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return descendants;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/*
|
|
179
|
+
* The group itself followed by all of its descendants - the set of groups a
|
|
180
|
+
* rolled up number has to cover.
|
|
181
|
+
*/
|
|
182
|
+
public static getGroupAndDescendants(data: {
|
|
183
|
+
statusPageGroup: StatusPageGroup;
|
|
184
|
+
statusPageGroups: Array<StatusPageGroup>;
|
|
185
|
+
}): Array<StatusPageGroup> {
|
|
186
|
+
return [
|
|
187
|
+
data.statusPageGroup,
|
|
188
|
+
...this.getDescendantGroups({
|
|
189
|
+
statusPageGroup: data.statusPageGroup,
|
|
190
|
+
statusPageGroups: data.statusPageGroups,
|
|
191
|
+
}),
|
|
192
|
+
];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/*
|
|
196
|
+
* Ancestors, closest parent first. Stops at a cycle instead of looping.
|
|
197
|
+
*/
|
|
198
|
+
public static getAncestorGroups(data: {
|
|
199
|
+
statusPageGroup: StatusPageGroup;
|
|
200
|
+
statusPageGroups: Array<StatusPageGroup>;
|
|
201
|
+
}): Array<StatusPageGroup> {
|
|
202
|
+
const byId: Map<string, StatusPageGroup> = this.getGroupsById(
|
|
203
|
+
data.statusPageGroups,
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
const ancestors: Array<StatusPageGroup> = [];
|
|
207
|
+
const visited: Set<string> = new Set<string>([
|
|
208
|
+
data.statusPageGroup._id?.toString() || "",
|
|
209
|
+
]);
|
|
210
|
+
|
|
211
|
+
let parentId: string | null = this.getParentId(data.statusPageGroup);
|
|
212
|
+
|
|
213
|
+
while (parentId && !visited.has(parentId)) {
|
|
214
|
+
const parent: StatusPageGroup | undefined = byId.get(parentId);
|
|
215
|
+
|
|
216
|
+
if (!parent) {
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
ancestors.push(parent);
|
|
221
|
+
visited.add(parentId);
|
|
222
|
+
parentId = this.getParentId(parent);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return ancestors;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/*
|
|
229
|
+
* 0 for a top level group, 1 for its children, and so on.
|
|
230
|
+
*/
|
|
231
|
+
public static getDepth(data: {
|
|
232
|
+
statusPageGroup: StatusPageGroup;
|
|
233
|
+
statusPageGroups: Array<StatusPageGroup>;
|
|
234
|
+
}): number {
|
|
235
|
+
return this.getAncestorGroups({
|
|
236
|
+
statusPageGroup: data.statusPageGroup,
|
|
237
|
+
statusPageGroups: data.statusPageGroups,
|
|
238
|
+
}).length;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
public static isDescendantOf(data: {
|
|
242
|
+
statusPageGroup: StatusPageGroup;
|
|
243
|
+
possibleAncestorId: string;
|
|
244
|
+
statusPageGroups: Array<StatusPageGroup>;
|
|
245
|
+
}): boolean {
|
|
246
|
+
return this.getAncestorGroups({
|
|
247
|
+
statusPageGroup: data.statusPageGroup,
|
|
248
|
+
statusPageGroups: data.statusPageGroups,
|
|
249
|
+
}).some((ancestor: StatusPageGroup) => {
|
|
250
|
+
return ancestor._id?.toString() === data.possibleAncestorId;
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private static getGroupsById(
|
|
255
|
+
statusPageGroups: Array<StatusPageGroup>,
|
|
256
|
+
): Map<string, StatusPageGroup> {
|
|
257
|
+
const byId: Map<string, StatusPageGroup> = new Map<
|
|
258
|
+
string,
|
|
259
|
+
StatusPageGroup
|
|
260
|
+
>();
|
|
261
|
+
|
|
262
|
+
for (const group of statusPageGroups) {
|
|
263
|
+
const groupId: string | undefined = group._id?.toString();
|
|
264
|
+
|
|
265
|
+
if (groupId) {
|
|
266
|
+
byId.set(groupId, group);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return byId;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private static getIdSet(
|
|
274
|
+
statusPageGroups: Array<StatusPageGroup>,
|
|
275
|
+
): Set<string> {
|
|
276
|
+
const ids: Set<string> = new Set<string>();
|
|
277
|
+
|
|
278
|
+
for (const group of statusPageGroups) {
|
|
279
|
+
const groupId: string | undefined = group._id?.toString();
|
|
280
|
+
|
|
281
|
+
if (groupId) {
|
|
282
|
+
ids.add(groupId);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return ids;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/*
|
|
290
|
+
* Siblings render in `order`. Groups without an order keep their incoming
|
|
291
|
+
* position, after the ordered ones.
|
|
292
|
+
*/
|
|
293
|
+
private static sortByOrder(
|
|
294
|
+
statusPageGroups: Array<StatusPageGroup>,
|
|
295
|
+
): Array<StatusPageGroup> {
|
|
296
|
+
return [...statusPageGroups].sort(
|
|
297
|
+
(a: StatusPageGroup, b: StatusPageGroup) => {
|
|
298
|
+
const orderA: number =
|
|
299
|
+
typeof a.order === "number" ? a.order : Number.MAX_SAFE_INTEGER;
|
|
300
|
+
const orderB: number =
|
|
301
|
+
typeof b.order === "number" ? b.order : Number.MAX_SAFE_INTEGER;
|
|
302
|
+
|
|
303
|
+
return orderA - orderB;
|
|
304
|
+
},
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
}
|