@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
@@ -8,6 +8,7 @@ import {
8
8
  test,
9
9
  } from "@jest/globals";
10
10
  import {
11
+ act,
11
12
  cleanup,
12
13
  fireEvent,
13
14
  render,
@@ -17,19 +18,16 @@ import {
17
18
  } from "@testing-library/react";
18
19
  import React from "react";
19
20
  import { MemoryRouter } from "react-router-dom";
20
- import AIFeatures, {
21
- AI_FEATURES_CARD_TITLE,
22
- AI_FEATURE_FIELDS,
23
- canEditAiFeatures,
24
- getAiFeaturesPermissionMessage,
25
- getAiFeaturesUpdatePermissions,
26
- } from "../../../../App/FeatureSet/Dashboard/src/Pages/Settings/AIFeatures";
21
+ import AIFeatures from "../../../../App/FeatureSet/Dashboard/src/Pages/Settings/AIFeatures";
27
22
  import AICredits from "../../../../App/FeatureSet/Dashboard/src/Pages/Settings/AICredits";
28
23
  import SettingsSideMenu from "../../../../App/FeatureSet/Dashboard/src/Pages/Settings/SideMenu";
29
- import IncidentAISettings, {
30
- POSTMORTEM_DRAFT_CARD_TITLE,
31
- POSTMORTEM_DRAFT_FIELDS,
32
- } from "../../../../App/FeatureSet/Dashboard/src/Pages/Incidents/Settings/IncidentAISettings";
24
+ import IncidentAISettings from "../../../../App/FeatureSet/Dashboard/src/Pages/Incidents/Settings/IncidentAISettings";
25
+ import {
26
+ ENABLE_AI_COLUMN,
27
+ ENABLE_AI_SWITCH_TEST_ID,
28
+ EnableAiCopy,
29
+ getProjectAiSwitchTestId,
30
+ } from "../../../../App/FeatureSet/Dashboard/src/Components/AISettings/ProjectAiSettingsCopy";
33
31
  import {
34
32
  ProjectColumnsEditGate,
35
33
  canUpdateProjectColumns,
@@ -43,13 +41,19 @@ import RouteMap, {
43
41
  } from "../../../../App/FeatureSet/Dashboard/src/Utils/RouteMap";
44
42
  import { getSettingsBreadcrumbs } from "../../../../App/FeatureSet/Dashboard/src/Utils/Breadcrumbs/SettingsBreadcrumbs";
45
43
  import Project from "../../../Models/DatabaseModels/Project";
44
+ import HTTPResponse from "../../../Types/API/HTTPResponse";
46
45
  import Route from "../../../Types/API/Route";
47
46
  import ListResult from "../../../Types/BaseDatabase/ListResult";
47
+ import { JSONObject } from "../../../Types/JSON";
48
48
  import Link from "../../../Types/Link";
49
49
  import ObjectID from "../../../Types/ObjectID";
50
50
  import Permission from "../../../Types/Permission";
51
+ import API from "../../../UI/Utils/API/API";
51
52
  import ModelAPI from "../../../UI/Utils/ModelAPI/ModelAPI";
52
53
  import PermissionUtil from "../../../UI/Utils/Permission";
54
+ import PermissionGate, {
55
+ PermissionGateResult,
56
+ } from "../../../UI/Utils/PermissionGate";
53
57
  import User from "../../../UI/Utils/User";
54
58
  import {
55
59
  MenuLink,
@@ -108,13 +112,14 @@ jest.mock("../../../UI/Config", () => {
108
112
  * Features", first in the AI section of the menu and outside the billing
109
113
  * branch. It is the project's only AI switch: "Enable Auto-Remediation" and
110
114
  * "Enable AI Command Execution (for Runners)" once sat next to it and were
111
- * folded into it, so the card shows and saves Enable AI alone. The same
112
- * pages are rendered for real here, with the model API and the permission
113
- * snapshot stubbed.
115
+ * folded into it. The page is that one switch, saving the moment it is
116
+ * flipped (it used to sit behind "Edit AI Features" and a dialog), asking
117
+ * first before it turns AI off. The same pages are rendered for real here,
118
+ * with the model API and the permission snapshot stubbed.
114
119
  *
115
- * Also here: the incident AI settings page's new "Draft a postmortem
116
- * automatically when an incident resolves" switch, which is its own card so
117
- * it can never ride on (or be overwritten by) the investigation settings.
120
+ * Also here: the incident AI settings page's "Draft a postmortem when an
121
+ * incident resolves" switch, its own column, which no other switch or card
122
+ * on the page can ride on or overwrite.
118
123
  */
119
124
 
120
125
  const WAIT_TIMEOUT: number = 20000;
@@ -132,7 +137,7 @@ const ENABLE_AI_TITLE: string = "Enable AI";
132
137
 
133
138
  /*
134
139
  * The switches folded into Enable AI, by the titles the card gave them. The
135
- * page must never show either again, in the detail view or the form.
140
+ * page must never show either again.
136
141
  */
137
142
  const RETIRED_SWITCH_TITLES: Array<string> = [
138
143
  "Enable Auto-Remediation",
@@ -153,12 +158,13 @@ const RETIRED_SWITCH_WORDING: Array<RegExp> = [
153
158
 
154
159
  /*
155
160
  * Every Project column the page may read or write. Anything else on a
156
- * saved model is a field riding along.
161
+ * request is a field riding along.
157
162
  */
158
163
  const AI_FEATURES_COLUMNS: Array<string> = ["_id", "enableAi"];
159
164
 
160
165
  let project: Project;
161
166
  let getItemSpy: ReturnType<typeof jest.spyOn>;
167
+ let updateByIdSpy: ReturnType<typeof jest.spyOn>;
162
168
  let createOrUpdateSpy: ReturnType<typeof jest.spyOn>;
163
169
 
164
170
  function grant(permissions: Array<Permission>, isMasterAdmin?: boolean): void {
@@ -199,6 +205,14 @@ async function findText(text: string | RegExp): Promise<HTMLElement> {
199
205
  return await screen.findByText(text, {}, { timeout: WAIT_TIMEOUT });
200
206
  }
201
207
 
208
+ async function flush(): Promise<void> {
209
+ await act(async () => {
210
+ for (let i: number = 0; i < 10; i++) {
211
+ await Promise.resolve();
212
+ }
213
+ });
214
+ }
215
+
202
216
  function itemRequests(): Array<{ select?: Record<string, unknown> }> {
203
217
  return getItemSpy.mock.calls.map(
204
218
  (call: Array<unknown>): { select?: Record<string, unknown> } => {
@@ -207,44 +221,29 @@ function itemRequests(): Array<{ select?: Record<string, unknown> }> {
207
221
  );
208
222
  }
209
223
 
210
- function postedProject(): Project {
211
- return (createOrUpdateSpy.mock.calls[0]![0] as { model: Project }).model;
224
+ // Every update the page sent, as the columns and values it wrote.
225
+ function updates(): Array<Record<string, unknown>> {
226
+ return updateByIdSpy.mock.calls.map(
227
+ (call: Array<unknown>): Record<string, unknown> => {
228
+ return (call[0] as { data: Record<string, unknown> }).data;
229
+ },
230
+ );
212
231
  }
213
232
 
214
- /*
215
- * The Project columns a saved model carries a value for, sorted, leaving
216
- * out its id: the columns the save writes.
217
- */
218
- function writtenColumns(model: Project): Array<string> {
219
- const values: Record<string, unknown> = model as unknown as Record<
220
- string,
221
- unknown
222
- >;
223
-
224
- return Object.keys(values)
225
- .filter((key: string): boolean => {
226
- return (
227
- key !== "_id" && model.isTableColumn(key) && values[key] !== undefined
228
- );
229
- })
230
- .sort();
233
+ async function enableAiSwitch(): Promise<HTMLElement> {
234
+ return await screen.findByTestId(
235
+ ENABLE_AI_SWITCH_TEST_ID,
236
+ {},
237
+ { timeout: WAIT_TIMEOUT },
238
+ );
231
239
  }
232
240
 
233
241
  async function aiFeaturesCard(): Promise<HTMLElement> {
234
- return (await findText(AI_FEATURES_CARD_TITLE)).closest(
242
+ return (await findText(EnableAiCopy.cardTitle)).closest(
235
243
  '[data-testid="card"]',
236
244
  ) as HTMLElement;
237
245
  }
238
246
 
239
- // The titles of a card's detail rows, in order.
240
- function detailTitlesIn(card: HTMLElement): Array<string> {
241
- return Array.from(card.querySelectorAll("label > span")).map(
242
- (title: Element): string => {
243
- return title.textContent || "";
244
- },
245
- );
246
- }
247
-
248
247
  function expectNoRetiredSwitch(container: HTMLElement): void {
249
248
  const text: string = container.textContent || "";
250
249
 
@@ -256,66 +255,15 @@ function expectNoRetiredSwitch(container: HTMLElement): void {
256
255
  }
257
256
  }
258
257
 
259
- // A detail row's title, as ModelDetail renders it.
260
- function detailTitle(title: string): HTMLElement {
261
- return screen.getByText(title, { selector: "label > span" });
262
- }
263
-
264
- // The value a detail row shows, by its title.
265
- function detailValue(title: string): string {
266
- const row: HTMLElement | null =
267
- detailTitle(title).closest("div.space-y-1")?.parentElement || null;
268
- return row?.textContent || "";
269
- }
270
-
271
- async function openEditModal(buttonText: string): Promise<HTMLElement> {
272
- const button: HTMLElement = await findText(buttonText);
273
- fireEvent.click(button);
274
- return await screen.findByRole("dialog", {}, { timeout: WAIT_TIMEOUT });
275
- }
276
-
277
- /*
278
- * A form switch by its field title. The accessible name is the field label,
279
- * which also carries "(Optional)" for a field that is not required.
280
- */
281
- function switchName(title: string): RegExp {
282
- return new RegExp(
283
- `^${title.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}( \\(Optional\\))?$`,
284
- );
285
- }
286
-
287
- async function waitForSwitch(
288
- dialog: HTMLElement,
289
- name: string,
290
- checked: boolean,
291
- ): Promise<HTMLElement> {
292
- const toggle: HTMLElement = await within(dialog).findByRole(
293
- "switch",
294
- { name: switchName(name) },
295
- { timeout: WAIT_TIMEOUT },
296
- );
297
- await waitFor(
298
- () => {
299
- expect(toggle).toHaveAttribute("aria-checked", String(checked));
300
- },
301
- { timeout: WAIT_TIMEOUT },
302
- );
303
- return toggle;
304
- }
305
-
306
- async function save(dialog: HTMLElement): Promise<void> {
307
- fireEvent.click(within(dialog).getByTestId("modal-footer-submit-button"));
308
- await waitFor(
309
- () => {
310
- expect(createOrUpdateSpy).toHaveBeenCalledTimes(1);
311
- },
312
- { timeout: WAIT_TIMEOUT },
313
- );
258
+ async function press(control: HTMLElement): Promise<void> {
259
+ fireEvent.click(control);
260
+ await flush();
314
261
  }
315
262
 
316
263
  beforeEach(() => {
317
264
  window.localStorage.clear();
318
265
  window.sessionStorage.clear();
266
+ PermissionGate.clearPermissionPropsCache();
319
267
  grant([...BASE_PERMISSIONS, Permission.ProjectOwner]);
320
268
 
321
269
  project = Object.assign(new Project(), {
@@ -344,11 +292,28 @@ beforeEach(() => {
344
292
  .mockImplementation(async (): Promise<number> => {
345
293
  return 0;
346
294
  });
295
+ updateByIdSpy = jest
296
+ .spyOn(ModelAPI, "updateById")
297
+ .mockImplementation(async (): Promise<never> => {
298
+ return {} as never;
299
+ });
347
300
  createOrUpdateSpy = jest
348
301
  .spyOn(ModelAPI, "createOrUpdate")
349
302
  .mockImplementation(async (): Promise<never> => {
350
303
  return { data: {} } as never;
351
304
  });
305
+ // The provider the project would use (the notice asks): a global one.
306
+ jest.spyOn(API, "post").mockImplementation(async (): Promise<never> => {
307
+ return new HTTPResponse<JSONObject>(
308
+ 200,
309
+ {
310
+ isAIEnabledForProject: true,
311
+ defaultProviderId: "9d9d9d9d-0000-4000-8000-000000000001",
312
+ providers: [],
313
+ },
314
+ {},
315
+ ) as unknown as never;
316
+ });
352
317
  });
353
318
 
354
319
  afterEach(() => {
@@ -357,51 +322,43 @@ afterEach(() => {
357
322
  billingEnabledForTest = false;
358
323
  });
359
324
 
360
- describe("who may change the AI features", () => {
361
- test("the card edits Enable AI and nothing else", () => {
362
- expect(AI_FEATURE_FIELDS).toEqual(["enableAi"]);
325
+ describe("who may change Enable AI", () => {
326
+ test("the page saves Enable AI and nothing else", () => {
327
+ expect(ENABLE_AI_COLUMN).toBe("enableAi");
363
328
  });
364
329
 
365
330
  test("follows Enable AI's own update permissions", () => {
366
- expect(getAiFeaturesUpdatePermissions()).toEqual(
367
- new Project().getColumnAccessControlFor("enableAi")?.update,
331
+ expect(new Project().getColumnAccessControlFor("enableAi")?.update).toEqual(
332
+ [Permission.ProjectOwner, Permission.ManageProjectBilling],
368
333
  );
369
- expect(getAiFeaturesUpdatePermissions()).toEqual([
370
- Permission.ProjectOwner,
371
- Permission.ManageProjectBilling,
372
- ]);
373
334
  });
374
335
 
375
336
  /*
376
- * The folded switches are not Project columns any more. Were either name
377
- * ever listed on the card again, the gate would find no update list for
378
- * it and lock the card for everyone but a master admin.
337
+ * The folded switches are not Project columns any more: no switch could
338
+ * be drawn for either.
379
339
  */
380
340
  test.each([["enableAutoRemediation"], ["enableAiCommandExecution"]])(
381
- "%s is no longer a column the card could list",
341
+ "%s is no longer a column a switch could save",
382
342
  (retiredField: string) => {
383
343
  expect(new Project().hasColumn(retiredField)).toBe(false);
384
344
  expect(new Project().getColumnAccessControlFor(retiredField)).toBeNull();
385
345
  expect(
386
- getProjectColumnsUpdatePermissions([
387
- ...AI_FEATURE_FIELDS,
388
- retiredField,
389
- ]),
346
+ getProjectColumnsUpdatePermissions([ENABLE_AI_COLUMN, retiredField]),
390
347
  ).toEqual([]);
391
348
  },
392
349
  );
393
350
 
394
351
  test("is narrower than the Project table's update list", () => {
395
- // Why the card cannot rely on CardModelDetail's table-level gate.
352
+ // Why the switch is gated on its column, not on the table.
396
353
  expect(new Project().getUpdatePermissions()).toEqual(
397
354
  expect.arrayContaining([Permission.ProjectAdmin, Permission.EditProject]),
398
355
  );
399
- expect(getAiFeaturesUpdatePermissions()).not.toContain(
400
- Permission.ProjectAdmin,
401
- );
402
- expect(getAiFeaturesUpdatePermissions()).not.toContain(
403
- Permission.EditProject,
404
- );
356
+
357
+ const enableAiUpdate: Array<Permission> =
358
+ new Project().getColumnAccessControlFor("enableAi")?.update || [];
359
+
360
+ expect(enableAiUpdate).not.toContain(Permission.ProjectAdmin);
361
+ expect(enableAiUpdate).not.toContain(Permission.EditProject);
405
362
  });
406
363
 
407
364
  test.each([
@@ -411,26 +368,44 @@ describe("who may change the AI features", () => {
411
368
  [Permission.EditProject, false],
412
369
  [Permission.ProjectMember, false],
413
370
  [Permission.Viewer, false],
414
- ])("%s may change them: %s", (permission: Permission, allowed: boolean) => {
371
+ ])("%s may change it: %s", (permission: Permission, allowed: boolean) => {
415
372
  grant([...BASE_PERMISSIONS, permission]);
416
- expect(canEditAiFeatures()).toBe(allowed);
373
+
374
+ expect(
375
+ PermissionGate.checkColumnUpdate(new Project(), ENABLE_AI_COLUMN)
376
+ .isAllowed,
377
+ ).toBe(allowed);
417
378
  });
418
379
 
419
- test("a master admin may change them", () => {
380
+ test("a master admin may change it", () => {
420
381
  grant([], true);
421
- expect(canEditAiFeatures()).toBe(true);
382
+
383
+ expect(
384
+ PermissionGate.checkColumnUpdate(new Project(), ENABLE_AI_COLUMN)
385
+ .isAllowed,
386
+ ).toBe(true);
422
387
  });
423
388
 
424
- test("the locked button's reason names the permissions", () => {
425
- expect(getAiFeaturesPermissionMessage()).toBe(
426
- "Changing these needs one of these permissions: Project Owner, Manage Billing.",
389
+ test("the locked switch's reason names the permissions it needs", () => {
390
+ grant([...BASE_PERMISSIONS, Permission.ProjectAdmin]);
391
+
392
+ const gate: PermissionGateResult = PermissionGate.checkColumnUpdate(
393
+ new Project(),
394
+ ENABLE_AI_COLUMN,
395
+ );
396
+
397
+ expect(gate.disabledReason).toContain(
398
+ "You need one of these permissions: Project Owner, Manage Billing.",
427
399
  );
428
400
  });
429
401
  });
430
402
 
431
403
  /*
432
- * The shared gate the AI Features card and the postmortem draft card use in
433
- * place of CardModelDetail's table-level one.
404
+ * The shared gate the cards of Project settings use in place of
405
+ * CardModelDetail's table-level one: the AI limit cards under Advanced on
406
+ * Incidents and Alerts → Settings → AI, Linked Alerts and the number
407
+ * prefixes. (A switch gates itself the same way, on its own column:
408
+ * PermissionGate.checkColumnUpdate.)
434
409
  */
435
410
  describe("the Project column edit gate", () => {
436
411
  test("keeps the permissions every listed column allows, in the first column's order", () => {
@@ -528,88 +503,73 @@ describe("the Project column edit gate", () => {
528
503
  });
529
504
 
530
505
  describe("AI Features page", () => {
531
- test("shows its one switch, Enable AI, with the project's value", async () => {
506
+ test("is Enable AI's switch, with the project's value", async () => {
532
507
  openAiFeatures();
533
508
 
534
- expect(await findText(AI_FEATURES_CARD_TITLE)).toBeInTheDocument();
509
+ expect(await findText(EnableAiCopy.cardTitle)).toBeInTheDocument();
535
510
  expect(
536
511
  screen.getByText("Turn OneUptime AI on or off for this project."),
537
512
  ).toBeInTheDocument();
538
513
 
539
- await waitFor(
540
- () => {
541
- expect(screen.getAllByText("Yes").length).toBe(1);
542
- },
543
- { timeout: WAIT_TIMEOUT },
544
- );
545
- expect(screen.queryByText("No")).not.toBeInTheDocument();
514
+ const enableAi: HTMLElement = await enableAiSwitch();
546
515
 
547
- expect(detailTitle(ENABLE_AI_TITLE)).toBeInTheDocument();
548
- expect(detailValue(ENABLE_AI_TITLE)).toContain("Yes");
549
- expect(
550
- screen.getByText(
551
- "The master switch for every AI feature in this project, auto-remediation and AI commands on Runners included.",
552
- ),
553
- ).toBeInTheDocument();
516
+ expect(enableAi).toHaveAttribute("aria-checked", "true");
517
+ expect(screen.getByRole("switch", { name: ENABLE_AI_TITLE })).toBe(
518
+ enableAi,
519
+ );
520
+ // The switch is the setting: no Edit button, no dialog.
521
+ expect(screen.queryByText("Edit AI Features")).toBeNull();
522
+ expect(screen.queryByRole("dialog")).toBeNull();
554
523
  });
555
524
 
556
- test("the card has exactly one detail row", async () => {
525
+ test("the card holds exactly one switch", async () => {
557
526
  openAiFeatures();
558
527
 
559
528
  const card: HTMLElement = await aiFeaturesCard();
560
- await waitFor(
561
- () => {
562
- expect(within(card).getAllByText("Yes").length).toBe(1);
563
- },
564
- { timeout: WAIT_TIMEOUT },
565
- );
566
- expect(detailTitlesIn(card)).toEqual([ENABLE_AI_TITLE]);
529
+ await enableAiSwitch();
530
+
531
+ expect(within(card).getAllByRole("switch")).toHaveLength(1);
567
532
  });
568
533
 
569
- /*
570
- * ModelDetail leaves out a row whose column the viewer may not read, and a
571
- * column the model no longer has grants nobody. A master admin is shown
572
- * every row the card lists, so the rows counted here are the card's own.
573
- */
574
- test("a master admin, who is shown every row the card lists, still sees one", async () => {
534
+ test("a master admin sees the one switch too", async () => {
575
535
  grant([], true);
576
536
  openAiFeatures();
577
537
 
578
538
  const card: HTMLElement = await aiFeaturesCard();
579
- await waitFor(
580
- () => {
581
- expect(within(card).getAllByText("Yes").length).toBe(1);
582
- },
583
- { timeout: WAIT_TIMEOUT },
584
- );
585
- expect(detailTitlesIn(card)).toEqual([ENABLE_AI_TITLE]);
539
+ await enableAiSwitch();
540
+
541
+ expect(within(card).getAllByRole("switch")).toHaveLength(1);
586
542
  expectNoRetiredSwitch(card);
587
543
  });
588
544
 
589
- test("shows AI switched off as No", async () => {
545
+ test("shows AI switched off as off", async () => {
590
546
  project.enableAi = false;
591
547
  openAiFeatures();
592
548
 
593
- await findText(AI_FEATURES_CARD_TITLE);
594
- await waitFor(
595
- () => {
596
- expect(detailValue(ENABLE_AI_TITLE)).toContain("No");
597
- },
598
- { timeout: WAIT_TIMEOUT },
599
- );
600
- expect(screen.queryByText("Yes")).not.toBeInTheDocument();
549
+ expect(await enableAiSwitch()).toHaveAttribute("aria-checked", "false");
601
550
  });
602
551
 
603
- test("never shows the switches folded into Enable AI", async () => {
552
+ test("says what it covers", async () => {
604
553
  openAiFeatures();
554
+ await enableAiSwitch();
605
555
 
606
- await findText(AI_FEATURES_CARD_TITLE);
607
- await waitFor(
608
- () => {
609
- expect(screen.getAllByText("Yes").length).toBe(1);
610
- },
611
- { timeout: WAIT_TIMEOUT },
556
+ const row: HTMLElement = screen.getByTestId(
557
+ `${ENABLE_AI_SWITCH_TEST_ID}-row`,
558
+ );
559
+
560
+ expect(row).toHaveTextContent(
561
+ /The master switch\. When off, every AI feature in this project stops: Ask AI, investigations, postmortem drafts, auto-remediation and AI commands on Runners\./,
562
+ );
563
+ // Nothing else in the project has to be switched on as well.
564
+ expect(row).toHaveTextContent(
565
+ /Auto-remediation and AI commands on Runners need no other project switch\./,
612
566
  );
567
+ expectNoRetiredSwitch(row);
568
+ });
569
+
570
+ test("never shows the switches folded into Enable AI", async () => {
571
+ openAiFeatures();
572
+ await enableAiSwitch();
613
573
 
614
574
  for (const title of RETIRED_SWITCH_TITLES) {
615
575
  expect(screen.queryByText(title)).not.toBeInTheDocument();
@@ -619,7 +579,7 @@ describe("AI Features page", () => {
619
579
 
620
580
  test("reads the project it is on, and only Enable AI", async () => {
621
581
  openAiFeatures();
622
- await findText("Edit AI Features");
582
+ await enableAiSwitch();
623
583
 
624
584
  await waitFor(
625
585
  () => {
@@ -627,149 +587,115 @@ describe("AI Features page", () => {
627
587
  },
628
588
  { timeout: WAIT_TIMEOUT },
629
589
  );
630
- const call: { id?: unknown; select?: Record<string, unknown> } = getItemSpy
631
- .mock.calls[0]![0] as {
632
- id?: unknown;
633
- select?: Record<string, unknown>;
634
- };
635
- expect(String(call.id)).toBe(PROJECT_ID);
636
- expect(call.select).toHaveProperty("enableAi");
637
- for (const column of Object.keys(call.select || {})) {
638
- expect(AI_FEATURES_COLUMNS).toContain(column);
639
- }
640
- expect(call.select).not.toHaveProperty("enableAutoRemediation");
641
- expect(call.select).not.toHaveProperty("enableAiCommandExecution");
642
- expect(call.select).not.toHaveProperty("aiCurrentBalanceInUSDCents");
643
- });
644
590
 
645
- test("the edit form holds one switch, Enable AI, and says what it covers", async () => {
646
- openAiFeatures();
591
+ for (const call of getItemSpy.mock.calls) {
592
+ const request: { id?: unknown; select?: Record<string, unknown> } =
593
+ call[0] as { id?: unknown; select?: Record<string, unknown> };
647
594
 
648
- const dialog: HTMLElement = await openEditModal("Edit AI Features");
649
- await waitForSwitch(dialog, ENABLE_AI_TITLE, true);
595
+ expect(String(request.id)).toBe(PROJECT_ID);
596
+ expect(request.select).toHaveProperty("enableAi");
650
597
 
651
- expect(within(dialog).getAllByRole("switch")).toHaveLength(1);
652
- for (const title of RETIRED_SWITCH_TITLES) {
653
- expect(
654
- within(dialog).queryByRole("switch", { name: switchName(title) }),
655
- ).not.toBeInTheDocument();
598
+ for (const column of Object.keys(request.select || {})) {
599
+ expect(AI_FEATURES_COLUMNS).toContain(column);
600
+ }
656
601
  }
657
-
658
- expect(
659
- within(dialog).getByText(
660
- /^The master switch\. When off, every AI feature in this project stops: Ask AI, investigations, postmortem drafts, auto-remediation and AI commands on Runners\./,
661
- ),
662
- ).toBeInTheDocument();
663
- // Nothing else in the project has to be switched on as well.
664
- expect(
665
- within(dialog).getByText(
666
- /Auto-remediation and AI commands on Runners need no other project switch\.$/,
667
- ),
668
- ).toBeInTheDocument();
669
- expectNoRetiredSwitch(dialog);
670
602
  });
671
603
 
672
- test("a project owner turns AI off and saves exactly that switch", async () => {
604
+ test("a project owner turns AI off: it asks first, then saves exactly that switch", async () => {
673
605
  openAiFeatures();
674
606
 
675
- const dialog: HTMLElement = await openEditModal("Edit AI Features");
676
- const enableAi: HTMLElement = await waitForSwitch(
677
- dialog,
678
- ENABLE_AI_TITLE,
679
- true,
607
+ await press(await enableAiSwitch());
608
+
609
+ const dialog: HTMLElement = screen.getByRole("dialog");
610
+ expect(dialog).toHaveTextContent(EnableAiCopy.turnOffConfirmTitle);
611
+ expect(updateByIdSpy).not.toHaveBeenCalled();
612
+
613
+ fireEvent.click(
614
+ within(dialog).getByRole("button", {
615
+ name: EnableAiCopy.turnOffConfirmButton,
616
+ }),
680
617
  );
618
+ await flush();
681
619
 
682
- fireEvent.click(enableAi);
683
- await save(dialog);
684
-
685
- const posted: Project = postedProject();
686
- expect(posted.enableAi).toBe(false);
687
- // Nothing else on the project rides along.
688
- expect(writtenColumns(posted)).toEqual(["enableAi"]);
689
- expect(posted).not.toHaveProperty("enableAutoRemediation");
690
- expect(posted).not.toHaveProperty("enableAiCommandExecution");
691
- expect(posted.aiCurrentBalanceInUSDCents).toBeUndefined();
692
- expect(posted.enableAutomaticIncidentInvestigation).toBeUndefined();
693
- expect(posted.enableAutomaticPostmortemDraft).toBeUndefined();
620
+ expect(updates()).toEqual([{ enableAi: false }]);
621
+ expect(
622
+ String((updateByIdSpy.mock.calls[0]![0] as { id: unknown }).id),
623
+ ).toBe(PROJECT_ID);
624
+ // Nothing goes through a form, so nothing rides along.
625
+ expect(createOrUpdateSpy).not.toHaveBeenCalled();
694
626
  });
695
627
 
696
- test("a project owner turns AI back on the same way", async () => {
628
+ test("a project owner turns AI back on at once", async () => {
697
629
  project.enableAi = false;
698
630
  openAiFeatures();
699
631
 
700
- const dialog: HTMLElement = await openEditModal("Edit AI Features");
701
- const enableAi: HTMLElement = await waitForSwitch(
702
- dialog,
703
- ENABLE_AI_TITLE,
704
- false,
705
- );
706
-
707
- fireEvent.click(enableAi);
708
- await save(dialog);
632
+ await press(await enableAiSwitch());
709
633
 
710
- const posted: Project = postedProject();
711
- expect(posted.enableAi).toBe(true);
712
- expect(writtenColumns(posted)).toEqual(["enableAi"]);
634
+ expect(screen.queryByRole("dialog")).toBeNull();
635
+ expect(updates()).toEqual([{ enableAi: true }]);
636
+ expect(
637
+ screen.getByTestId(`${ENABLE_AI_SWITCH_TEST_ID}-status`),
638
+ ).toHaveTextContent("Saved");
713
639
  });
714
640
 
715
- test("someone with Manage Project Billing may edit", async () => {
641
+ test("someone with Manage Project Billing may flip it", async () => {
716
642
  grant([...BASE_PERMISSIONS, Permission.ManageProjectBilling]);
717
643
  openAiFeatures();
718
644
 
719
- const button: HTMLElement = await findText("Edit AI Features");
720
- expect(button.closest("button")).not.toBeDisabled();
645
+ expect(await enableAiSwitch()).not.toHaveAttribute("aria-disabled");
721
646
  });
722
647
 
723
- test("a master admin may edit", async () => {
648
+ test("a master admin may flip it", async () => {
724
649
  grant([], true);
725
650
  openAiFeatures();
726
651
 
727
- const button: HTMLElement = await findText("Edit AI Features");
728
- expect(button.closest("button")).not.toBeDisabled();
652
+ expect(await enableAiSwitch()).not.toHaveAttribute("aria-disabled");
729
653
  });
730
654
 
655
+ /*
656
+ * A Project Admin may update the project, but not this column: the reason
657
+ * names the column's own permissions. A member or a viewer may not update
658
+ * the project at all, and is told so.
659
+ */
731
660
  test.each([
732
- [Permission.ProjectAdmin],
733
- [Permission.ProjectMember],
734
- [Permission.Viewer],
735
- ])("is locked, with the reason, for %s", async (permission: Permission) => {
736
- grant([...BASE_PERMISSIONS, permission]);
737
- openAiFeatures();
661
+ [Permission.ProjectAdmin, "Project Owner, Manage Billing"],
662
+ [Permission.ProjectMember, "You do not have permission to update this"],
663
+ [Permission.Viewer, "You do not have permission to update this"],
664
+ ])(
665
+ "is locked, with the reason, for %s",
666
+ async (permission: Permission, reason: string) => {
667
+ grant([...BASE_PERMISSIONS, permission]);
668
+ openAiFeatures();
738
669
 
739
- await findText(AI_FEATURES_CARD_TITLE);
740
- // Everyone who may read the project reads the switch.
741
- await waitFor(
742
- () => {
743
- expect(detailValue(ENABLE_AI_TITLE)).toContain("Yes");
744
- },
745
- { timeout: WAIT_TIMEOUT },
746
- );
670
+ const enableAi: HTMLElement = await enableAiSwitch();
747
671
 
748
- const buttons: Array<HTMLElement> = screen
749
- .getAllByText("Edit AI Features")
750
- .map((text: HTMLElement): HTMLElement => {
751
- return text.closest("button") as HTMLElement;
752
- });
753
- expect(buttons.length).toBe(1);
754
- expect(buttons[0]).toBeDisabled();
672
+ // Everyone who may read the project reads the switch.
673
+ expect(enableAi).toHaveAttribute("aria-checked", "true");
674
+ expect(enableAi).toHaveAttribute("aria-disabled", "true");
675
+ expect(
676
+ screen.getByTestId(`${ENABLE_AI_SWITCH_TEST_ID}-row`),
677
+ ).toHaveTextContent(reason);
755
678
 
756
- fireEvent.click(buttons[0]!);
757
- expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
758
- expect(createOrUpdateSpy).not.toHaveBeenCalled();
759
- });
679
+ await press(enableAi);
680
+ expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
681
+ expect(updateByIdSpy).not.toHaveBeenCalled();
682
+ },
683
+ );
760
684
 
761
- test("offers no button at all before the permission snapshot has landed", async () => {
685
+ test("before the permission snapshot has landed it is locked, accusing nobody", async () => {
762
686
  grant([]);
763
687
  openAiFeatures();
764
688
 
689
+ const enableAi: HTMLElement = await enableAiSwitch();
690
+
765
691
  /*
766
692
  * Telling somebody they need a permission they may well hold is worse
767
- * than briefly not offering the button: neither the card's own gate nor
768
- * the locked copy renders until the snapshot lands.
693
+ * than briefly not letting the switch move.
769
694
  */
770
- await findText(AI_FEATURES_CARD_TITLE);
771
- await findText("Turn OneUptime AI on or off for this project.");
772
- expect(screen.queryByText("Edit AI Features")).not.toBeInTheDocument();
695
+ expect(enableAi).toHaveAttribute("aria-disabled", "true");
696
+ expect(
697
+ screen.getByTestId(`${ENABLE_AI_SWITCH_TEST_ID}-row`),
698
+ ).not.toHaveTextContent("You do not have permission");
773
699
  });
774
700
  });
775
701
 
@@ -878,7 +804,11 @@ describe("settings menu, route and breadcrumbs", () => {
878
804
 
879
805
  describe("Incidents → Settings → AI", () => {
880
806
  const POSTMORTEM_SWITCH: string =
881
- "Draft a postmortem automatically when an incident resolves";
807
+ "Draft a postmortem when an incident resolves";
808
+
809
+ const POSTMORTEM_TEST_ID: string = getProjectAiSwitchTestId(
810
+ "enableAutomaticPostmortemDraft",
811
+ );
882
812
 
883
813
  function openIncidentAiSettings(): void {
884
814
  renderPage(
@@ -891,162 +821,110 @@ describe("Incidents → Settings → AI", () => {
891
821
  );
892
822
  }
893
823
 
894
- test("has its own card for the postmortem draft, off in this project", async () => {
824
+ async function postmortemSwitch(): Promise<HTMLElement> {
825
+ return await screen.findByTestId(
826
+ POSTMORTEM_TEST_ID,
827
+ {},
828
+ { timeout: WAIT_TIMEOUT },
829
+ );
830
+ }
831
+
832
+ test("drafting a postmortem is its own switch, off in this project", async () => {
895
833
  openIncidentAiSettings();
896
834
 
897
- expect(await findText("Automatic Postmortem Draft")).toBeInTheDocument();
898
- expect(
899
- screen.getByText(/This is separate from automatic investigation\./),
900
- ).toBeInTheDocument();
901
- await waitFor(
902
- () => {
903
- expect(detailTitle(POSTMORTEM_SWITCH)).toBeInTheDocument();
904
- },
905
- { timeout: WAIT_TIMEOUT },
835
+ const postmortem: HTMLElement = await postmortemSwitch();
836
+
837
+ expect(screen.getByRole("switch", { name: POSTMORTEM_SWITCH })).toBe(
838
+ postmortem,
906
839
  );
907
- await waitFor(
908
- () => {
909
- expect(detailValue(POSTMORTEM_SWITCH)).toContain("No");
910
- },
911
- { timeout: WAIT_TIMEOUT },
840
+ expect(postmortem).toHaveAttribute("aria-checked", "false");
841
+ expect(screen.getByTestId(`${POSTMORTEM_TEST_ID}-row`)).toHaveTextContent(
842
+ "It never replaces a postmortem that already exists.",
912
843
  );
913
844
  });
914
845
 
915
- test("the investigation card no longer says anything about postmortems", async () => {
846
+ test("the investigation switch says nothing about postmortems", async () => {
916
847
  openIncidentAiSettings();
848
+ await postmortemSwitch();
917
849
 
918
- const investigationTitle: HTMLElement = await findText(
919
- "Automatic Incident Investigation",
920
- );
921
- const card: HTMLElement | null = investigationTitle.closest(
922
- '[data-testid="card"]',
923
- );
924
- expect(card).not.toBeNull();
925
- expect(card!.textContent || "").not.toMatch(/postmortem/i);
850
+ expect(
851
+ screen.getByTestId(
852
+ `${getProjectAiSwitchTestId("enableAutomaticIncidentInvestigation")}-row`,
853
+ ).textContent || "",
854
+ ).not.toMatch(/postmortem/i);
926
855
  });
927
856
 
928
857
  test("turning the draft on saves only that switch", async () => {
929
858
  openIncidentAiSettings();
930
- await findText("Automatic Postmortem Draft");
931
-
932
- const card: HTMLElement = (
933
- await findText("Automatic Postmortem Draft")
934
- ).closest('[data-testid="card"]') as HTMLElement;
935
- fireEvent.click(within(card).getByText("Update"));
936
- const dialog: HTMLElement = await screen.findByRole(
937
- "dialog",
938
- {},
939
- { timeout: WAIT_TIMEOUT },
940
- );
941
- const toggle: HTMLElement = await waitForSwitch(
942
- dialog,
943
- POSTMORTEM_SWITCH,
944
- false,
945
- );
946
- expect(
947
- within(dialog).getByText(
948
- /never replaces a postmortem that already exists/,
949
- ),
950
- ).toBeInTheDocument();
951
859
 
952
- fireEvent.click(toggle);
953
- await save(dialog);
860
+ await press(await postmortemSwitch());
954
861
 
955
- const posted: Project = postedProject();
956
- expect(posted.enableAutomaticPostmortemDraft).toBe(true);
957
- expect(posted.enableAutomaticIncidentInvestigation).toBeUndefined();
958
- expect(posted.incidentAiDailyAutonomousTokenLimit).toBeUndefined();
862
+ expect(updates()).toEqual([{ enableAutomaticPostmortemDraft: true }]);
863
+ expect(createOrUpdateSpy).not.toHaveBeenCalled();
959
864
  });
960
865
 
961
- async function postmortemCard(): Promise<HTMLElement> {
962
- return (await findText(POSTMORTEM_DRAFT_CARD_TITLE)).closest(
963
- '[data-testid="card"]',
964
- ) as HTMLElement;
965
- }
966
-
967
- test("the card is gated on exactly the column it writes", () => {
968
- expect(POSTMORTEM_DRAFT_FIELDS).toEqual(["enableAutomaticPostmortemDraft"]);
969
- expect(getProjectColumnsUpdatePermissions(POSTMORTEM_DRAFT_FIELDS)).toEqual(
866
+ test("the switch is gated on exactly the column it writes", () => {
867
+ expect(
970
868
  new Project().getColumnAccessControlFor("enableAutomaticPostmortemDraft")
971
869
  ?.update,
972
- );
870
+ ).toEqual([Permission.ProjectOwner, Permission.ProjectAdmin]);
973
871
  });
974
872
 
975
873
  test.each([[Permission.ProjectOwner], [Permission.ProjectAdmin]])(
976
- "%s gets a working Update button on the postmortem card",
874
+ "%s may flip it",
977
875
  async (permission: Permission) => {
978
876
  grant([...BASE_PERMISSIONS, permission]);
979
877
  openIncidentAiSettings();
980
878
 
981
- const card: HTMLElement = await postmortemCard();
982
- const buttons: Array<HTMLElement> = within(card)
983
- .getAllByText("Update")
984
- .map((text: HTMLElement): HTMLElement => {
985
- return text.closest("button") as HTMLElement;
986
- });
987
- expect(buttons.length).toBe(1);
988
- expect(buttons[0]).not.toBeDisabled();
879
+ const postmortem: HTMLElement = await postmortemSwitch();
880
+ expect(postmortem).not.toHaveAttribute("aria-disabled");
989
881
 
990
- fireEvent.click(buttons[0]!);
991
- expect(
992
- await screen.findByRole("dialog", {}, { timeout: WAIT_TIMEOUT }),
993
- ).toBeInTheDocument();
882
+ await press(postmortem);
883
+ expect(updates()).toEqual([{ enableAutomaticPostmortemDraft: true }]);
994
884
  },
995
885
  );
996
886
 
997
887
  /*
998
888
  * The Project table's update list lets these two in, but the column does
999
- * not: the card's own gate would give them a save the server refuses.
889
+ * not: the switch is locked, and says which permissions it needs.
1000
890
  */
1001
891
  test.each([[Permission.ManageProjectBilling], [Permission.EditProject]])(
1002
- "%s sees the postmortem card's Update button locked, with the reason",
892
+ "%s sees it locked, with the reason",
1003
893
  async (permission: Permission) => {
1004
894
  grant([...BASE_PERMISSIONS, permission]);
1005
895
  openIncidentAiSettings();
1006
896
 
1007
- /*
1008
- * Neither role may read the column, so the card shows no value; the
1009
- * locked button is all there is to wait for.
1010
- */
1011
- const card: HTMLElement = await postmortemCard();
1012
- await within(card).findByText("Update", {}, { timeout: WAIT_TIMEOUT });
1013
-
1014
- const buttons: Array<HTMLElement> = within(card)
1015
- .getAllByText("Update")
1016
- .map((text: HTMLElement): HTMLElement => {
1017
- return text.closest("button") as HTMLElement;
1018
- });
1019
- expect(buttons.length).toBe(1);
1020
- expect(buttons[0]).toBeDisabled();
1021
-
1022
- fireEvent.click(buttons[0]!);
1023
- expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
1024
- expect(createOrUpdateSpy).not.toHaveBeenCalled();
897
+ const postmortem: HTMLElement = await postmortemSwitch();
898
+
899
+ expect(postmortem).toHaveAttribute("aria-disabled", "true");
900
+ expect(screen.getByTestId(`${POSTMORTEM_TEST_ID}-row`)).toHaveTextContent(
901
+ "Project Owner, Project Admin",
902
+ );
903
+
904
+ await press(postmortem);
905
+ expect(updateByIdSpy).not.toHaveBeenCalled();
1025
906
  },
1026
907
  );
1027
908
 
1028
- test("a viewer still reads the postmortem switch, behind a locked button", async () => {
909
+ test("a viewer still reads it, locked", async () => {
1029
910
  grant([...BASE_PERMISSIONS, Permission.Viewer]);
1030
911
  openIncidentAiSettings();
1031
912
 
1032
- const card: HTMLElement = await postmortemCard();
1033
- await waitFor(
1034
- () => {
1035
- expect(detailValue(POSTMORTEM_SWITCH)).toContain("No");
1036
- },
1037
- { timeout: WAIT_TIMEOUT },
1038
- );
1039
- const button: HTMLElement | null = within(card)
1040
- .getByText("Update")
1041
- .closest("button");
1042
- expect(button).toBeDisabled();
913
+ const postmortem: HTMLElement = await postmortemSwitch();
914
+
915
+ expect(postmortem).toHaveAttribute("aria-checked", "false");
916
+ expect(postmortem).toHaveAttribute("aria-disabled", "true");
1043
917
  });
1044
918
 
1045
- test("the postmortem card offers no button before the permission snapshot has landed", async () => {
919
+ test("before the permission snapshot has landed it is locked, accusing nobody", async () => {
1046
920
  grant([]);
1047
921
  openIncidentAiSettings();
1048
922
 
1049
- const card: HTMLElement = await postmortemCard();
1050
- expect(within(card).queryByText("Update")).not.toBeInTheDocument();
923
+ const postmortem: HTMLElement = await postmortemSwitch();
924
+
925
+ expect(postmortem).toHaveAttribute("aria-disabled", "true");
926
+ expect(
927
+ screen.getByTestId(`${POSTMORTEM_TEST_ID}-row`),
928
+ ).not.toHaveTextContent("You do not have permission");
1051
929
  });
1052
930
  });