@oneuptime/common 14.0.13 → 14.0.14

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 (1045) hide show
  1. package/Models/DatabaseModels/AlertGroupingRule.ts +10 -6
  2. package/Models/DatabaseModels/File.ts +41 -2
  3. package/Models/DatabaseModels/Form.ts +126 -0
  4. package/Models/DatabaseModels/IncidentGroupingRule.ts +10 -6
  5. package/Models/DatabaseModels/LogDropFilter.ts +1 -0
  6. package/Models/DatabaseModels/LogPipeline.ts +1 -0
  7. package/Models/DatabaseModels/LogScrubRule.ts +14 -8
  8. package/Models/DatabaseModels/MetricRecordingRule.ts +2 -1
  9. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.ts +4 -2
  10. package/Models/DatabaseModels/OnCallDutyPolicyUserOverride.ts +22 -9
  11. package/Models/DatabaseModels/ProjectCallSMSConfig.ts +6 -1
  12. package/Models/DatabaseModels/StatusPage.ts +8 -4
  13. package/Models/DatabaseModels/TraceDropFilter.ts +1 -0
  14. package/Models/DatabaseModels/TracePipeline.ts +1 -0
  15. package/Models/DatabaseModels/TraceRecordingRule.ts +2 -1
  16. package/Models/DatabaseModels/TraceScrubRule.ts +14 -8
  17. package/Models/DatabaseModels/UserOnCallLog.ts +4 -2
  18. package/Server/API/CustomDomainRoutes.ts +251 -0
  19. package/Server/API/DashboardAPI.ts +33 -4
  20. package/Server/API/DashboardDomainAPI.ts +63 -93
  21. package/Server/API/StatusPageAPI.ts +92 -0
  22. package/Server/API/StatusPageDomainAPI.ts +59 -96
  23. package/Server/Infrastructure/GlobalCache.ts +84 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1797700000000-AddFormBranding.ts +47 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  26. package/Server/Services/AlertGroupingEngineService.ts +48 -70
  27. package/Server/Services/AlertGroupingRuleService.ts +38 -0
  28. package/Server/Services/CephClusterService.ts +25 -0
  29. package/Server/Services/CloudResourceService.ts +42 -0
  30. package/Server/Services/DashboardDomainService.ts +640 -214
  31. package/Server/Services/DashboardService.ts +30 -8
  32. package/Server/Services/DatabaseService.ts +143 -12
  33. package/Server/Services/DockerHostService.ts +60 -0
  34. package/Server/Services/DockerSwarmClusterService.ts +25 -0
  35. package/Server/Services/FileService.ts +60 -0
  36. package/Server/Services/FormService.ts +212 -2
  37. package/Server/Services/GlobalOidcService.ts +10 -0
  38. package/Server/Services/GlobalSsoService.ts +10 -0
  39. package/Server/Services/HostService.ts +58 -0
  40. package/Server/Services/IncidentGroupingEngineService.ts +48 -70
  41. package/Server/Services/IncidentGroupingRuleService.ts +38 -0
  42. package/Server/Services/IoTFleetService.ts +26 -0
  43. package/Server/Services/KubernetesClusterService.ts +64 -0
  44. package/Server/Services/LabelService.ts +6 -17
  45. package/Server/Services/LogScrubRuleService.ts +50 -0
  46. package/Server/Services/OnCallDutyPolicyScheduleService.ts +264 -0
  47. package/Server/Services/OnCallDutyPolicyUserOverrideService.ts +9 -1
  48. package/Server/Services/OnCallNotificationAlertingService.ts +24 -29
  49. package/Server/Services/OnCallSetupReminderService.ts +41 -40
  50. package/Server/Services/PodmanHostService.ts +60 -0
  51. package/Server/Services/ProfileAggregationService.ts +38 -0
  52. package/Server/Services/ProjectCallSMSConfigService.ts +76 -3
  53. package/Server/Services/ProjectOidcService.ts +20 -0
  54. package/Server/Services/ProjectSsoService.ts +20 -0
  55. package/Server/Services/ProxmoxClusterService.ts +25 -0
  56. package/Server/Services/RumApplicationService.ts +45 -0
  57. package/Server/Services/ScheduledMaintenanceService.ts +9 -23
  58. package/Server/Services/ServerlessFunctionService.ts +47 -0
  59. package/Server/Services/ServiceService.ts +33 -10
  60. package/Server/Services/StatusPageDomainService.ts +622 -213
  61. package/Server/Services/StatusPageOidcService.ts +20 -0
  62. package/Server/Services/StatusPageResourceService.ts +89 -34
  63. package/Server/Services/StatusPageService.ts +270 -54
  64. package/Server/Services/StatusPageSsoService.ts +20 -0
  65. package/Server/Services/TraceScrubRuleService.ts +50 -0
  66. package/Server/Services/UserIncomingCallNumberService.ts +28 -14
  67. package/Server/Services/VMwareVCenterService.ts +25 -0
  68. package/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.ts +3 -3
  69. package/Server/Utils/Greenlock/CertificateOrder.ts +482 -0
  70. package/Server/Utils/Greenlock/CertificateOrderBudget.ts +134 -0
  71. package/Server/Utils/Greenlock/CertificateOrderFailures.ts +288 -0
  72. package/Server/Utils/Greenlock/CertificateOrderLock.ts +163 -0
  73. package/Server/Utils/Greenlock/CertificateOrderOutcome.ts +29 -0
  74. package/Server/Utils/Greenlock/CertificateOwners.ts +72 -0
  75. package/Server/Utils/Greenlock/CertificateReissueOrder.ts +99 -0
  76. package/Server/Utils/Greenlock/CustomDomainOrders.ts +397 -0
  77. package/Server/Utils/Greenlock/Greenlock.ts +839 -203
  78. package/Server/Utils/Rules/GroupingRuleEpisodeOwners.ts +551 -0
  79. package/Server/Utils/Rules/OwnerRuleAssignment.ts +8 -1
  80. package/Server/Utils/ScrubRuleValidation.ts +248 -0
  81. package/Server/Utils/StatusPage/AffectedStatusPageResources.ts +138 -0
  82. package/Server/Utils/StatusPage/StatusPagesListingMonitorsBuilder.ts +294 -0
  83. package/Server/Utils/Telemetry/DiscoveredResourceCreate.ts +275 -0
  84. package/Server/Utils/Telemetry/DiscoveredResourceUpdate.ts +217 -0
  85. package/Server/Utils/Telemetry/MessageQueueDiscovery.ts +8 -2
  86. package/Tests/App/Accounts/FormPage.test.tsx +238 -0
  87. package/Tests/App/Accounts/FormUtils.test.ts +108 -0
  88. package/Tests/App/AdminDashboard/AdminAddToProjectMembersTeam.test.tsx +1087 -0
  89. package/Tests/App/AdminDashboard/AdminAuthenticationRequireSso.test.tsx +140 -138
  90. package/Tests/App/AdminDashboard/AdminAuthenticationSsoCardLocales.test.tsx +144 -145
  91. package/Tests/App/AdminDashboard/AdminSettingsFormsOnePage.test.tsx +907 -0
  92. package/Tests/App/AdminDashboard/AdminSettingsSwitches.test.tsx +906 -0
  93. package/Tests/App/AdminDashboard/AdminSmtpSettingsForm.test.tsx +823 -0
  94. package/Tests/App/AdminDashboard/BulkAddUsersToProjectModal.test.tsx +341 -368
  95. package/Tests/App/AdminDashboard/GlobalSsoOidcPages.test.tsx +199 -54
  96. package/Tests/App/AdminDashboard/ProjectScopedTeamsPicker.test.tsx +991 -0
  97. package/Tests/App/Dashboard/AIInvestigationSettingsLimits.test.tsx +147 -90
  98. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +224 -104
  99. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +302 -0
  100. package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +408 -152
  101. package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +55 -0
  102. package/Tests/App/Dashboard/AffectedResourcesPickerEditForm.test.tsx +206 -115
  103. package/Tests/App/Dashboard/AffectedResourcesPickerFocusLeave.test.tsx +32 -0
  104. package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +206 -71
  105. package/Tests/App/Dashboard/AlertEpisodeViewFields.test.tsx +45 -9
  106. package/Tests/App/Dashboard/AnnouncementCreateForm.test.tsx +1208 -0
  107. package/Tests/App/Dashboard/AnnouncementEditAndTemplateForms.test.tsx +693 -0
  108. package/Tests/App/Dashboard/AnnouncementFormsStructure.test.ts +546 -0
  109. package/Tests/App/Dashboard/AnnouncementStatusPageSuggestions.test.tsx +425 -0
  110. package/Tests/App/Dashboard/AnnouncementsTableCreateLinks.test.tsx +267 -0
  111. package/Tests/App/Dashboard/ApiKeyCreateForm.test.ts +68 -51
  112. package/Tests/App/Dashboard/ApiKeyViewPermissions.test.tsx +11 -9
  113. package/Tests/App/Dashboard/ApiKeysCreateAccess.test.tsx +24 -16
  114. package/Tests/App/Dashboard/BulkChangeStateModalOnePage.test.tsx +333 -0
  115. package/Tests/App/Dashboard/CardDescriptionsSayWhatFor.test.tsx +307 -0
  116. package/Tests/App/Dashboard/ChangeAlertStateAIHeader.test.tsx +18 -4
  117. package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +7 -2
  118. package/Tests/App/Dashboard/ColorFieldsPrefilledPages.test.tsx +453 -0
  119. package/Tests/App/Dashboard/CreateFromRecordBreadcrumbs.test.ts +272 -0
  120. package/Tests/App/Dashboard/CreateFromRecordLinks.test.tsx +495 -0
  121. package/Tests/App/Dashboard/CreateFromRecordPages.test.tsx +1026 -0
  122. package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +65 -23
  123. package/Tests/App/Dashboard/CriteriaName.test.ts +5 -1
  124. package/Tests/App/Dashboard/CustomDomainCreateFlow.test.tsx +516 -0
  125. package/Tests/App/Dashboard/CustomDomainDnsSetupModal.test.tsx +547 -0
  126. package/Tests/App/Dashboard/CustomDomainsPages.test.tsx +1077 -0
  127. package/Tests/App/Dashboard/CustomFieldSimpleCreate.test.tsx +2 -2
  128. package/Tests/App/Dashboard/CustomFieldSimpleCreateRender.test.tsx +12 -6
  129. package/Tests/App/Dashboard/CustomFieldsSettingsIncidentOptions.test.tsx +1 -1
  130. package/Tests/App/Dashboard/CustomSmtpConfigForm.test.tsx +969 -0
  131. package/Tests/App/Dashboard/DashboardBlankCanvasAddWidget.test.tsx +425 -0
  132. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +400 -0
  133. package/Tests/App/Dashboard/DashboardComponentsMRTranslation.test.tsx +4 -3
  134. package/Tests/App/Dashboard/DashboardCreateForm.test.ts +375 -0
  135. package/Tests/App/Dashboard/DashboardCreateFromTemplate.test.tsx +727 -0
  136. package/Tests/App/Dashboard/DashboardEmptyCanvasAddWidget.test.tsx +86 -0
  137. package/Tests/App/Dashboard/DashboardPhoneProductsMenu.test.tsx +99 -9
  138. package/Tests/App/Dashboard/DashboardSharingCard.test.tsx +1226 -0
  139. package/Tests/App/Dashboard/DashboardSharingEntryPoints.test.tsx +383 -0
  140. package/Tests/App/Dashboard/DashboardSharingPage.test.tsx +478 -0
  141. package/Tests/App/Dashboard/DeclareFormsAdvancedRender.test.tsx +90 -34
  142. package/Tests/App/Dashboard/DeclareIncidentMonitorsApart.test.tsx +1028 -0
  143. package/Tests/App/Dashboard/DefaultSsoTeams.test.tsx +215 -0
  144. package/Tests/App/Dashboard/DisabledWarningArchived.test.tsx +3 -3
  145. package/Tests/App/Dashboard/DisabledWarningRobustness.test.tsx +15 -12
  146. package/Tests/App/Dashboard/DiscoveredResourceCreateForms.test.tsx +936 -0
  147. package/Tests/App/Dashboard/EmbeddedMetricCardGroup.test.tsx +720 -0
  148. package/Tests/App/Dashboard/EpisodeMemberRoleAssignmentsFormField.test.tsx +331 -0
  149. package/Tests/App/Dashboard/EpisodePostmortemPage.test.tsx +327 -0
  150. package/Tests/App/Dashboard/EscalationRuleForm.test.ts +2 -2
  151. package/Tests/App/Dashboard/EscalationRuleFormGuard.test.ts +6 -2
  152. package/Tests/App/Dashboard/EscalationRuleOneStep.test.tsx +8 -4
  153. package/Tests/App/Dashboard/EventMeasurements.test.ts +1175 -0
  154. package/Tests/App/Dashboard/EventMeasurementsCard.test.tsx +993 -0
  155. package/Tests/App/Dashboard/EventNoteComposerDialog.test.tsx +939 -0
  156. package/Tests/App/Dashboard/EventNotes.test.tsx +34 -1
  157. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +186 -1
  158. package/Tests/App/Dashboard/EventSettingsSwitchPages.test.tsx +625 -0
  159. package/Tests/App/Dashboard/ExceptionMonitorEnvironmentFilter.test.tsx +6 -2
  160. package/Tests/App/Dashboard/FeedNoteComposerDialog.test.tsx +1327 -0
  161. package/Tests/App/Dashboard/FeedNoteDialogHelpers.ts +109 -0
  162. package/Tests/App/Dashboard/FilterChipClearButton.test.tsx +356 -0
  163. package/Tests/App/Dashboard/FormBrandingSection.test.tsx +504 -0
  164. package/Tests/App/Dashboard/FormBrandingValues.test.ts +255 -0
  165. package/Tests/App/Dashboard/FormBuilderParts.test.tsx +38 -1
  166. package/Tests/App/Dashboard/FormBuilderUi.test.tsx +176 -2
  167. package/Tests/App/Dashboard/FormMappingCard.test.tsx +33 -13
  168. package/Tests/App/Dashboard/FormsMovedPagesAndSubmissions.test.tsx +1 -1
  169. package/Tests/App/Dashboard/GeneratedKeyForms.test.tsx +30 -7
  170. package/Tests/App/Dashboard/GlobalProbesOnNewMonitorsCard.test.tsx +258 -0
  171. package/Tests/App/Dashboard/GroupingRuleFormFlow.test.tsx +653 -37
  172. package/Tests/App/Dashboard/GroupingRulePages.test.tsx +218 -9
  173. package/Tests/App/Dashboard/IncidentCreateStatusPageScope.test.tsx +52 -4
  174. package/Tests/App/Dashboard/IncidentEpisodeFeedPublicNoteNotifyDefault.test.tsx +230 -338
  175. package/Tests/App/Dashboard/IncidentEpisodeViewFields.test.tsx +45 -9
  176. package/Tests/App/Dashboard/IncidentFeedPublicNoteNotifyDefault.test.tsx +227 -295
  177. package/Tests/App/Dashboard/IncidentLinkedAlertsSettingsPage.test.tsx +157 -181
  178. package/Tests/App/Dashboard/IncidentPostmortemPage.test.tsx +775 -0
  179. package/Tests/App/Dashboard/IncidentRoleFormField.test.tsx +379 -15
  180. package/Tests/App/Dashboard/IncidentRolesSettingsPage.test.tsx +148 -32
  181. package/Tests/App/Dashboard/IncidentTemplateInitialState.test.tsx +430 -0
  182. package/Tests/App/Dashboard/IncidentTemplateMonitorsApart.test.tsx +492 -0
  183. package/Tests/App/Dashboard/IncomingCallEscalationOneStep.test.tsx +830 -0
  184. package/Tests/App/Dashboard/IncomingCallEscalationRuleForm.test.ts +510 -0
  185. package/Tests/App/Dashboard/IncomingCallEscalationRuleFormGuard.test.ts +378 -0
  186. package/Tests/App/Dashboard/IngestionKeyForm.test.ts +664 -0
  187. package/Tests/App/Dashboard/IngestionKeySelectorCreate.test.tsx +523 -0
  188. package/Tests/App/Dashboard/InventoryTypeAndStatusFacets.test.tsx +130 -9
  189. package/Tests/App/Dashboard/IpAllowlistCopy.test.ts +122 -0
  190. package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +19 -3
  191. package/Tests/App/Dashboard/KubernetesMetricsSetupEmptyState.test.tsx +275 -0
  192. package/Tests/App/Dashboard/KubernetesMetricsSetupHints.test.tsx +720 -0
  193. package/Tests/App/Dashboard/LabelsFormField.test.tsx +18 -13
  194. package/Tests/App/Dashboard/LegacyDefaultAssigneeNote.test.tsx +359 -0
  195. package/Tests/App/Dashboard/LogMonitorAttributeOperatorPreview.test.tsx +10 -10
  196. package/Tests/App/Dashboard/MarkdownTemplateDialogsWide.test.tsx +42 -20
  197. package/Tests/App/Dashboard/MeasurementForms.test.tsx +191 -5
  198. package/Tests/App/Dashboard/MeasurementPagesI18n.test.ts +2 -0
  199. package/Tests/App/Dashboard/MeasurementSetup.test.ts +5 -2
  200. package/Tests/App/Dashboard/MenuSpecificFoldedSections.test.tsx +38 -12
  201. package/Tests/App/Dashboard/MessageQueueRulePages.test.tsx +34 -11
  202. package/Tests/App/Dashboard/MetricAndRecordingRuleFormsRender.test.tsx +1206 -0
  203. package/Tests/App/Dashboard/MetricResultsState.test.ts +248 -0
  204. package/Tests/App/Dashboard/MetricViewResultsState.test.tsx +404 -0
  205. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +1 -1
  206. package/Tests/App/Dashboard/MonitorCriteriaAdvancedOptions.test.tsx +77 -27
  207. package/Tests/App/Dashboard/MonitorCriteriaAttributeFilter.test.tsx +5 -8
  208. package/Tests/App/Dashboard/MonitorCriteriaHeaderControls.test.tsx +228 -0
  209. package/Tests/App/Dashboard/MonitorCriteriaIncidentRoles.test.tsx +411 -0
  210. package/Tests/App/Dashboard/MonitorFeedRefresh.test.tsx +5 -1
  211. package/Tests/App/Dashboard/MonitorFormIncidentRoles.test.tsx +460 -0
  212. package/Tests/App/Dashboard/MonitorIntervalRedirect.test.tsx +299 -0
  213. package/Tests/App/Dashboard/MonitorOverviewHero.test.tsx +243 -2
  214. package/Tests/App/Dashboard/MonitorProbesAndIntervalPage.test.tsx +638 -0
  215. package/Tests/App/Dashboard/MonitorStepsDefaultStatusAdvanced.test.tsx +2 -2
  216. package/Tests/App/Dashboard/MonitorSummaryTestMonitorButton.test.tsx +2 -2
  217. package/Tests/App/Dashboard/MonitoringIntervalCard.test.tsx +493 -0
  218. package/Tests/App/Dashboard/MonitoringSwitch.test.tsx +597 -0
  219. package/Tests/App/Dashboard/MovedRunnerSettingsRedirects.test.tsx +4 -5
  220. package/Tests/App/Dashboard/NotificationChannelOffSwitchLists.test.tsx +636 -0
  221. package/Tests/App/Dashboard/OnCallPolicyCreateFormGuard.test.ts +8 -4
  222. package/Tests/App/Dashboard/OnCallPolicyFirstResponders.test.tsx +1 -1
  223. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +54 -0
  224. package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +43 -24
  225. package/Tests/App/Dashboard/OnCallRulesRedirects.test.tsx +530 -0
  226. package/Tests/App/Dashboard/OnCallRulesTable.test.tsx +158 -74
  227. package/Tests/App/Dashboard/OnCallRulesTabs.test.tsx +511 -0
  228. package/Tests/App/Dashboard/OnCallScheduleAddLayerDefaults.test.tsx +236 -0
  229. package/Tests/App/Dashboard/OnCallScheduleCreateFormGuard.test.ts +633 -0
  230. package/Tests/App/Dashboard/OnCallScheduleOverrideClarity.test.tsx +13 -2
  231. package/Tests/App/Dashboard/OnCallScheduleWhoTakesTurns.test.tsx +771 -0
  232. package/Tests/App/Dashboard/OnCallSharedCalendarFeedSettingsForm.test.tsx +357 -0
  233. package/Tests/App/Dashboard/OnCallShiftRemindersAndUpcomingShifts.test.tsx +16 -6
  234. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +112 -23
  235. package/Tests/App/Dashboard/PageSearchIndexCoversMenus.test.tsx +594 -0
  236. package/Tests/App/Dashboard/PageSearchIndexCoversRoutes.test.tsx +271 -0
  237. package/Tests/App/Dashboard/PageSearchRanking.test.tsx +373 -0
  238. package/Tests/App/Dashboard/PostmortemPageParts.test.tsx +548 -0
  239. package/Tests/App/Dashboard/ProbeAgreementCard.test.tsx +483 -0
  240. package/Tests/App/Dashboard/ProductOrientation.test.tsx +9 -2
  241. package/Tests/App/Dashboard/ProjectAISettingsPages.test.tsx +282 -404
  242. package/Tests/App/Dashboard/ProjectAiSettingsSwitchPages.test.tsx +1414 -0
  243. package/Tests/App/Dashboard/ProjectNotificationChannels.test.tsx +1191 -0
  244. package/Tests/App/Dashboard/ProjectSettingsSwitchCards.test.tsx +603 -0
  245. package/Tests/App/Dashboard/RemindersCard.test.tsx +477 -0
  246. package/Tests/App/Dashboard/ResourceDetailsCard.test.tsx +458 -0
  247. package/Tests/App/Dashboard/ResourceRuleForm.test.ts +525 -0
  248. package/Tests/App/Dashboard/ResourceRuleFormsRender.test.tsx +803 -0
  249. package/Tests/App/Dashboard/RoleAccess.test.ts +753 -0
  250. package/Tests/App/Dashboard/RoleCardSelectOptions.test.ts +13 -6
  251. package/Tests/App/Dashboard/RouteUtilPageRoute.test.ts +116 -0
  252. package/Tests/App/Dashboard/RowActionPlacementOverrides.test.tsx +1 -1
  253. package/Tests/App/Dashboard/RumSessionReplayRetentionSettings.test.tsx +172 -219
  254. package/Tests/App/Dashboard/RunbookStepHeaderControls.test.tsx +269 -0
  255. package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +45 -85
  256. package/Tests/App/Dashboard/RunnerSupersededByAiAgentNote.test.tsx +16 -23
  257. package/Tests/App/Dashboard/ScheduledMaintenanceAffectedResourcesEditForm.test.tsx +485 -0
  258. package/Tests/App/Dashboard/ScheduledMaintenanceChangeStateNotifyDefault.test.tsx +27 -2
  259. package/Tests/App/Dashboard/ScheduledMaintenanceCreateForm.test.tsx +65 -28
  260. package/Tests/App/Dashboard/ScheduledMaintenanceFeedPublicNoteNotifyDefault.test.tsx +208 -309
  261. package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +36 -53
  262. package/Tests/App/Dashboard/ScheduledMaintenanceFormsStructure.test.ts +83 -14
  263. package/Tests/App/Dashboard/ScheduledMaintenanceMonitorsApart.test.tsx +1085 -0
  264. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +378 -25
  265. package/Tests/App/Dashboard/ScheduledMaintenanceStatusPageSuggestions.test.tsx +513 -0
  266. package/Tests/App/Dashboard/ScheduledMaintenanceTemplateForm.test.tsx +31 -9
  267. package/Tests/App/Dashboard/ScheduledMaintenanceTemplateMonitorsApart.test.tsx +760 -0
  268. package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +11 -13
  269. package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +228 -69
  270. package/Tests/App/Dashboard/SelectedProjectSwitches.test.tsx +359 -0
  271. package/Tests/App/Dashboard/ServerlessSetupGuide.test.ts +1 -1
  272. package/Tests/App/Dashboard/SessionReplayAllowedCard.test.tsx +297 -0
  273. package/Tests/App/Dashboard/SetupGuideCard.test.tsx +7 -1
  274. package/Tests/App/Dashboard/ShortFormsOnePage.test.tsx +591 -0
  275. package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +253 -6
  276. package/Tests/App/Dashboard/SloOverviewData.test.tsx +99 -0
  277. package/Tests/App/Dashboard/SloOverviewLayout.test.tsx +3 -1
  278. package/Tests/App/Dashboard/SloSettings.test.tsx +257 -4
  279. package/Tests/App/Dashboard/SsoPages.test.tsx +448 -52
  280. package/Tests/App/Dashboard/StateChangeDialogsFolded.test.tsx +695 -0
  281. package/Tests/App/Dashboard/StateChangeFormFields.test.ts +376 -0
  282. package/Tests/App/Dashboard/StatusPageAccessCard.test.tsx +1088 -0
  283. package/Tests/App/Dashboard/StatusPageAccessCopy.test.ts +450 -0
  284. package/Tests/App/Dashboard/StatusPageAccessMenu.test.tsx +137 -0
  285. package/Tests/App/Dashboard/StatusPageAccessPage.test.tsx +458 -0
  286. package/Tests/App/Dashboard/StatusPageAdvancedSettingsPage.test.tsx +30 -86
  287. package/Tests/App/Dashboard/StatusPageBrandingPage.test.tsx +28 -15
  288. package/Tests/App/Dashboard/StatusPageDisplaySettingsCard.test.tsx +949 -14
  289. package/Tests/App/Dashboard/StatusPagePrivateUsersNotice.test.tsx +233 -0
  290. package/Tests/App/Dashboard/StatusPageReportsCard.test.tsx +1001 -0
  291. package/Tests/App/Dashboard/StatusPageRequireSsoCard.test.tsx +247 -0
  292. package/Tests/App/Dashboard/StatusPageSubscriberSettingsPages.test.tsx +4 -17
  293. package/Tests/App/Dashboard/StatusPageSuggestions.test.tsx +930 -0
  294. package/Tests/App/Dashboard/StatusPageSwitchCardPages.test.tsx +335 -0
  295. package/Tests/App/Dashboard/TeamBlockPermissionsRedirect.test.tsx +332 -0
  296. package/Tests/App/Dashboard/TeamCreateForm.test.ts +206 -0
  297. package/Tests/App/Dashboard/TeamViewPermissions.test.tsx +713 -0
  298. package/Tests/App/Dashboard/TeamViewSideMenuBlockPermissions.test.tsx +113 -0
  299. package/Tests/App/Dashboard/TeamsCreateAccess.test.tsx +799 -0
  300. package/Tests/App/Dashboard/TelemetryDataRuleForms.test.ts +655 -0
  301. package/Tests/App/Dashboard/TelemetryDataRuleFormsRender.test.tsx +1014 -0
  302. package/Tests/App/Dashboard/TelemetryIngestionKeyEdit.test.tsx +6 -3
  303. package/Tests/App/Dashboard/TelemetryIngestionKeyForm.test.tsx +446 -446
  304. package/Tests/App/Dashboard/TelemetryMonitorFiltersFold.test.tsx +613 -0
  305. package/Tests/App/Dashboard/TelemetryRetentionShells.test.tsx +37 -2
  306. package/Tests/App/Dashboard/TemplateFormsNoInternalDataWarning.test.tsx +3 -3
  307. package/Tests/App/Dashboard/TraceExplorer.test.tsx +338 -0
  308. package/Tests/App/Dashboard/TwilioConfigFirstDefault.test.tsx +786 -0
  309. package/Tests/App/Dashboard/UpcomingShiftGetCover.test.tsx +306 -0
  310. package/Tests/App/Dashboard/UseBulkShortenDeviceNames.test.tsx +36 -11
  311. package/Tests/App/Dashboard/UserOverrideForm.test.ts +505 -0
  312. package/Tests/App/Dashboard/UserOverrideFormGuard.test.ts +334 -0
  313. package/Tests/App/Dashboard/UserOverrideWhoIsAway.test.tsx +999 -0
  314. package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +33 -11
  315. package/Tests/App/Dashboard/UserSettingsSetupChecklistPage.test.tsx +49 -4
  316. package/Tests/App/Dashboard/UsersPageEmptyState.test.tsx +245 -0
  317. package/Tests/App/Dashboard/WorkflowVariableOAuthSettingsEditSteps.test.tsx +13 -6
  318. package/Tests/App/Dashboard/WorkspaceMenusConnected.test.tsx +0 -2
  319. package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +108 -86
  320. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +397 -0
  321. package/Tests/App/StatusPage/StatusPageResourceForm.test.tsx +931 -0
  322. package/Tests/App/StatusPage/StatusPageSubscribeOnePage.test.tsx +686 -0
  323. package/Tests/DialogActionRules.ts +16 -5
  324. package/Tests/Helpers/CardHeaderScan.ts +258 -0
  325. package/Tests/Helpers/FormStepsScan.ts +576 -11
  326. package/Tests/Helpers/MonitorGroupStatusPageRows.ts +237 -0
  327. package/Tests/Helpers/NestedControls.ts +184 -0
  328. package/Tests/Helpers/NestedControlsScan.ts +414 -0
  329. package/Tests/Helpers/SteppedFooterScan.ts +722 -0
  330. package/Tests/Models/DatabaseModels/FormModel.test.ts +31 -7
  331. package/Tests/Models/DatabaseModels/UserOverrideColumnDescriptions.test.ts +123 -0
  332. package/Tests/Models/TelemetryDataRuleColumnDefaults.test.ts +239 -0
  333. package/Tests/ResponsiveFlexLayout.test.ts +111 -0
  334. package/Tests/ResponsiveFlexLayout.ts +165 -0
  335. package/Tests/Server/API/DashboardDomainOrderSslAPI.test.ts +372 -0
  336. package/Tests/Server/API/DashboardDomainVerifyCnameAPI.test.ts +921 -0
  337. package/Tests/Server/API/DashboardSharingPublicRoutes.test.ts +559 -0
  338. package/Tests/Server/API/FormBrandingPublicRoutes.test.ts +680 -0
  339. package/Tests/Server/API/ProjectAPICreateWithTenantHeader.test.ts +300 -0
  340. package/Tests/Server/API/ProjectCreateTestHelpers.ts +211 -0
  341. package/Tests/Server/API/ProjectCreateWithTenantHeaderPostgres.test.ts +387 -0
  342. package/Tests/Server/API/PublicRouteInvalidAccessToken.test.ts +29 -12
  343. package/Tests/Server/API/StatusPageDomainVerifyCnameAPI.test.ts +1090 -0
  344. package/Tests/Server/API/StatusPageMasterPageAccess.test.ts +254 -0
  345. package/Tests/Server/API/StatusPageReportScheduleWrites.test.ts +829 -0
  346. package/Tests/Server/API/StatusPageUptimeSettingsWrites.test.ts +417 -0
  347. package/Tests/Server/API/StatusPagesListingMonitorsAPI.test.ts +1029 -0
  348. package/Tests/Server/API/StatusPagesListingMonitorsRoute.test.ts +286 -0
  349. package/Tests/Server/Infrastructure/GlobalCache.test.ts +156 -0
  350. package/Tests/Server/Infrastructure/Postgres/MigrateIncidentFormsToFormsMigration.test.ts +52 -1
  351. package/Tests/Server/Services/CustomDomainCertificateLifecycle.test.ts +1559 -0
  352. package/Tests/Server/Services/CustomDomainCertificateReissue.test.ts +186 -16
  353. package/Tests/Server/Services/DashboardAccessChoice.test.ts +657 -0
  354. package/Tests/Server/Services/DashboardCreateFromTemplate.test.ts +200 -0
  355. package/Tests/Server/Services/DashboardDomainCertificateSweeps.test.ts +1142 -0
  356. package/Tests/Server/Services/DiscoveredResourceCreate.test.ts +864 -0
  357. package/Tests/Server/Services/DiscoveredResourceUpdate.test.ts +822 -0
  358. package/Tests/Server/Services/EpisodeRuleSeverityRepair.test.ts +3 -4
  359. package/Tests/Server/Services/FileServiceProject.test.ts +345 -0
  360. package/Tests/Server/Services/FormBranding.test.ts +982 -0
  361. package/Tests/Server/Services/FormPublicForm.test.ts +15 -0
  362. package/Tests/Server/Services/GroupingRuleEpisodeOwners.test.ts +857 -0
  363. package/Tests/Server/Services/IncidentFormPostgres.test.ts +297 -1
  364. package/Tests/Server/Services/MachinePickedColors.test.ts +202 -0
  365. package/Tests/Server/Services/OidcProviderCreateDefaults.test.ts +252 -0
  366. package/Tests/Server/Services/OnCallDutyPolicyScheduleFirstLayer.test.ts +799 -0
  367. package/Tests/Server/Services/OnCallDutyPolicyScheduleFirstLayerPlans.test.ts +172 -0
  368. package/Tests/Server/Services/OnCallDutyPolicyUserOverrideWhoIsAway.test.ts +571 -0
  369. package/Tests/Server/Services/OnCallSetupReminder.test.ts +35 -13
  370. package/Tests/Server/Services/OnCallUndeliverablePageRulesLink.test.ts +217 -0
  371. package/Tests/Server/Services/ProfileAggregationService.test.ts +213 -4
  372. package/Tests/Server/Services/ProjectCallSMSConfigFirstDefault.test.ts +699 -0
  373. package/Tests/Server/Services/ProjectCallSMSConfigFirstDefaultBilling.test.ts +247 -0
  374. package/Tests/Server/Services/SamlProviderCreateDefaults.test.ts +255 -0
  375. package/Tests/Server/Services/ScheduledMaintenanceSubscriberMonitorGroups.test.ts +333 -0
  376. package/Tests/Server/Services/ScrubRuleSaveValidation.test.ts +947 -0
  377. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +17 -4
  378. package/Tests/Server/Services/StatusPageAccessChoice.test.ts +548 -0
  379. package/Tests/Server/Services/StatusPageDomainCertificateSweeps.test.ts +1238 -0
  380. package/Tests/Server/Services/TeamCreateAccessGrant.test.ts +607 -0
  381. package/Tests/Server/Services/TwilioConfigSendersGuard.test.ts +249 -0
  382. package/Tests/Server/Services/VerificationCodesUseProjectTwilioConfig.test.ts +264 -0
  383. package/Tests/Server/Types/Database/Permissions/FormBrandingColumns.test.ts +270 -0
  384. package/Tests/Server/Utils/Greenlock/CertificateCleanup.test.ts +526 -0
  385. package/Tests/Server/Utils/Greenlock/CertificateOrder.test.ts +1062 -0
  386. package/Tests/Server/Utils/Greenlock/CertificateOrderBudget.test.ts +243 -0
  387. package/Tests/Server/Utils/Greenlock/CertificateOrderFailures.test.ts +293 -0
  388. package/Tests/Server/Utils/Greenlock/CertificateOrderLock.test.ts +152 -0
  389. package/Tests/Server/Utils/Greenlock/CertificateOwnersGuard.test.ts +119 -0
  390. package/Tests/Server/Utils/Greenlock/CertificateRenewalOwnership.test.ts +1170 -0
  391. package/Tests/Server/Utils/Greenlock/CertificateRenewalSafety.test.ts +368 -0
  392. package/Tests/Server/Utils/Greenlock/CertificateRenewalSchedule.test.ts +188 -11
  393. package/Tests/Server/Utils/Greenlock/CustomDomainOrders.test.ts +723 -0
  394. package/Tests/Server/Utils/Greenlock/InMemoryRedis.ts +189 -0
  395. package/Tests/Server/Utils/Greenlock/NginxAcmeCertificatesToDisk.test.ts +242 -0
  396. package/Tests/Server/Utils/Greenlock/NginxCustomCertificatesToDisk.test.ts +305 -0
  397. package/Tests/Server/Utils/Greenlock/OrderCertGuards.test.ts +583 -0
  398. package/Tests/Server/Utils/Greenlock/OrderCertStorage.test.ts +203 -0
  399. package/Tests/Server/Utils/StatusPage/AffectedStatusPageResources.test.ts +700 -0
  400. package/Tests/Server/Utils/StatusPage/StatusPagesListingMonitorsBuilder.test.ts +744 -0
  401. package/Tests/Types/CustomDomain/CustomDomainCertificates.test.ts +106 -0
  402. package/Tests/Types/CustomDomain/CustomDomainVerification.test.ts +94 -0
  403. package/Tests/Types/Dashboard/DashboardAccess.test.ts +460 -0
  404. package/Tests/Types/Filter/FilterConditionUtil.test.ts +59 -0
  405. package/Tests/Types/Form/FormBranding.test.ts +760 -0
  406. package/Tests/Types/IncomingCall/IncomingCallRingTime.test.ts +80 -0
  407. package/Tests/Types/NotificationRule/OnCallRuleKind.test.ts +271 -0
  408. package/Tests/Types/OnCallDutyPolicy/ScheduleFirstLayer.test.ts +300 -0
  409. package/Tests/Types/OnCallDutyPolicy/ScheduleLayerDefaults.test.ts +316 -0
  410. package/Tests/Types/OnCallDutyPolicy/UserOverrideCoverRequest.test.ts +257 -0
  411. package/Tests/Types/SSO/OidcProviderDefaults.test.ts +474 -0
  412. package/Tests/Types/SSO/SamlProviderDefaults.test.ts +150 -0
  413. package/Tests/Types/SSO/SsoProviderDefaults.test.ts +181 -0
  414. package/Tests/Types/StatusPage/StatusPageAccess.test.ts +393 -0
  415. package/Tests/Types/StatusPage/StatusPagesListingMonitors.test.ts +149 -0
  416. package/Tests/Types/Telemetry/ScrubRule.test.ts +375 -0
  417. package/Tests/UI/Components/AdvancedPageSection.test.tsx +201 -61
  418. package/Tests/UI/Components/BasicFormModalSteps.test.tsx +129 -153
  419. package/Tests/UI/Components/Card.test.tsx +354 -367
  420. package/Tests/UI/Components/CardHeaderActionsGuard.test.tsx +605 -0
  421. package/Tests/UI/Components/CardModelDetailHeaderLayout.test.tsx +23 -8
  422. package/Tests/UI/Components/CardModelDetailOnBeforeUpdate.test.tsx +224 -0
  423. package/Tests/UI/Components/CardModelDetailPageButtons.test.tsx +231 -0
  424. package/Tests/UI/Components/ChoiceRows.test.tsx +365 -0
  425. package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +341 -5
  426. package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +655 -64
  427. package/Tests/UI/Components/Detail/DetailCreatedOnIdLine.test.tsx +669 -0
  428. package/Tests/UI/Components/Detail/DetailIdLineDarkMode.test.ts +34 -7
  429. package/Tests/UI/Components/Detail/DetailIdLineInLocale.test.tsx +71 -0
  430. package/Tests/UI/Components/Detail/DetailRecordIdLine.test.tsx +26 -7
  431. package/Tests/UI/Components/Detail/DetailRecordLine.test.tsx +326 -0
  432. package/Tests/UI/Components/Detail/DetailRecordTime.test.ts +324 -0
  433. package/Tests/UI/Components/DetailCompactStyle.test.tsx +7 -3
  434. package/Tests/UI/Components/Dropdown/DropdownChange.test.ts +163 -0
  435. package/Tests/UI/Components/EntityDropdown.test.tsx +103 -1
  436. package/Tests/UI/Components/EntityDropdownClearButton.test.tsx +638 -0
  437. package/Tests/UI/Components/EntityDropdownEscape.test.tsx +6 -6
  438. package/Tests/UI/Components/EntityDropdownFocusLeave.test.tsx +21 -4
  439. package/Tests/UI/Components/EntityDropdownQuery.test.tsx +411 -0
  440. package/Tests/UI/Components/EntityDropdownQueryHelpers.test.ts +131 -0
  441. package/Tests/UI/Components/FilePicker.test.tsx +220 -1
  442. package/Tests/UI/Components/FoldedSection/FoldedSection.test.tsx +582 -0
  443. package/Tests/UI/Components/FoldedSection/FoldedSectionDarkMode.test.ts +197 -0
  444. package/Tests/UI/Components/FoldedSection/FoldedSectionItem.test.ts +247 -0
  445. package/Tests/UI/Components/FoldedSection/FoldedSectionQueries.ts +86 -0
  446. package/Tests/UI/Components/Forms/AdvancedStepsGuard.test.ts +358 -32
  447. package/Tests/UI/Components/Forms/AnchoredFieldPopupPlacement.test.tsx +195 -0
  448. package/Tests/UI/Components/Forms/BasicFormCollapsibleSections.test.tsx +187 -23
  449. package/Tests/UI/Components/Forms/BasicFormFillsInOnShow.test.tsx +246 -0
  450. package/Tests/UI/Components/Forms/BasicFormFooterSetValue.test.tsx +283 -0
  451. package/Tests/UI/Components/Forms/BasicFormPrimaryActionLastStep.test.tsx +780 -0
  452. package/Tests/UI/Components/Forms/BasicFormSingleStep.test.tsx +232 -0
  453. package/Tests/UI/Components/Forms/BasicFormStepValidation.test.tsx +7 -4
  454. package/Tests/UI/Components/Forms/BasicFormSubmitAllSteps.test.tsx +4 -3
  455. package/Tests/UI/Components/Forms/CreateFormDefaultsGuard.test.ts +252 -7
  456. package/Tests/UI/Components/Forms/DeclareAndCreateFormsGuard.test.ts +247 -7
  457. package/Tests/UI/Components/Forms/DiscoveredResourceCreateFormsGuard.test.ts +492 -0
  458. package/Tests/UI/Components/Forms/FilterConditionOnlyWithTwoFiltersGuard.test.ts +333 -0
  459. package/Tests/UI/Components/Forms/FoldedEditorWidthTiming.test.tsx +127 -0
  460. package/Tests/UI/Components/Forms/FoldedSectionsGuard.test.ts +523 -0
  461. package/Tests/UI/Components/Forms/FollowPickName.test.ts +88 -0
  462. package/Tests/UI/Components/Forms/FormFieldDropdownChange.test.tsx +294 -0
  463. package/Tests/UI/Components/Forms/FormModalWidth.test.tsx +237 -2
  464. package/Tests/UI/Components/Forms/FormSummary.test.tsx +181 -0
  465. package/Tests/UI/Components/Forms/IncidentEpisodePublicNoteNotifyPayload.test.tsx +110 -86
  466. package/Tests/UI/Components/Forms/LabelsFormFieldGuard.test.ts +101 -96
  467. package/Tests/UI/Components/Forms/LongFormStepsGuard.test.ts +559 -10
  468. package/Tests/UI/Components/Forms/MarkdownFormsAreWide.test.ts +56 -4
  469. package/Tests/UI/Components/Forms/MetricAndRecordingRuleFormsGuard.test.ts +400 -0
  470. package/Tests/UI/Components/Forms/ModelFormColorDefaults.test.tsx +659 -0
  471. package/Tests/UI/Components/Forms/ModelFormCreateDefaults.test.tsx +108 -4
  472. package/Tests/UI/Components/Forms/ModelFormDropdownQuery.test.tsx +403 -0
  473. package/Tests/UI/Components/Forms/ModelFormPreservesUserInput.test.tsx +126 -0
  474. package/Tests/UI/Components/Forms/ModelFormSinglePickPeoplePicker.test.tsx +453 -0
  475. package/Tests/UI/Components/Forms/OidcProviderFormsGuard.test.ts +321 -0
  476. package/Tests/UI/Components/Forms/OneIncidentRolePickerGuard.test.ts +823 -0
  477. package/Tests/UI/Components/Forms/OneSwitchCardsGuard.test.ts +739 -0
  478. package/Tests/UI/Components/Forms/OpenFormSections.test.tsx +169 -0
  479. package/Tests/UI/Components/Forms/OverloadedFormStepsGuard.test.ts +21 -9
  480. package/Tests/UI/Components/Forms/PrimaryActionLastStepGuard.test.ts +478 -0
  481. package/Tests/UI/Components/Forms/ProjectTeamFormsGuard.test.ts +240 -0
  482. package/Tests/UI/Components/Forms/ResourceDetailsOnePlaceGuard.test.ts +936 -0
  483. package/Tests/UI/Components/Forms/ResourceRuleFormsGuard.test.ts +527 -0
  484. package/Tests/UI/Components/Forms/SamlProviderFormsGuard.test.ts +387 -0
  485. package/Tests/UI/Components/Forms/SmallWizardsOnePageGuard.test.ts +331 -0
  486. package/Tests/UI/Components/Forms/SmtpConfigFormsGuard.test.ts +470 -0
  487. package/Tests/UI/Components/Forms/StateChangeDialogsFoldTheNote.test.ts +322 -0
  488. package/Tests/UI/Components/Forms/StatusPageResourceFormsGuard.test.ts +381 -0
  489. package/Tests/UI/Components/Forms/SteppedFormFooter.test.ts +225 -0
  490. package/Tests/UI/Components/Forms/SteppedFormFooterTiming.test.tsx +82 -40
  491. package/Tests/UI/Components/Forms/SwitchCardsGuard.test.ts +339 -0
  492. package/Tests/UI/Components/Forms/TelemetryDataRuleFormsGuard.test.ts +383 -0
  493. package/Tests/UI/Components/Forms/UniqueName.test.ts +163 -0
  494. package/Tests/UI/Components/Forms/Utils/AdvancedFormSection.test.ts +131 -11
  495. package/Tests/UI/Components/Forms/Utils/CreateFormColorDefaults.test.ts +373 -0
  496. package/Tests/UI/Components/Forms/Utils/FoldedFormFields.test.ts +482 -0
  497. package/Tests/UI/Components/LabelRuleImportExport.test.tsx +32 -0
  498. package/Tests/UI/Components/MemberRoleAssignment.test.tsx +51 -7
  499. package/Tests/UI/Components/ModalSecondaryButton.test.tsx +60 -3
  500. package/Tests/UI/Components/ModelFormDraftValues.test.tsx +255 -0
  501. package/Tests/UI/Components/ModelPageHeaderChanged.test.tsx +293 -0
  502. package/Tests/UI/Components/ModelSwitchCard.test.tsx +813 -0
  503. package/Tests/UI/Components/ModelSwitchEvents.test.ts +188 -0
  504. package/Tests/UI/Components/ModelSwitchRow.test.tsx +861 -0
  505. package/Tests/UI/Components/ModelSwitchUtil.test.ts +239 -0
  506. package/Tests/UI/Components/ModelSwitchesCard.test.tsx +699 -0
  507. package/Tests/UI/Components/NavBar.test.tsx +41 -2
  508. package/Tests/UI/Components/NavBarCategoryToggleDarkMode.test.ts +12 -0
  509. package/Tests/UI/Components/NavBarMenuCatalog.test.tsx +197 -30
  510. package/Tests/UI/Components/NavBarMenuFolding.test.tsx +221 -39
  511. package/Tests/UI/Components/NavBarMenuSearch.test.tsx +15 -10
  512. package/Tests/UI/Components/NestedControlsGuard.test.ts +300 -0
  513. package/Tests/UI/Components/PageBreadcrumbOverride.test.tsx +202 -0
  514. package/Tests/UI/Components/PeoplePicker/OwnersFieldGuard.test.ts +269 -5
  515. package/Tests/UI/Components/PeoplePicker/PeoplePickerChange.test.tsx +414 -0
  516. package/Tests/UI/Components/PeoplePicker/PeoplePickerExcludePicks.test.tsx +582 -0
  517. package/Tests/UI/Components/PeoplePicker/PeoplePickerSinglePick.test.tsx +519 -0
  518. package/Tests/UI/Components/PeoplePicker/PeoplePickerSinglePickTypes.test.ts +174 -0
  519. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +8 -3
  520. package/Tests/UI/Components/RuleCriteria/RuleCriteriaNamesGuard.test.ts +14 -6
  521. package/Tests/UI/Components/RuleRun/RuleViewDescription.test.tsx +107 -0
  522. package/Tests/UI/Components/SaveStatus.test.tsx +81 -0
  523. package/Tests/UI/Components/SmtpConfig/SmtpConfigFormFields.test.ts +1078 -0
  524. package/Tests/UI/Components/Sso/OidcProviderForm.test.tsx +608 -0
  525. package/Tests/UI/Components/Sso/OidcProviderFormFields.test.ts +698 -0
  526. package/Tests/UI/Components/Sso/SamlProviderForm.test.tsx +583 -0
  527. package/Tests/UI/Components/Sso/SamlProviderFormFields.test.ts +619 -0
  528. package/Tests/UI/Components/SteppedEditFormSave.test.tsx +199 -141
  529. package/Tests/UI/Components/Table/TableEmptyStateComponent.test.tsx +143 -0
  530. package/Tests/UI/Components/UseSaveModelSwitch.test.tsx +409 -0
  531. package/Tests/UI/Components/Workflow/ArgumentsForm.test.tsx +3 -3
  532. package/Tests/UI/Components/Workflow/ArgumentsFormAdvancedSettings.test.tsx +83 -27
  533. package/Tests/UI/Components/Workflow/WorkflowLogModal.test.tsx +7 -2
  534. package/Tests/UI/Components/useSaveOnChange.test.tsx +341 -0
  535. package/Tests/UI/Monitor/MonitorStepRetrySettings.test.tsx +1 -1
  536. package/Tests/UI/Rum/ReplayTimeline.test.tsx +75 -5
  537. package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +97 -0
  538. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +12 -39
  539. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +1 -6
  540. package/Tests/{App/Dashboard → UI/Utils}/DefaultInviteTeam.test.ts +126 -4
  541. package/Tests/UI/Utils/GrantablePermission.test.ts +172 -0
  542. package/Tests/UI/Utils/PermissionGateColumnUpdate.test.ts +211 -0
  543. package/Tests/UI/Utils/TranslateTemplate.test.ts +31 -0
  544. package/Tests/Utils/DistinctColor.test.ts +446 -0
  545. package/Tests/Utils/Monitor/MonitorOverviewPresentationUtil.test.ts +14 -2
  546. package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +1 -1
  547. package/Tests/Utils/NetworkDiscovery/ShortHostnameUtil.test.ts +2 -2
  548. package/Tests/Utils/Slo/SloHealth.test.ts +28 -6
  549. package/Tests/Utils/StatusPage/ReportSchedule.test.ts +867 -0
  550. package/Tests/Utils/Telemetry/DiscoveredResourceName.test.ts +189 -0
  551. package/Tests/Utils/WordMatch.test.ts +104 -0
  552. package/Types/BrandColors.ts +10 -0
  553. package/Types/CustomDomain/CustomDomainCertificates.ts +128 -0
  554. package/Types/CustomDomain/CustomDomainVerification.ts +78 -0
  555. package/Types/Dashboard/DashboardAccess.ts +250 -0
  556. package/Types/Dashboard/DashboardTemplates.ts +33 -0
  557. package/Types/Filter/FilterConditionUtil.ts +29 -0
  558. package/Types/Form/FormBranding.ts +475 -0
  559. package/Types/Form/FormPublic.ts +26 -0
  560. package/Types/IncomingCall/IncomingCallRingTime.ts +48 -0
  561. package/Types/Log/LogScrubField.ts +14 -0
  562. package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +1 -1
  563. package/Types/NotificationRule/OnCallRuleKind.ts +194 -0
  564. package/Types/OnCallDutyPolicy/FirstResponders.ts +3 -32
  565. package/Types/OnCallDutyPolicy/MiscDataId.ts +38 -0
  566. package/Types/OnCallDutyPolicy/ScheduleFirstLayer.ts +165 -0
  567. package/Types/OnCallDutyPolicy/ScheduleLayerDefaults.ts +160 -0
  568. package/Types/OnCallDutyPolicy/UserOverrideCoverRequest.ts +148 -0
  569. package/Types/SSO/OidcProviderDefaults.ts +282 -0
  570. package/Types/SSO/SamlProviderDefaults.ts +77 -0
  571. package/Types/SSO/SsoProviderDefaults.ts +101 -0
  572. package/Types/StatusPage/StatusPageAccess.ts +215 -0
  573. package/Types/StatusPage/StatusPagesListingMonitors.ts +150 -0
  574. package/Types/Telemetry/ScrubRule.ts +240 -0
  575. package/UI/Components/AdvancedPageSection/AdvancedPageSection.tsx +59 -29
  576. package/UI/Components/Card/Card.tsx +139 -80
  577. package/UI/Components/ChoiceRows/ChoiceRows.tsx +249 -0
  578. package/UI/Components/CommandPalette/CommandPalette.tsx +28 -12
  579. package/UI/Components/CommandPalette/PaletteFilter.ts +962 -75
  580. package/UI/Components/CommandPalette/PaletteRow.tsx +35 -3
  581. package/UI/Components/CommandPalette/Types.ts +37 -1
  582. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +6 -0
  583. package/UI/Components/Detail/Detail.tsx +52 -15
  584. package/UI/Components/Detail/DetailRecordLine.tsx +96 -0
  585. package/UI/Components/Detail/DetailRecordTime.ts +196 -0
  586. package/UI/Components/Dropdown/DropdownChange.ts +198 -0
  587. package/UI/Components/EntityDropdown/EntityDropdown.tsx +270 -106
  588. package/UI/Components/EntityDropdown/EntityDropdownQuery.ts +119 -0
  589. package/UI/Components/FilePicker/FilePicker.tsx +90 -6
  590. package/UI/Components/FoldedSection/FoldedSection.tsx +370 -0
  591. package/UI/Components/FoldedSection/FoldedSectionItem.ts +141 -0
  592. package/UI/Components/FoldedSection/FoldedSectionTitles.ts +39 -0
  593. package/UI/Components/FormModal/BasicFormModal.tsx +40 -67
  594. package/UI/Components/Forms/BasicForm.tsx +218 -119
  595. package/UI/Components/Forms/BasicModelForm.tsx +0 -2
  596. package/UI/Components/Forms/CollapsibleFormSection.tsx +108 -18
  597. package/UI/Components/Forms/Fields/FormField.tsx +62 -15
  598. package/UI/Components/Forms/Fields/GeneratedKeyField.tsx +1 -5
  599. package/UI/Components/Forms/FormSummary.tsx +5 -3
  600. package/UI/Components/Forms/ModelForm.tsx +123 -16
  601. package/UI/Components/Forms/Types/Field.ts +98 -16
  602. package/UI/Components/Forms/Utils/AdvancedFormSection.ts +102 -31
  603. package/UI/Components/Forms/Utils/CreateFormDefaults.ts +158 -17
  604. package/UI/Components/Forms/Utils/FoldedFormFields.ts +393 -0
  605. package/UI/Components/Forms/Utils/FollowPickName.ts +52 -0
  606. package/UI/Components/Forms/Utils/FormModalWidth.ts +35 -4
  607. package/UI/Components/Forms/Utils/OpenFormSections.ts +104 -0
  608. package/UI/Components/Forms/Utils/SteppedFormFooter.ts +151 -0
  609. package/UI/Components/Forms/Utils/UniqueName.ts +81 -0
  610. package/UI/Components/LabelRule/ImportLabelRulesModal.tsx +22 -3
  611. package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +6 -5
  612. package/UI/Components/Modal/ModalFooter.tsx +10 -1
  613. package/UI/Components/ModelDetail/CardModelDetail.tsx +33 -8
  614. package/UI/Components/ModelFormModal/ModelFormModal.tsx +44 -58
  615. package/UI/Components/ModelSwitch/ModelSwitchCard.tsx +305 -0
  616. package/UI/Components/ModelSwitch/ModelSwitchEvents.ts +109 -0
  617. package/UI/Components/ModelSwitch/ModelSwitchRow.tsx +438 -0
  618. package/UI/Components/ModelSwitch/ModelSwitchUtil.ts +120 -0
  619. package/UI/Components/ModelSwitch/ModelSwitchesCard.tsx +265 -0
  620. package/UI/Components/ModelSwitch/useSaveModelSwitch.ts +144 -0
  621. package/UI/Components/ModelTable/BaseModelTable.tsx +6 -0
  622. package/UI/Components/ModelTable/ModelTable.tsx +5 -0
  623. package/UI/Components/Navbar/NavBar.tsx +10 -9
  624. package/UI/Components/Navbar/NavBarMenuCatalog.ts +57 -22
  625. package/UI/Components/Navbar/NavBarMenuModal.tsx +17 -13
  626. package/UI/Components/Navbar/NavBarMobileMenu.tsx +40 -23
  627. package/UI/Components/Page/ModelHeaderEvents.ts +75 -0
  628. package/UI/Components/Page/ModelPage.tsx +21 -1
  629. package/UI/Components/Page/Page.tsx +68 -13
  630. package/UI/Components/PeoplePicker/PeoplePicker.tsx +150 -45
  631. package/UI/Components/PeoplePicker/PeoplePickerTypes.ts +193 -4
  632. package/UI/Components/PeoplePicker/PeopleSearchPopup.tsx +37 -10
  633. package/UI/Components/PublicForm/PublicFormFavicon.ts +99 -0
  634. package/UI/Components/PublicForm/PublicFormLogo.tsx +81 -0
  635. package/UI/Components/RuleCriteria/RuleCriteriaBuilder.tsx +5 -3
  636. package/UI/Components/RuleRun/RuleView.tsx +2 -5
  637. package/UI/Components/SaveStatus/SaveStatus.tsx +76 -0
  638. package/UI/Components/SaveStatus/useSaveOnChange.ts +178 -0
  639. package/UI/Components/SmtpConfig/SmtpConfigFormFields.ts +815 -0
  640. package/UI/Components/Sso/OidcProviderFormFields.ts +481 -0
  641. package/UI/Components/Sso/SamlProviderFormFields.ts +322 -0
  642. package/UI/Components/Sso/SsoProviderFormFields.ts +331 -0
  643. package/UI/Components/Table/TableEmptyState.tsx +39 -5
  644. package/UI/Components/Workflow/ArgumentsForm.tsx +21 -78
  645. package/UI/Components/Workflow/ComponentPicker/ComponentSearch.ts +18 -145
  646. package/UI/Components/Workflow/WorkflowLogModal.tsx +1 -3
  647. package/UI/Types/UseAnchoredFieldPopup.ts +46 -4
  648. package/UI/Utils/DefaultInviteTeam.ts +306 -0
  649. package/UI/Utils/GrantablePermission.ts +46 -0
  650. package/UI/Utils/PermissionGate.ts +80 -7
  651. package/UI/Utils/TranslateTemplate.ts +22 -0
  652. package/Utils/DistinctColor.ts +223 -0
  653. package/Utils/Monitor/MonitorOverviewPresentationUtil.ts +47 -2
  654. package/Utils/Slo/SloHealth.ts +9 -3
  655. package/Utils/StatusPage/ReportSchedule.ts +462 -0
  656. package/Utils/Telemetry/DiscoveredResourceName.ts +95 -0
  657. package/Utils/WordMatch.ts +185 -0
  658. package/build/dist/Models/DatabaseModels/AlertGroupingRule.js +6 -6
  659. package/build/dist/Models/DatabaseModels/AlertGroupingRule.js.map +1 -1
  660. package/build/dist/Models/DatabaseModels/File.js +47 -1
  661. package/build/dist/Models/DatabaseModels/File.js.map +1 -1
  662. package/build/dist/Models/DatabaseModels/Form.js +125 -0
  663. package/build/dist/Models/DatabaseModels/Form.js.map +1 -1
  664. package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js +6 -6
  665. package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js.map +1 -1
  666. package/build/dist/Models/DatabaseModels/LogDropFilter.js +1 -0
  667. package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
  668. package/build/dist/Models/DatabaseModels/LogPipeline.js +1 -0
  669. package/build/dist/Models/DatabaseModels/LogPipeline.js.map +1 -1
  670. package/build/dist/Models/DatabaseModels/LogScrubRule.js +14 -8
  671. package/build/dist/Models/DatabaseModels/LogScrubRule.js.map +1 -1
  672. package/build/dist/Models/DatabaseModels/MetricRecordingRule.js +1 -1
  673. package/build/dist/Models/DatabaseModels/MetricRecordingRule.js.map +1 -1
  674. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js +2 -2
  675. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js.map +1 -1
  676. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js +20 -9
  677. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js.map +1 -1
  678. package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js +6 -1
  679. package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js.map +1 -1
  680. package/build/dist/Models/DatabaseModels/StatusPage.js +4 -4
  681. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  682. package/build/dist/Models/DatabaseModels/TraceDropFilter.js +1 -0
  683. package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
  684. package/build/dist/Models/DatabaseModels/TracePipeline.js +1 -0
  685. package/build/dist/Models/DatabaseModels/TracePipeline.js.map +1 -1
  686. package/build/dist/Models/DatabaseModels/TraceRecordingRule.js +1 -1
  687. package/build/dist/Models/DatabaseModels/TraceRecordingRule.js.map +1 -1
  688. package/build/dist/Models/DatabaseModels/TraceScrubRule.js +14 -8
  689. package/build/dist/Models/DatabaseModels/TraceScrubRule.js.map +1 -1
  690. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +2 -2
  691. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  692. package/build/dist/Server/API/CustomDomainRoutes.js +124 -0
  693. package/build/dist/Server/API/CustomDomainRoutes.js.map +1 -0
  694. package/build/dist/Server/API/DashboardAPI.js +22 -4
  695. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  696. package/build/dist/Server/API/DashboardDomainAPI.js +56 -49
  697. package/build/dist/Server/API/DashboardDomainAPI.js.map +1 -1
  698. package/build/dist/Server/API/StatusPageAPI.js +101 -39
  699. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  700. package/build/dist/Server/API/StatusPageDomainAPI.js +52 -51
  701. package/build/dist/Server/API/StatusPageDomainAPI.js.map +1 -1
  702. package/build/dist/Server/Infrastructure/GlobalCache.js +63 -0
  703. package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
  704. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1797700000000-AddFormBranding.js +36 -0
  705. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1797700000000-AddFormBranding.js.map +1 -0
  706. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  707. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  708. package/build/dist/Server/Services/AlertGroupingEngineService.js +44 -61
  709. package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
  710. package/build/dist/Server/Services/AlertGroupingRuleService.js +45 -0
  711. package/build/dist/Server/Services/AlertGroupingRuleService.js.map +1 -1
  712. package/build/dist/Server/Services/CephClusterService.js +23 -0
  713. package/build/dist/Server/Services/CephClusterService.js.map +1 -1
  714. package/build/dist/Server/Services/CloudResourceService.js +39 -0
  715. package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
  716. package/build/dist/Server/Services/DashboardDomainService.js +510 -172
  717. package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
  718. package/build/dist/Server/Services/DashboardService.js +22 -9
  719. package/build/dist/Server/Services/DashboardService.js.map +1 -1
  720. package/build/dist/Server/Services/DatabaseService.js +114 -10
  721. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  722. package/build/dist/Server/Services/DockerHostService.js +51 -0
  723. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  724. package/build/dist/Server/Services/DockerSwarmClusterService.js +23 -0
  725. package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
  726. package/build/dist/Server/Services/FileService.js +45 -0
  727. package/build/dist/Server/Services/FileService.js.map +1 -1
  728. package/build/dist/Server/Services/FormService.js +158 -14
  729. package/build/dist/Server/Services/FormService.js.map +1 -1
  730. package/build/dist/Server/Services/GlobalOidcService.js +9 -0
  731. package/build/dist/Server/Services/GlobalOidcService.js.map +1 -1
  732. package/build/dist/Server/Services/GlobalSsoService.js +9 -0
  733. package/build/dist/Server/Services/GlobalSsoService.js.map +1 -1
  734. package/build/dist/Server/Services/HostService.js +50 -0
  735. package/build/dist/Server/Services/HostService.js.map +1 -1
  736. package/build/dist/Server/Services/IncidentGroupingEngineService.js +45 -62
  737. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  738. package/build/dist/Server/Services/IncidentGroupingRuleService.js +45 -0
  739. package/build/dist/Server/Services/IncidentGroupingRuleService.js.map +1 -1
  740. package/build/dist/Server/Services/IoTFleetService.js +23 -0
  741. package/build/dist/Server/Services/IoTFleetService.js.map +1 -1
  742. package/build/dist/Server/Services/KubernetesClusterService.js +54 -0
  743. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  744. package/build/dist/Server/Services/LabelService.js +6 -16
  745. package/build/dist/Server/Services/LabelService.js.map +1 -1
  746. package/build/dist/Server/Services/LogScrubRuleService.js +31 -0
  747. package/build/dist/Server/Services/LogScrubRuleService.js.map +1 -1
  748. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +202 -0
  749. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  750. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js +7 -1
  751. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js.map +1 -1
  752. package/build/dist/Server/Services/OnCallNotificationAlertingService.js +17 -24
  753. package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -1
  754. package/build/dist/Server/Services/OnCallSetupReminderService.js +32 -38
  755. package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -1
  756. package/build/dist/Server/Services/PodmanHostService.js +51 -0
  757. package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
  758. package/build/dist/Server/Services/ProfileAggregationService.js +34 -0
  759. package/build/dist/Server/Services/ProfileAggregationService.js.map +1 -1
  760. package/build/dist/Server/Services/ProjectCallSMSConfigService.js +53 -3
  761. package/build/dist/Server/Services/ProjectCallSMSConfigService.js.map +1 -1
  762. package/build/dist/Server/Services/ProjectOidcService.js +28 -0
  763. package/build/dist/Server/Services/ProjectOidcService.js.map +1 -1
  764. package/build/dist/Server/Services/ProjectSsoService.js +28 -0
  765. package/build/dist/Server/Services/ProjectSsoService.js.map +1 -1
  766. package/build/dist/Server/Services/ProxmoxClusterService.js +23 -0
  767. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
  768. package/build/dist/Server/Services/RumApplicationService.js +42 -0
  769. package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
  770. package/build/dist/Server/Services/ScheduledMaintenanceService.js +18 -26
  771. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  772. package/build/dist/Server/Services/ServerlessFunctionService.js +44 -0
  773. package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
  774. package/build/dist/Server/Services/ServiceService.js +30 -4
  775. package/build/dist/Server/Services/ServiceService.js.map +1 -1
  776. package/build/dist/Server/Services/StatusPageDomainService.js +495 -174
  777. package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
  778. package/build/dist/Server/Services/StatusPageOidcService.js +28 -0
  779. package/build/dist/Server/Services/StatusPageOidcService.js.map +1 -1
  780. package/build/dist/Server/Services/StatusPageResourceService.js +82 -46
  781. package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
  782. package/build/dist/Server/Services/StatusPageService.js +174 -45
  783. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  784. package/build/dist/Server/Services/StatusPageSsoService.js +28 -0
  785. package/build/dist/Server/Services/StatusPageSsoService.js.map +1 -1
  786. package/build/dist/Server/Services/TraceScrubRuleService.js +31 -0
  787. package/build/dist/Server/Services/TraceScrubRuleService.js.map +1 -1
  788. package/build/dist/Server/Services/UserIncomingCallNumberService.js +20 -10
  789. package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
  790. package/build/dist/Server/Services/VMwareVCenterService.js +23 -0
  791. package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -1
  792. package/build/dist/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.js +3 -3
  793. package/build/dist/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.js.map +1 -1
  794. package/build/dist/Server/Utils/Greenlock/CertificateOrder.js +353 -0
  795. package/build/dist/Server/Utils/Greenlock/CertificateOrder.js.map +1 -0
  796. package/build/dist/Server/Utils/Greenlock/CertificateOrderBudget.js +119 -0
  797. package/build/dist/Server/Utils/Greenlock/CertificateOrderBudget.js.map +1 -0
  798. package/build/dist/Server/Utils/Greenlock/CertificateOrderFailures.js +208 -0
  799. package/build/dist/Server/Utils/Greenlock/CertificateOrderFailures.js.map +1 -0
  800. package/build/dist/Server/Utils/Greenlock/CertificateOrderLock.js +111 -0
  801. package/build/dist/Server/Utils/Greenlock/CertificateOrderLock.js.map +1 -0
  802. package/build/dist/Server/Utils/Greenlock/CertificateOrderOutcome.js +30 -0
  803. package/build/dist/Server/Utils/Greenlock/CertificateOrderOutcome.js.map +1 -0
  804. package/build/dist/Server/Utils/Greenlock/CertificateOwners.js +52 -0
  805. package/build/dist/Server/Utils/Greenlock/CertificateOwners.js.map +1 -0
  806. package/build/dist/Server/Utils/Greenlock/CertificateReissueOrder.js +80 -0
  807. package/build/dist/Server/Utils/Greenlock/CertificateReissueOrder.js.map +1 -0
  808. package/build/dist/Server/Utils/Greenlock/CustomDomainOrders.js +296 -0
  809. package/build/dist/Server/Utils/Greenlock/CustomDomainOrders.js.map +1 -0
  810. package/build/dist/Server/Utils/Greenlock/Greenlock.js +595 -146
  811. package/build/dist/Server/Utils/Greenlock/Greenlock.js.map +1 -1
  812. package/build/dist/Server/Utils/Rules/GroupingRuleEpisodeOwners.js +366 -0
  813. package/build/dist/Server/Utils/Rules/GroupingRuleEpisodeOwners.js.map +1 -0
  814. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js +7 -0
  815. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js.map +1 -1
  816. package/build/dist/Server/Utils/ScrubRuleValidation.js +127 -0
  817. package/build/dist/Server/Utils/ScrubRuleValidation.js.map +1 -0
  818. package/build/dist/Server/Utils/StatusPage/AffectedStatusPageResources.js +97 -0
  819. package/build/dist/Server/Utils/StatusPage/AffectedStatusPageResources.js.map +1 -0
  820. package/build/dist/Server/Utils/StatusPage/StatusPagesListingMonitorsBuilder.js +195 -0
  821. package/build/dist/Server/Utils/StatusPage/StatusPagesListingMonitorsBuilder.js.map +1 -0
  822. package/build/dist/Server/Utils/Telemetry/DiscoveredResourceCreate.js +177 -0
  823. package/build/dist/Server/Utils/Telemetry/DiscoveredResourceCreate.js.map +1 -0
  824. package/build/dist/Server/Utils/Telemetry/DiscoveredResourceUpdate.js +129 -0
  825. package/build/dist/Server/Utils/Telemetry/DiscoveredResourceUpdate.js.map +1 -0
  826. package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js +8 -2
  827. package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js.map +1 -1
  828. package/build/dist/Types/BrandColors.js +9 -0
  829. package/build/dist/Types/BrandColors.js.map +1 -1
  830. package/build/dist/Types/CustomDomain/CustomDomainCertificates.js +71 -0
  831. package/build/dist/Types/CustomDomain/CustomDomainCertificates.js.map +1 -0
  832. package/build/dist/Types/CustomDomain/CustomDomainVerification.js +58 -0
  833. package/build/dist/Types/CustomDomain/CustomDomainVerification.js.map +1 -0
  834. package/build/dist/Types/Dashboard/DashboardAccess.js +157 -0
  835. package/build/dist/Types/Dashboard/DashboardAccess.js.map +1 -0
  836. package/build/dist/Types/Dashboard/DashboardTemplates.js +26 -0
  837. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  838. package/build/dist/Types/Filter/FilterConditionUtil.js +24 -0
  839. package/build/dist/Types/Filter/FilterConditionUtil.js.map +1 -0
  840. package/build/dist/Types/Form/FormBranding.js +266 -0
  841. package/build/dist/Types/Form/FormBranding.js.map +1 -0
  842. package/build/dist/Types/Form/FormPublic.js +6 -0
  843. package/build/dist/Types/Form/FormPublic.js.map +1 -1
  844. package/build/dist/Types/IncomingCall/IncomingCallRingTime.js +37 -0
  845. package/build/dist/Types/IncomingCall/IncomingCallRingTime.js.map +1 -0
  846. package/build/dist/Types/Log/LogScrubField.js +15 -0
  847. package/build/dist/Types/Log/LogScrubField.js.map +1 -0
  848. package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +1 -1
  849. package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
  850. package/build/dist/Types/NotificationRule/OnCallRuleKind.js +134 -0
  851. package/build/dist/Types/NotificationRule/OnCallRuleKind.js.map +1 -0
  852. package/build/dist/Types/OnCallDutyPolicy/FirstResponders.js +2 -23
  853. package/build/dist/Types/OnCallDutyPolicy/FirstResponders.js.map +1 -1
  854. package/build/dist/Types/OnCallDutyPolicy/MiscDataId.js +30 -0
  855. package/build/dist/Types/OnCallDutyPolicy/MiscDataId.js.map +1 -0
  856. package/build/dist/Types/OnCallDutyPolicy/ScheduleFirstLayer.js +113 -0
  857. package/build/dist/Types/OnCallDutyPolicy/ScheduleFirstLayer.js.map +1 -0
  858. package/build/dist/Types/OnCallDutyPolicy/ScheduleLayerDefaults.js +95 -0
  859. package/build/dist/Types/OnCallDutyPolicy/ScheduleLayerDefaults.js.map +1 -0
  860. package/build/dist/Types/OnCallDutyPolicy/UserOverrideCoverRequest.js +99 -0
  861. package/build/dist/Types/OnCallDutyPolicy/UserOverrideCoverRequest.js.map +1 -0
  862. package/build/dist/Types/SSO/OidcProviderDefaults.js +189 -0
  863. package/build/dist/Types/SSO/OidcProviderDefaults.js.map +1 -0
  864. package/build/dist/Types/SSO/SamlProviderDefaults.js +55 -0
  865. package/build/dist/Types/SSO/SamlProviderDefaults.js.map +1 -0
  866. package/build/dist/Types/SSO/SsoProviderDefaults.js +67 -0
  867. package/build/dist/Types/SSO/SsoProviderDefaults.js.map +1 -0
  868. package/build/dist/Types/StatusPage/StatusPageAccess.js +132 -0
  869. package/build/dist/Types/StatusPage/StatusPageAccess.js.map +1 -0
  870. package/build/dist/Types/StatusPage/StatusPagesListingMonitors.js +84 -0
  871. package/build/dist/Types/StatusPage/StatusPagesListingMonitors.js.map +1 -0
  872. package/build/dist/Types/Telemetry/ScrubRule.js +180 -0
  873. package/build/dist/Types/Telemetry/ScrubRule.js.map +1 -0
  874. package/build/dist/UI/Components/AdvancedPageSection/AdvancedPageSection.js +9 -7
  875. package/build/dist/UI/Components/AdvancedPageSection/AdvancedPageSection.js.map +1 -1
  876. package/build/dist/UI/Components/Card/Card.js +81 -35
  877. package/build/dist/UI/Components/Card/Card.js.map +1 -1
  878. package/build/dist/UI/Components/ChoiceRows/ChoiceRows.js +54 -0
  879. package/build/dist/UI/Components/ChoiceRows/ChoiceRows.js.map +1 -0
  880. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +25 -12
  881. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
  882. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +632 -64
  883. package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -1
  884. package/build/dist/UI/Components/CommandPalette/PaletteRow.js +7 -1
  885. package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -1
  886. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +7 -1
  887. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  888. package/build/dist/UI/Components/Detail/Detail.js +26 -13
  889. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  890. package/build/dist/UI/Components/Detail/DetailRecordLine.js +32 -0
  891. package/build/dist/UI/Components/Detail/DetailRecordLine.js.map +1 -0
  892. package/build/dist/UI/Components/Detail/DetailRecordTime.js +134 -0
  893. package/build/dist/UI/Components/Detail/DetailRecordTime.js.map +1 -0
  894. package/build/dist/UI/Components/Dropdown/DropdownChange.js +102 -0
  895. package/build/dist/UI/Components/Dropdown/DropdownChange.js.map +1 -0
  896. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +134 -57
  897. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  898. package/build/dist/UI/Components/EntityDropdown/EntityDropdownQuery.js +78 -0
  899. package/build/dist/UI/Components/EntityDropdown/EntityDropdownQuery.js.map +1 -0
  900. package/build/dist/UI/Components/FilePicker/FilePicker.js +55 -6
  901. package/build/dist/UI/Components/FilePicker/FilePicker.js.map +1 -1
  902. package/build/dist/UI/Components/FoldedSection/FoldedSection.js +139 -0
  903. package/build/dist/UI/Components/FoldedSection/FoldedSection.js.map +1 -0
  904. package/build/dist/UI/Components/FoldedSection/FoldedSectionItem.js +58 -0
  905. package/build/dist/UI/Components/FoldedSection/FoldedSectionItem.js.map +1 -0
  906. package/build/dist/UI/Components/FoldedSection/FoldedSectionTitles.js +34 -0
  907. package/build/dist/UI/Components/FoldedSection/FoldedSectionTitles.js.map +1 -0
  908. package/build/dist/UI/Components/FormModal/BasicFormModal.js +29 -45
  909. package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
  910. package/build/dist/UI/Components/Forms/BasicForm.js +148 -89
  911. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  912. package/build/dist/UI/Components/Forms/BasicModelForm.js +1 -1
  913. package/build/dist/UI/Components/Forms/BasicModelForm.js.map +1 -1
  914. package/build/dist/UI/Components/Forms/CollapsibleFormSection.js +49 -10
  915. package/build/dist/UI/Components/Forms/CollapsibleFormSection.js.map +1 -1
  916. package/build/dist/UI/Components/Forms/Fields/FormField.js +25 -11
  917. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  918. package/build/dist/UI/Components/Forms/Fields/GeneratedKeyField.js +2 -5
  919. package/build/dist/UI/Components/Forms/Fields/GeneratedKeyField.js.map +1 -1
  920. package/build/dist/UI/Components/Forms/FormSummary.js +5 -3
  921. package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
  922. package/build/dist/UI/Components/Forms/ModelForm.js +72 -14
  923. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  924. package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
  925. package/build/dist/UI/Components/Forms/Utils/AdvancedFormSection.js +80 -23
  926. package/build/dist/UI/Components/Forms/Utils/AdvancedFormSection.js.map +1 -1
  927. package/build/dist/UI/Components/Forms/Utils/CreateFormDefaults.js +91 -9
  928. package/build/dist/UI/Components/Forms/Utils/CreateFormDefaults.js.map +1 -1
  929. package/build/dist/UI/Components/Forms/Utils/FoldedFormFields.js +243 -0
  930. package/build/dist/UI/Components/Forms/Utils/FoldedFormFields.js.map +1 -0
  931. package/build/dist/UI/Components/Forms/Utils/FollowPickName.js +32 -0
  932. package/build/dist/UI/Components/Forms/Utils/FollowPickName.js.map +1 -0
  933. package/build/dist/UI/Components/Forms/Utils/FormModalWidth.js +25 -5
  934. package/build/dist/UI/Components/Forms/Utils/FormModalWidth.js.map +1 -1
  935. package/build/dist/UI/Components/Forms/Utils/OpenFormSections.js +32 -0
  936. package/build/dist/UI/Components/Forms/Utils/OpenFormSections.js.map +1 -0
  937. package/build/dist/UI/Components/Forms/Utils/SteppedFormFooter.js +71 -0
  938. package/build/dist/UI/Components/Forms/Utils/SteppedFormFooter.js.map +1 -0
  939. package/build/dist/UI/Components/Forms/Utils/UniqueName.js +56 -0
  940. package/build/dist/UI/Components/Forms/Utils/UniqueName.js.map +1 -0
  941. package/build/dist/UI/Components/LabelRule/ImportLabelRulesModal.js +17 -1
  942. package/build/dist/UI/Components/LabelRule/ImportLabelRulesModal.js.map +1 -1
  943. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +1 -2
  944. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
  945. package/build/dist/UI/Components/Modal/ModalFooter.js +8 -1
  946. package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
  947. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +19 -6
  948. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
  949. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js +33 -43
  950. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
  951. package/build/dist/UI/Components/ModelSwitch/ModelSwitchCard.js +151 -0
  952. package/build/dist/UI/Components/ModelSwitch/ModelSwitchCard.js.map +1 -0
  953. package/build/dist/UI/Components/ModelSwitch/ModelSwitchEvents.js +54 -0
  954. package/build/dist/UI/Components/ModelSwitch/ModelSwitchEvents.js.map +1 -0
  955. package/build/dist/UI/Components/ModelSwitch/ModelSwitchRow.js +201 -0
  956. package/build/dist/UI/Components/ModelSwitch/ModelSwitchRow.js.map +1 -0
  957. package/build/dist/UI/Components/ModelSwitch/ModelSwitchUtil.js +60 -0
  958. package/build/dist/UI/Components/ModelSwitch/ModelSwitchUtil.js.map +1 -0
  959. package/build/dist/UI/Components/ModelSwitch/ModelSwitchesCard.js +116 -0
  960. package/build/dist/UI/Components/ModelSwitch/ModelSwitchesCard.js.map +1 -0
  961. package/build/dist/UI/Components/ModelSwitch/useSaveModelSwitch.js +68 -0
  962. package/build/dist/UI/Components/ModelSwitch/useSaveModelSwitch.js.map +1 -0
  963. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -0
  964. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  965. package/build/dist/UI/Components/ModelTable/ModelTable.js +3 -1
  966. package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
  967. package/build/dist/UI/Components/Navbar/NavBar.js +2 -2
  968. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  969. package/build/dist/UI/Components/Navbar/NavBarMenuCatalog.js +21 -10
  970. package/build/dist/UI/Components/Navbar/NavBarMenuCatalog.js.map +1 -1
  971. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +10 -7
  972. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  973. package/build/dist/UI/Components/Navbar/NavBarMobileMenu.js +17 -9
  974. package/build/dist/UI/Components/Navbar/NavBarMobileMenu.js.map +1 -1
  975. package/build/dist/UI/Components/Page/ModelHeaderEvents.js +43 -0
  976. package/build/dist/UI/Components/Page/ModelHeaderEvents.js.map +1 -0
  977. package/build/dist/UI/Components/Page/ModelPage.js +19 -1
  978. package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
  979. package/build/dist/UI/Components/Page/Page.js +31 -13
  980. package/build/dist/UI/Components/Page/Page.js.map +1 -1
  981. package/build/dist/UI/Components/PeoplePicker/PeoplePicker.js +62 -20
  982. package/build/dist/UI/Components/PeoplePicker/PeoplePicker.js.map +1 -1
  983. package/build/dist/UI/Components/PeoplePicker/PeoplePickerTypes.js +98 -1
  984. package/build/dist/UI/Components/PeoplePicker/PeoplePickerTypes.js.map +1 -1
  985. package/build/dist/UI/Components/PeoplePicker/PeopleSearchPopup.js +35 -14
  986. package/build/dist/UI/Components/PeoplePicker/PeopleSearchPopup.js.map +1 -1
  987. package/build/dist/UI/Components/PublicForm/PublicFormFavicon.js +66 -0
  988. package/build/dist/UI/Components/PublicForm/PublicFormFavicon.js.map +1 -0
  989. package/build/dist/UI/Components/PublicForm/PublicFormLogo.js +38 -0
  990. package/build/dist/UI/Components/PublicForm/PublicFormLogo.js.map +1 -0
  991. package/build/dist/UI/Components/RuleCriteria/RuleCriteriaBuilder.js +5 -3
  992. package/build/dist/UI/Components/RuleCriteria/RuleCriteriaBuilder.js.map +1 -1
  993. package/build/dist/UI/Components/RuleRun/RuleView.js +2 -2
  994. package/build/dist/UI/Components/RuleRun/RuleView.js.map +1 -1
  995. package/build/dist/UI/Components/SaveStatus/SaveStatus.js +46 -0
  996. package/build/dist/UI/Components/SaveStatus/SaveStatus.js.map +1 -0
  997. package/build/dist/UI/Components/SaveStatus/useSaveOnChange.js +98 -0
  998. package/build/dist/UI/Components/SaveStatus/useSaveOnChange.js.map +1 -0
  999. package/build/dist/UI/Components/SmtpConfig/SmtpConfigFormFields.js +503 -0
  1000. package/build/dist/UI/Components/SmtpConfig/SmtpConfigFormFields.js.map +1 -0
  1001. package/build/dist/UI/Components/Sso/OidcProviderFormFields.js +283 -0
  1002. package/build/dist/UI/Components/Sso/OidcProviderFormFields.js.map +1 -0
  1003. package/build/dist/UI/Components/Sso/SamlProviderFormFields.js +182 -0
  1004. package/build/dist/UI/Components/Sso/SamlProviderFormFields.js.map +1 -0
  1005. package/build/dist/UI/Components/Sso/SsoProviderFormFields.js +208 -0
  1006. package/build/dist/UI/Components/Sso/SsoProviderFormFields.js.map +1 -0
  1007. package/build/dist/UI/Components/Table/TableEmptyState.js +17 -4
  1008. package/build/dist/UI/Components/Table/TableEmptyState.js.map +1 -1
  1009. package/build/dist/UI/Components/Workflow/ArgumentsForm.js +17 -52
  1010. package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
  1011. package/build/dist/UI/Components/Workflow/ComponentPicker/ComponentSearch.js +7 -89
  1012. package/build/dist/UI/Components/Workflow/ComponentPicker/ComponentSearch.js.map +1 -1
  1013. package/build/dist/UI/Components/Workflow/WorkflowLogModal.js +1 -1
  1014. package/build/dist/UI/Components/Workflow/WorkflowLogModal.js.map +1 -1
  1015. package/build/dist/UI/Types/UseAnchoredFieldPopup.js +22 -3
  1016. package/build/dist/UI/Types/UseAnchoredFieldPopup.js.map +1 -1
  1017. package/build/dist/UI/Utils/DefaultInviteTeam.js +207 -0
  1018. package/build/dist/UI/Utils/DefaultInviteTeam.js.map +1 -0
  1019. package/build/dist/UI/Utils/GrantablePermission.js +31 -0
  1020. package/build/dist/UI/Utils/GrantablePermission.js.map +1 -1
  1021. package/build/dist/UI/Utils/PermissionGate.js +54 -3
  1022. package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
  1023. package/build/dist/UI/Utils/TranslateTemplate.js +16 -0
  1024. package/build/dist/UI/Utils/TranslateTemplate.js.map +1 -1
  1025. package/build/dist/Utils/DistinctColor.js +151 -0
  1026. package/build/dist/Utils/DistinctColor.js.map +1 -0
  1027. package/build/dist/Utils/Monitor/MonitorOverviewPresentationUtil.js +12 -1
  1028. package/build/dist/Utils/Monitor/MonitorOverviewPresentationUtil.js.map +1 -1
  1029. package/build/dist/Utils/Slo/SloHealth.js +9 -3
  1030. package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
  1031. package/build/dist/Utils/StatusPage/ReportSchedule.js +304 -0
  1032. package/build/dist/Utils/StatusPage/ReportSchedule.js.map +1 -0
  1033. package/build/dist/Utils/Telemetry/DiscoveredResourceName.js +65 -0
  1034. package/build/dist/Utils/Telemetry/DiscoveredResourceName.js.map +1 -0
  1035. package/build/dist/Utils/WordMatch.js +115 -0
  1036. package/build/dist/Utils/WordMatch.js.map +1 -0
  1037. package/package.json +1 -1
  1038. package/Tests/App/Dashboard/BulkChangeStateModalSteps.test.ts +0 -109
  1039. package/Tests/App/StatusPage/StatusPageSubscribeFromFirstStep.test.tsx +0 -382
  1040. package/Tests/UI/Components/Forms/BasicFormFinishFromAnyStep.test.tsx +0 -729
  1041. package/Tests/UI/Components/Forms/FinishFromAnyStep.test.ts +0 -571
  1042. package/Tests/UI/Components/Forms/FinishFromAnyStepGuard.test.ts +0 -566
  1043. package/UI/Components/Forms/Utils/FinishFromAnyStep.ts +0 -284
  1044. package/build/dist/UI/Components/Forms/Utils/FinishFromAnyStep.js +0 -132
  1045. package/build/dist/UI/Components/Forms/Utils/FinishFromAnyStep.js.map +0 -1
