@oneuptime/common 13.0.8 → 14.0.1
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/AuditLog.ts +23 -15
- package/Models/DatabaseModels/GlobalConfig.ts +24 -0
- package/Models/DatabaseModels/Index.ts +4 -0
- package/Models/DatabaseModels/Monitor.ts +3 -2
- package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
- package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +2 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.ts +522 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +38 -4
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.ts +603 -0
- package/Scripts/generate-service-worker.js +65 -4
- package/Server/API/BaseAPI.ts +26 -5
- package/Server/API/GlobalConfigAPI.ts +228 -462
- package/Server/API/ProjectOIDC.ts +25 -16
- package/Server/API/ProjectSSO.ts +24 -16
- package/Server/API/StatusPageAPI.ts +100 -42
- package/Server/API/TeamMemberAPI.ts +10 -1
- package/Server/Enterprise/EnterpriseEdition.ts +649 -0
- package/Server/Enterprise/EnterpriseFeature.ts +48 -0
- package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
- package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
- package/Server/EnvironmentConfig.ts +147 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.ts +248 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/UserAuthorization.ts +38 -16
- package/Server/Services/AuditLogService.ts +84 -1079
- package/Server/Services/DatabaseService.ts +10 -0
- package/Server/Services/EnterpriseLicenseService.ts +38 -0
- package/Server/Services/GlobalConfigService.ts +80 -1
- package/Server/Services/Index.ts +4 -0
- package/Server/Services/MonitorProbeService.ts +116 -20
- package/Server/Services/MonitorService.ts +59 -6
- package/Server/Services/MonitorStatusTimelineService.ts +284 -0
- package/Server/Services/MonitorTemplateService.ts +26 -0
- package/Server/Services/ProjectService.ts +284 -0
- package/Server/Services/RumSessionPinService.ts +25 -6
- package/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.ts +385 -0
- package/Server/Services/ServiceLevelObjectiveLabelRuleService.ts +51 -0
- package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +92 -16
- package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +36 -1
- package/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.ts +521 -0
- package/Server/Services/ServiceLevelObjectiveOwnerRuleService.ts +51 -0
- package/Server/Services/ServiceLevelObjectiveService.ts +28 -0
- package/Server/Services/StatusPagePrivateUserService.ts +7 -3
- package/Server/Services/StatusPageService.ts +78 -1
- package/Server/Services/TeamMemberService.ts +11 -0
- package/Server/Services/TeamService.ts +10 -0
- package/Server/Services/UserService.ts +10 -17
- package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
- package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
- package/Server/Types/Database/Permissions/TablePermission.ts +10 -3
- package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
- package/Server/Types/Markdown.ts +41 -0
- package/Server/Types/Workflow/Components/Telegram/SendMessageToChat.ts +27 -1
- package/Server/Utils/AI/Toolbox/SloTools.ts +1 -0
- package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
- package/Server/Utils/EditionEnforcement.ts +233 -0
- package/Server/Utils/FrontendEnvironment.ts +41 -2
- package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
- package/Server/Utils/Monitor/AffectedResourceList.ts +148 -0
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +1 -1
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +1 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +720 -465
- package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
- package/Server/Utils/Monitor/RootCauseList.ts +139 -0
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +28 -0
- package/Server/Utils/Slo/SloRulePatternValidator.ts +42 -0
- package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
- package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
- package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
- package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
- package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
- package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
- package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
- package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
- package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
- package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
- package/Tests/App/Dashboard/FeedFilterSortIntegration.test.tsx +1632 -0
- package/Tests/App/Dashboard/FeedOptionsLocales.test.ts +250 -0
- package/Tests/App/Dashboard/FeedOrdering.test.ts +279 -9
- package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +60 -1
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +594 -3
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +646 -0
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +612 -2
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +30 -0
- package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +1202 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +52 -1
- package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +45 -9
- package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
- package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
- package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -83
- package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
- package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
- package/Tests/App/Dashboard/SloFeed.test.tsx +106 -1
- package/Tests/App/Dashboard/SloMonitorRuleCriteria.test.tsx +566 -0
- package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +6 -4
- package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +186 -0
- package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +388 -44
- package/Tests/App/Dashboard/SloOverviewLayout.test.tsx +613 -0
- package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
- package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
- package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
- package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +0 -8
- package/Tests/Models/DatabaseModels/SloLabelAndOwnerRuleModels.test.ts +404 -0
- package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +17 -1
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
- package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
- package/Tests/Server/API/GlobalConfigLicense.test.ts +742 -497
- package/Tests/Server/API/OnCallReadinessAPI.test.ts +35 -909
- package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
- package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
- package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
- package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
- package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
- package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
- package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
- package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
- package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
- package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
- package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
- package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
- package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddSloLabelAndOwnerRulesMigration.test.ts +407 -0
- package/Tests/Server/Infrastructure/Postgres/AddSloMonitorRuleMonitorTypeMigration.test.ts +171 -0
- package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +88 -4
- package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
- package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
- package/Tests/Server/Services/AuditLogService.test.ts +460 -990
- package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
- package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +104 -0
- package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
- package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
- package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
- package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
- package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
- package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
- package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +48 -1
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -0
- package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
- package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +1170 -0
- package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleServices.test.ts +172 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +323 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +115 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleTriggers.test.ts +21 -2
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorTypePostgres.test.ts +480 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +162 -0
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +45 -6
- package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
- package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
- package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
- package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +745 -0
- package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
- package/Tests/Server/Types/Markdown.test.ts +183 -1
- package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +49 -0
- package/Tests/Server/Types/Workflow/Components/TelegramSendMessageToChat.test.ts +331 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +10 -0
- package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
- package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
- package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
- package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
- package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +1 -1
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +1339 -96
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +1101 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +106 -80
- package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
- package/Tests/Server/Utils/Monitor/RootCauseList.test.ts +252 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +154 -0
- package/Tests/Server/Utils/SSRFProtection.test.ts +111 -0
- package/Tests/Server/Utils/Slo/SloRulePatternValidator.test.ts +67 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +213 -0
- package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
- package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
- package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
- package/Tests/Types/API/Route.test.ts +56 -0
- package/Tests/Types/API/URLSchemeLikePath.test.ts +304 -0
- package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
- package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
- package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
- package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +84 -178
- package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
- package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
- package/Tests/UI/Components/FeedOptions.test.ts +1404 -0
- package/Tests/UI/Components/FeedOptionsButton.test.tsx +2603 -0
- package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
- package/Tests/UI/Components/Icon.test.tsx +26 -0
- package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
- package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
- package/Tests/UI/Components/useFeedItemsViewKey.test.tsx +1017 -0
- package/Tests/UI/Components/useFeedOptions.test.tsx +1107 -0
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
- package/Tests/Utils/HostAddressUtil.test.ts +138 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +102 -0
- package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
- package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
- package/Tests/Utils/Slo/SloDuration.test.ts +115 -24
- package/Tests/Utils/Slo/SloHealth.test.ts +93 -10
- package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +109 -0
- package/Tests/Utils/Slo/SloOverviewText.test.ts +64 -0
- package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
- package/Types/API/Hostname.ts +63 -16
- package/Types/API/Route.ts +19 -2
- package/Types/API/URL.ts +26 -2
- package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
- package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
- package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
- package/Types/Database/CanonicalModelInstance.ts +102 -0
- package/Types/Database/TableColumn.ts +20 -6
- package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
- package/Types/IP/IPv6.ts +6 -1
- package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +6 -5
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +9 -0
- package/Types/Monitor/MonitorStep.ts +6 -1
- package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
- package/Types/Permission.ts +90 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +11 -0
- package/Types/Rules/RuleRun.ts +4 -0
- package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
- package/UI/Components/EditionLabel/EditionLabel.tsx +796 -1195
- package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
- package/UI/Components/Feed/FeedOptions.ts +427 -0
- package/UI/Components/Feed/FeedOptionsButton.tsx +692 -0
- package/UI/Components/Feed/useFeedItems.ts +28 -9
- package/UI/Components/Feed/useFeedOptions.ts +225 -0
- package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
- package/UI/Components/Icon/Icon.tsx +1 -1
- package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
- package/UI/Components/ModelList/ModelList.tsx +11 -1
- package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
- package/UI/esbuild-enterprise.js +263 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
- package/Utils/HostAddressUtil.ts +94 -0
- package/Utils/LabelRuleImportExport.ts +27 -9
- package/Utils/Monitor/MetricValueFormatter.ts +2 -2
- package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
- package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
- package/Utils/Rules/MonitorTypeRuleCriteria.ts +31 -0
- package/Utils/Slo/SloDuration.ts +22 -6
- package/Utils/Slo/SloHealth.ts +8 -7
- package/Utils/Slo/SloMonitorRuleCriteria.ts +33 -1
- package/Utils/Slo/SloOverviewText.ts +33 -0
- package/Utils/Slo/SloProjection.ts +4 -3
- package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
- package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
- package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +4 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +2 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js +530 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +39 -4
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js +612 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js.map +1 -0
- package/build/dist/Server/API/BaseAPI.js +26 -5
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +148 -344
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectOIDC.js +24 -16
- package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
- package/build/dist/Server/API/ProjectSSO.js +24 -16
- package/build/dist/Server/API/ProjectSSO.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +93 -43
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/TeamMemberAPI.js +8 -1
- package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
- package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
- package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
- package/build/dist/Server/EnvironmentConfig.js +84 -2
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js +93 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.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/Middleware/UserAuthorization.js +30 -11
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AuditLogService.js +71 -740
- package/build/dist/Server/Services/AuditLogService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +7 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/GlobalConfigService.js +63 -0
- package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +4 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +90 -17
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +48 -6
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +214 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RumSessionPinService.js +24 -6
- package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js +295 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js +56 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +59 -14
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +22 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js +400 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js +56 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +21 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +71 -0
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +10 -0
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TeamService.js +9 -0
- package/build/dist/Server/Services/TeamService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +10 -16
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js +10 -3
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +31 -0
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js +20 -1
- package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
- package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
- package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
- package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
- package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
- package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
- package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +67 -0
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +585 -367
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
- package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/RootCauseList.js +101 -0
- package/build/dist/Server/Utils/Monitor/RootCauseList.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +28 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js +28 -0
- package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Types/API/Hostname.js +59 -11
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/API/Route.js +18 -2
- package/build/dist/Types/API/Route.js.map +1 -1
- package/build/dist/Types/API/URL.js +23 -2
- package/build/dist/Types/API/URL.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
- package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
- package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
- package/build/dist/Types/Database/TableColumn.js +19 -6
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
- package/build/dist/Types/IP/IPv6.js +6 -1
- package/build/dist/Types/IP/IPv6.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +5 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
- package/build/dist/Types/Permission.js +84 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +11 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -1
- package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
- package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +414 -585
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
- package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
- package/build/dist/UI/Components/Feed/FeedOptions.js +235 -0
- package/build/dist/UI/Components/Feed/FeedOptions.js.map +1 -0
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js +346 -0
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -0
- package/build/dist/UI/Components/Feed/useFeedItems.js +17 -7
- package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -1
- package/build/dist/UI/Components/Feed/useFeedOptions.js +130 -0
- package/build/dist/UI/Components/Feed/useFeedOptions.js.map +1 -0
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +1 -1
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
- package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
- package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
- package/build/dist/Utils/HostAddressUtil.js +80 -0
- package/build/dist/Utils/HostAddressUtil.js.map +1 -0
- package/build/dist/Utils/LabelRuleImportExport.js +22 -6
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/Monitor/MetricValueFormatter.js +2 -2
- package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
- package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
- package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
- package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js +18 -0
- package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js.map +1 -0
- package/build/dist/Utils/Slo/SloDuration.js +13 -5
- package/build/dist/Utils/Slo/SloDuration.js.map +1 -1
- package/build/dist/Utils/Slo/SloHealth.js +8 -7
- package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +16 -1
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -1
- package/build/dist/Utils/Slo/SloOverviewText.js +16 -0
- package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -1
- package/build/dist/Utils/Slo/SloProjection.js.map +1 -1
- package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
- package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
- package/jest.config.json +3 -1
- package/package.json +1 -1
- package/test-setup.sh +103 -34
- package/tsconfig.json +13 -0
- package/Server/API/EnterpriseLicenseAPI.ts +0 -925
- package/Server/API/TeamComplianceAPI.ts +0 -158
- package/Server/Middleware/SCIMAuthorization.ts +0 -141
- package/Server/Services/TeamComplianceService.ts +0 -733
- package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
- package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
- package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
- package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
- package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +0 -761
- package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
- package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
- package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +0 -321
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
- package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
- package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
- package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
- package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
- package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
- package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
- package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
- package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
- package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
- package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
- package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
- package/build/dist/Server/Services/TeamComplianceService.js +0 -537
- package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
- package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
- package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
- package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
- package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
|
@@ -25,6 +25,14 @@ export interface FeedPage<TFeedModel> {
|
|
|
25
25
|
|
|
26
26
|
export interface UseFeedItemsProps<TFeedModel> {
|
|
27
27
|
resourceKey: string;
|
|
28
|
+
/*
|
|
29
|
+
* What the reader has chosen to see of this resource's feed - its sort
|
|
30
|
+
* order and event type filter (see useFeedOptions). A change re-reads the
|
|
31
|
+
* feed from its first window, exactly like moving to another resource:
|
|
32
|
+
* rows already loaded were read for the old view, so keeping them, or the
|
|
33
|
+
* size of the window they filled, would mix two different feeds.
|
|
34
|
+
*/
|
|
35
|
+
viewKey?: string | undefined;
|
|
28
36
|
refreshToken?: number | undefined;
|
|
29
37
|
getItems: (limit: number) => Promise<FeedPage<TFeedModel>>;
|
|
30
38
|
mapItems: (items: Array<TFeedModel>) => Array<FeedItemProps>;
|
|
@@ -50,7 +58,8 @@ interface FetchOptions {
|
|
|
50
58
|
|
|
51
59
|
/*
|
|
52
60
|
* Every dashboard activity feed follows the same paging contract: read the
|
|
53
|
-
*
|
|
61
|
+
* first N rows in the reader's chosen order (newest first unless they asked
|
|
62
|
+
* for oldest first) and replace that window when the reader asks for more.
|
|
54
63
|
* Re-reading from zero matters for a live feed. Offset-appending can duplicate
|
|
55
64
|
* or skip a row when a new event arrives between page requests.
|
|
56
65
|
*/
|
|
@@ -71,10 +80,20 @@ const useFeedItems: <TFeedModel>(
|
|
|
71
80
|
null,
|
|
72
81
|
);
|
|
73
82
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
/*
|
|
84
|
+
* The resource and the view together name the feed being shown. Everything
|
|
85
|
+
* below that guards against a stale response or resets the window keys on
|
|
86
|
+
* this, so a response for the previous view is dropped the same way as a
|
|
87
|
+
* response for the previous resource.
|
|
88
|
+
*/
|
|
89
|
+
const feedKey: string =
|
|
90
|
+
props.viewKey === undefined
|
|
91
|
+
? props.resourceKey
|
|
92
|
+
: `${props.resourceKey}\u0000${props.viewKey}`;
|
|
93
|
+
|
|
94
|
+
const activeResourceKeyRef: MutableRefObject<string> =
|
|
95
|
+
useRef<string>(feedKey);
|
|
96
|
+
activeResourceKeyRef.current = feedKey;
|
|
78
97
|
const previousResourceKeyRef: MutableRefObject<string | null> = useRef<
|
|
79
98
|
string | null
|
|
80
99
|
>(null);
|
|
@@ -184,8 +203,8 @@ const useFeedItems: <TFeedModel>(
|
|
|
184
203
|
|
|
185
204
|
useEffect(() => {
|
|
186
205
|
const hasResourceChanged: boolean =
|
|
187
|
-
previousResourceKeyRef.current !==
|
|
188
|
-
previousResourceKeyRef.current =
|
|
206
|
+
previousResourceKeyRef.current !== feedKey;
|
|
207
|
+
previousResourceKeyRef.current = feedKey;
|
|
189
208
|
|
|
190
209
|
if (hasResourceChanged) {
|
|
191
210
|
currentLimitRef.current = DEFAULT_LIMIT;
|
|
@@ -200,7 +219,7 @@ const useFeedItems: <TFeedModel>(
|
|
|
200
219
|
}).catch(() => {
|
|
201
220
|
// fetchItems converts request failures into the appropriate UI state.
|
|
202
221
|
});
|
|
203
|
-
}, [fetchItems,
|
|
222
|
+
}, [fetchItems, feedKey, props.refreshToken]);
|
|
204
223
|
|
|
205
224
|
useEffect(() => {
|
|
206
225
|
return () => {
|
|
@@ -208,7 +227,7 @@ const useFeedItems: <TFeedModel>(
|
|
|
208
227
|
};
|
|
209
228
|
}, []);
|
|
210
229
|
|
|
211
|
-
const isCurrentFeedLoaded: boolean = loadedResourceKey ===
|
|
230
|
+
const isCurrentFeedLoaded: boolean = loadedResourceKey === feedKey;
|
|
212
231
|
|
|
213
232
|
return {
|
|
214
233
|
feedItems,
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MutableRefObject,
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from "react";
|
|
9
|
+
import SortOrder from "../../../Types/BaseDatabase/SortOrder";
|
|
10
|
+
import LocalStorage from "../../Utils/LocalStorage";
|
|
11
|
+
import {
|
|
12
|
+
DEFAULT_FEED_SORT_ORDER,
|
|
13
|
+
FeedEventTypeOption,
|
|
14
|
+
FeedOptions,
|
|
15
|
+
GetFeedEventTypeIconFunction,
|
|
16
|
+
GetFeedEventTypeLabelFunction,
|
|
17
|
+
getFeedEventTypeOptions,
|
|
18
|
+
getFeedOptionsKey,
|
|
19
|
+
isFeedFiltered,
|
|
20
|
+
isFeedSortOrder,
|
|
21
|
+
sanitizeFeedEventTypes,
|
|
22
|
+
} from "./FeedOptions";
|
|
23
|
+
|
|
24
|
+
export interface UseFeedOptionsProps {
|
|
25
|
+
// Every event type the feed model can record, e.g. Object.values(the enum).
|
|
26
|
+
eventTypes: Array<string>;
|
|
27
|
+
getEventTypeLabel?: GetFeedEventTypeLabelFunction | undefined;
|
|
28
|
+
getEventTypeIcon?: GetFeedEventTypeIconFunction | undefined;
|
|
29
|
+
/*
|
|
30
|
+
* Names this kind of feed ("incident", "monitor", ...) so the reader's sort
|
|
31
|
+
* order is remembered across pages and visits. The event type filter is
|
|
32
|
+
* deliberately not remembered: it narrows one investigation, and a filter
|
|
33
|
+
* that silently followed the reader to the next incident would read as a
|
|
34
|
+
* feed with missing events.
|
|
35
|
+
*/
|
|
36
|
+
storageKey?: string | undefined;
|
|
37
|
+
/*
|
|
38
|
+
* The resource whose feed this is (the incident id, the cluster id, ...).
|
|
39
|
+
* The dashboard moves between resources without remounting the feed, and
|
|
40
|
+
* the event type filter belongs to the resource it was chosen on, so a new
|
|
41
|
+
* resource starts unfiltered. The sort order is a preference and stays.
|
|
42
|
+
*/
|
|
43
|
+
resetKey?: string | undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface UseFeedOptionsResult {
|
|
47
|
+
options: FeedOptions;
|
|
48
|
+
// Pass to useFeedItems as viewKey: a change re-reads the feed.
|
|
49
|
+
optionsKey: string;
|
|
50
|
+
eventTypeOptions: Array<FeedEventTypeOption>;
|
|
51
|
+
isFiltered: boolean;
|
|
52
|
+
setOptions: (options: FeedOptions) => void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const SORT_ORDER_STORAGE_KEY_PREFIX: string = "feed-sort-order:";
|
|
56
|
+
|
|
57
|
+
// One shared empty selection, so an unfiltered render keeps its identity.
|
|
58
|
+
const NO_EVENT_TYPES: Array<string> = [];
|
|
59
|
+
|
|
60
|
+
type GetSortOrderStorageKey = (storageKey: string) => string;
|
|
61
|
+
|
|
62
|
+
export const getSortOrderStorageKey: GetSortOrderStorageKey = (
|
|
63
|
+
storageKey: string,
|
|
64
|
+
): string => {
|
|
65
|
+
return `${SORT_ORDER_STORAGE_KEY_PREFIX}${storageKey}`;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
type ReadStoredSortOrder = (storageKey: string | undefined) => SortOrder;
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
* Storage can be missing, blocked or hold anything, so every read falls back
|
|
72
|
+
* to the default order.
|
|
73
|
+
*/
|
|
74
|
+
const readStoredSortOrder: ReadStoredSortOrder = (
|
|
75
|
+
storageKey: string | undefined,
|
|
76
|
+
): SortOrder => {
|
|
77
|
+
if (!storageKey) {
|
|
78
|
+
return DEFAULT_FEED_SORT_ORDER;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const storedValue: unknown = LocalStorage.getItem(
|
|
83
|
+
getSortOrderStorageKey(storageKey),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
return isFeedSortOrder(storedValue) ? storedValue : DEFAULT_FEED_SORT_ORDER;
|
|
87
|
+
} catch {
|
|
88
|
+
return DEFAULT_FEED_SORT_ORDER;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
type WriteStoredSortOrder = (
|
|
93
|
+
storageKey: string | undefined,
|
|
94
|
+
sortOrder: SortOrder,
|
|
95
|
+
) => void;
|
|
96
|
+
|
|
97
|
+
const writeStoredSortOrder: WriteStoredSortOrder = (
|
|
98
|
+
storageKey: string | undefined,
|
|
99
|
+
sortOrder: SortOrder,
|
|
100
|
+
): void => {
|
|
101
|
+
if (!storageKey) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
if (sortOrder === DEFAULT_FEED_SORT_ORDER) {
|
|
107
|
+
LocalStorage.removeItem(getSortOrderStorageKey(storageKey));
|
|
108
|
+
} else {
|
|
109
|
+
LocalStorage.setItem(getSortOrderStorageKey(storageKey), sortOrder);
|
|
110
|
+
}
|
|
111
|
+
} catch {
|
|
112
|
+
// A preference that cannot be saved still applies to this page.
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const useFeedOptions: (props: UseFeedOptionsProps) => UseFeedOptionsResult = (
|
|
117
|
+
props: UseFeedOptionsProps,
|
|
118
|
+
): UseFeedOptionsResult => {
|
|
119
|
+
/*
|
|
120
|
+
* Callers pass Object.values(SomeEnum), a new array on every render, so the
|
|
121
|
+
* list is keyed by its contents.
|
|
122
|
+
*/
|
|
123
|
+
const eventTypesKey: string = props.eventTypes.join("\u0000");
|
|
124
|
+
const knownEventTypes: Array<string> = useMemo(() => {
|
|
125
|
+
return props.eventTypes;
|
|
126
|
+
}, [eventTypesKey]);
|
|
127
|
+
|
|
128
|
+
const [sortOrder, setSortOrder] = useState<SortOrder>(() => {
|
|
129
|
+
return readStoredSortOrder(props.storageKey);
|
|
130
|
+
});
|
|
131
|
+
/*
|
|
132
|
+
* The selection remembers which resource it was made on. It is read through
|
|
133
|
+
* that, during render rather than in an effect, so the first render for a
|
|
134
|
+
* new resource is already unfiltered and never asks the API for the old
|
|
135
|
+
* resource's filter. The stale selection is also dropped (React's "adjust
|
|
136
|
+
* state when a prop changes" pattern), so going back to the first resource
|
|
137
|
+
* does not bring its old filter back either.
|
|
138
|
+
*/
|
|
139
|
+
const [selection, setSelection] = useState<{
|
|
140
|
+
resetKey: string | undefined;
|
|
141
|
+
eventTypes: Array<string>;
|
|
142
|
+
}>(() => {
|
|
143
|
+
return {
|
|
144
|
+
resetKey: props.resetKey,
|
|
145
|
+
eventTypes: [],
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
const isSelectionForThisResource: boolean =
|
|
149
|
+
selection.resetKey === props.resetKey;
|
|
150
|
+
|
|
151
|
+
if (!isSelectionForThisResource) {
|
|
152
|
+
setSelection({
|
|
153
|
+
resetKey: props.resetKey,
|
|
154
|
+
eventTypes: NO_EVENT_TYPES,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const selectedEventTypes: Array<string> = isSelectionForThisResource
|
|
159
|
+
? selection.eventTypes
|
|
160
|
+
: NO_EVENT_TYPES;
|
|
161
|
+
|
|
162
|
+
const options: FeedOptions = useMemo(() => {
|
|
163
|
+
return {
|
|
164
|
+
sortOrder,
|
|
165
|
+
eventTypes: sanitizeFeedEventTypes({
|
|
166
|
+
selectedEventTypes,
|
|
167
|
+
knownEventTypes,
|
|
168
|
+
}),
|
|
169
|
+
};
|
|
170
|
+
}, [sortOrder, selectedEventTypes, knownEventTypes]);
|
|
171
|
+
|
|
172
|
+
const eventTypeOptions: Array<FeedEventTypeOption> = useMemo(() => {
|
|
173
|
+
return getFeedEventTypeOptions({
|
|
174
|
+
eventTypes: knownEventTypes,
|
|
175
|
+
getEventTypeLabel: props.getEventTypeLabel,
|
|
176
|
+
getEventTypeIcon: props.getEventTypeIcon,
|
|
177
|
+
});
|
|
178
|
+
}, [knownEventTypes, props.getEventTypeLabel, props.getEventTypeIcon]);
|
|
179
|
+
|
|
180
|
+
const setOptions: (nextOptions: FeedOptions) => void = useCallback(
|
|
181
|
+
(nextOptions: FeedOptions): void => {
|
|
182
|
+
const nextSortOrder: SortOrder = isFeedSortOrder(nextOptions.sortOrder)
|
|
183
|
+
? nextOptions.sortOrder
|
|
184
|
+
: DEFAULT_FEED_SORT_ORDER;
|
|
185
|
+
|
|
186
|
+
setSortOrder(nextSortOrder);
|
|
187
|
+
setSelection({
|
|
188
|
+
resetKey: props.resetKey,
|
|
189
|
+
eventTypes: sanitizeFeedEventTypes({
|
|
190
|
+
selectedEventTypes: nextOptions.eventTypes,
|
|
191
|
+
knownEventTypes,
|
|
192
|
+
}),
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
[knownEventTypes, props.resetKey],
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
/*
|
|
199
|
+
* The stored order follows the committed state, not each setOptions call:
|
|
200
|
+
* two changes batched into one render would otherwise leave storage holding
|
|
201
|
+
* the first while the page shows the second. The first run is the value
|
|
202
|
+
* just read from storage, so there is nothing to write.
|
|
203
|
+
*/
|
|
204
|
+
const hasCommittedSortOrderRef: MutableRefObject<boolean> =
|
|
205
|
+
useRef<boolean>(false);
|
|
206
|
+
|
|
207
|
+
useEffect(() => {
|
|
208
|
+
if (!hasCommittedSortOrderRef.current) {
|
|
209
|
+
hasCommittedSortOrderRef.current = true;
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
writeStoredSortOrder(props.storageKey, sortOrder);
|
|
214
|
+
}, [sortOrder]);
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
options,
|
|
218
|
+
optionsKey: getFeedOptionsKey(options),
|
|
219
|
+
eventTypeOptions,
|
|
220
|
+
isFiltered: isFeedFiltered(options),
|
|
221
|
+
setOptions,
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export default useFeedOptions;
|
|
@@ -39,10 +39,52 @@ export interface UptimeBarDaySummary {
|
|
|
39
39
|
incidents: Array<UptimeBarTooltipIncident>;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/*
|
|
43
|
+
* One day's reading, measured server-side.
|
|
44
|
+
*
|
|
45
|
+
* The bars used to be derived purely from the timeline rows the browser
|
|
46
|
+
* happened to receive, and those rows arrive under a cap that silently drops
|
|
47
|
+
* history (see MonitorStatusTimelineService.getDailyUptimeAggregate). A day
|
|
48
|
+
* whose rows were dropped is indistinguishable, client-side, from a day that
|
|
49
|
+
* was genuinely quiet - so the graph painted both as the status page's
|
|
50
|
+
* `defaultBarColor`, which is GREEN on the overwhelming majority of pages.
|
|
51
|
+
* The page then asserted uptime for periods it had no data for.
|
|
52
|
+
*
|
|
53
|
+
* A reading carries how much of the day was actually COVERED by data, which
|
|
54
|
+
* is the thing the browser cannot infer for itself.
|
|
55
|
+
*/
|
|
56
|
+
export interface DayReading {
|
|
57
|
+
dayStart: Date;
|
|
58
|
+
daySeconds: number;
|
|
59
|
+
/* Zero means nothing was ever recorded for this day. */
|
|
60
|
+
coveredSeconds: number;
|
|
61
|
+
statusDurations: Array<StatusDuration>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/*
|
|
65
|
+
* A day nobody measured is not a colour the operator gets to choose.
|
|
66
|
+
*
|
|
67
|
+
* `defaultBarColor` is branding for an ordinary good day; letting it also
|
|
68
|
+
* stand for "we have no idea" is exactly the conflation that made a page with
|
|
69
|
+
* a green default claim uptime it never recorded, and a page with a grey
|
|
70
|
+
* default look unmonitored while it was passing every check. This is a fixed
|
|
71
|
+
* neutral, drawn with a hatch so it is still distinguishable in greyscale and
|
|
72
|
+
* to a colour-blind reader.
|
|
73
|
+
*/
|
|
74
|
+
export const NO_DATA_BAR_COLOR: Color = new Color("#9CA3AF");
|
|
75
|
+
|
|
42
76
|
export interface ComponentProps {
|
|
43
77
|
startDate: Date;
|
|
44
78
|
endDate: Date;
|
|
45
79
|
events: Array<Event>;
|
|
80
|
+
/*
|
|
81
|
+
* Server-measured coverage per day. When a day has a reading, it decides
|
|
82
|
+
* whether that day has data and what its durations are; the `events` array
|
|
83
|
+
* is then only used for incident overlays. When absent - the dashboard
|
|
84
|
+
* monitor page, which does not fetch the aggregate - the old event-derived
|
|
85
|
+
* behaviour applies unchanged.
|
|
86
|
+
*/
|
|
87
|
+
dayReadings?: Array<DayReading> | undefined;
|
|
46
88
|
height?: number | undefined;
|
|
47
89
|
barColorRules?: Array<BarChartRule> | undefined;
|
|
48
90
|
downtimeEventStatusIds?: Array<ObjectID> | undefined;
|
|
@@ -173,6 +215,20 @@ const DayUptimeGraph: FunctionComponent<ComponentProps> = (
|
|
|
173
215
|
const startOfTheDay: Date = OneUptimeDate.getStartOfDay(todaysDay);
|
|
174
216
|
const endOfTheDay: Date = OneUptimeDate.getEndOfDay(todaysDay);
|
|
175
217
|
|
|
218
|
+
/*
|
|
219
|
+
* The server's reading for this day, when the caller supplied one. It is
|
|
220
|
+
* matched by instant rather than by index: the window's first bucket is
|
|
221
|
+
* clipped to the window start, so bucket i is not necessarily day i.
|
|
222
|
+
*/
|
|
223
|
+
const todaysReading: DayReading | undefined = (
|
|
224
|
+
props.dayReadings || []
|
|
225
|
+
).find((reading: DayReading) => {
|
|
226
|
+
return (
|
|
227
|
+
reading.dayStart.getTime() >= startOfTheDay.getTime() &&
|
|
228
|
+
reading.dayStart.getTime() <= endOfTheDay.getTime()
|
|
229
|
+
);
|
|
230
|
+
});
|
|
231
|
+
|
|
176
232
|
const todaysEvents: Array<Event> = props.events.filter((event: Event) => {
|
|
177
233
|
let doesEventBelongsToToday: boolean = false;
|
|
178
234
|
|
|
@@ -274,32 +330,75 @@ const DayUptimeGraph: FunctionComponent<ComponentProps> = (
|
|
|
274
330
|
}
|
|
275
331
|
}
|
|
276
332
|
|
|
333
|
+
/*
|
|
334
|
+
* Does this day have data at all?
|
|
335
|
+
*
|
|
336
|
+
* With a server reading, coverage is the answer and it is authoritative -
|
|
337
|
+
* the browser cannot tell a quiet day from a day whose rows were dropped
|
|
338
|
+
* by the fetch cap. Without one, fall back to the old test.
|
|
339
|
+
*/
|
|
340
|
+
const hasDataForTheDay: boolean = todaysReading
|
|
341
|
+
? todaysReading.coveredSeconds > 0
|
|
342
|
+
: todaysEvents.length > 0;
|
|
343
|
+
|
|
277
344
|
// now check bar rules and finalize the color of the bar
|
|
278
345
|
|
|
279
|
-
|
|
280
|
-
|
|
346
|
+
/*
|
|
347
|
+
* The denominator is what was MEASURED, not the length of the day. A day
|
|
348
|
+
* only half covered - the day a monitor was created - reports the
|
|
349
|
+
* percentage of the half we watched rather than being marked down for the
|
|
350
|
+
* hours nobody was looking.
|
|
351
|
+
*
|
|
352
|
+
* The old expression ended in `: 100`, which said "no readings at all
|
|
353
|
+
* means a perfect day". That is the single line that let a status page
|
|
354
|
+
* assert uptime for a period it had no data for, so it is gone rather
|
|
355
|
+
* than adjusted: with no data there is no percentage.
|
|
356
|
+
*/
|
|
357
|
+
const uptimePercentForTheDay: number = !hasDataForTheDay
|
|
358
|
+
? 0
|
|
359
|
+
: totalUptimeInSeconds + totalDowntimeInSeconds > 0
|
|
281
360
|
? (totalUptimeInSeconds /
|
|
282
361
|
(totalDowntimeInSeconds + totalUptimeInSeconds)) *
|
|
283
362
|
100
|
|
284
363
|
: 100;
|
|
285
364
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
365
|
+
/*
|
|
366
|
+
* Rules are skipped entirely on a day with no data. Otherwise a page
|
|
367
|
+
* configuring ">= 99% is green" would have that rule matched by a day
|
|
368
|
+
* nobody measured, which is the very claim this change removes. No-data
|
|
369
|
+
* outranks operator rules on purpose.
|
|
370
|
+
*/
|
|
371
|
+
if (hasDataForTheDay) {
|
|
372
|
+
for (const rules of props.barColorRules || []) {
|
|
373
|
+
if (uptimePercentForTheDay >= rules.uptimePercentGreaterThanOrEqualTo) {
|
|
374
|
+
color = rules.barColor;
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
290
377
|
}
|
|
291
378
|
}
|
|
292
379
|
|
|
293
|
-
if (todaysEvents.length
|
|
380
|
+
if (todaysEvents.length >= 1) {
|
|
294
381
|
hasEvents = true;
|
|
295
382
|
}
|
|
296
383
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
384
|
+
/*
|
|
385
|
+
* THE FIX.
|
|
386
|
+
*
|
|
387
|
+
* This used to read: no events today, so paint `defaultBarColor`. That
|
|
388
|
+
* single line is how a status page claimed uptime for days it had no data
|
|
389
|
+
* for - `defaultBarColor` is green on the overwhelming majority of pages,
|
|
390
|
+
* and "no events" was true both for a quiet day and for a day whose rows
|
|
391
|
+
* the fetch cap had thrown away.
|
|
392
|
+
*
|
|
393
|
+
* Now the two are separated. A day with data but no events of its own is
|
|
394
|
+
* an ordinary good day and still gets the operator's colour. A day with
|
|
395
|
+
* no data gets the fixed no-data treatment and says so.
|
|
396
|
+
*/
|
|
397
|
+
hasEvents = hasDataForTheDay;
|
|
300
398
|
|
|
301
|
-
if (
|
|
302
|
-
|
|
399
|
+
if (!hasDataForTheDay) {
|
|
400
|
+
color = NO_DATA_BAR_COLOR;
|
|
401
|
+
} else if (todaysEvents.length === 0) {
|
|
303
402
|
color = props.defaultBarColor || Green;
|
|
304
403
|
}
|
|
305
404
|
|
|
@@ -315,9 +414,18 @@ const DayUptimeGraph: FunctionComponent<ComponentProps> = (
|
|
|
315
414
|
className = "w-20 h-" + props.height;
|
|
316
415
|
}
|
|
317
416
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
417
|
+
/*
|
|
418
|
+
* Build status durations for the tooltip and the day dialog.
|
|
419
|
+
*
|
|
420
|
+
* A server reading wins: its durations are measured over the whole day
|
|
421
|
+
* server-side, while `secondsOfEvent` can only describe the rows this
|
|
422
|
+
* browser happened to receive.
|
|
423
|
+
*/
|
|
424
|
+
const statusDurations: Array<StatusDuration> = todaysReading
|
|
425
|
+
? todaysReading.statusDurations
|
|
426
|
+
: [];
|
|
427
|
+
|
|
428
|
+
for (const key in todaysReading ? {} : secondsOfEvent) {
|
|
321
429
|
statusDurations.push({
|
|
322
430
|
label: eventLabels[key] || "Unknown",
|
|
323
431
|
seconds: secondsOfEvent[key] || 0,
|
|
@@ -800,7 +800,7 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
|
|
800
800
|
<path
|
|
801
801
|
strokeLinecap="round"
|
|
802
802
|
strokeLinejoin="round"
|
|
803
|
-
d="M3 4.5h14.25M3 9h9.75M3 13.
|
|
803
|
+
d="M3 4.5h14.25M3 9h9.75M3 13.5h5.25m5.25-.75L17.25 9m0 0L21 12.75M17.25 9v12"
|
|
804
804
|
/>,
|
|
805
805
|
);
|
|
806
806
|
} else if (icon === IconProp.CheckCircle) {
|
|
Binary file
|
|
@@ -37,6 +37,13 @@ export interface ComponentProps<TBaseModel extends BaseModel> {
|
|
|
37
37
|
fetchRequestOptions?: RequestOptions | undefined;
|
|
38
38
|
customElement?: ((item: TBaseModel) => ReactElement) | undefined;
|
|
39
39
|
noItemsMessage: string;
|
|
40
|
+
/*
|
|
41
|
+
* Render nothing, rather than noItemsMessage (or its "No items found."
|
|
42
|
+
* fallback), when the list loads empty. For a caller that explains an empty
|
|
43
|
+
* list itself, e.g. from onListLoaded. A search that matches nothing still
|
|
44
|
+
* says so.
|
|
45
|
+
*/
|
|
46
|
+
hideEmptyState?: boolean | undefined;
|
|
40
47
|
headerField?: string | ((item: TBaseModel) => ReactElement) | undefined;
|
|
41
48
|
onSelectChange?: ((list: Array<TBaseModel>) => void) | undefined;
|
|
42
49
|
refreshToggle?: string | undefined;
|
|
@@ -260,7 +267,10 @@ const ModelList: <TBaseModel extends BaseModel>(
|
|
|
260
267
|
{error ? <ErrorMessage message={error} /> : <></>}
|
|
261
268
|
{isLoading ? <ComponentLoader /> : <></>}
|
|
262
269
|
|
|
263
|
-
{!isLoading &&
|
|
270
|
+
{!isLoading &&
|
|
271
|
+
!error &&
|
|
272
|
+
searchedList.length === 0 &&
|
|
273
|
+
(Boolean(searchText) || !props.hideEmptyState) ? (
|
|
264
274
|
<ErrorMessage
|
|
265
275
|
message={
|
|
266
276
|
searchText
|
|
@@ -2,9 +2,16 @@ import ComponentLoader from "../ComponentLoader/ComponentLoader";
|
|
|
2
2
|
import ErrorMessage from "../ErrorMessage/ErrorMessage";
|
|
3
3
|
import DayUptimeGraph, {
|
|
4
4
|
BarChartRule,
|
|
5
|
+
DayReading,
|
|
5
6
|
Event,
|
|
6
7
|
UptimeBarDaySummary,
|
|
7
8
|
} from "../Graphs/DayUptimeGraph";
|
|
9
|
+
import { StatusDuration } from "../Graphs/UptimeDaySummary";
|
|
10
|
+
import Dictionary from "../../../Types/Dictionary";
|
|
11
|
+
import {
|
|
12
|
+
UptimeDayBucket,
|
|
13
|
+
UptimeStatusDuration,
|
|
14
|
+
} from "../../../Types/StatusPage/UptimeDailyAggregate";
|
|
8
15
|
import UptimeUtil from "./UptimeUtil";
|
|
9
16
|
import Color from "../../../Types/Color";
|
|
10
17
|
import CommonMonitorEvent from "../../../Utils/Uptime/MonitorEvent";
|
|
@@ -27,6 +34,17 @@ export interface ComponentProps {
|
|
|
27
34
|
height?: number | undefined;
|
|
28
35
|
barColorRules?: Array<StatusPageHistoryChartBarColorRule> | undefined;
|
|
29
36
|
downtimeMonitorStatuses: Array<MonitorStatus> | undefined;
|
|
37
|
+
/*
|
|
38
|
+
* Server-measured per-day coverage for THIS monitor.
|
|
39
|
+
*
|
|
40
|
+
* The `items` array above arrives under a fetch cap that silently drops
|
|
41
|
+
* history, so it cannot answer "did we have data for this day". These
|
|
42
|
+
* buckets can. When absent the graph keeps its old event-derived
|
|
43
|
+
* behaviour, which is what the dashboard monitor page still uses.
|
|
44
|
+
*/
|
|
45
|
+
uptimeBuckets?: Array<UptimeDayBucket> | undefined;
|
|
46
|
+
/* Statuses by id, so a bucket's durations can be given a name and colour. */
|
|
47
|
+
monitorStatuses?: Array<MonitorStatus> | undefined;
|
|
30
48
|
defaultBarColor: Color;
|
|
31
49
|
incidents?: Array<UptimeBarTooltipIncident> | undefined;
|
|
32
50
|
onBarClick?: (
|
|
@@ -62,6 +80,56 @@ const MonitorUptimeGraph: FunctionComponent<ComponentProps> = (
|
|
|
62
80
|
);
|
|
63
81
|
}, [props.barColorRules]);
|
|
64
82
|
|
|
83
|
+
/*
|
|
84
|
+
* Turn the server's buckets into the graph's per-day readings, resolving
|
|
85
|
+
* each status id to the name and colour the page already knows.
|
|
86
|
+
*/
|
|
87
|
+
const dayReadings: Array<DayReading> | undefined = useMemo(() => {
|
|
88
|
+
if (!props.uptimeBuckets) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const statusById: Dictionary<MonitorStatus> = {};
|
|
93
|
+
|
|
94
|
+
for (const status of props.monitorStatuses || []) {
|
|
95
|
+
if (status.id) {
|
|
96
|
+
statusById[status.id.toString()] = status;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const downtimeIds: Array<string> = (
|
|
101
|
+
props.downtimeMonitorStatuses || []
|
|
102
|
+
).map((status: MonitorStatus) => {
|
|
103
|
+
return status.id?.toString() || "";
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return props.uptimeBuckets.map((bucket: UptimeDayBucket): DayReading => {
|
|
107
|
+
return {
|
|
108
|
+
dayStart: bucket.bucketStart,
|
|
109
|
+
daySeconds: bucket.daySeconds,
|
|
110
|
+
coveredSeconds: bucket.coveredSeconds,
|
|
111
|
+
statusDurations: bucket.statusDurations.map(
|
|
112
|
+
(duration: UptimeStatusDuration): StatusDuration => {
|
|
113
|
+
const statusId: string = duration.monitorStatusId.toString();
|
|
114
|
+
const status: MonitorStatus | undefined = statusById[statusId];
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
label: status?.name || "Unknown",
|
|
118
|
+
seconds: duration.seconds,
|
|
119
|
+
color: status?.color || props.defaultBarColor,
|
|
120
|
+
isDowntime: downtimeIds.includes(statusId),
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
),
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
}, [
|
|
127
|
+
props.uptimeBuckets,
|
|
128
|
+
props.monitorStatuses,
|
|
129
|
+
props.downtimeMonitorStatuses,
|
|
130
|
+
props.defaultBarColor,
|
|
131
|
+
]);
|
|
132
|
+
|
|
65
133
|
if (props.isLoading) {
|
|
66
134
|
return <ComponentLoader />;
|
|
67
135
|
}
|
|
@@ -80,6 +148,7 @@ const MonitorUptimeGraph: FunctionComponent<ComponentProps> = (
|
|
|
80
148
|
startDate={props.startDate}
|
|
81
149
|
endDate={props.endDate}
|
|
82
150
|
events={events}
|
|
151
|
+
dayReadings={dayReadings}
|
|
83
152
|
defaultBarColor={props.defaultBarColor}
|
|
84
153
|
height={props.height}
|
|
85
154
|
barColorRules={barColorRules}
|
|
@@ -33,6 +33,18 @@ export interface TelemetryViewerProps<T> {
|
|
|
33
33
|
error?: string | undefined;
|
|
34
34
|
onRefresh?: (() => void) | undefined;
|
|
35
35
|
emptyMessage?: string | undefined;
|
|
36
|
+
/*
|
|
37
|
+
* Replaces the default "No results / try adjusting filters" block when the
|
|
38
|
+
* list comes back empty.
|
|
39
|
+
*
|
|
40
|
+
* For most signals the default is right: an empty list means the filters
|
|
41
|
+
* are too narrow. For a signal that a project may not be SENDING at all,
|
|
42
|
+
* it is usually wrong — the reader needs the setup guide, not an
|
|
43
|
+
* invitation to widen a time range over data that does not exist. Takes
|
|
44
|
+
* precedence over `emptyMessage`; nothing is rendered around it, so the
|
|
45
|
+
* caller owns the whole empty area.
|
|
46
|
+
*/
|
|
47
|
+
emptyContent?: ReactNode;
|
|
36
48
|
|
|
37
49
|
// -- Layout --
|
|
38
50
|
/** Render one item row in the main list. */
|
|
@@ -296,18 +308,22 @@ function TelemetryViewerInner<T>(props: TelemetryViewerProps<T>): ReactElement {
|
|
|
296
308
|
<ComponentLoader />
|
|
297
309
|
</div>
|
|
298
310
|
) : props.items.length === 0 ? (
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
+
props.emptyContent !== undefined ? (
|
|
312
|
+
<>{props.emptyContent}</>
|
|
313
|
+
) : (
|
|
314
|
+
<div className="flex h-48 flex-col items-center justify-center gap-2 px-6 text-center">
|
|
315
|
+
<Icon
|
|
316
|
+
icon={IconProp.Search}
|
|
317
|
+
className="h-8 w-8 text-gray-300"
|
|
318
|
+
/>
|
|
319
|
+
<p className="text-sm font-medium text-gray-500">
|
|
320
|
+
{props.emptyMessage || "No results"}
|
|
321
|
+
</p>
|
|
322
|
+
<p className="text-xs text-gray-400">
|
|
323
|
+
Try adjusting filters or time range.
|
|
324
|
+
</p>
|
|
325
|
+
</div>
|
|
326
|
+
)
|
|
311
327
|
) : (
|
|
312
328
|
<ul className="divide-y divide-gray-100">
|
|
313
329
|
{props.items.map((item: T, index: number) => {
|