@oneuptime/common 11.6.1 → 11.6.2
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/Index.ts +4 -0
- package/Models/AnalyticsModels/KubernetesCostAllocation.ts +842 -0
- package/Models/AnalyticsModels/NetworkFlow.ts +54 -0
- package/Models/AnalyticsModels/SloHistory.ts +240 -0
- package/Models/DatabaseModels/Index.ts +20 -0
- package/Models/DatabaseModels/NetworkDevice.ts +453 -6
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +7 -6
- package/Models/DatabaseModels/NetworkEndpoint.ts +753 -0
- package/Models/DatabaseModels/NetworkSite.ts +1155 -0
- package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +517 -0
- package/Models/DatabaseModels/NetworkSiteLink.ts +611 -0
- package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +520 -0
- package/Models/DatabaseModels/NetworkSiteType.ts +499 -0
- package/Models/DatabaseModels/ServiceLevelObjective.ts +1106 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +762 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +444 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +443 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.ts +359 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.ts +48 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.ts +65 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.ts +88 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.ts +391 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Services/AnalyticsDatabaseService.ts +25 -9
- package/Server/Services/Index.ts +24 -0
- package/Server/Services/KubernetesCostAllocationService.ts +14 -0
- package/Server/Services/MetricService.ts +21 -2
- package/Server/Services/MonitorService.ts +22 -0
- package/Server/Services/NetworkDeviceService.ts +438 -2
- package/Server/Services/NetworkEndpointService.ts +414 -0
- package/Server/Services/NetworkSiteAssignmentRuleService.ts +98 -0
- package/Server/Services/NetworkSiteLinkService.ts +10 -0
- package/Server/Services/NetworkSiteService.ts +1254 -0
- package/Server/Services/NetworkSiteStatusTimelineService.ts +10 -0
- package/Server/Services/NetworkSiteTypeService.ts +10 -0
- package/Server/Services/ProjectService.ts +122 -2
- package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +457 -0
- package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +10 -0
- package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +10 -0
- package/Server/Services/ServiceLevelObjectiveService.ts +677 -0
- package/Server/Services/SloHistoryService.ts +101 -0
- package/Server/Services/UserNotificationSettingService.ts +37 -0
- package/Server/Types/AnalyticsDatabase/AggregateBy.ts +9 -0
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +15 -0
- package/Server/Utils/AnalyticsDatabase/Statement.ts +39 -3
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +87 -48
- package/Server/Utils/Memory.ts +9 -1
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +190 -12
- package/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
- package/Server/Utils/Monitor/DnsResolutionCache.ts +129 -0
- package/Server/Utils/Monitor/MonitorResource.ts +4 -30
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +214 -39
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +343 -0
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +251 -0
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +176 -142
- package/Server/Utils/Monitor/OuiLookupUtil.ts +49 -0
- package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +17 -13
- package/Server/Utils/WhatsAppTemplateUtil.ts +7 -3
- package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +135 -0
- package/Tests/Models/NetworkSiteHierarchy.test.ts +134 -0
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +239 -0
- package/Tests/Server/Services/KubernetesCostAllocationAggregate.test.ts +338 -0
- package/Tests/Server/Services/MetricServiceAggregate.test.ts +142 -0
- package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +484 -0
- package/Tests/Server/Services/NetworkEndpointServiceUpsert.test.ts +686 -0
- package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +185 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +1354 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +1313 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +1988 -0
- package/Tests/Server/Utils/AnalyticsDatabase/Statement.test.ts +22 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +404 -0
- package/Tests/Server/Utils/Encryption.test.ts +70 -0
- package/Tests/Server/Utils/FileAttachmentMarkdownUtil.test.ts +225 -0
- package/Tests/Server/Utils/JsonWebToken.test.ts +175 -0
- package/Tests/Server/Utils/LocalFile.test.ts +258 -0
- package/Tests/Server/Utils/Memory.test.ts +213 -0
- package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +30 -0
- package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +385 -0
- package/Tests/Server/Utils/Monitor/DnsResolutionCache.test.ts +194 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +155 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +600 -0
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +151 -124
- package/Tests/Server/Utils/Monitor/SnmpInterfaceRateUtil.test.ts +496 -0
- package/Tests/Server/Utils/MonitorCriteriaDataExtractor.test.ts +175 -0
- package/Tests/Server/Utils/MonitorCriteriaMessageFormatter.test.ts +282 -0
- package/Tests/Server/Utils/OuiLookupUtil.test.ts +59 -0
- package/Tests/Server/Utils/SeriesResourceLabels.test.ts +117 -0
- package/Tests/Server/Utils/StackTraceParser.test.ts +370 -0
- package/Tests/Server/Utils/Stream.test.ts +87 -0
- package/Tests/Server/Utils/ValidateGlobalProviderProjectTeams.test.ts +221 -0
- package/Tests/Server/Utils/WhatsAppTemplateUtil.test.ts +199 -0
- package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +33 -0
- package/Tests/Types/Email.test.ts +198 -0
- package/Tests/Types/Kubernetes/KubernetesObjectParser.test.ts +177 -0
- package/Tests/Types/Log/LogQueryToFilter.test.ts +111 -0
- package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +141 -1
- package/Tests/Types/Monitor/MonitorType.test.ts +59 -1
- package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +97 -0
- package/Tests/Types/Monitor/SnmpEndpointDiscovery.test.ts +151 -0
- package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +110 -6
- package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +129 -0
- package/Tests/Types/SerializableObjectDictionary.test.ts +166 -0
- package/Tests/Types/Time/RangeStartAndEndDateTime.test.ts +98 -0
- package/Tests/Types/WebsiteRequest.test.ts +230 -0
- package/Tests/UI/Components/EntityFilterRoundTrip.test.tsx +103 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +612 -0
- package/Tests/UI/Components/ModelTable/FilterDataToQuery.test.ts +275 -0
- package/Tests/UI/Utils/LogExport.test.ts +159 -0
- package/Tests/UI/Utils/Navigation.test.ts +183 -0
- package/Tests/UI/Utils/TableFilterUrlState.test.ts +539 -0
- package/Tests/UI/Utils/TableViewUrlState.test.ts +272 -0
- package/Tests/Utils/Base64.test.ts +51 -0
- package/Tests/Utils/Boolean.test.ts +76 -0
- package/Tests/Utils/Crypto.test.ts +48 -0
- package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +259 -0
- package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +162 -0
- package/Tests/Utils/Enum.test.ts +54 -0
- package/Tests/Utils/IpCanonicalUtil.test.ts +85 -0
- package/Tests/Utils/Metrics/MetricSeriesFingerprint.test.ts +160 -0
- package/Tests/Utils/Monitor/EndpointAttachmentUtil.test.ts +836 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +218 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +447 -0
- package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +440 -0
- package/Tests/Utils/NetworkSite/MaterializedPathUtil.test.ts +205 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +221 -0
- package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +283 -0
- package/Tests/Utils/ObjectUtil.test.ts +30 -0
- package/Tests/Utils/Slo/SloStatusColor.test.ts +89 -0
- package/Tests/Utils/Slo/SloUtil.test.ts +1980 -0
- package/Tests/Utils/Slo/SloWidgetFormat.test.ts +605 -0
- package/Tests/Utils/TechStack.test.ts +50 -0
- package/Tests/Utils/Traces/CriticalPath.test.ts +178 -0
- package/Types/AnalyticsDatabase/AnalyticsTableName.ts +10 -0
- package/Types/BaseDatabase/EqualTo.ts +9 -1
- package/Types/BaseDatabase/EqualToOrNull.ts +9 -1
- package/Types/BaseDatabase/NotEqual.ts +9 -1
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +42 -0
- package/Types/Dashboard/DashboardTemplates.ts +214 -0
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/Kubernetes/KubernetesCostIngest.ts +79 -0
- package/Types/Monitor/CriteriaFilter.ts +9 -0
- package/Types/Monitor/MonitorStep.ts +5 -8
- package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +27 -5
- package/Types/Monitor/MonitorType.ts +15 -5
- package/Types/Monitor/SnmpMonitor/ArpEntry.ts +14 -0
- package/Types/Monitor/SnmpMonitor/FdbEntry.ts +18 -0
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +10 -3
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -5
- package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +12 -0
- package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +231 -3
- package/Types/NetworkSite/DefaultNetworkSiteType.ts +20 -0
- package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
- package/Types/Permission.ts +449 -0
- package/Types/ServiceLevelObjective/SliType.ts +6 -0
- package/Types/ServiceLevelObjective/SloMultiMonitorMode.ts +6 -0
- package/Types/ServiceLevelObjective/SloStatus.ts +9 -0
- package/Types/ServiceLevelObjective/SloWindowType.ts +6 -0
- package/Types/Telemetry/ServiceType.ts +1 -0
- package/UI/Components/Filters/EntityFilter.tsx +16 -0
- package/UI/Components/Filters/FilterViewer.tsx +22 -5
- package/UI/Components/List/List.tsx +8 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +309 -106
- package/UI/Components/ModelTable/FilterDataToQuery.ts +172 -0
- package/UI/Components/Navbar/NavBar.tsx +16 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +3 -3
- package/UI/Utils/Navigation.ts +10 -0
- package/UI/Utils/TableFilterUrlState.ts +204 -17
- package/UI/Utils/TableViewUrlState.ts +165 -0
- package/Utils/Dashboard/Components/DashboardSloComponent.ts +114 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/IpCanonicalUtil.ts +134 -0
- package/Utils/Monitor/EndpointAttachmentUtil.ts +508 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +157 -5
- package/Utils/NetworkSite/CidrMatchUtil.ts +296 -0
- package/Utils/NetworkSite/MaterializedPathUtil.ts +115 -0
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +97 -0
- package/Utils/NetworkSite/SiteUptimeUtil.ts +111 -0
- package/Utils/Slo/SloStatusColor.ts +54 -0
- package/Utils/Slo/SloUtil.ts +637 -0
- package/Utils/Slo/SloWidgetFormat.ts +383 -0
- package/build/dist/Models/AnalyticsModels/Index.js +4 -0
- package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +713 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -0
- package/build/dist/Models/AnalyticsModels/NetworkFlow.js +44 -0
- package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/SloHistory.js +215 -0
- package/build/dist/Models/AnalyticsModels/SloHistory.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +20 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +458 -6
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +0 -6
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkEndpoint.js +779 -0
- package/build/dist/Models/DatabaseModels/NetworkEndpoint.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js +1180 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +534 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteLink.js +629 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteLink.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +538 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js +522 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +1124 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +769 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +460 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +459 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js +130 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js +49 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js +140 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +23 -6
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +24 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/KubernetesCostAllocationService.js +12 -0
- package/build/dist/Server/Services/KubernetesCostAllocationService.js.map +1 -0
- package/build/dist/Server/Services/MetricService.js +21 -3
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +19 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +351 -1
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkEndpointService.js +319 -0
- package/build/dist/Server/Services/NetworkEndpointService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +90 -0
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteLinkService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteLinkService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteService.js +1038 -0
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -0
- package/build/dist/Server/Services/ProjectService.js +98 -2
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +358 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +9 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +9 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +582 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -0
- package/build/dist/Server/Services/SloHistoryService.js +77 -0
- package/build/dist/Server/Services/SloHistoryService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js +20 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +15 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +31 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +76 -48
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Memory.js +9 -1
- package/build/dist/Server/Utils/Memory.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +132 -10
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
- package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js +77 -0
- package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +21 -41
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +152 -40
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +262 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +201 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +152 -120
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js +44 -0
- package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +10 -10
- package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -1
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +5 -0
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +10 -0
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
- package/build/dist/Types/BaseDatabase/EqualTo.js +9 -1
- package/build/dist/Types/BaseDatabase/EqualTo.js.map +1 -1
- package/build/dist/Types/BaseDatabase/EqualToOrNull.js +9 -1
- package/build/dist/Types/BaseDatabase/EqualToOrNull.js.map +1 -1
- package/build/dist/Types/BaseDatabase/NotEqual.js +9 -1
- package/build/dist/Types/BaseDatabase/NotEqual.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js +23 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +205 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.js +21 -0
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +5 -5
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +8 -0
- package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +15 -5
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +9 -3
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +217 -3
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js +21 -0
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
- package/build/dist/Types/Permission.js +409 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/ServiceLevelObjective/SliType.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SliType.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloStatus.js +10 -0
- package/build/dist/Types/ServiceLevelObjective/SloStatus.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloWindowType.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SloWindowType.js.map +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Filters/EntityFilter.js +15 -0
- package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/FilterViewer.js +19 -4
- package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
- package/build/dist/UI/Components/List/List.js +1 -1
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +235 -89
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js +96 -0
- package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js.map +1 -0
- package/build/dist/UI/Components/Navbar/NavBar.js +14 -2
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +3 -2
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +9 -0
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/TableFilterUrlState.js +159 -15
- package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
- package/build/dist/UI/Utils/TableViewUrlState.js +103 -0
- package/build/dist/UI/Utils/TableViewUrlState.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +93 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/IpCanonicalUtil.js +110 -0
- package/build/dist/Utils/IpCanonicalUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js +311 -0
- package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +98 -5
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +222 -0
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js +89 -0
- package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +60 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +76 -0
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -0
- package/build/dist/Utils/Slo/SloStatusColor.js +18 -0
- package/build/dist/Utils/Slo/SloStatusColor.js.map +1 -0
- package/build/dist/Utils/Slo/SloUtil.js +393 -0
- package/build/dist/Utils/Slo/SloUtil.js.map +1 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js +174 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -0
- package/package.json +2 -2
- package/Types/Dashboard/DashboardComponents/Index.ts +0 -7
- package/build/dist/Types/Dashboard/DashboardComponents/Index.js +0 -8
- package/build/dist/Types/Dashboard/DashboardComponents/Index.js.map +0 -1
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import Filter from "../ModelFilter/Filter";
|
|
2
|
+
import FilterData from "../Filters/Types/FilterData";
|
|
3
|
+
import FieldType from "../Types/FieldType";
|
|
4
|
+
import AnalyticsBaseModel from "../../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
|
|
5
|
+
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
6
|
+
import Includes from "../../../Types/BaseDatabase/Includes";
|
|
7
|
+
import InBetween from "../../../Types/BaseDatabase/InBetween";
|
|
8
|
+
import Query from "../../../Types/BaseDatabase/Query";
|
|
9
|
+
import QueryOperator from "../../../Types/BaseDatabase/QueryOperator";
|
|
10
|
+
import Search from "../../../Types/BaseDatabase/Search";
|
|
11
|
+
import Typeof from "../../../Types/Typeof";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Translate the filter popup's selections into the database query the table
|
|
15
|
+
* fetches with.
|
|
16
|
+
*
|
|
17
|
+
* Lives outside `BaseModelTable` on purpose: the table needs to derive the
|
|
18
|
+
* query *synchronously during its first render* when filters are restored from
|
|
19
|
+
* the URL (otherwise the first fetch would go out unfiltered and be
|
|
20
|
+
* immediately superseded), and a pure function is the only way to do that
|
|
21
|
+
* without an effect.
|
|
22
|
+
*/
|
|
23
|
+
export type GetFilterKeysFunction = <
|
|
24
|
+
TBaseModel extends BaseModel | AnalyticsBaseModel,
|
|
25
|
+
>(
|
|
26
|
+
filters: Array<Filter<TBaseModel>>,
|
|
27
|
+
) => Array<string>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The model fields this table actually exposes a filter for.
|
|
31
|
+
*/
|
|
32
|
+
export const getFilterKeys: GetFilterKeysFunction = <
|
|
33
|
+
TBaseModel extends BaseModel | AnalyticsBaseModel,
|
|
34
|
+
>(
|
|
35
|
+
filters: Array<Filter<TBaseModel>>,
|
|
36
|
+
): Array<string> => {
|
|
37
|
+
const keys: Array<string> = [];
|
|
38
|
+
|
|
39
|
+
for (const filter of filters || []) {
|
|
40
|
+
const key: string | undefined = filter.field
|
|
41
|
+
? Object.keys(filter.field)[0]
|
|
42
|
+
: undefined;
|
|
43
|
+
|
|
44
|
+
if (key) {
|
|
45
|
+
keys.push(key);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return keys;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type SanitizeFilterDataFunction = <
|
|
53
|
+
TBaseModel extends BaseModel | AnalyticsBaseModel,
|
|
54
|
+
>(data: {
|
|
55
|
+
filterData: FilterData<TBaseModel>;
|
|
56
|
+
filters: Array<Filter<TBaseModel>>;
|
|
57
|
+
}) => FilterData<TBaseModel>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Drop any key that this table does not expose as a filter.
|
|
61
|
+
*
|
|
62
|
+
* The filter snapshot arrives from the URL, which anyone can edit, and the
|
|
63
|
+
* result is spread into the outgoing list query *after* the caller's own
|
|
64
|
+
* scoping query. Without this, a hand-crafted link could add a constraint on a
|
|
65
|
+
* field the table never offered — or overwrite the page's own scoping (say the
|
|
66
|
+
* `projectId` on a nested list) — just by naming it in the query string.
|
|
67
|
+
*
|
|
68
|
+
* Restricting to declared filter keys keeps a shared link to exactly what the
|
|
69
|
+
* filter UI could have produced.
|
|
70
|
+
*/
|
|
71
|
+
const sanitizeFilterData: SanitizeFilterDataFunction = <
|
|
72
|
+
TBaseModel extends BaseModel | AnalyticsBaseModel,
|
|
73
|
+
>(data: {
|
|
74
|
+
filterData: FilterData<TBaseModel>;
|
|
75
|
+
filters: Array<Filter<TBaseModel>>;
|
|
76
|
+
}): FilterData<TBaseModel> => {
|
|
77
|
+
const allowedKeys: Array<string> = getFilterKeys<TBaseModel>(data.filters);
|
|
78
|
+
const sanitized: FilterData<TBaseModel> = {};
|
|
79
|
+
|
|
80
|
+
for (const key in data.filterData || {}) {
|
|
81
|
+
if (!allowedKeys.includes(key)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const value: unknown = (data.filterData as any)[key];
|
|
86
|
+
|
|
87
|
+
if (value === undefined || value === null) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
(sanitized as any)[key] = value;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return sanitized;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export { sanitizeFilterData };
|
|
98
|
+
|
|
99
|
+
export type BuildQueryFromFilterDataFunction = <
|
|
100
|
+
TBaseModel extends BaseModel | AnalyticsBaseModel,
|
|
101
|
+
>(data: {
|
|
102
|
+
filterData: FilterData<TBaseModel>;
|
|
103
|
+
filters: Array<Filter<TBaseModel>>;
|
|
104
|
+
}) => Query<TBaseModel>;
|
|
105
|
+
|
|
106
|
+
const buildQueryFromFilterData: BuildQueryFromFilterDataFunction = <
|
|
107
|
+
TBaseModel extends BaseModel | AnalyticsBaseModel,
|
|
108
|
+
>(data: {
|
|
109
|
+
filterData: FilterData<TBaseModel>;
|
|
110
|
+
filters: Array<Filter<TBaseModel>>;
|
|
111
|
+
}): Query<TBaseModel> => {
|
|
112
|
+
const filterData: FilterData<TBaseModel> = data.filterData || {};
|
|
113
|
+
const filters: Array<Filter<TBaseModel>> = data.filters || [];
|
|
114
|
+
|
|
115
|
+
const query: Query<TBaseModel> = {};
|
|
116
|
+
|
|
117
|
+
for (const key in filterData) {
|
|
118
|
+
const value: unknown = filterData[key];
|
|
119
|
+
|
|
120
|
+
if (value && typeof value === Typeof.String) {
|
|
121
|
+
query[key as keyof TBaseModel] = (value || "").toString();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (typeof value === Typeof.Boolean) {
|
|
125
|
+
query[key as keyof TBaseModel] = Boolean(value);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (typeof value === Typeof.Number) {
|
|
129
|
+
query[key as keyof TBaseModel] = value as any;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (value instanceof Date) {
|
|
133
|
+
query[key as keyof TBaseModel] = value as any;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (value instanceof Search) {
|
|
137
|
+
query[key as keyof TBaseModel] = value as any;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (value instanceof InBetween) {
|
|
141
|
+
query[key as keyof TBaseModel] = value as any;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (
|
|
145
|
+
filters.find((f: Filter<TBaseModel>) => {
|
|
146
|
+
return f.field && (f.field as any)[key];
|
|
147
|
+
})?.type === FieldType.JSON &&
|
|
148
|
+
typeof value === Typeof.Object
|
|
149
|
+
) {
|
|
150
|
+
query[key as keyof TBaseModel] = value as any;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (Array.isArray(value)) {
|
|
154
|
+
query[key as keyof TBaseModel] = new Includes(
|
|
155
|
+
value as Array<string>,
|
|
156
|
+
) as any;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/*
|
|
160
|
+
* Pass any QueryOperator instance (IncludesAll, IncludesNone, StartsWith,
|
|
161
|
+
* EndsWith, NotContains, EqualTo, NotEqual, GreaterThan, LessThan,
|
|
162
|
+
* InBetween, IsNull, NotNull, ...) through to the query as-is.
|
|
163
|
+
*/
|
|
164
|
+
if (value instanceof QueryOperator) {
|
|
165
|
+
query[key as keyof TBaseModel] = value as any;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return query;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export default buildQueryFromFilterData;
|
|
@@ -33,6 +33,21 @@ export interface MoreMenuItem {
|
|
|
33
33
|
iconColor?: string; // Tailwind color name like "blue", "purple", "amber"
|
|
34
34
|
category?: string; // Category for grouping items (e.g., "Essentials", "Observability")
|
|
35
35
|
activeRoute?: Route | undefined; // Route to check for active state
|
|
36
|
+
additionalActiveRoutes?: Array<Route> | undefined; // Extra routes that also mark this item active
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/*
|
|
40
|
+
* One menu item can own several route prefixes (e.g. a merged "Network" item
|
|
41
|
+
* spanning /network-devices and /network-sites) — check them all.
|
|
42
|
+
*/
|
|
43
|
+
export function isMoreMenuItemActive(item: MoreMenuItem): boolean {
|
|
44
|
+
const routesToCheck: Array<Route> = [
|
|
45
|
+
item.activeRoute || item.route,
|
|
46
|
+
...(item.additionalActiveRoutes || []),
|
|
47
|
+
];
|
|
48
|
+
return routesToCheck.some((route: Route) => {
|
|
49
|
+
return Navigation.isStartWith(route);
|
|
50
|
+
});
|
|
36
51
|
}
|
|
37
52
|
|
|
38
53
|
export interface ComponentProps {
|
|
@@ -254,8 +269,7 @@ const Navbar: FunctionComponent<ComponentProps> = (
|
|
|
254
269
|
// Find active item in more menu items (needed for breadcrumb)
|
|
255
270
|
const activeMoreItem: MoreMenuItem | undefined = props.moreMenuItems?.find(
|
|
256
271
|
(item: MoreMenuItem) => {
|
|
257
|
-
|
|
258
|
-
return Navigation.isStartWith(routeToCheck);
|
|
272
|
+
return isMoreMenuItemActive(item);
|
|
259
273
|
},
|
|
260
274
|
);
|
|
261
275
|
|
|
@@ -3,7 +3,7 @@ import Link from "../Link/Link";
|
|
|
3
3
|
import Navigation from "../../Utils/Navigation";
|
|
4
4
|
import IconProp from "../../../Types/Icon/IconProp";
|
|
5
5
|
import URL from "../../../Types/API/URL";
|
|
6
|
-
import type
|
|
6
|
+
import { isMoreMenuItemActive, type MoreMenuItem } from "./NavBar";
|
|
7
7
|
import React, {
|
|
8
8
|
FunctionComponent,
|
|
9
9
|
ReactElement,
|
|
@@ -209,7 +209,7 @@ const NavBarMenuModal: FunctionComponent<ComponentProps> = (
|
|
|
209
209
|
const resolved: MoreMenuItem[] = [];
|
|
210
210
|
recentRoutes.forEach((route: string) => {
|
|
211
211
|
const item: MoreMenuItem | undefined = itemByRoute.get(route);
|
|
212
|
-
if (item && !
|
|
212
|
+
if (item && !isMoreMenuItemActive(item)) {
|
|
213
213
|
resolved.push(item);
|
|
214
214
|
}
|
|
215
215
|
});
|
|
@@ -269,7 +269,7 @@ const NavBarMenuModal: FunctionComponent<ComponentProps> = (
|
|
|
269
269
|
// Index of the product matching the current page (the "you are here" item).
|
|
270
270
|
const currentFlatIndex: number = useMemo(() => {
|
|
271
271
|
return flatItems.findIndex((item: MoreMenuItem) => {
|
|
272
|
-
return
|
|
272
|
+
return isMoreMenuItemActive(item);
|
|
273
273
|
});
|
|
274
274
|
}, [flatItems]);
|
|
275
275
|
|
package/UI/Utils/Navigation.ts
CHANGED
|
@@ -52,6 +52,16 @@ abstract class Navigation {
|
|
|
52
52
|
return pathes?.[0]?.route.path || "";
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* The raw query string of the current URL, including the leading "?" when
|
|
57
|
+
* non-empty (i.e. exactly `window.location.search`). Reading it through
|
|
58
|
+
* Navigation keeps callers testable and consistent with
|
|
59
|
+
* {@link setQueryString}, which also works off `window.location`.
|
|
60
|
+
*/
|
|
61
|
+
public static getQueryString(): string {
|
|
62
|
+
return window.location.search;
|
|
63
|
+
}
|
|
64
|
+
|
|
55
65
|
public static getQueryStringByName(paramName: string): string | null {
|
|
56
66
|
const urlSearchParams: URLSearchParams = new URLSearchParams(
|
|
57
67
|
window.location.search,
|
|
@@ -1,28 +1,126 @@
|
|
|
1
1
|
import Navigation from "./Navigation";
|
|
2
|
+
import Dictionary from "../../Types/Dictionary";
|
|
2
3
|
import { JSONObject } from "../../Types/JSON";
|
|
3
4
|
import JSONFunctions from "../../Types/JSONFunctions";
|
|
5
|
+
import { Logger } from "./Logger";
|
|
6
|
+
import { VoidFunction } from "../../Types/FunctionTypes";
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
/**
|
|
9
|
+
* The three independent slices of a table's view state. Each is stored under
|
|
10
|
+
* its own `<tableId>-<kind>` query param so a change to one never has to
|
|
11
|
+
* re-serialize the others.
|
|
12
|
+
*
|
|
13
|
+
* - `filter` — the classic column-filter popup selections (`FilterData`).
|
|
14
|
+
* - `facets` — the chip/facet bar selections (see `useResourceOwners`).
|
|
15
|
+
* - `view` — search text, label chips, sort and pagination.
|
|
16
|
+
*/
|
|
17
|
+
export type TableFilterUrlStateKind = "facets" | "filter" | "view";
|
|
18
|
+
|
|
19
|
+
export const TableFilterUrlStateKinds: Array<TableFilterUrlStateKind> = [
|
|
20
|
+
"filter",
|
|
21
|
+
"facets",
|
|
22
|
+
"view",
|
|
23
|
+
];
|
|
6
24
|
|
|
7
25
|
/**
|
|
8
|
-
* Persists a table's filter/facet selections in the URL query string
|
|
26
|
+
* Persists a table's filter / facet / view selections in the URL query string
|
|
27
|
+
* so they:
|
|
9
28
|
* - survive navigating to a detail page and clicking the browser "Back" button
|
|
10
29
|
* (the list page remounts with the params still on the URL), and
|
|
11
30
|
* - are shareable/bookmarkable (the URL fully describes the filtered view).
|
|
12
31
|
*
|
|
13
32
|
* The snapshot is run through {@link JSONFunctions} so OneUptime's typed query
|
|
14
33
|
* values (Search, Includes, InBetween, ...) round-trip as real class instances
|
|
15
|
-
* rather than plain objects. Params are namespaced by `tableId` so
|
|
16
|
-
* the same route
|
|
34
|
+
* rather than plain objects. Params are namespaced by `tableId` so several
|
|
35
|
+
* tables on the same route each keep their own state.
|
|
17
36
|
*/
|
|
18
37
|
export default class TableFilterUrlState {
|
|
19
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Upper bound on the whole query string we are willing to produce.
|
|
40
|
+
*
|
|
41
|
+
* nginx's default `large_client_header_buffers` gives ~8KB for the entire
|
|
42
|
+
* request line, and that budget is shared with the path and every other
|
|
43
|
+
* table on the page. We stay well under it: past this point the table keeps
|
|
44
|
+
* working from React state, it just stops mirroring the offending slice into
|
|
45
|
+
* the URL (so the link degrades to "unshared" rather than the page failing
|
|
46
|
+
* to load on refresh).
|
|
47
|
+
*/
|
|
48
|
+
public static readonly MaxQueryStringLength: number = 4000;
|
|
49
|
+
|
|
50
|
+
public static getParamName(
|
|
20
51
|
tableId: string,
|
|
21
52
|
kind: TableFilterUrlStateKind,
|
|
22
53
|
): string {
|
|
23
54
|
return `${tableId}-${kind}`;
|
|
24
55
|
}
|
|
25
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Keys currently claimed by mounted tables, so a duplicate can be reported.
|
|
59
|
+
* Not used to change behaviour — two tables sharing a key would already have
|
|
60
|
+
* shared their `userPreferencesKey` page-size preference, so the fix always
|
|
61
|
+
* belongs at the call site.
|
|
62
|
+
*/
|
|
63
|
+
private static claimedKeys: Map<string, number> = new Map<string, number>();
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Register a mounted table's URL namespace. Returns a release function to
|
|
67
|
+
* call on unmount.
|
|
68
|
+
*
|
|
69
|
+
* Two tables on one route claiming the same key would read and write the
|
|
70
|
+
* same params — paging one would repaginate the other, and a reload would
|
|
71
|
+
* restore whichever wrote last. That is always a call-site bug (give the
|
|
72
|
+
* tables distinct `userPreferencesKey`/`urlStateKey` values), so this warns
|
|
73
|
+
* loudly rather than silently renaming a key that may already be in
|
|
74
|
+
* someone's bookmarks.
|
|
75
|
+
*/
|
|
76
|
+
public static claimKey(tableId: string | undefined): VoidFunction {
|
|
77
|
+
if (!tableId) {
|
|
78
|
+
return () => {
|
|
79
|
+
// nothing claimed
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const claims: number = (this.claimedKeys.get(tableId) || 0) + 1;
|
|
84
|
+
this.claimedKeys.set(tableId, claims);
|
|
85
|
+
|
|
86
|
+
if (claims > 1) {
|
|
87
|
+
Logger.warn(
|
|
88
|
+
`TableFilterUrlState: ${claims} tables on this page share the URL state key "${tableId}". ` +
|
|
89
|
+
`They will overwrite each other's filters, sort and pagination in the URL. ` +
|
|
90
|
+
`Give each table a distinct "userPreferencesKey" (or pass "urlStateKey").`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return () => {
|
|
95
|
+
const remaining: number = (this.claimedKeys.get(tableId) || 1) - 1;
|
|
96
|
+
|
|
97
|
+
if (remaining <= 0) {
|
|
98
|
+
this.claimedKeys.delete(tableId);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.claimedKeys.set(tableId, remaining);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Test seam — drops every claim so one test's mounted tables don't leak into
|
|
108
|
+
* the next.
|
|
109
|
+
*/
|
|
110
|
+
public static resetClaimedKeys(): void {
|
|
111
|
+
this.claimedKeys.clear();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Every param name this table could own. Used to clear a table's state and
|
|
116
|
+
* by tests.
|
|
117
|
+
*/
|
|
118
|
+
public static getAllParamNames(tableId: string): Array<string> {
|
|
119
|
+
return TableFilterUrlStateKinds.map((kind: TableFilterUrlStateKind) => {
|
|
120
|
+
return this.getParamName(tableId, kind);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
26
124
|
/*
|
|
27
125
|
* Read a previously-persisted snapshot from the URL. Returns null when absent,
|
|
28
126
|
* empty, or unparseable (e.g. a hand-edited param) so callers fall back to
|
|
@@ -67,26 +165,115 @@ export default class TableFilterUrlState {
|
|
|
67
165
|
tableId: string | undefined,
|
|
68
166
|
kind: TableFilterUrlStateKind,
|
|
69
167
|
state: JSONObject | null,
|
|
168
|
+
): void {
|
|
169
|
+
this.writeMany(tableId, { [kind]: state });
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Write several slices in one `history.replaceState` call. Passing a kind
|
|
174
|
+
* with a `null`/empty value removes that param; omitting a kind leaves
|
|
175
|
+
* whatever is already on the URL untouched.
|
|
176
|
+
*/
|
|
177
|
+
public static writeMany(
|
|
178
|
+
tableId: string | undefined,
|
|
179
|
+
states: Partial<Record<TableFilterUrlStateKind, JSONObject | null>>,
|
|
70
180
|
): void {
|
|
71
181
|
if (!tableId) {
|
|
72
182
|
return;
|
|
73
183
|
}
|
|
74
184
|
|
|
75
|
-
|
|
76
|
-
|
|
185
|
+
const params: Dictionary<string | null> = {};
|
|
186
|
+
|
|
187
|
+
/*
|
|
188
|
+
* Track the query string as it would look after each param is applied, so
|
|
189
|
+
* the size check accounts for the other params in this same batch — not
|
|
190
|
+
* just the URL as it was before the batch started.
|
|
191
|
+
*/
|
|
192
|
+
const projected: URLSearchParams = this.getCurrentSearchParams();
|
|
193
|
+
|
|
194
|
+
for (const kind of Object.keys(states) as Array<TableFilterUrlStateKind>) {
|
|
195
|
+
const state: JSONObject | null | undefined = states[kind];
|
|
196
|
+
const paramName: string = this.getParamName(tableId, kind);
|
|
197
|
+
|
|
198
|
+
let value: string | null = null;
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
const hasState: boolean = Boolean(
|
|
202
|
+
state && Object.keys(state).length > 0,
|
|
203
|
+
);
|
|
77
204
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
205
|
+
value = hasState
|
|
206
|
+
? JSON.stringify(JSONFunctions.serialize(state as JSONObject))
|
|
207
|
+
: null;
|
|
208
|
+
} catch (err) {
|
|
209
|
+
/*
|
|
210
|
+
* Serialization failure (shouldn't happen for filter data) — drop the
|
|
211
|
+
* param rather than break the table, and leave a breadcrumb.
|
|
212
|
+
*/
|
|
213
|
+
Logger.warn(
|
|
214
|
+
`TableFilterUrlState: could not serialize "${paramName}": ${err}`,
|
|
215
|
+
);
|
|
216
|
+
value = null;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (value === null) {
|
|
220
|
+
projected.delete(paramName);
|
|
221
|
+
} else {
|
|
222
|
+
const previous: string | null = projected.get(paramName);
|
|
223
|
+
projected.set(paramName, value);
|
|
224
|
+
|
|
225
|
+
if (projected.toString().length > this.MaxQueryStringLength) {
|
|
226
|
+
/*
|
|
227
|
+
* Too big to share. Drop the param so a page refresh doesn't hit an
|
|
228
|
+
* over-long request line — React state remains the source of truth
|
|
229
|
+
* for this session.
|
|
230
|
+
*/
|
|
231
|
+
Logger.warn(
|
|
232
|
+
`TableFilterUrlState: "${paramName}" is too large for the URL (${value.length} chars) and was not persisted.`,
|
|
233
|
+
);
|
|
234
|
+
value = null;
|
|
235
|
+
|
|
236
|
+
if (previous === null) {
|
|
237
|
+
projected.delete(paramName);
|
|
238
|
+
} else {
|
|
239
|
+
projected.set(paramName, previous);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
params[paramName] = value;
|
|
245
|
+
}
|
|
81
246
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
247
|
+
Navigation.setQueryString(params);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Remove every param this table owns from the URL.
|
|
252
|
+
*/
|
|
253
|
+
public static clear(tableId: string | undefined): void {
|
|
254
|
+
if (!tableId) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const params: Dictionary<string | null> = {};
|
|
259
|
+
|
|
260
|
+
for (const paramName of this.getAllParamNames(tableId)) {
|
|
261
|
+
params[paramName] = null;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
Navigation.setQueryString(params);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* The current query string as a mutable `URLSearchParams`. Size checks
|
|
269
|
+
* measure `toString()` on this — the *encoded* length, because that is what
|
|
270
|
+
* actually travels on the wire.
|
|
271
|
+
*/
|
|
272
|
+
private static getCurrentSearchParams(): URLSearchParams {
|
|
273
|
+
try {
|
|
274
|
+
return new URLSearchParams(Navigation.getQueryString());
|
|
85
275
|
} catch {
|
|
86
|
-
|
|
87
|
-
* Serialization failure (shouldn't happen for filter data) — skip the
|
|
88
|
-
* URL sync rather than break the table.
|
|
89
|
-
*/
|
|
276
|
+
return new URLSearchParams();
|
|
90
277
|
}
|
|
91
278
|
}
|
|
92
279
|
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { JSONObject } from "../../Types/JSON";
|
|
2
|
+
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
3
|
+
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The "everything that isn't a column filter or a facet" slice of a table's
|
|
7
|
+
* view: the search box, the label chips next to it, the active sort and where
|
|
8
|
+
* in the pagination the user is.
|
|
9
|
+
*
|
|
10
|
+
* Kept deliberately primitive (strings / numbers / string arrays) so the URL
|
|
11
|
+
* param stays short and human-readable, and so a hand-edited link can never
|
|
12
|
+
* smuggle a typed object into the table's query.
|
|
13
|
+
*/
|
|
14
|
+
export interface TableViewUrlStateData {
|
|
15
|
+
search?: string | undefined;
|
|
16
|
+
labels?: Array<string> | undefined;
|
|
17
|
+
sortBy?: string | undefined;
|
|
18
|
+
sortOrder?: SortOrder | undefined;
|
|
19
|
+
page?: number | undefined;
|
|
20
|
+
itemsOnPage?: number | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The values a slice is compared against before being written. Anything equal
|
|
25
|
+
* to its default is left out of the URL, so a table the user hasn't touched
|
|
26
|
+
* contributes no query params at all.
|
|
27
|
+
*/
|
|
28
|
+
export interface TableViewUrlStateDefaults {
|
|
29
|
+
sortBy?: string | undefined;
|
|
30
|
+
sortOrder?: SortOrder | undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Hard ceiling on a restored page size. Anything above this is a hand-edited
|
|
35
|
+
* URL trying to make the table ask the API for an unbounded page.
|
|
36
|
+
*/
|
|
37
|
+
export const MaxItemsOnPage: number = 1000;
|
|
38
|
+
|
|
39
|
+
export default class TableViewUrlState {
|
|
40
|
+
/**
|
|
41
|
+
* Serialize to the plain object that goes in the URL, omitting every value
|
|
42
|
+
* that matches its default. Returns `null` when nothing is worth persisting
|
|
43
|
+
* so the caller can drop the param entirely.
|
|
44
|
+
*/
|
|
45
|
+
public static toJSON(
|
|
46
|
+
state: TableViewUrlStateData,
|
|
47
|
+
defaults?: TableViewUrlStateDefaults | undefined,
|
|
48
|
+
): JSONObject | null {
|
|
49
|
+
const json: JSONObject = {};
|
|
50
|
+
|
|
51
|
+
const search: string = (state.search || "").trim();
|
|
52
|
+
if (search.length > 0) {
|
|
53
|
+
json["search"] = search;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const labels: Array<string> = (state.labels || []).filter((l: string) => {
|
|
57
|
+
return Boolean(l);
|
|
58
|
+
});
|
|
59
|
+
if (labels.length > 0) {
|
|
60
|
+
json["labels"] = labels;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
* Sort is only worth persisting when it differs from the sort the table
|
|
65
|
+
* was mounted with — otherwise every table on the page would carry a
|
|
66
|
+
* redundant param.
|
|
67
|
+
*/
|
|
68
|
+
const sortIsDefault: boolean =
|
|
69
|
+
(state.sortBy || null) === (defaults?.sortBy || null) &&
|
|
70
|
+
(state.sortOrder || null) === (defaults?.sortOrder || null);
|
|
71
|
+
|
|
72
|
+
if (state.sortBy && !sortIsDefault) {
|
|
73
|
+
json["sortBy"] = state.sortBy;
|
|
74
|
+
json["sortOrder"] = state.sortOrder || SortOrder.Ascending;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (state.page && state.page > 1) {
|
|
78
|
+
json["page"] = state.page;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (state.itemsOnPage && state.itemsOnPage > 0) {
|
|
82
|
+
json["itemsOnPage"] = state.itemsOnPage;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (Object.keys(json).length === 0) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return json;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Rebuild the view state from a URL param. Every field is validated
|
|
94
|
+
* independently: a bad `page` doesn't discard a good `search`, and an
|
|
95
|
+
* unrecognised value is dropped rather than passed through to the query.
|
|
96
|
+
*/
|
|
97
|
+
public static fromJSON(
|
|
98
|
+
json: JSONObject | null | undefined,
|
|
99
|
+
): TableViewUrlStateData {
|
|
100
|
+
const state: TableViewUrlStateData = {};
|
|
101
|
+
|
|
102
|
+
if (!json || typeof json !== "object") {
|
|
103
|
+
return state;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (typeof json["search"] === "string" && json["search"].trim() !== "") {
|
|
107
|
+
state.search = json["search"];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (Array.isArray(json["labels"])) {
|
|
111
|
+
const labels: Array<string> = (json["labels"] as Array<unknown>)
|
|
112
|
+
.filter((l: unknown) => {
|
|
113
|
+
return typeof l === "string" && l.trim() !== "";
|
|
114
|
+
})
|
|
115
|
+
.map((l: unknown) => {
|
|
116
|
+
return l as string;
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
if (labels.length > 0) {
|
|
120
|
+
state.labels = labels;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (typeof json["sortBy"] === "string" && json["sortBy"].trim() !== "") {
|
|
125
|
+
state.sortBy = json["sortBy"];
|
|
126
|
+
|
|
127
|
+
state.sortOrder =
|
|
128
|
+
json["sortOrder"] === SortOrder.Descending
|
|
129
|
+
? SortOrder.Descending
|
|
130
|
+
: SortOrder.Ascending;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const page: number | null = this.toPositiveInteger(json["page"]);
|
|
134
|
+
if (page !== null && page >= 1) {
|
|
135
|
+
state.page = page;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const itemsOnPage: number | null = this.toPositiveInteger(
|
|
139
|
+
json["itemsOnPage"],
|
|
140
|
+
);
|
|
141
|
+
if (
|
|
142
|
+
itemsOnPage !== null &&
|
|
143
|
+
itemsOnPage >= 1 &&
|
|
144
|
+
itemsOnPage <= MaxItemsOnPage
|
|
145
|
+
) {
|
|
146
|
+
state.itemsOnPage = itemsOnPage;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return state;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private static toPositiveInteger(value: unknown): number | null {
|
|
153
|
+
if (typeof value !== "number" || !isFinite(value)) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const asInteger: number = Math.floor(value);
|
|
158
|
+
|
|
159
|
+
if (asInteger < 1 || asInteger > LIMIT_MAX) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return asInteger;
|
|
164
|
+
}
|
|
165
|
+
}
|