@@ -1,28 +1,96 @@
1
1
  import { PaletteCommand } from "./Types";
2
+ import {
3
+ getWordVariants,
4
+ isSameWord,
5
+ matchWordWithTypo,
6
+ } from "../../../Utils/WordMatch";
2
7
 
3
8
  /*
4
- * Pure, React-free filtering and ranking for the command palette. Kept out of
5
- * the component so the ranking contract can be unit-tested directly and reused
6
- * by anything that needs "which commands match this text, best first".
9
+ * Pure, React-free search for the command palette. Kept out of the component
10
+ * so the ranking contract can be unit-tested directly and reused by anything
11
+ * that needs "which commands match this text, best first".
12
+ *
13
+ * What a match is, in plain words:
14
+ *
15
+ * - Case, accents, punctuation and spacing do not matter: "on call",
16
+ * "on-call" and "oncall" are the same, and so are "resume" and "résumé".
17
+ * - Each word of the query is matched against the start of a word, in any
18
+ * order, and the number does not matter: "keys api" and "api key" both
19
+ * find API Keys. Words are compared whole, so "runs" is not "Runners".
20
+ * - Keywords are other names for a command ("pager" for On-Call, "delete
21
+ * project" for the Danger Zone). A breadcrumb says where a page lives
22
+ * ("Incidents > Settings"); it narrows a search down ("incident custom
23
+ * fields") but never finds a page on its own for a one-word query, or
24
+ * "incidents" would list every page in Incidents.
25
+ * - A title many pages share ("Custom Fields", "API", "Slack") says little on
26
+ * its own, so a match on it ranks below a distinctive title: "api" opens
27
+ * API Keys before the thirty Developer pages called API.
28
+ * - Fallbacks, offered only when nothing matches better: a title's initials
29
+ * ("ak" finds API Keys), the group a command is listed under
30
+ * ("observability" lists the observability products), a typo in a word
31
+ * ("incidnet") and the title's letters in order ("mntr" finds Monitors).
32
+ * - Between equally good matches, the command's searchPriority decides (the
33
+ * Dashboard puts products before pages, and pages before actions), then
34
+ * the caller's order.
35
+ *
36
+ * Plurals and typos are matched by Utils/WordMatch, which the workflow step
37
+ * pickers use too.
7
38
  */
