@oneuptime/common 12.0.23 → 12.0.24

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.
Files changed (294) hide show
  1. package/Models/DatabaseModels/DetectionRule.ts +55 -0
  2. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +27 -7
  3. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +67 -0
  4. package/Models/DatabaseModels/Project.ts +68 -0
  5. package/Models/DatabaseModels/User.ts +68 -0
  6. package/Server/API/TelemetryAPI.ts +29 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.ts +28 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.ts +49 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.ts +33 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  11. package/Server/Middleware/GzipRequestBody.ts +311 -0
  12. package/Server/Middleware/MultipartFormData.ts +87 -3
  13. package/Server/Services/DetectionRuleService.ts +73 -6
  14. package/Server/Services/Index.ts +205 -0
  15. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +59 -0
  16. package/Server/Services/NetworkDeviceService.ts +148 -0
  17. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
  18. package/Server/Services/OnCallDutyPolicyFeedService.ts +1 -1
  19. package/Server/Services/ProjectService.ts +29 -19
  20. package/Server/Services/SecurityEventService.ts +90 -13
  21. package/Server/Services/StatusPageResourceService.ts +223 -0
  22. package/Server/Services/TelemetryAttributeService.ts +17 -0
  23. package/Server/Services/UserService.ts +4 -6
  24. package/Server/Types/Markdown.ts +161 -67
  25. package/Server/Utils/AI/Toolbox/OnCallTools.ts +12 -4
  26. package/Server/Utils/AnalyticsDatabase/Statement.ts +13 -1
  27. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +297 -6
  28. package/Server/Utils/Attribution.ts +4 -0
  29. package/Server/Utils/Marketing/MarketingEventUtil.ts +45 -7
  30. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +55 -3
  31. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +21 -0
  32. package/Server/Utils/StartServer.ts +12 -32
  33. package/Server/Utils/Telemetry/LlmCostBudgetEvaluator.ts +101 -4
  34. package/Server/Utils/Telemetry/LlmMetricSpend.ts +130 -0
  35. package/Server/Views/Partials/AnalyticsConsent.ejs +159 -102
  36. package/Server/Views/Partials/Head.ejs +2 -1
  37. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +776 -38
  38. package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +359 -0
  39. package/Tests/App/Dashboard/CorrelateGraph.test.tsx +865 -0
  40. package/Tests/App/Dashboard/CorrelationGraph.test.ts +346 -0
  41. package/Tests/App/Dashboard/CriteriaFilterConditionDropdown.test.tsx +256 -0
  42. package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +738 -0
  43. package/Tests/App/Dashboard/CriteriaFilterMonitorTypeChange.test.ts +1122 -0
  44. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +283 -0
  45. package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +407 -0
  46. package/Tests/App/Dashboard/MetricSeriesInvestigateMenu.test.tsx +5 -14
  47. package/Tests/App/Dashboard/MonitorCriteriaActionToggles.test.tsx +426 -0
  48. package/Tests/App/Dashboard/MonitorStepsCriteriaAlignmentWiring.test.tsx +352 -0
  49. package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +278 -0
  50. package/Tests/App/Dashboard/OnCallLayerShiftPreviewOverrides.test.ts +237 -0
  51. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +2 -2
  52. package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +460 -0
  53. package/Tests/App/Dashboard/SecurityEventAttributeUtil.test.ts +171 -0
  54. package/Tests/App/Dashboard/SecurityEventCorrelation.test.ts +857 -0
  55. package/Tests/App/Dashboard/SecurityEventDetailObservables.test.tsx +194 -0
  56. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +124 -0
  57. package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +79 -19
  58. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +382 -0
  59. package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +216 -0
  60. package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +590 -11
  61. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +757 -0
  62. package/Tests/Models/DiscoveryScanNameColumn.test.ts +293 -0
  63. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +564 -0
  64. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +120 -4
  65. package/Tests/Server/Middleware/GzipRequestBody.test.ts +725 -0
  66. package/Tests/Server/Middleware/MultipartFormData.test.ts +298 -0
  67. package/Tests/Server/Services/AddDetectionRuleDistinctCountColumnsMigration.test.ts +311 -0
  68. package/Tests/Server/Services/DetectionRuleService.test.ts +134 -2
  69. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +7 -1
  70. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +131 -0
  71. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +194 -0
  72. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +800 -0
  73. package/Tests/Server/Services/OnCallScheduleAttachRosterRefresh.test.ts +244 -0
  74. package/Tests/Server/Services/SecurityEventService.test.ts +376 -0
  75. package/Tests/Server/Services/StatusPageResourceDuplicates.test.ts +703 -0
  76. package/Tests/Server/Services/TelemetryAttributeServiceSecurityEvent.test.ts +256 -0
  77. package/Tests/Server/Types/Workflow/Components/ComponentRegistryParity.test.ts +417 -0
  78. package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWhereOperators.test.ts +677 -0
  79. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +43 -0
  80. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +15 -11
  81. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +369 -8
  82. package/Tests/Server/Utils/SecurityEvent/SigmaClickhouseCompiler.test.ts +35 -0
  83. package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +368 -4
  84. package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +245 -0
  85. package/Tests/Server/Views/AnalyticsConsentPartial.test.ts +48 -5
  86. package/Tests/Types/Code/YamlSyntax.test.ts +396 -0
  87. package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +957 -0
  88. package/Tests/Types/Monitor/MonitorCriteriaActionValidation.test.ts +598 -0
  89. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +49 -0
  90. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +6 -6
  91. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +4 -4
  92. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +4 -3
  93. package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +193 -0
  94. package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +0 -12
  95. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +1 -17
  96. package/Tests/UI/Components/CodeEditor.test.tsx +474 -10
  97. package/Tests/UI/Components/Detail/YamlField.test.tsx +105 -0
  98. package/Tests/UI/Components/EntityDropdownLabelsBulkAdd.test.tsx +319 -0
  99. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +231 -0
  100. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +1 -0
  101. package/Tests/UI/Components/Forms/ValidationYAML.test.ts +234 -0
  102. package/Tests/UI/Components/ModelTable/AttributeColumns.test.tsx +573 -0
  103. package/Tests/UI/Components/ModelTable/BaseModelTableAttributeColumns.test.tsx +824 -0
  104. package/Tests/UI/Components/ModelTable/ColumnCustomizationModalAddableColumns.test.tsx +707 -0
  105. package/Tests/UI/Components/SideOver.test.tsx +1 -1
  106. package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +294 -0
  107. package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +436 -0
  108. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +6 -2
  109. package/Tests/UI/Components/Toggle.test.tsx +25 -0
  110. package/Tests/UI/Components/YamlEditor.test.tsx +847 -0
  111. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +252 -0
  112. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +221 -0
  113. package/Tests/Utils/NetworkDiscovery/ScanNameUtil.test.ts +312 -0
  114. package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +468 -0
  115. package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +472 -0
  116. package/Types/Code/YamlSyntax.ts +396 -0
  117. package/Types/Exception/ExceptionCode.ts +1 -0
  118. package/Types/Exception/PayloadTooLargeException.ts +8 -0
  119. package/Types/Marketing/Attribution.ts +10 -0
  120. package/Types/Marketing/MarketingEvent.ts +4 -0
  121. package/Types/Monitor/MonitorCriteriaInstance.ts +116 -56
  122. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +2 -1
  123. package/Types/SecurityEvent/DetectionFindingConstants.ts +11 -0
  124. package/Types/Telemetry/LlmMetricConventions.ts +124 -0
  125. package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +3 -0
  126. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +10 -1
  127. package/UI/Components/CodeEditor/CodeEditor.tsx +241 -79
  128. package/UI/Components/CodeEditor/YamlEditor.tsx +369 -0
  129. package/UI/Components/Detail/Detail.tsx +10 -0
  130. package/UI/Components/EntityDropdown/EntityDropdown.tsx +33 -0
  131. package/UI/Components/Forms/Fields/FormField.tsx +31 -0
  132. package/UI/Components/Forms/Types/Field.ts +8 -0
  133. package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
  134. package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -0
  135. package/UI/Components/Forms/Validation.ts +46 -0
  136. package/UI/Components/Input/Input.tsx +3 -0
  137. package/UI/Components/ModelTable/AttributeColumns.tsx +321 -0
  138. package/UI/Components/ModelTable/BaseModelTable.tsx +263 -14
  139. package/UI/Components/ModelTable/Column.ts +8 -0
  140. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +310 -0
  141. package/UI/Components/ModelTable/ColumnPreference.ts +13 -1
  142. package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +2 -2
  143. package/UI/Components/SideOver/SideOver.tsx +5 -5
  144. package/UI/Components/StatusPage/ResourceGrid.tsx +82 -2
  145. package/UI/Components/StatusPage/ResourceList.tsx +197 -38
  146. package/UI/Components/Toggle/Toggle.tsx +9 -1
  147. package/UI/Components/Types/FieldType.ts +1 -0
  148. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +73 -1
  149. package/Utils/NetworkDiscovery/ScanNameUtil.ts +181 -0
  150. package/Utils/StatusPage/ResourceExplorer.ts +258 -0
  151. package/Utils/Telemetry/LlmMetricQuery.ts +204 -0
  152. package/build/dist/Models/DatabaseModels/DetectionRule.js +57 -0
  153. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  154. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +27 -7
  155. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  156. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +69 -0
  157. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  158. package/build/dist/Models/DatabaseModels/Project.js +76 -0
  159. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  160. package/build/dist/Models/DatabaseModels/User.js +76 -0
  161. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  162. package/build/dist/Server/API/TelemetryAPI.js +17 -0
  163. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  164. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js +21 -0
  165. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js.map +1 -0
  166. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js +42 -0
  167. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js.map +1 -0
  168. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js +22 -0
  169. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js.map +1 -0
  170. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  171. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  172. package/build/dist/Server/Middleware/GzipRequestBody.js +224 -0
  173. package/build/dist/Server/Middleware/GzipRequestBody.js.map +1 -0
  174. package/build/dist/Server/Middleware/MultipartFormData.js +71 -2
  175. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  176. package/build/dist/Server/Services/DetectionRuleService.js +49 -4
  177. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  178. package/build/dist/Server/Services/Index.js +204 -0
  179. package/build/dist/Server/Services/Index.js.map +1 -1
  180. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +50 -0
  181. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  182. package/build/dist/Server/Services/NetworkDeviceService.js +124 -0
  183. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  184. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +68 -13
  185. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  186. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +1 -1
  187. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -1
  188. package/build/dist/Server/Services/ProjectService.js +25 -45
  189. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  190. package/build/dist/Server/Services/SecurityEventService.js +57 -5
  191. package/build/dist/Server/Services/SecurityEventService.js.map +1 -1
  192. package/build/dist/Server/Services/StatusPageResourceService.js +140 -0
  193. package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
  194. package/build/dist/Server/Services/TelemetryAttributeService.js +17 -0
  195. package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
  196. package/build/dist/Server/Services/UserService.js +2 -12
  197. package/build/dist/Server/Services/UserService.js.map +1 -1
  198. package/build/dist/Server/Types/Markdown.js +147 -61
  199. package/build/dist/Server/Types/Markdown.js.map +1 -1
  200. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +12 -4
  201. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -1
  202. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +12 -1
  203. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  204. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +246 -9
  205. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  206. package/build/dist/Server/Utils/Attribution.js.map +1 -1
  207. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +27 -7
  208. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
  209. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +42 -7
  210. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  211. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +18 -0
  212. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  213. package/build/dist/Server/Utils/StartServer.js +12 -21
  214. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  215. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js +76 -5
  216. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js.map +1 -1
  217. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +102 -0
  218. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -0
  219. package/build/dist/Types/Code/YamlSyntax.js +212 -0
  220. package/build/dist/Types/Code/YamlSyntax.js.map +1 -0
  221. package/build/dist/Types/Exception/ExceptionCode.js +1 -0
  222. package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
  223. package/build/dist/Types/Exception/PayloadTooLargeException.js +8 -0
  224. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -0
  225. package/build/dist/Types/Marketing/Attribution.js +10 -0
  226. package/build/dist/Types/Marketing/Attribution.js.map +1 -1
  227. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +112 -51
  228. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  229. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +2 -1
  230. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
  231. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +9 -0
  232. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  233. package/build/dist/Types/Telemetry/LlmMetricConventions.js +98 -0
  234. package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -0
  235. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
  236. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
  237. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +5 -2
  238. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  239. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +206 -76
  240. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  241. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +201 -0
  242. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -0
  243. package/build/dist/UI/Components/Detail/Detail.js +9 -0
  244. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  245. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +16 -1
  246. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  247. package/build/dist/UI/Components/Forms/Fields/FormField.js +14 -1
  248. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  249. package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
  250. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
  251. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
  252. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -0
  253. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
  254. package/build/dist/UI/Components/Forms/Validation.js +27 -0
  255. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  256. package/build/dist/UI/Components/Input/Input.js +1 -1
  257. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  258. package/build/dist/UI/Components/ModelTable/AttributeColumns.js +159 -0
  259. package/build/dist/UI/Components/ModelTable/AttributeColumns.js.map +1 -0
  260. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +179 -17
  261. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  262. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +133 -2
  263. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
  264. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +7 -1
  265. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -1
  266. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +2 -2
  267. package/build/dist/UI/Components/SideOver/SideOver.js +5 -5
  268. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +28 -2
  269. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
  270. package/build/dist/UI/Components/StatusPage/ResourceList.js +87 -20
  271. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
  272. package/build/dist/UI/Components/Toggle/Toggle.js +9 -1
  273. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  274. package/build/dist/UI/Components/Types/FieldType.js +1 -0
  275. package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
  276. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +37 -1
  277. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  278. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js +120 -0
  279. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js.map +1 -0
  280. package/build/dist/Utils/StatusPage/ResourceExplorer.js +171 -0
  281. package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -1
  282. package/build/dist/Utils/Telemetry/LlmMetricQuery.js +119 -0
  283. package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -0
  284. package/jest.config.json +2 -0
  285. package/package.json +1 -1
  286. package/tsconfig.json +2 -1
  287. package/Tests/UI/Components/Toast.test.tsx +0 -197
  288. package/Tests/UI/Components/ToastStacking.test.tsx +0 -198
  289. package/UI/Components/Toast/Toast.tsx +0 -189
  290. package/UI/Components/Toast/ToastInit.tsx +0 -110
  291. package/build/dist/UI/Components/Toast/Toast.js +0 -123
  292. package/build/dist/UI/Components/Toast/Toast.js.map +0 -1
  293. package/build/dist/UI/Components/Toast/ToastInit.js +0 -53
  294. package/build/dist/UI/Components/Toast/ToastInit.js.map +0 -1
