@oneuptime/common 13.0.8 → 14.0.0
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/Monitor.ts +3 -2
- package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
- 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/Index.ts +2 -0
- package/Server/Middleware/UserAuthorization.ts +38 -16
- package/Server/Services/AuditLogService.ts +84 -1079
- package/Server/Services/EnterpriseLicenseService.ts +38 -0
- package/Server/Services/GlobalConfigService.ts +80 -1
- package/Server/Services/MonitorProbeService.ts +116 -20
- package/Server/Services/MonitorService.ts +56 -4
- 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/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/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 +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +543 -333
- package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -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/IdentityEnterpriseShells.test.tsx +319 -0
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
- 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/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/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/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/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/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
- 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/Permissions/EditionPermission.test.ts +1823 -0
- package/Tests/Server/Types/Markdown.test.ts +181 -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/MonitorCriteriaEvaluator.test.ts +934 -96
- package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -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/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/Graphs/DayUptimeGraph.test.tsx +49 -2
- package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
- package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
- package/Tests/Utils/HostAddressUtil.test.ts +138 -0
- package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
- package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
- package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
- package/Types/API/Hostname.ts +63 -16
- 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/MonitorStep.ts +6 -1
- package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
- 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/Graphs/DayUptimeGraph.tsx +123 -15
- 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/Monitor/MonitorDestinationUtil.ts +157 -0
- package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
- 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/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/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/Index.js +2 -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/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/MonitorProbeService.js +90 -17
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +45 -4
- 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/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/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 +96 -0
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
- 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/MonitorCriteriaEvaluator.js +449 -261
- 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/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/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/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/Graphs/DayUptimeGraph.js +90 -17
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.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/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/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
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
2
|
+
import { ComponentType, ReactElement, ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* The contract between the edition dialog (EditionLabel) and the Enterprise
|
|
6
|
+
* license management UI.
|
|
7
|
+
*
|
|
8
|
+
* EditionLabel only READS the license: it asks GET /global-config/license and
|
|
9
|
+
* shows what the answer says - the edition pill, the status, grace and trial
|
|
10
|
+
* notices, the version card. Everything that CHANGES the license lives in the
|
|
11
|
+
* Enterprise Edition (ee/AdminDashboard/License, under ee/LICENSE), because
|
|
12
|
+
* the routes it calls exist only in the Enterprise server: activating it with
|
|
13
|
+
* a key or an offline token, refreshing it from oneuptime.com, replacing it,
|
|
14
|
+
* and the seat usage and instance tables a master admin manages it by.
|
|
15
|
+
*
|
|
16
|
+
* The Dashboard and the Admin Dashboard hand that UI to EditionLabel as their
|
|
17
|
+
* LicenseManager plugin (src/Enterprise/EnterprisePlugins.ts). The Community
|
|
18
|
+
* stubs have none, and the login page passes none: there the dialog shows
|
|
19
|
+
* the license status only, and nobody is told to manage the license from it.
|
|
20
|
+
*
|
|
21
|
+
* The manager wraps the dialog rather than filling one spot inside it. Its
|
|
22
|
+
* sections land in three places in the dialog body (messages at the top, seat
|
|
23
|
+
* usage after the version card, the activation input near the bottom) and it
|
|
24
|
+
* drives the dialog's footer buttons, so EditionLabel gives it renderDialog
|
|
25
|
+
* and the manager calls it with those parts. It stays mounted while the
|
|
26
|
+
* dialog is closed, so what an admin typed and which input they chose
|
|
27
|
+
* survive closing and reopening the dialog.
|
|
28
|
+
*
|
|
29
|
+
* Types only: nothing here ships any license management code.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* How close the installation is to its licensed seats. "breached" also
|
|
34
|
+
* covers an enforced limit that is exactly full: new users are already
|
|
35
|
+
* refused there.
|
|
36
|
+
*/
|
|
37
|
+
export type SeatTone = "healthy" | "approaching" | "breached";
|
|
38
|
+
|
|
39
|
+
// What EditionLabel knows about the license, read-only.
|
|
40
|
+
export interface LicenseSnapshot {
|
|
41
|
+
/*
|
|
42
|
+
* The body of the last GET /global-config/license that succeeded, or null
|
|
43
|
+
* before the first one and after one that failed. A new object on every
|
|
44
|
+
* successful load, so a manager can tell that the license was (re)loaded.
|
|
45
|
+
*/
|
|
46
|
+
payload: JSONObject | null;
|
|
47
|
+
isLoading: boolean;
|
|
48
|
+
// Why the last load failed; "" when it did not.
|
|
49
|
+
loadError: string;
|
|
50
|
+
/*
|
|
51
|
+
* A master admin, in a dialog that has a license manager. The server
|
|
52
|
+
* accepts license writes from a master admin only, so nobody else is
|
|
53
|
+
* offered them.
|
|
54
|
+
*/
|
|
55
|
+
canManageLicense: boolean;
|
|
56
|
+
licenseValid: boolean;
|
|
57
|
+
// Enterprise Edition with no license yet, inside its first-run trial.
|
|
58
|
+
isUnlicensedTrial: boolean;
|
|
59
|
+
// A real license (not the trial) is valid and loaded: show what it covers.
|
|
60
|
+
showLicenseDetails: boolean;
|
|
61
|
+
// "" when the server did not say.
|
|
62
|
+
companyName: string;
|
|
63
|
+
// The stored license key; "" when there is none or the caller may not see it.
|
|
64
|
+
licenseKey: string;
|
|
65
|
+
userLimit: number | null;
|
|
66
|
+
// What oneuptime.com last counted across every instance on the license.
|
|
67
|
+
currentUserCount: number | null;
|
|
68
|
+
/*
|
|
69
|
+
* The seat figure everything is measured against: the live, enforced count
|
|
70
|
+
* when this installation enforces its seat limit, else currentUserCount.
|
|
71
|
+
*/
|
|
72
|
+
effectiveUserCount: number | null;
|
|
73
|
+
isSeatLimitEnforced: boolean;
|
|
74
|
+
canAddMoreUsers: boolean;
|
|
75
|
+
seatTone: SeatTone;
|
|
76
|
+
// The percent of licensed seats in use, as the admin reads it (may exceed 100).
|
|
77
|
+
seatUsageDisplayPercent: number | null;
|
|
78
|
+
currentVersion: string;
|
|
79
|
+
latestVersion: string;
|
|
80
|
+
// currentVersion is a real release number that can be compared.
|
|
81
|
+
hasComparableVersion: boolean;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// What a manager adds to the dialog. Every part is optional.
|
|
85
|
+
export interface LicenseManagerDialogParts {
|
|
86
|
+
// Top of the body: the outcome of the last license action.
|
|
87
|
+
messages?: ReactNode | undefined;
|
|
88
|
+
// After the version card: seat usage and the instances on the license.
|
|
89
|
+
usage?: ReactNode | undefined;
|
|
90
|
+
// Near the bottom of the body: the license key or offline token input.
|
|
91
|
+
activation?: ReactNode | undefined;
|
|
92
|
+
// The dialog's primary button, when the manager offers one.
|
|
93
|
+
submitButtonText?: string | undefined;
|
|
94
|
+
onSubmit?: (() => void) | undefined;
|
|
95
|
+
isSubmitting?: boolean | undefined;
|
|
96
|
+
disableSubmitButton?: boolean | undefined;
|
|
97
|
+
// Left of the footer: actions on a license that is already in place.
|
|
98
|
+
leftFooterElement?: ReactElement | undefined;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface LicenseManagerProps {
|
|
102
|
+
license: LicenseSnapshot;
|
|
103
|
+
isDialogOpen: boolean;
|
|
104
|
+
// Asks GET /global-config/license again; the pill and the dialog follow.
|
|
105
|
+
reloadLicense: () => Promise<void>;
|
|
106
|
+
/*
|
|
107
|
+
* Applies the seat fields (isSeatLimitEnforced, seatsInUse, canAddMoreUsers)
|
|
108
|
+
* a license write answers with, the same way the GET's are applied.
|
|
109
|
+
*/
|
|
110
|
+
applySeatEnforcement: (payload: JSONObject) => void;
|
|
111
|
+
// Renders the dialog (nothing while it is closed) with the manager's parts.
|
|
112
|
+
renderDialog: (parts: LicenseManagerDialogParts) => ReactElement;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/*
|
|
116
|
+
* Must render renderDialog's result, and must not be React.lazy: it is
|
|
117
|
+
* mounted with the edition pill on every page, and the dialog is inside it.
|
|
118
|
+
*/
|
|
119
|
+
export type LicenseManagerComponent = ComponentType<LicenseManagerProps>;
|
|
@@ -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,
|
|
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) => {
|