8
39
 
9
40
  /**
10
- * How a command matched the query, best match first. The palette sorts by
11
- * this tier and keeps the caller's original order within a tier, so two
12
- * commands whose titles both start with the query stay in catalog order.
41
+ * How a command matched the query, best first. The palette orders matches by
42
+ * score, which starts from the rank and is adjusted for shared titles and
43
+ * for how much of the query a context match found in the title.
13
44
  */
14
45
  export enum PaletteMatchRank {
15
- TitlePrefix = 0,
16
- TitleSubstring = 1,
17
- Keyword = 2,
18
- Category = 3,
19
- /** Query characters appear in order in the title, but not adjacently. */
20
- TitleSubsequence = 4,
46
+ /** The whole title: "api keys", "API-Keys" and "apikeys" all name API Keys. */
47
+ TitleExact = 0,
48
+ /** The title starts with the query: "api k" and "oncall" are prefixes. */
49
+ TitlePrefix = 1,
50
+ /** Every query word starts a word of the title, in any order: "keys api". */
51
+ TitleWords = 2,
52
+ /** A keyword is the query, starts with it, or holds every word of it. */
53
+ Keyword = 3,
54
+ /**
55
+ * Every query word is found across the title, keywords and where the
56
+ * command lives (its breadcrumb, or the group it is listed under), at
57
+ * least one in its own names: "incident custom fields", "logs
58
+ * observability".
59
+ */
60
+ Context = 4,
61
+ /**
62
+ * The query appears inside the title or a keyword, not at a word start:
63
+ * "eys" finds API Keys.
64
+ */
65
+ Substring = 5,
66
+ /** The query starts the title's initials: "ak" finds API Keys. A fallback. */
67
+ TitleInitials = 6,
68
+ /**
69
+ * Only the group a command is listed under holds the query: "observability"
70
+ * lists the observability products. A fallback.
71
+ */
72
+ Category = 7,
73
+ /**
74
+ * A typo in a query word, or the title's letters in order with gaps. A
75
+ * fallback.
76
+ */
77
+ Fuzzy = 8,
21
78
  }