@@ -10,6 +10,7 @@ import StatusPageResourceExplorerUtil, {
10
10
  StatusPageResourceNavigatorResult,
11
11
  StatusPageResourceNavigatorRow,
12
12
  StatusPageResourceSelection,
13
+ StatusPageResourceSelectionState,
13
14
  StatusPageResourceSelectionType,
14
15
  } from "../../../Utils/StatusPage/ResourceExplorer";
15
16
  import { describe, expect, test } from "@jest/globals";
@@ -928,4 +929,471 @@ describe("StatusPageResourceExplorerUtil", () => {
928
929
  ).toBe("12 sub groups");
929
930
  });
930
931
  });
932
+
933
+ /*
934
+ * Ticking rows, so that clearing a group is one decision rather than twenty
935
+ * seven (issue #3419).
936
+ *
937
+ * A selection is a set of id strings held by the pane, and the pane re-fetches
938
+ * the group after every write - so the two properties worth pinning down are
939
+ * that an operation only ever touches the resources it was handed, and that a
940
+ * no-op hands back the very set it was given rather than an equal copy. The
941
+ * second one is not tidiness: the set is React state, and returning a new
942
+ * instance for a no-op is a re-render of the whole pane per keystroke.
943
+ */
944
+ describe("selecting resources", () => {
945
+ type MakeSelectionFunction = (ids: Array<string>) => Set<string>;
946
+
947
+ const makeSelection: MakeSelectionFunction = (
948
+ ids: Array<string>,
949
+ ): Set<string> => {
950
+ return new Set<string>(ids);
951
+ };
952
+
953
+ /* A resource the server would never return: no id at all. */
954
+ type MakeIdlessResourceFunction = (name: string) => StatusPageResource;
955
+
956
+ const makeIdlessResource: MakeIdlessResourceFunction = (
957
+ name: string,
958
+ ): StatusPageResource => {
959
+ const resource: StatusPageResource = new StatusPageResource();
960
+ resource.displayName = name;
961
+
962
+ return resource;
963
+ };
964
+
965
+ describe("reading a resource's id", () => {
966
+ test("hands back the id as a string", () => {
967
+ expect(
968
+ StatusPageResourceExplorerUtil.getResourceId(
969
+ makeResource({ id: "a" }),
970
+ ),
971
+ ).toBe("a");
972
+ });
973
+
974
+ test("is null for a resource with no id", () => {
975
+ expect(
976
+ StatusPageResourceExplorerUtil.getResourceId(
977
+ makeIdlessResource("Nameless"),
978
+ ),
979
+ ).toBeNull();
980
+ });
981
+
982
+ test("is null rather than the empty string, which would collide", () => {
983
+ const resource: StatusPageResource = new StatusPageResource();
984
+ resource._id = "";
985
+
986
+ expect(
987
+ StatusPageResourceExplorerUtil.getResourceId(resource),
988
+ ).toBeNull();
989
+ });
990
+ });
991
+
992
+ describe("the ids a list offers", () => {
993
+ test("are in the order the list draws them", () => {
994
+ expect(
995
+ StatusPageResourceExplorerUtil.getResourceIds([
996
+ makeResource({ id: "c" }),
997
+ makeResource({ id: "a" }),
998
+ makeResource({ id: "b" }),
999
+ ]),
1000
+ ).toEqual(["c", "a", "b"]);
1001
+ });
1002
+
1003
+ test("skip anything that cannot be held on to", () => {
1004
+ expect(
1005
+ StatusPageResourceExplorerUtil.getResourceIds([
1006
+ makeResource({ id: "a" }),
1007
+ makeIdlessResource("Nameless"),
1008
+ makeResource({ id: "b" }),
1009
+ ]),
1010
+ ).toEqual(["a", "b"]);
1011
+ });
1012
+
1013
+ test("say each id once, however many rows carry it", () => {
1014
+ expect(
1015
+ StatusPageResourceExplorerUtil.getResourceIds([
1016
+ makeResource({ id: "a" }),
1017
+ makeResource({ id: "a" }),
1018
+ makeResource({ id: "b" }),
1019
+ ]),
1020
+ ).toEqual(["a", "b"]);
1021
+ });
1022
+
1023
+ test("are empty for an empty list", () => {
1024
+ expect(StatusPageResourceExplorerUtil.getResourceIds([])).toEqual([]);
1025
+ });
1026
+ });
1027
+
1028
+ describe("ticking one row", () => {
1029
+ test("adds an id that was not selected", () => {
1030
+ const next: Set<string> =
1031
+ StatusPageResourceExplorerUtil.toggleSelectedResourceId({
1032
+ selectedResourceIds: makeSelection(["a"]),
1033
+ resourceId: "b",
1034
+ });
1035
+
1036
+ expect([...next].sort()).toEqual(["a", "b"]);
1037
+ });
1038
+
1039
+ test("removes an id that was", () => {
1040
+ const next: Set<string> =
1041
+ StatusPageResourceExplorerUtil.toggleSelectedResourceId({
1042
+ selectedResourceIds: makeSelection(["a", "b"]),
1043
+ resourceId: "a",
1044
+ });
1045
+
1046
+ expect([...next]).toEqual(["b"]);
1047
+ });
1048
+
1049
+ test("leaves the set it was given alone", () => {
1050
+ const current: Set<string> = makeSelection(["a"]);
1051
+
1052
+ const next: Set<string> =
1053
+ StatusPageResourceExplorerUtil.toggleSelectedResourceId({
1054
+ selectedResourceIds: current,
1055
+ resourceId: "b",
1056
+ });
1057
+
1058
+ expect(next).not.toBe(current);
1059
+ expect([...current]).toEqual(["a"]);
1060
+ });
1061
+ });
1062
+
1063
+ describe("the box at the top of the list", () => {
1064
+ test("selects every resource it was handed", () => {
1065
+ const next: Set<string> =
1066
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1067
+ selectedResourceIds: makeSelection([]),
1068
+ statusPageResources: [
1069
+ makeResource({ id: "a" }),
1070
+ makeResource({ id: "b" }),
1071
+ ],
1072
+ isSelected: true,
1073
+ });
1074
+
1075
+ expect([...next].sort()).toEqual(["a", "b"]);
1076
+ });
1077
+
1078
+ /*
1079
+ * The list is filtered as often as not, and the rows the search hid are
1080
+ * still selected. Un-ticking over four matches must not drop the twenty
1081
+ * that were selected before the operator started typing.
1082
+ */
1083
+ test("leaves selected rows it was not handed alone, in both directions", () => {
1084
+ const selected: Set<string> =
1085
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1086
+ selectedResourceIds: makeSelection(["hidden"]),
1087
+ statusPageResources: [makeResource({ id: "shown" })],
1088
+ isSelected: true,
1089
+ });
1090
+
1091
+ expect([...selected].sort()).toEqual(["hidden", "shown"]);
1092
+
1093
+ const deselected: Set<string> =
1094
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1095
+ selectedResourceIds: selected,
1096
+ statusPageResources: [makeResource({ id: "shown" })],
1097
+ isSelected: false,
1098
+ });
1099
+
1100
+ expect([...deselected]).toEqual(["hidden"]);
1101
+ });
1102
+
1103
+ test("ignores rows that cannot be selected at all", () => {
1104
+ const next: Set<string> =
1105
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1106
+ selectedResourceIds: makeSelection([]),
1107
+ statusPageResources: [
1108
+ makeResource({ id: "a" }),
1109
+ makeIdlessResource("Nameless"),
1110
+ ],
1111
+ isSelected: true,
1112
+ });
1113
+
1114
+ expect([...next]).toEqual(["a"]);
1115
+ });
1116
+
1117
+ test("hands back the same set when everything was already selected", () => {
1118
+ const current: Set<string> = makeSelection(["a", "b"]);
1119
+
1120
+ expect(
1121
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1122
+ selectedResourceIds: current,
1123
+ statusPageResources: [
1124
+ makeResource({ id: "a" }),
1125
+ makeResource({ id: "b" }),
1126
+ ],
1127
+ isSelected: true,
1128
+ }),
1129
+ ).toBe(current);
1130
+ });
1131
+
1132
+ test("hands back the same set when nothing handed in was selected", () => {
1133
+ const current: Set<string> = makeSelection(["other"]);
1134
+
1135
+ expect(
1136
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1137
+ selectedResourceIds: current,
1138
+ statusPageResources: [makeResource({ id: "a" })],
1139
+ isSelected: false,
1140
+ }),
1141
+ ).toBe(current);
1142
+ });
1143
+
1144
+ test("hands back the same set for an empty list", () => {
1145
+ const current: Set<string> = makeSelection(["a"]);
1146
+
1147
+ expect(
1148
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1149
+ selectedResourceIds: current,
1150
+ statusPageResources: [],
1151
+ isSelected: true,
1152
+ }),
1153
+ ).toBe(current);
1154
+ });
1155
+ });
1156
+
1157
+ describe("what the box at the top of the list looks like", () => {
1158
+ type StateFunction = (
1159
+ resources: Array<StatusPageResource>,
1160
+ ids: Array<string>,
1161
+ ) => StatusPageResourceSelectionState;
1162
+
1163
+ const state: StateFunction = (
1164
+ resources: Array<StatusPageResource>,
1165
+ ids: Array<string>,
1166
+ ): StatusPageResourceSelectionState => {
1167
+ return StatusPageResourceExplorerUtil.getSelectionState({
1168
+ statusPageResources: resources,
1169
+ selectedResourceIds: makeSelection(ids),
1170
+ });
1171
+ };
1172
+
1173
+ test("is empty when nothing is selected", () => {
1174
+ expect(
1175
+ state([makeResource({ id: "a" }), makeResource({ id: "b" })], []),
1176
+ ).toEqual({
1177
+ isAllSelected: false,
1178
+ isIndeterminate: false,
1179
+ selectedCount: 0,
1180
+ selectableCount: 2,
1181
+ });
1182
+ });
1183
+
1184
+ test("is half filled when some of them are", () => {
1185
+ expect(
1186
+ state([makeResource({ id: "a" }), makeResource({ id: "b" })], ["a"]),
1187
+ ).toEqual({
1188
+ isAllSelected: false,
1189
+ isIndeterminate: true,
1190
+ selectedCount: 1,
1191
+ selectableCount: 2,
1192
+ });
1193
+ });
1194
+
1195
+ test("is filled when all of them are", () => {
1196
+ expect(
1197
+ state(
1198
+ [makeResource({ id: "a" }), makeResource({ id: "b" })],
1199
+ ["a", "b"],
1200
+ ),
1201
+ ).toEqual({
1202
+ isAllSelected: true,
1203
+ isIndeterminate: false,
1204
+ selectedCount: 2,
1205
+ selectableCount: 2,
1206
+ });
1207
+ });
1208
+
1209
+ /*
1210
+ * A ticked box over nothing to tick reads as a selection that was lost -
1211
+ * which is exactly what an operator sees when a search matches nothing.
1212
+ */
1213
+ test("is never filled over an empty list", () => {
1214
+ expect(state([], ["a"])).toEqual({
1215
+ isAllSelected: false,
1216
+ isIndeterminate: false,
1217
+ selectedCount: 0,
1218
+ selectableCount: 0,
1219
+ });
1220
+ });
1221
+
1222
+ /*
1223
+ * The selection outlives the filter, so it routinely holds ids that the
1224
+ * rows on screen know nothing about. They must not make the box on screen
1225
+ * look fuller than it is.
1226
+ */
1227
+ test("counts only the rows it was handed", () => {
1228
+ expect(state([makeResource({ id: "a" })], ["a", "elsewhere"])).toEqual({
1229
+ isAllSelected: true,
1230
+ isIndeterminate: false,
1231
+ selectedCount: 1,
1232
+ selectableCount: 1,
1233
+ });
1234
+ });
1235
+
1236
+ test("is filled when every selectable row is selected, id-less ones aside", () => {
1237
+ expect(
1238
+ state(
1239
+ [makeResource({ id: "a" }), makeIdlessResource("Nameless")],
1240
+ ["a"],
1241
+ ),
1242
+ ).toEqual({
1243
+ isAllSelected: true,
1244
+ isIndeterminate: false,
1245
+ selectedCount: 1,
1246
+ selectableCount: 1,
1247
+ });
1248
+ });
1249
+ });
1250
+
1251
+ describe("resolving a selection to resources", () => {
1252
+ test("hands them back in the order the list holds them", () => {
1253
+ const resources: Array<StatusPageResource> = [
1254
+ makeResource({ id: "a", monitorName: "API" }),
1255
+ makeResource({ id: "b", monitorName: "Database" }),
1256
+ makeResource({ id: "c", monitorName: "Cache" }),
1257
+ ];
1258
+
1259
+ const selected: Array<StatusPageResource> =
1260
+ StatusPageResourceExplorerUtil.getSelectedResources({
1261
+ statusPageResources: resources,
1262
+ /* Ticked bottom up; reported top down. */
1263
+ selectedResourceIds: makeSelection(["c", "a"]),
1264
+ });
1265
+
1266
+ expect(
1267
+ selected.map((resource: StatusPageResource) => {
1268
+ return StatusPageResourceExplorerUtil.getResourceName(resource);
1269
+ }),
1270
+ ).toEqual(["API", "Cache"]);
1271
+ });
1272
+
1273
+ test("drops ids that match nothing on screen", () => {
1274
+ expect(
1275
+ StatusPageResourceExplorerUtil.getSelectedResources({
1276
+ statusPageResources: [makeResource({ id: "a" })],
1277
+ selectedResourceIds: makeSelection(["a", "gone"]),
1278
+ }).length,
1279
+ ).toBe(1);
1280
+ });
1281
+
1282
+ test("hands back one resource per id", () => {
1283
+ expect(
1284
+ StatusPageResourceExplorerUtil.getSelectedResources({
1285
+ statusPageResources: [
1286
+ makeResource({ id: "a" }),
1287
+ makeResource({ id: "a" }),
1288
+ ],
1289
+ selectedResourceIds: makeSelection(["a"]),
1290
+ }).length,
1291
+ ).toBe(1);
1292
+ });
1293
+
1294
+ test("is empty when nothing is selected", () => {
1295
+ expect(
1296
+ StatusPageResourceExplorerUtil.getSelectedResources({
1297
+ statusPageResources: [makeResource({ id: "a" })],
1298
+ selectedResourceIds: makeSelection([]),
1299
+ }),
1300
+ ).toEqual([]);
1301
+ });
1302
+ });
1303
+
1304
+ describe("keeping a selection honest across a refetch", () => {
1305
+ test("drops whatever the group no longer holds", () => {
1306
+ const next: Set<string> =
1307
+ StatusPageResourceExplorerUtil.retainSelectedResourceIds({
1308
+ selectedResourceIds: makeSelection(["a", "b", "c"]),
1309
+ statusPageResources: [
1310
+ makeResource({ id: "a" }),
1311
+ makeResource({ id: "c" }),
1312
+ ],
1313
+ });
1314
+
1315
+ expect([...next].sort()).toEqual(["a", "c"]);
1316
+ });
1317
+
1318
+ test("hands back the same set when nothing was dropped", () => {
1319
+ const current: Set<string> = makeSelection(["a", "b"]);
1320
+
1321
+ expect(
1322
+ StatusPageResourceExplorerUtil.retainSelectedResourceIds({
1323
+ selectedResourceIds: current,
1324
+ statusPageResources: [
1325
+ makeResource({ id: "a" }),
1326
+ makeResource({ id: "b" }),
1327
+ ],
1328
+ }),
1329
+ ).toBe(current);
1330
+ });
1331
+
1332
+ test("hands back the same empty set rather than a new one", () => {
1333
+ const current: Set<string> = makeSelection([]);
1334
+
1335
+ expect(
1336
+ StatusPageResourceExplorerUtil.retainSelectedResourceIds({
1337
+ selectedResourceIds: current,
1338
+ statusPageResources: [makeResource({ id: "a" })],
1339
+ }),
1340
+ ).toBe(current);
1341
+ });
1342
+
1343
+ test("empties a selection whose group came back empty", () => {
1344
+ expect(
1345
+ StatusPageResourceExplorerUtil.retainSelectedResourceIds({
1346
+ selectedResourceIds: makeSelection(["a"]),
1347
+ statusPageResources: [],
1348
+ }).size,
1349
+ ).toBe(0);
1350
+ });
1351
+ });
1352
+
1353
+ describe("what the confirmation says", () => {
1354
+ test("uses the singular for one resource, and says the monitor survives", () => {
1355
+ expect(
1356
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmTitle({
1357
+ count: 1,
1358
+ }),
1359
+ ).toBe("Remove 1 resource");
1360
+
1361
+ expect(
1362
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmMessage({
1363
+ count: 1,
1364
+ }),
1365
+ ).toBe(
1366
+ "Are you sure you want to remove 1 resource from this status page? The monitor itself is not deleted.",
1367
+ );
1368
+ });
1369
+
1370
+ test("uses the plural for several, and says the monitors survive", () => {
1371
+ expect(
1372
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmTitle({
1373
+ count: 27,
1374
+ }),
1375
+ ).toBe("Remove 27 resources");
1376
+
1377
+ expect(
1378
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmMessage({
1379
+ count: 27,
1380
+ }),
1381
+ ).toContain("remove 27 resources from this status page");
1382
+
1383
+ expect(
1384
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmMessage({
1385
+ count: 27,
1386
+ }),
1387
+ ).toContain("The monitors themselves are not deleted.");
1388
+ });
1389
+
1390
+ test("groups the thousands, because the number is the whole warning", () => {
1391
+ expect(
1392
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmTitle({
1393
+ count: 1506,
1394
+ }),
1395
+ ).toBe(`Remove ${(1506).toLocaleString()} resources`);
1396
+ });
1397
+ });
1398
+ });
931
1399
  });