22
79
 
80
+ // Ranks offered only when nothing matches better.
81
+ const FALLBACK_RANKS: ReadonlySet<PaletteMatchRank> = new Set<PaletteMatchRank>(
82
+ [
83
+ PaletteMatchRank.TitleInitials,
84
+ PaletteMatchRank.Category,
85
+ PaletteMatchRank.Fuzzy,
86
+ ],
87
+ );
88
+
23
89
  export interface PaletteCommandMatch {
24
90
  command: PaletteCommand;
25
91
  rank: PaletteMatchRank;
92
+ /** Higher is better. */
93
+ score: number;
26
94
  }
27
95
 
28
96
  /** One run of text in a title/description, flagged when it matched the query. */
@@ -31,16 +99,103 @@ export interface PaletteHighlightSegment {
31
99
  isMatch: boolean;
32
100
  }
33
101
 
102
+ const RANK_SCORES: Readonly<Record<PaletteMatchRank, number>> = {
103
+ [PaletteMatchRank.TitleExact]: 100,
104
+ [PaletteMatchRank.TitlePrefix]: 90,
105
+ [PaletteMatchRank.TitleWords]: 80,
106
+ [PaletteMatchRank.Keyword]: 62,
107
+ [PaletteMatchRank.Context]: 50,
108
+ [PaletteMatchRank.Substring]: 40,
109
+ [PaletteMatchRank.TitleInitials]: 45,
110
+ [PaletteMatchRank.Category]: 30,
111
+ [PaletteMatchRank.Fuzzy]: 20,
112
+ };
113
+
114
+ // A keyword that is exactly the query is worth more than one it starts.
115
+ const KEYWORD_EXACT_BONUS: number = 8;
116
+
117
+ // The query inside a keyword is weaker evidence than inside the title.
118
+ const KEYWORD_SUBSTRING_PENALTY: number = 6;
119
+
120
+ // The shortest query found inside a keyword: one or two letters are anywhere.
121
+ const KEYWORD_SUBSTRING_MIN_LENGTH: number = 3;
122
+
123
+ // A context match that found query words in the title is worth more.
124
+ const CONTEXT_TITLE_WORD_BONUS: number = 4;
125
+ const CONTEXT_TITLE_WORD_BONUS_CAP: number = 12;
126
+
127
+ // ...and so is one whose other words all name the same place.
128
+ const CONTEXT_ONE_PLACE_BONUS: number = 4;
129
+
130
+ // A typo is closer to the title than its letters scattered through it.
131
+ const TYPO_BONUS: number = 10;
132
+
133
+ // The shortest query word a typo is forgiven in: "rule" must not find "role".
134
+ const TYPO_MIN_LENGTH: number = 5;
135
+
136
+ // The shortest query that may match a title's letters in order.
137
+ const SUBSEQUENCE_MIN_LENGTH: number = 2;
138
+
139
+ /*
140
+ * The shortest query word whose plural or singular counts as the same word:
141
+ * "is" is not the plural of "i".
142
+ */
143
+ const SAME_WORD_MIN_LENGTH: number = 3;
144
+
145
+ /*
146
+ * A title shared by k pages: subtracted from its title-based matches. Two
147
+ * pages called "Settings" lose 25, so "settings" opens Project Settings
148
+ * first; thirty called "API" lose 45, so "api" opens API Keys first.
149
+ */
150
+ export const getSharedTitlePenalty: (sharedBy: number) => number = (
151
+ sharedBy: number,
152
+ ): number => {
153
+ if (sharedBy < 2) {
154
+ return 0;
155
+ }
156
+
157
+ return Math.min(45, 20 + 5 * Math.log2(sharedBy));
158
+ };
159
+
160
+ /*
161
+ * The accents of the Latin, Greek and Cyrillic letters (é, ü, ñ, ё), which
162
+ * people often leave out when they type. The breve is kept: Russian й is a
163
+ * letter of its own, not an accented и. Other scripts' marks (Hindi vowel
164
+ * signs, Japanese voicing marks) are part of their words and are kept too.
165
+ */
166
+ const LETTER_ACCENTS: RegExp = /[\u0300-\u0305\u0307-\u036f]+/g;
167
+ const NOT_A_LETTER_OR_DIGIT: RegExp = /[^\p{L}\p{M}\p{N}]+/gu;
168
+ const WORD_CHARACTER: RegExp = /[\p{L}\p{M}\p{N}]/u;
169
+
170
+ /**
171
+ * Text the way the search compares it: lowercase, accents dropped, and
172
+ * every run of punctuation or space turned into one space.
173
+ */
34
174
  export const normalizePaletteQuery: (query: string) => string = (
35
175
  query: string,
36
176
  ): string => {
37
- return query.trim().toLowerCase();
177
+ return query
178
+ .normalize("NFKD")
179
+ .replace(LETTER_ACCENTS, "")
180
+ .normalize("NFC")
181
+ .toLowerCase()
182
+ .replace(NOT_A_LETTER_OR_DIGIT, " ")
183
+ .trim();
184
+ };
185
+
186
+ /** The query's words, normalized: what gets highlighted and matched. */
187
+ export const getPaletteQueryWords: (query: string) => Array<string> = (
188
+ query: string,
189
+ ): Array<string> => {
190
+ const normalized: string = normalizePaletteQuery(query);
191
+
192
+ return normalized ? normalized.split(" ") : [];
38
193
  };
39
194
 
40
195
  /**
41
196
  * True when every character of `needle` appears in `haystack` in order (not
42
197
  * necessarily adjacent) — the "mntr" finds "Monitors" fallback. Both inputs
43
- * are expected to be lowercased already.
198
+ * are expected to be normalized already.
44
199
  */
45
200
  export const isSubsequenceMatch: (
46
201
  needle: string,
@@ -63,46 +218,611 @@ export const isSubsequenceMatch: (
63
218
  };
64
219
 
65
220
  /**
66
- * Rank one command against an already-normalized query, or null when it does
67
- * not match at all.
221
+ * True when the words, run together, start with `compactQuery` without
222
+ * cutting a word short in the middle of the query: "oncall" starts
223
+ * "On-Call Duty" and "oncal" too, but "alerts" does not start "Alert State"
224
+ * (it would end on the "s" of "State"). A query that stops inside the first
225
+ * word is fine ("mon"); inside a later one it needs two of its letters.
68
226
  */
69
- export const rankPaletteCommand: (
70
- command: PaletteCommand,
71
- normalizedQuery: string,
72
- ) => PaletteMatchRank | null = (
227
+ export const isCompactWordPrefix: (
228
+ words: Array<string>,
229
+ compactQuery: string,
230
+ ) => boolean = (words: Array<string>, compactQuery: string): boolean => {
231
+ let rest: string = compactQuery;
232
+
233
+ for (let index: number = 0; index < words.length; index++) {
234
+ const word: string = words[index]!;
235
+
236
+ if (rest.length <= word.length) {
237
+ return word.startsWith(rest) && (index === 0 || rest.length >= 2);
238
+ }
239
+
240
+ if (!rest.startsWith(word)) {
241
+ return false;
242
+ }
243
+
244
+ rest = rest.slice(word.length);
245
+ }
246
+
247
+ return false;
248
+ };
249
+
250
+ interface PreparedText {
251
+ words: Array<string>;
252
+ // getWordVariants of each word, worked out once.
253
+ variants: Array<Array<string>>;
254
+ // The words run together: "on-call duty" is "oncallduty".
255
+ compact: string;
256
+ // The words joined with single spaces.
257
+ spaced: string;
258
+ }
259
+
260
+ const prepareText: (text: string) => PreparedText = (
261
+ text: string,
262
+ ): PreparedText => {
263
+ const normalized: string = normalizePaletteQuery(text);
264
+ const words: Array<string> = normalized ? normalized.split(" ") : [];
265
+
266
+ return {
267
+ words,
268
+ variants: words.map((word: string): Array<string> => {
269
+ return getWordVariants(word);
270
+ }),
271
+ compact: words.join(""),
272
+ spaced: words.join(" "),
273
+ };
274
+ };
275
+
276
+ interface PreparedCommand {
277
+ title: PreparedText;
278
+ // The title and its aliases, the title first.
279
+ titles: Array<PreparedText>;
280
+ keywords: Array<PreparedText>;
281
+ /*
282
+ * Where the command lives, one entry per name: each crumb of the
283
+ * breadcrumb and of its search-only words (or the category, without a
284
+ * breadcrumb).
285
+ */
286
+ context: Array<PreparedText>;
287
+ hasBreadcrumb: boolean;
288
+ }
289
+
290
+ /*
291
+ * The palette re-runs the search on every keystroke over the same command
292
+ * objects, so each one is normalized once.
293
+ */
294
+ const preparedCommands: WeakMap<PaletteCommand, PreparedCommand> =
295
+ new WeakMap();
296
+
297
+ const prepareTexts: (texts: Array<string>) => Array<PreparedText> = (
298
+ texts: Array<string>,
299
+ ): Array<PreparedText> => {
300
+ return texts
301
+ .map((text: string): PreparedText => {
302
+ return prepareText(text);
303
+ })
304
+ .filter((prepared: PreparedText): boolean => {
305
+ return prepared.words.length > 0;
306
+ });
307
+ };
308
+
309
+ const prepareCommand: (command: PaletteCommand) => PreparedCommand = (
73
310
  command: PaletteCommand,
74
- normalizedQuery: string,
75
- ): PaletteMatchRank | null => {
76
- const title: string = command.title.toLowerCase();
311
+ ): PreparedCommand => {
312
+ const cached: PreparedCommand | undefined = preparedCommands.get(command);
313
+
314
+ if (cached) {
315
+ return cached;
316
+ }
317
+
318
+ const hasBreadcrumb: boolean = Boolean(
319
+ command.breadcrumb && command.breadcrumb.length > 0,
320
+ );
77
321
 
78
- if (title.startsWith(normalizedQuery)) {
322
+ const title: PreparedText = prepareText(command.title);
323
+
324
+ const prepared: PreparedCommand = {
325
+ title,
326
+ titles: [title, ...prepareTexts(command.titleAliases || [])],
327
+ keywords: prepareTexts(command.keywords || []),
328
+ context: prepareTexts(
329
+ hasBreadcrumb
330
+ ? [...(command.breadcrumb || []), ...(command.breadcrumbKeywords || [])]
331
+ : [command.category],
332
+ ),
333
+ hasBreadcrumb,
334
+ };
335
+
336
+ preparedCommands.set(command, prepared);
337
+
338
+ return prepared;
339
+ };
340
+
341
+ type PreparedQuery = PreparedText;
342
+
343
+ /*
344
+ * Whether one query word matches one word of a name: the word starts with
345
+ * it, or it is the same word in the singular or plural ("keys" is "key").
346
+ */
347
+ const wordMatches: (
348
+ token: string,
349
+ tokenVariants: Array<string>,
350
+ word: string,
351
+ wordVariants: Array<string>,
352
+ ) => boolean = (
353
+ token: string,
354
+ tokenVariants: Array<string>,
355
+ word: string,
356
+ wordVariants: Array<string>,
357
+ ): boolean => {
358
+ if (word.startsWith(token)) {
359
+ return true;
360
+ }
361
+
362
+ return (
363
+ token.length >= SAME_WORD_MIN_LENGTH &&
364
+ isSameWord(token, word, tokenVariants, wordVariants)
365
+ );
366
+ };
367
+
368
+ const textHasWord: (
369
+ text: PreparedText,
370
+ token: string,
371
+ tokenVariants: Array<string>,
372
+ ) => boolean = (
373
+ text: PreparedText,
374
+ token: string,
375
+ tokenVariants: Array<string>,
376
+ ): boolean => {
377
+ return text.words.some((word: string, index: number): boolean => {
378
+ return wordMatches(token, tokenVariants, word, text.variants[index] || []);
379
+ });
380
+ };
381
+
382
+ const textHasEveryWord: (
383
+ text: PreparedText,
384
+ query: PreparedQuery,
385
+ ) => boolean = (text: PreparedText, query: PreparedQuery): boolean => {
386
+ return query.words.every((token: string, index: number): boolean => {
387
+ return textHasWord(text, token, query.variants[index] || []);
388
+ });
389
+ };
390
+
391
+ /*
392
+ * The same words, in the same order, the number aside: "api key" is "API
393
+ * Keys".
394
+ */
395
+ const isSameWords: (text: PreparedText, query: PreparedQuery) => boolean = (
396
+ text: PreparedText,
397
+ query: PreparedQuery,
398
+ ): boolean => {
399
+ return (
400
+ text.words.length === query.words.length &&
401
+ text.words.every((word: string, index: number): boolean => {
402
+ return isSameWord(
403
+ query.words[index]!,
404
+ word,
405
+ query.variants[index],
406
+ text.variants[index],
407
+ );
408
+ })
409
+ );
410
+ };
411
+
412
+ // How a name (a title, or a keyword) matches the whole query, or null.
413
+ const matchName: (
414
+ name: PreparedText,
415
+ query: PreparedQuery,
416
+ ) =>
417
+ | PaletteMatchRank.TitleExact
418
+ | PaletteMatchRank.TitlePrefix
419
+ | PaletteMatchRank.TitleWords
420
+ | null = (
421
+ name: PreparedText,
422
+ query: PreparedQuery,
423
+ ):
424
+ | PaletteMatchRank.TitleExact
425
+ | PaletteMatchRank.TitlePrefix
426
+ | PaletteMatchRank.TitleWords
427
+ | null => {
428
+ if (name.compact.length === 0) {
429
+ return null;
430
+ }
431
+
432
+ if (name.compact === query.compact || isSameWords(name, query)) {
433
+ return PaletteMatchRank.TitleExact;
434
+ }
435
+
436
+ if (
437
+ name.spaced.startsWith(query.spaced) ||
438
+ isCompactWordPrefix(name.words, query.compact)
439
+ ) {
79
440
  return PaletteMatchRank.TitlePrefix;
80
441
  }
81
- if (title.includes(normalizedQuery)) {
82
- return PaletteMatchRank.TitleSubstring;
442
+
443
+ if (textHasEveryWord(name, query)) {
444
+ return PaletteMatchRank.TitleWords;
83
445
  }
84
- const keywordMatches: boolean = (command.keywords || []).some(
85
- (keyword: string) => {
86
- return keyword.toLowerCase().includes(normalizedQuery);
446
+
447
+ return null;
448
+ };
449
+
450
+ // A query word that is a typo of the start of one of these words.
451
+ const hasTypoOf: (token: string, words: Array<string>) => boolean = (
452
+ token: string,
453
+ words: Array<string>,
454
+ ): boolean => {
455
+ if (token.length < TYPO_MIN_LENGTH) {
456
+ return false;
457
+ }
458
+
459
+ return words.some((word: string): boolean => {
460
+ return matchWordWithTypo(token, word);
461
+ });
462
+ };
463
+
464
+ /*
465
+ * The title's letters in order, starting at the start of one of its words:
466
+ * "mntr" finds Monitors, but "ors" finds nothing.
467
+ */
468
+ const isWordStartSubsequence: (
469
+ needle: string,
470
+ title: PreparedText,
471
+ ) => boolean = (needle: string, title: PreparedText): boolean => {
472
+ let offset: number = 0;
473
+
474
+ for (const word of title.words) {
475
+ if (
476
+ word.charAt(0) === needle.charAt(0) &&
477
+ isSubsequenceMatch(needle, title.compact.slice(offset))
478
+ ) {
479
+ return true;
480
+ }
481
+
482
+ offset += word.length;
483
+ }
484
+
485
+ return false;
486
+ };
487
+
488
+ const getRankScore: (rank: PaletteMatchRank) => number = (
489
+ rank: PaletteMatchRank,
490
+ ): number => {
491
+ return RANK_SCORES[rank];
492
+ };
493
+
494
+ /*
495
+ * The query's words, each once: "incidents incident" is one word, so
496
+ * repeating a word cannot stand in for a second one.
497
+ */
498
+ const countDistinctWords: (query: PreparedQuery) => number = (
499
+ query: PreparedQuery,
500
+ ): number => {
501
+ let distinct: number = 0;
502
+
503
+ query.words.forEach((token: string, index: number): void => {
504
+ const isRepeat: boolean = query.words
505
+ .slice(0, index)
506
+ .some((earlier: string, earlierIndex: number): boolean => {
507
+ return isSameWord(
508
+ token,
509
+ earlier,
510
+ query.variants[index],
511
+ query.variants[earlierIndex],
512
+ );
513
+ });
514
+
515
+ if (!isRepeat) {
516
+ distinct++;
517
+ }
518
+ });
519
+
520
+ return distinct;
521
+ };
522
+
523
+ /*
524
+ * The match, or null. `sharedBy` is how many commands share this one's title
525
+ * (1 when it is the only one); only a command with a breadcrumb gives way.
526
+ */
527
+ const matchPreparedCommand: (data: {
528
+ command: PaletteCommand;
529
+ prepared: PreparedCommand;
530
+ query: PreparedQuery;
531
+ sharedBy: number;
532
+ }) => PaletteCommandMatch | null = (data: {
533
+ command: PaletteCommand;
534
+ prepared: PreparedCommand;
535
+ query: PreparedQuery;
536
+ sharedBy: number;
537
+ }): PaletteCommandMatch | null => {
538
+ const title: PreparedText = data.prepared.title;
539
+ const query: PreparedQuery = data.query;
540
+ const tokens: Array<string> = query.words;
541
+
542
+ const penalty: number = data.prepared.hasBreadcrumb
543
+ ? getSharedTitlePenalty(data.sharedBy)
544
+ : 0;
545
+
546
+ const titleMatch: (
547
+ rank: PaletteMatchRank,
548
+ bonus?: number,
549
+ ) => PaletteCommandMatch = (
550
+ rank: PaletteMatchRank,
551
+ bonus?: number,
552
+ ): PaletteCommandMatch => {
553
+ return {
554
+ command: data.command,
555
+ rank,
556
+ score: getRankScore(rank) + (bonus || 0) - penalty,
557
+ };
558
+ };
559
+
560
+ // The title, or one of its aliases, matched as the title.
561
+ let bestTitleRank: PaletteMatchRank | null = null;
562
+
563
+ for (const candidate of data.prepared.titles) {
564
+ const rank: PaletteMatchRank | null = matchName(candidate, query);
565
+
566
+ if (rank !== null && (bestTitleRank === null || rank < bestTitleRank)) {
567
+ bestTitleRank = rank;
568
+ }
569
+ }
570
+
571
+ if (bestTitleRank !== null) {
572
+ return titleMatch(bestTitleRank);
573
+ }
574
+
575
+ // Keywords: other names for the command, matched like a weaker title.
576
+ let bestKeywordScore: number | null = null;
577
+
578
+ for (const keyword of data.prepared.keywords) {
579
+ const rank: PaletteMatchRank | null = matchName(keyword, query);
580
+
581
+ if (rank === PaletteMatchRank.TitleExact) {
582
+ bestKeywordScore =
583
+ getRankScore(PaletteMatchRank.Keyword) + KEYWORD_EXACT_BONUS;
584
+ break;
585
+ }
586
+
587
+ if (rank !== null) {
588
+ bestKeywordScore = getRankScore(PaletteMatchRank.Keyword);
589
+ }
590
+ }
591
+
592
+ if (bestKeywordScore !== null) {
593
+ return {
594
+ command: data.command,
595
+ rank: PaletteMatchRank.Keyword,
596
+ score: bestKeywordScore,
597
+ };
598
+ }
599
+
600
+ /*
601
+ * Context: every word somewhere across the title, the keywords and where
602
+ * the command lives. A command with a breadcrumb needs a word of its own
603
+ * name, or two different words: "incident settings" lists Incidents >
604
+ * Settings, but "incidents" (or "incidents incidents") does not list
605
+ * every page in Incidents.
606
+ */
607
+ const ownNames: Array<PreparedText> = [
608
+ ...data.prepared.titles,
609
+ ...data.prepared.keywords,
610
+ ];
611
+
612
+ let ownNameWordCount: number = 0;
613
+ let contextWordCount: number = 0;
614
+ let allWordsFound: boolean = true;
615
+ // The crumbs that hold the words the command's own names do not.
616
+ const crumbsUsed: Set<number> = new Set<number>();
617
+
618
+ tokens.forEach((token: string, index: number): void => {
619
+ const variants: Array<string> = query.variants[index] || [];
620
+
621
+ const inOwnNames: boolean = ownNames.some((name: PreparedText): boolean => {
622
+ return textHasWord(name, token, variants);
623
+ });
624
+
625
+ if (inOwnNames) {
626
+ ownNameWordCount++;
627
+ return;
628
+ }
629
+
630
+ const crumb: number = data.prepared.context.findIndex(
631
+ (part: PreparedText): boolean => {
632
+ return textHasWord(part, token, variants);
633
+ },
634
+ );
635
+
636
+ if (crumb === -1) {
637
+ allWordsFound = false;
638
+ return;
639
+ }
640
+
641
+ contextWordCount++;
642
+ crumbsUsed.add(crumb);
643
+ });
644
+
645
+ const isContextEnough: boolean = data.prepared.hasBreadcrumb
646
+ ? ownNameWordCount > 0 || countDistinctWords(query) > 1
647
+ : ownNameWordCount > 0;
648
+
649
+ if (allWordsFound && isContextEnough) {
650
+ /*
651
+ * Two words or more that all name one place ("user settings" names User
652
+ * Settings) say more than words scattered over the trail ("Real User
653
+ * Monitoring > Settings").
654
+ */
655
+ const namesOnePlace: boolean =
656
+ crumbsUsed.size === 1 && contextWordCount > 1;
657
+
658
+ return {
659
+ command: data.command,
660
+ rank: PaletteMatchRank.Context,
661
+ score:
662
+ getRankScore(PaletteMatchRank.Context) +
663
+ Math.min(
664
+ CONTEXT_TITLE_WORD_BONUS_CAP,
665
+ ownNameWordCount * CONTEXT_TITLE_WORD_BONUS,
666
+ ) +
667
+ (namesOnePlace ? CONTEXT_ONE_PLACE_BONUS : 0),
668
+ };
669
+ }
670
+
671
+ // Inside the title, or inside a keyword.
672
+ if (
673
+ title.compact.length > 0 &&
674
+ (title.spaced.includes(query.spaced) ||
675
+ title.compact.includes(query.compact))
676
+ ) {
677
+ return titleMatch(PaletteMatchRank.Substring);
678
+ }
679
+
680
+ if (
681
+ query.compact.length >= KEYWORD_SUBSTRING_MIN_LENGTH &&
682
+ data.prepared.keywords.some((keyword: PreparedText): boolean => {
683
+ return keyword.compact.includes(query.compact);
684
+ })
685
+ ) {
686
+ return {
687
+ command: data.command,
688
+ rank: PaletteMatchRank.Substring,
689
+ score:
690
+ getRankScore(PaletteMatchRank.Substring) - KEYWORD_SUBSTRING_PENALTY,
691
+ };
692
+ }
693
+
694
+ // Fallbacks from here on: shown only when nothing matches better.
695
+ const initials: string = title.words
696
+ .map((word: string): string => {
697
+ return word.charAt(0);
698
+ })
699
+ .join("");
700
+
701
+ if (
702
+ tokens.length === 1 &&
703
+ query.compact.length >= 2 &&
704
+ title.words.length >= 2 &&
705
+ initials.startsWith(query.compact)
706
+ ) {
707
+ return titleMatch(PaletteMatchRank.TitleInitials);
708
+ }
709
+
710
+ // Only the group the command is listed under holds every word.
711
+ if (allWordsFound && !data.prepared.hasBreadcrumb) {
712
+ return {
713
+ command: data.command,
714
+ rank: PaletteMatchRank.Category,
715
+ score: getRankScore(PaletteMatchRank.Category),
716
+ };
717
+ }
718
+
719
+ // A typo: every word found, at least one of them only with a typo.
720
+ const ownWords: Array<string> = ownNames.flatMap(
721
+ (name: PreparedText): Array<string> => {
722
+ return name.words;
87
723
  },
88
724
  );
89
- if (keywordMatches) {
90
- return PaletteMatchRank.Keyword;
91
- }
92
- if (command.category.toLowerCase().includes(normalizedQuery)) {
93
- return PaletteMatchRank.Category;
725
+
726
+ let typoCount: number = 0;
727
+
728
+ const everyWordWithTypos: boolean = tokens.every(
729
+ (token: string, index: number): boolean => {
730
+ const variants: Array<string> = query.variants[index] || [];
731
+
732
+ if (
733
+ ownNames.some((name: PreparedText): boolean => {
734
+ return textHasWord(name, token, variants);
735
+ })
736
+ ) {
737
+ return true;
738
+ }
739
+
740
+ if (hasTypoOf(token, ownWords)) {
741
+ typoCount++;
742
+ return true;
743
+ }
744
+
745
+ return false;
746
+ },
747
+ );
748
+
749
+ if (everyWordWithTypos && typoCount > 0) {
750
+ return titleMatch(PaletteMatchRank.Fuzzy, TYPO_BONUS);
94
751
  }
95
- if (isSubsequenceMatch(normalizedQuery, title)) {
96
- return PaletteMatchRank.TitleSubsequence;
752
+
753
+ if (
754
+ query.compact.length >= SUBSEQUENCE_MIN_LENGTH &&
755
+ isWordStartSubsequence(query.compact, title)
756
+ ) {
757
+ return titleMatch(PaletteMatchRank.Fuzzy);
97
758
  }
759
+
98
760
  return null;
99
761
  };
100
762
 
101
763
  /**
102
- * Filter commands against free text and return them best-match-first:
103
- * title-prefix > title-substring > keyword > category > title-subsequence.
104
- * The sort is stable — within a tier the caller's order is preserved. An
105
- * empty/whitespace query matches everything in the original order.
764
+ * How one command matches the query, or null when it does not match at all.
765
+ * `sharedBy` is how many commands share its title (see
766
+ * getSharedTitlePenalty); filterPaletteCommands works it out over the whole
767
+ * catalog. An empty query matches everything; a query of only punctuation
768
+ * matches nothing.
769
+ */
770
+ export const matchPaletteCommand: (
771
+ command: PaletteCommand,
772
+ query: string,
773
+ sharedBy?: number,
774
+ ) => PaletteCommandMatch | null = (
775
+ command: PaletteCommand,
776
+ query: string,
777
+ sharedBy?: number,
778
+ ): PaletteCommandMatch | null => {
779
+ if (query.trim().length === 0) {
780
+ return { command, rank: PaletteMatchRank.TitleExact, score: 0 };
781
+ }
782
+
783
+ const preparedQuery: PreparedQuery = prepareText(query);
784
+
785
+ if (preparedQuery.words.length === 0) {
786
+ return null;
787
+ }
788
+
789
+ return matchPreparedCommand({
790
+ command,
791
+ prepared: prepareCommand(command),
792
+ query: preparedQuery,
793
+ sharedBy: sharedBy || 1,
794
+ });
795
+ };
796
+
797
+ /** The rank alone: how one command matches the query, or null. */
798
+ export const rankPaletteCommand: (
799
+ command: PaletteCommand,
800
+ query: string,
801
+ ) => PaletteMatchRank | null = (
802
+ command: PaletteCommand,
803
+ query: string,
804
+ ): PaletteMatchRank | null => {
805
+ const match: PaletteCommandMatch | null = matchPaletteCommand(command, query);
806
+
807
+ return match ? match.rank : null;
808
+ };
809
+
810
+ interface IndexedMatch {
811
+ match: PaletteCommandMatch;
812
+ index: number;
813
+ }
814
+
815
+ /**
816
+ * Filter commands against free text and return them best match first.
817
+ * Equal scores go by searchPriority, then keep the caller's order, so two
818
+ * pages whose titles both match the same way stay in catalog order. An empty
819
+ * or whitespace query matches everything in the original order; a query of
820
+ * only punctuation ("#", "?") matches nothing.
821
+ *
822
+ * Initials, the group a command is listed under, typos and letters-in-order
823
+ * are fallbacks: they are offered only when nothing matches better, so
824
+ * "pager" lists On-Call and not Status Pages, and "settings" does not list
825
+ * Users for being in the Settings group.
106
826
  */
107
827
  export const filterPaletteCommands: (
108
828
  commands: Array<PaletteCommand>,
@@ -111,35 +831,147 @@ export const filterPaletteCommands: (
111
831
  commands: Array<PaletteCommand>,
112
832
  query: string,
113
833
  ): Array<PaletteCommandMatch> => {
114
- const normalizedQuery: string = normalizePaletteQuery(query);
115
-
116
- if (!normalizedQuery) {
834
+ if (query.trim().length === 0) {
117
835
  return commands.map((command: PaletteCommand) => {
118
- return { command, rank: PaletteMatchRank.TitlePrefix };
836
+ return { command, rank: PaletteMatchRank.TitleExact, score: 0 };
119
837
  });
120
838
  }
121
839
 
122
- const matches: Array<PaletteCommandMatch> = [];
123
- commands.forEach((command: PaletteCommand) => {
124
- const rank: PaletteMatchRank | null = rankPaletteCommand(
125
- command,
126
- normalizedQuery,
840
+ const preparedQuery: PreparedQuery = prepareText(query);
841
+
842
+ if (preparedQuery.words.length === 0) {
843
+ return [];
844
+ }
845
+
846
+ const prepared: Array<PreparedCommand> = commands.map(
847
+ (command: PaletteCommand): PreparedCommand => {
848
+ return prepareCommand(command);
849
+ },
850
+ );
851
+
852
+ /*
853
+ * How many commands carry each title. A page called "Monitors" shares its
854
+ * name with the Monitors product, so it is the one that gives way.
855
+ */
856
+ const titleCounts: Map<string, number> = new Map();
857
+
858
+ prepared.forEach((command: PreparedCommand): void => {
859
+ titleCounts.set(
860
+ command.title.compact,
861
+ (titleCounts.get(command.title.compact) || 0) + 1,
127
862
  );
128
- if (rank !== null) {
129
- matches.push({ command, rank });
130
- }
131
863
  });
132
864
 
133
- // Array.prototype.sort is stable, so equal ranks keep catalog order.
134
- return matches.sort((a: PaletteCommandMatch, b: PaletteCommandMatch) => {
135
- return a.rank - b.rank;
865
+ const matches: Array<IndexedMatch> = [];
866
+
867
+ commands.forEach((command: PaletteCommand, index: number): void => {
868
+ const preparedCommand: PreparedCommand = prepared[index]!;
869
+
870
+ const match: PaletteCommandMatch | null = matchPreparedCommand({
871
+ command,
872
+ prepared: preparedCommand,
873
+ query: preparedQuery,
874
+ sharedBy: titleCounts.get(preparedCommand.title.compact) || 1,
875
+ });
876
+
877
+ if (match) {
878
+ matches.push({ match, index });
879
+ }
136
880
  });
881
+
882
+ const hasBetterMatches: boolean = matches.some(
883
+ (entry: IndexedMatch): boolean => {
884
+ return !FALLBACK_RANKS.has(entry.match.rank);
885
+ },
886
+ );
887
+
888
+ return matches
889
+ .filter((entry: IndexedMatch): boolean => {
890
+ return !hasBetterMatches || !FALLBACK_RANKS.has(entry.match.rank);
891
+ })
892
+ .sort((a: IndexedMatch, b: IndexedMatch): number => {
893
+ if (b.match.score !== a.match.score) {
894
+ return b.match.score - a.match.score;
895
+ }
896
+
897
+ const priorityA: number = a.match.command.searchPriority || 0;
898
+ const priorityB: number = b.match.command.searchPriority || 0;
899
+
900
+ if (priorityB !== priorityA) {
901
+ return priorityB - priorityA;
902
+ }
903
+
904
+ return a.index - b.index;
905
+ })
906
+ .map((entry: IndexedMatch): PaletteCommandMatch => {
907
+ return entry.match;
908
+ });
909
+ };
910
+
911
+ /*
912
+ * A text's letters and digits as the search reads them (lowercase, accents
913
+ * dropped), run together, with where each one came from in the text: so a
914
+ * match found in the search's terms can be marked in the text as shown.
915
+ */
916
+ interface NormalizedTextMap {
917
+ compact: string;
918
+ // For each character of `compact`, its character's index in the text.
919
+ sourceIndex: Array<number>;
920
+ // For each character of `compact`, whether a word of the text starts there.
921
+ startsWord: Array<boolean>;
922
+ }
923
+
924
+ const mapNormalizedText: (text: string) => NormalizedTextMap = (
925
+ text: string,
926
+ ): NormalizedTextMap => {
927
+ const characters: Array<string> = [];
928
+ const sourceIndex: Array<number> = [];
929
+ const startsWord: Array<boolean> = [];
930
+ let isInWord: boolean = false;
931
+
932
+ for (let index: number = 0; index < text.length; index++) {
933
+ const character: string = text.charAt(index);
934
+
935
+ if (!WORD_CHARACTER.test(character)) {
936
+ isInWord = false;
937
+ continue;
938
+ }
939
+
940
+ const normalized: string = character
941
+ .normalize("NFKD")
942
+ .replace(LETTER_ACCENTS, "")
943
+ .normalize("NFC")
944
+ .toLowerCase();
945
+
946
+ let isFirst: boolean = true;
947
+
948
+ for (const part of normalized) {
949
+ if (!WORD_CHARACTER.test(part)) {
950
+ continue;
951
+ }
952
+
953
+ characters.push(part);
954
+ sourceIndex.push(index);
955
+ startsWord.push(!isInWord && isFirst);
956
+ isFirst = false;
957
+ }
958
+
959
+ // A lone accent written as a mark of its own stays inside its word.
960
+ isInWord = true;
961
+ }
962
+
963
+ return { compact: characters.join(""), sourceIndex, startsWord };
137
964
  };
138
965
 
139
966
  /**
140
- * Split text into segments for <mark> highlighting: every case-insensitive
141
- * occurrence of the query becomes a match segment. Subsequence-only matches
142
- * produce no highlight (per-character marks read as noise).
967
+ * Split text into segments for <mark> highlighting, reading it the way the
968
+ * search does (case, accents and punctuation aside): each query word is
969
+ * marked where it starts a word of the text ("keys api" marks "API" and
970
+ * "Keys"), the whole query where it runs across words ("oncall" marks
971
+ * "On-Call"), and, when it starts no word, where it first appears ("eys").
972
+ * A space or hyphen between two marked words is marked with them. Typo and
973
+ * letters-in-order matches produce no highlight (per-character marks read
974
+ * as noise).
143
975
  */
144
976
  export const getHighlightSegments: (
145
977
  text: string,
@@ -148,30 +980,85 @@ export const getHighlightSegments: (
148
980
  text: string,
149
981
  query: string,
150
982
  ): Array<PaletteHighlightSegment> => {
151
- const needle: string = normalizePaletteQuery(query);
152
- if (!needle) {
983
+ const tokens: Array<string> = getPaletteQueryWords(query);
984
+
985
+ if (tokens.length === 0 || text.length === 0) {
153
986
  return [{ text, isMatch: false }];
154
987
  }
155
988
 
156
- const haystack: string = text.toLowerCase();
157
- const segments: Array<PaletteHighlightSegment> = [];
158
- let cursor: number = 0;
159
- let matchAt: number = haystack.indexOf(needle);
989
+ const map: NormalizedTextMap = mapNormalizedText(text);
990
+ const marked: Array<boolean> = new Array<boolean>(text.length).fill(false);
991
+
992
+ const markRange: (start: number, length: number) => void = (
993
+ start: number,
994
+ length: number,
995
+ ): void => {
996
+ for (let index: number = start; index < start + length; index++) {
997
+ const source: number | undefined = map.sourceIndex[index];
160
998
 
161
- while (matchAt !== -1) {
162
- if (matchAt > cursor) {
163
- segments.push({ text: text.slice(cursor, matchAt), isMatch: false });
999
+ if (source !== undefined) {
1000
+ marked[source] = true;
1001
+ }
1002
+ }
1003
+ };
1004
+
1005
+ // The whole query first, then each of its words.
1006
+ const wholeQuery: string = tokens.join("");
1007
+ const needles: Array<string> = Array.from(
1008
+ new Set<string>([wholeQuery, ...tokens]),
1009
+ );
1010
+
1011
+ for (const needle of needles) {
1012
+ let foundAtWordStart: boolean = false;
1013
+ let firstAnywhere: number = -1;
1014
+ let at: number = map.compact.indexOf(needle);
1015
+
1016
+ while (at !== -1) {
1017
+ if (firstAnywhere === -1) {
1018
+ firstAnywhere = at;
1019
+ }
1020
+
1021
+ if (map.startsWord[at]) {
1022
+ foundAtWordStart = true;
1023
+ markRange(at, needle.length);
1024
+ }
1025
+
1026
+ at = map.compact.indexOf(needle, at + 1);
1027
+ }
1028
+
1029
+ if (!foundAtWordStart && firstAnywhere !== -1 && needle === wholeQuery) {
1030
+ // Only the whole query may be marked mid-word ("eys" in "Keys").
1031
+ markRange(firstAnywhere, needle.length);
1032
+ }
1033
+ }
1034
+
1035
+ /*
1036
+ * A space or hyphen between two marked words is marked too, so "on call"
1037
+ * marks "On-Call" as one run rather than two with a gap.
1038
+ */
1039
+ for (let index: number = 1; index < text.length - 1; index++) {
1040
+ if (
1041
+ !marked[index] &&
1042
+ marked[index - 1] &&
1043
+ marked[index + 1] &&
1044
+ !WORD_CHARACTER.test(text.charAt(index))
1045
+ ) {
1046
+ marked[index] = true;
164
1047
  }
165
- segments.push({
166
- text: text.slice(matchAt, matchAt + needle.length),
167
- isMatch: true,
168
- });
169
- cursor = matchAt + needle.length;
170
- matchAt = haystack.indexOf(needle, cursor);
171
1048
  }
172
1049
 
173
- if (cursor < text.length) {
174
- segments.push({ text: text.slice(cursor), isMatch: false });
1050
+ const segments: Array<PaletteHighlightSegment> = [];
1051
+
1052
+ for (let index: number = 0; index < text.length; index++) {
1053
+ const isMatch: boolean = Boolean(marked[index]);
1054
+ const last: PaletteHighlightSegment | undefined =
1055
+ segments[segments.length - 1];
1056
+
1057
+ if (last && last.isMatch === isMatch) {
1058
+ last.text += text.charAt(index);
1059
+ } else {
1060
+ segments.push({ text: text.charAt(index), isMatch });
1061
+ }
175
1062
  }
176
1063
 
177
1064
  if (segments.length === 0) {