@oneuptime/common 11.7.1 → 11.7.3

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 (285) hide show
  1. package/Models/AnalyticsModels/KubernetesCostAllocation.ts +103 -0
  2. package/Models/DatabaseModels/DashboardDomain.ts +1 -0
  3. package/Models/DatabaseModels/Incident.ts +2 -0
  4. package/Models/DatabaseModels/IncidentEpisode.ts +1 -0
  5. package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +1 -0
  6. package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
  7. package/Models/DatabaseModels/IncidentPublicNote.ts +1 -0
  8. package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
  9. package/Models/DatabaseModels/Monitor.ts +1 -0
  10. package/Models/DatabaseModels/MonitorStatusTimeline.ts +1 -0
  11. package/Models/DatabaseModels/NetworkSite.ts +1 -0
  12. package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +1 -0
  13. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +1 -0
  14. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +2 -0
  15. package/Models/DatabaseModels/Probe.ts +13 -13
  16. package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
  17. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +1 -0
  18. package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
  19. package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +1 -0
  20. package/Models/DatabaseModels/StatusPage.ts +1 -0
  21. package/Models/DatabaseModels/StatusPageAnnouncement.ts +1 -0
  22. package/Models/DatabaseModels/StatusPageDomain.ts +1 -0
  23. package/Models/DatabaseModels/TableView.ts +40 -0
  24. package/Models/DatabaseModels/WorkspaceNotificationSummary.ts +1 -0
  25. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +11 -0
  26. package/Server/API/BaseAPI.ts +17 -1
  27. package/Server/API/CommonAPI.ts +32 -0
  28. package/Server/API/MicrosoftTeamsAPI.ts +99 -2
  29. package/Server/API/ProbeAPI.ts +2 -0
  30. package/Server/API/SlackAPI.ts +62 -0
  31. package/Server/API/StatusPageAPI.ts +157 -192
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.ts +89 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.ts +61 -0
  34. package/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.ts +280 -0
  35. package/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.ts +13 -0
  36. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  37. package/Server/Services/DatabaseService.ts +11 -3
  38. package/Server/Services/MonitorGroupService.ts +145 -0
  39. package/Server/Services/MonitorService.ts +231 -30
  40. package/Server/Services/ProbeService.ts +319 -16
  41. package/Server/Services/StatusPageService.ts +72 -42
  42. package/Server/Services/WorkspaceNotificationRuleService.ts +232 -2
  43. package/Server/Utils/Database/PostgresErrorTranslator.ts +131 -0
  44. package/Server/Utils/Monitor/MonitorResource.ts +88 -35
  45. package/Server/Utils/Monitor/MonitorStatusTimeline.ts +21 -1
  46. package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +158 -0
  47. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +706 -6
  48. package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +16 -0
  49. package/Tests/Models/DatabaseModels/ProbeColumnAccessControl.test.ts +103 -0
  50. package/Tests/Server/API/BaseAPIUpdateNoOp.test.ts +135 -0
  51. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +317 -0
  52. package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +228 -0
  53. package/Tests/Server/API/ProbeAPI.test.ts +6 -0
  54. package/Tests/Server/API/ZZVerifyChatsAuth.test.ts +167 -0
  55. package/Tests/Server/Services/AddHotQueryIndexesMigration.test.ts +255 -0
  56. package/Tests/Server/Services/AddHotQueryIndexesSecondPassMigration.test.ts +258 -0
  57. package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +1 -1
  58. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +121 -0
  59. package/Tests/Server/Services/HeartbeatWriteFastPathSafety.test.ts +200 -0
  60. package/Tests/Server/Services/HookFreeWriteSafetySecondPass.test.ts +181 -0
  61. package/Tests/Server/Services/MonitorGroupServiceBatchedStatuses.test.ts +513 -0
  62. package/Tests/Server/Services/MonitorResourceProbeAgreementReuse.test.ts +492 -0
  63. package/Tests/Server/Services/MonitorServiceProbeSelection.test.ts +401 -0
  64. package/Tests/Server/Services/MonitorStatusTimelineFastPath.test.ts +453 -0
  65. package/Tests/Server/Services/ProbeAuthKeyCacheAndHeartbeat.test.ts +679 -0
  66. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +3 -3
  67. package/Tests/Server/Services/StatusPageDomainResolutionCache.test.ts +245 -0
  68. package/Tests/Server/Services/StatusPageOverviewTimelineWindow.test.ts +283 -0
  69. package/Tests/Server/Services/StatusPageServiceMcp.test.ts +17 -1
  70. package/Tests/Server/Services/StatusPageServiceMonitorGroupBatching.test.ts +331 -0
  71. package/Tests/Server/Services/UserOnCallLogClaimNotificationRule.test.ts +12 -12
  72. package/Tests/Server/Services/WorkspaceNotificationRuleChats.test.ts +1390 -0
  73. package/Tests/Server/Utils/AI/Insights/InsightFixRouting.test.ts +4 -4
  74. package/Tests/Server/Utils/AI/Insights/InsightScanner.test.ts +2 -2
  75. package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +1 -3
  76. package/Tests/Server/Utils/AI/Insights/InsightStoreHardening.test.ts +1 -3
  77. package/Tests/Server/Utils/AI/Insights/InsightTriage.test.ts +1 -1
  78. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +5 -5
  79. package/Tests/Server/Utils/Alert/AlertPrivacyFilter.test.ts +187 -0
  80. package/Tests/Server/Utils/AlertEpisode/AlertEpisodePrivacyFilter.test.ts +170 -0
  81. package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +125 -0
  82. package/Tests/Server/Utils/Incident/IncidentPrivacyFilter.test.ts +264 -0
  83. package/Tests/Server/Utils/IncidentEpisode/IncidentEpisodePrivacyFilter.test.ts +175 -0
  84. package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +181 -0
  85. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +1 -1
  86. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +2 -2
  87. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +341 -0
  88. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +2175 -0
  89. package/Tests/Server/Utils/Workspace/SlackChannelsList.test.ts +585 -0
  90. package/Tests/Types/Billing/MeteredPlan.test.ts +46 -0
  91. package/Tests/Types/JSONFunctions.test.ts +103 -1
  92. package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +219 -1
  93. package/Tests/UI/Components/BulkUpdateForm.test.tsx +174 -0
  94. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +315 -0
  95. package/Tests/UI/Components/ModelDetailSelect.test.tsx +229 -0
  96. package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1258 -0
  97. package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +679 -0
  98. package/Tests/UI/Components/ModelTable/ColumnCustomizationModal.test.tsx +572 -0
  99. package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +1678 -0
  100. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1094 -0
  101. package/Tests/UI/Components/ModelTableExportFromColumns.test.ts +153 -0
  102. package/Tests/UI/Components/MonacoLoader.test.ts +67 -0
  103. package/Tests/UI/Components/MonacoRuntime.test.ts +121 -0
  104. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +212 -3
  105. package/Tests/UI/Utils/Project.test.ts +809 -0
  106. package/Tests/UI/Utils/TableColumnsToCsv.test.ts +360 -0
  107. package/Tests/Utils/Alerts/AlertMetricType.test.ts +143 -0
  108. package/Tests/Utils/Dashboard/VariableUrlState.test.ts +219 -0
  109. package/Tests/Utils/Incident/IncidentMetricType.test.ts +174 -0
  110. package/Tests/Utils/Monitor/MonitorProbeSelectionUtil.test.ts +145 -0
  111. package/Tests/Utils/StatusPage/ResourceUptime.test.ts +263 -0
  112. package/Tests/Utils/UserPreferences.test.ts +563 -0
  113. package/Types/JSONFunctions.ts +7 -2
  114. package/Types/Kubernetes/KubernetesCostIngest.ts +37 -1
  115. package/Types/Workspace/NotificationRules/BaseNotificationRule.ts +4 -0
  116. package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +25 -10
  117. package/Types/Workspace/WorkspaceMessagePayload.ts +1 -0
  118. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +63 -8
  119. package/UI/Components/CodeEditor/CodeEditor.tsx +3 -0
  120. package/UI/Components/CodeEditor/MonacoLoader.ts +36 -0
  121. package/UI/Components/Forms/ModelForm.tsx +41 -18
  122. package/UI/Components/MasterPage/MasterPage.tsx +65 -0
  123. package/UI/Components/ModelDetail/CardModelDetail.tsx +23 -1
  124. package/UI/Components/ModelDetail/ModelDetail.tsx +46 -1
  125. package/UI/Components/ModelTable/BaseModelTable.tsx +687 -34
  126. package/UI/Components/ModelTable/Column.ts +29 -0
  127. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +420 -0
  128. package/UI/Components/ModelTable/ColumnPreference.ts +482 -0
  129. package/UI/Components/ModelTable/CustomFieldColumns.tsx +326 -0
  130. package/UI/Components/ModelTable/ExportFromColumns.ts +57 -0
  131. package/UI/Components/ModelTable/TableView.tsx +24 -2
  132. package/UI/Components/ModelTable/useCustomFieldColumns.ts +150 -0
  133. package/UI/Components/Navbar/NavBar.tsx +66 -1
  134. package/UI/Components/SideMenu/SideMenu.tsx +24 -4
  135. package/UI/Components/Table/Table.tsx +66 -14
  136. package/UI/Components/Table/TableRow.tsx +180 -175
  137. package/UI/Components/Table/Types/Column.ts +20 -0
  138. package/UI/Utils/Project.ts +214 -18
  139. package/UI/Utils/TableColumnsToCsv.ts +86 -6
  140. package/UI/esbuild-config.js +34 -0
  141. package/Utils/Monitor/MonitorProbeSelectionUtil.ts +72 -0
  142. package/Utils/UserPreferences.ts +53 -0
  143. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +86 -0
  144. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -1
  145. package/build/dist/Models/DatabaseModels/DashboardDomain.js +1 -0
  146. package/build/dist/Models/DatabaseModels/DashboardDomain.js.map +1 -1
  147. package/build/dist/Models/DatabaseModels/Incident.js +2 -0
  148. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  149. package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1 -0
  150. package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
  151. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +1 -0
  152. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
  153. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
  154. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
  155. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +1 -0
  156. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  157. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
  158. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
  159. package/build/dist/Models/DatabaseModels/Monitor.js +1 -0
  160. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  161. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +1 -0
  162. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
  163. package/build/dist/Models/DatabaseModels/NetworkSite.js +1 -0
  164. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
  165. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +1 -0
  166. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -1
  167. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +1 -0
  168. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  169. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +2 -0
  170. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  171. package/build/dist/Models/DatabaseModels/Probe.js +13 -13
  172. package/build/dist/Models/DatabaseModels/Probe.js.map +1 -1
  173. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -0
  174. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  175. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +1 -0
  176. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  177. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
  178. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
  179. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +1 -0
  180. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
  181. package/build/dist/Models/DatabaseModels/StatusPage.js +1 -0
  182. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  183. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +1 -0
  184. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  185. package/build/dist/Models/DatabaseModels/StatusPageDomain.js +1 -0
  186. package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
  187. package/build/dist/Models/DatabaseModels/TableView.js +40 -0
  188. package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
  189. package/build/dist/Models/DatabaseModels/WorkspaceNotificationSummary.js +1 -0
  190. package/build/dist/Models/DatabaseModels/WorkspaceNotificationSummary.js.map +1 -1
  191. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  192. package/build/dist/Server/API/BaseAPI.js +12 -1
  193. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  194. package/build/dist/Server/API/CommonAPI.js +21 -0
  195. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  196. package/build/dist/Server/API/MicrosoftTeamsAPI.js +72 -2
  197. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  198. package/build/dist/Server/API/ProbeAPI.js +2 -0
  199. package/build/dist/Server/API/ProbeAPI.js.map +1 -1
  200. package/build/dist/Server/API/SlackAPI.js +44 -0
  201. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  202. package/build/dist/Server/API/StatusPageAPI.js +98 -152
  203. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  204. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.js +36 -0
  205. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.js.map +1 -0
  206. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.js +26 -0
  207. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.js.map +1 -0
  208. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.js +254 -0
  209. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.js.map +1 -0
  210. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js +12 -0
  211. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js.map +1 -0
  212. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  213. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  214. package/build/dist/Server/Services/DatabaseService.js +10 -2
  215. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  216. package/build/dist/Server/Services/MonitorGroupService.js +118 -0
  217. package/build/dist/Server/Services/MonitorGroupService.js.map +1 -1
  218. package/build/dist/Server/Services/MonitorService.js +198 -24
  219. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  220. package/build/dist/Server/Services/ProbeService.js +238 -9
  221. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  222. package/build/dist/Server/Services/StatusPageService.js +46 -39
  223. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  224. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +178 -3
  225. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  226. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +80 -0
  227. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -0
  228. package/build/dist/Server/Utils/Monitor/MonitorResource.js +67 -29
  229. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  230. package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js +31 -14
  231. package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js.map +1 -1
  232. package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +117 -0
  233. package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -0
  234. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +549 -7
  235. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  236. package/build/dist/Types/JSONFunctions.js +8 -3
  237. package/build/dist/Types/JSONFunctions.js.map +1 -1
  238. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -1
  239. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +17 -7
  240. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
  241. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +37 -11
  242. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  243. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +2 -0
  244. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  245. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +34 -0
  246. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +1 -0
  247. package/build/dist/UI/Components/Forms/ModelForm.js +37 -17
  248. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  249. package/build/dist/UI/Components/MasterPage/MasterPage.js +50 -1
  250. package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
  251. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +22 -1
  252. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
  253. package/build/dist/UI/Components/ModelDetail/ModelDetail.js +31 -1
  254. package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
  255. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +472 -27
  256. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  257. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +189 -0
  258. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -0
  259. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +258 -0
  260. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -0
  261. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +168 -0
  262. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -0
  263. package/build/dist/UI/Components/ModelTable/ExportFromColumns.js +30 -0
  264. package/build/dist/UI/Components/ModelTable/ExportFromColumns.js.map +1 -0
  265. package/build/dist/UI/Components/ModelTable/TableView.js +13 -2
  266. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  267. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +84 -0
  268. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -0
  269. package/build/dist/UI/Components/Navbar/NavBar.js +39 -1
  270. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  271. package/build/dist/UI/Components/SideMenu/SideMenu.js +15 -5
  272. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  273. package/build/dist/UI/Components/Table/Table.js +46 -13
  274. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  275. package/build/dist/UI/Components/Table/TableRow.js +11 -6
  276. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  277. package/build/dist/UI/Utils/Project.js +161 -15
  278. package/build/dist/UI/Utils/Project.js.map +1 -1
  279. package/build/dist/UI/Utils/TableColumnsToCsv.js +67 -6
  280. package/build/dist/UI/Utils/TableColumnsToCsv.js.map +1 -1
  281. package/build/dist/Utils/Monitor/MonitorProbeSelectionUtil.js +52 -0
  282. package/build/dist/Utils/Monitor/MonitorProbeSelectionUtil.js.map +1 -0
  283. package/build/dist/Utils/UserPreferences.js +33 -0
  284. package/build/dist/Utils/UserPreferences.js.map +1 -1
  285. package/package.json +4 -3
@@ -0,0 +1,315 @@
1
+ import { describe, expect, it, jest, beforeEach } from "@jest/globals";
2
+ import { render, screen, waitFor } from "@testing-library/react";
3
+ import userEvent from "@testing-library/user-event";
4
+ import * as React from "react";
5
+ import ObjectID from "../../../Types/ObjectID";
6
+ import Permission, { UserPermission } from "../../../Types/Permission";
7
+ import FieldType from "../../../UI/Components/Types/FieldType";
8
+ import FormFieldSchemaType from "../../../UI/Components/Forms/Types/FormFieldSchemaType";
9
+ import getJestMockFunction, { MockFunction } from "../../MockType";
10
+
11
+ /*
12
+ * The "Probe Details" card - and every other CardModelDetail - used to derive
13
+ * the id its edit modal updates from the record the card had finished loading:
14
+ *
15
+ * modelIdToEdit={item?.id || undefined}
16
+ *
17
+ * The Edit button is rendered by Card, outside ModelDetail, in a mount-only
18
+ * effect - so it is clickable while the card is still on its spinner. Opening
19
+ * the modal then gave ModelForm an Update form with no id, and ModelForm's
20
+ * fetch effect (guarded on the id, deps []) skipped the prefill with no loader
21
+ * and no error. The form rendered defaults, BasicForm coerced every untouched
22
+ * Toggle to false, and pressing Save wrote that over the real probe - which is
23
+ * how "Enable monitoring automatically on new monitors" silently went back to
24
+ * off, and why the page looked unchanged after a refresh.
25
+ *
26
+ * These tests drive the real components: they open the modal before the detail
27
+ * fetch resolves and assert on what actually reaches the API.
28
+ */
29
+
30
+ const getItemMock: MockFunction = getJestMockFunction();
31
+ const createOrUpdateMock: MockFunction = getJestMockFunction();
32
+ const showToastMock: MockFunction = getJestMockFunction();
33
+
34
+ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
35
+ return {
36
+ __esModule: true,
37
+ default: {
38
+ getItem: (...args: Array<any>) => {
39
+ return getItemMock(...args);
40
+ },
41
+ createOrUpdate: (...args: Array<any>) => {
42
+ return createOrUpdateMock(...args);
43
+ },
44
+ },
45
+ };
46
+ });
47
+
48
+ jest.mock("../../../UI/Components/Toast/ToastInit", () => {
49
+ return {
50
+ __esModule: true,
51
+ default: () => {
52
+ return null;
53
+ },
54
+ ShowToastNotification: (...args: Array<any>) => {
55
+ return showToastMock(...args);
56
+ },
57
+ };
58
+ });
59
+
60
+ const OWNER_PERMISSIONS: Array<Permission> = [
61
+ Permission.Public,
62
+ Permission.User,
63
+ Permission.CurrentUser,
64
+ Permission.ProjectOwner,
65
+ ];
66
+
67
+ jest.mock("../../../UI/Utils/Permission", () => {
68
+ return {
69
+ __esModule: true,
70
+ default: {
71
+ getAllPermissions: () => {
72
+ return OWNER_PERMISSIONS;
73
+ },
74
+ getProjectPermissions: () => {
75
+ return {
76
+ permissions: OWNER_PERMISSIONS.map((permission: Permission) => {
77
+ return {
78
+ permission,
79
+ labelIds: [],
80
+ _type: "UserPermission",
81
+ } as UserPermission;
82
+ }),
83
+ };
84
+ },
85
+ getGlobalPermissions: () => {
86
+ return { globalPermissions: OWNER_PERMISSIONS };
87
+ },
88
+ },
89
+ };
90
+ });
91
+
92
+ jest.mock("../../../UI/Utils/User", () => {
93
+ return {
94
+ __esModule: true,
95
+ default: {
96
+ isMasterAdmin: () => {
97
+ return false;
98
+ },
99
+ },
100
+ };
101
+ });
102
+
103
+ import CardModelDetail from "../../../UI/Components/ModelDetail/CardModelDetail";
104
+ import Probe from "../../../Models/DatabaseModels/Probe";
105
+
106
+ /*
107
+ * These render real components that fetch, so give the waits enough room to
108
+ * survive a loaded CI box - the testing-library default of 1s flakes there.
109
+ */
110
+ const WAIT_TIMEOUT: number = 20000;
111
+
112
+ const PROBE_ID: ObjectID = new ObjectID("11111111-1111-4111-8111-111111111111");
113
+
114
+ type RenderProbeCardFunction = () => void;
115
+
116
+ const renderProbeCard: RenderProbeCardFunction = (): void => {
117
+ render(
118
+ <CardModelDetail<Probe>
119
+ name="Probe Details"
120
+ cardProps={{
121
+ title: "Probe Details",
122
+ description: "Here are more details for this probe.",
123
+ }}
124
+ isEditable={true}
125
+ formFields={[
126
+ {
127
+ field: { name: true },
128
+ title: "Name",
129
+ fieldType: FormFieldSchemaType.Text,
130
+ required: true,
131
+ },
132
+ {
133
+ field: { shouldAutoEnableProbeOnNewMonitors: true },
134
+ title: "Enable monitoring automatically on new monitors",
135
+ fieldType: FormFieldSchemaType.Toggle,
136
+ required: false,
137
+ dataTestId: "auto-enable-toggle",
138
+ },
139
+ ]}
140
+ modelDetailProps={{
141
+ modelType: Probe,
142
+ id: "probe-detail",
143
+ modelId: PROBE_ID,
144
+ fields: [
145
+ {
146
+ field: { name: true },
147
+ title: "Name",
148
+ },
149
+ {
150
+ field: { shouldAutoEnableProbeOnNewMonitors: true },
151
+ title: "Enable Monitoring on New Monitors",
152
+ fieldType: FieldType.Boolean,
153
+ },
154
+ ],
155
+ }}
156
+ />,
157
+ );
158
+ };
159
+
160
+ type LoadedProbeFunction = () => Probe;
161
+
162
+ const loadedProbe: LoadedProbeFunction = (): Probe => {
163
+ const probe: Probe = new Probe();
164
+ probe.id = PROBE_ID;
165
+ probe.name = "WBHQ";
166
+ probe.shouldAutoEnableProbeOnNewMonitors = true;
167
+ return probe;
168
+ };
169
+
170
+ describe("CardModelDetail edit modal", () => {
171
+ beforeEach(() => {
172
+ getItemMock.mockReset();
173
+ createOrUpdateMock.mockReset();
174
+ showToastMock.mockReset();
175
+ createOrUpdateMock.mockResolvedValue({ data: {} });
176
+ });
177
+
178
+ it("edits the record the card was told to show, even while the card is still loading", async () => {
179
+ /*
180
+ * The card's own detail fetch never settles, so the card stays on its
181
+ * spinner and never reports a loaded item - which is what used to leave
182
+ * the edit modal with no id. ModelDetail's request is the one that asks
183
+ * for _id; ModelForm's is built from the form fields only.
184
+ */
185
+ getItemMock.mockImplementation((data: any) => {
186
+ if (data?.select?.["_id"]) {
187
+ return new Promise(() => {});
188
+ }
189
+ return Promise.resolve(loadedProbe());
190
+ });
191
+
192
+ renderProbeCard();
193
+
194
+ await userEvent.click(
195
+ await screen.findByText("Edit Probe", {}, { timeout: WAIT_TIMEOUT }),
196
+ );
197
+
198
+ // Prefilled, rather than a blank form or a "still loading" error.
199
+ await waitFor(
200
+ () => {
201
+ expect(screen.getByDisplayValue("WBHQ")).toBeDefined();
202
+ },
203
+ { timeout: WAIT_TIMEOUT },
204
+ );
205
+
206
+ await userEvent.click(screen.getByText("Save Changes"));
207
+
208
+ await waitFor(
209
+ () => {
210
+ expect(createOrUpdateMock).toHaveBeenCalled();
211
+ },
212
+ { timeout: WAIT_TIMEOUT },
213
+ );
214
+
215
+ const submitted: any = (createOrUpdateMock.mock.calls[0] as Array<any>)[0];
216
+
217
+ expect(submitted.model._id).toEqual(PROBE_ID.toString());
218
+ expect(submitted.model.shouldAutoEnableProbeOnNewMonitors).toBe(true);
219
+ });
220
+
221
+ it("prefills the form from the record instead of blanking untouched toggles", async () => {
222
+ getItemMock.mockResolvedValue(loadedProbe());
223
+
224
+ renderProbeCard();
225
+
226
+ await userEvent.click(
227
+ await screen.findByText("Edit Probe", {}, { timeout: WAIT_TIMEOUT }),
228
+ );
229
+
230
+ await waitFor(
231
+ () => {
232
+ expect(screen.getByDisplayValue("WBHQ")).toBeDefined();
233
+ },
234
+ { timeout: WAIT_TIMEOUT },
235
+ );
236
+
237
+ await userEvent.click(screen.getByText("Save Changes"));
238
+
239
+ await waitFor(
240
+ () => {
241
+ expect(createOrUpdateMock).toHaveBeenCalled();
242
+ },
243
+ { timeout: WAIT_TIMEOUT },
244
+ );
245
+
246
+ const submitted: any = (createOrUpdateMock.mock.calls[0] as Array<any>)[0];
247
+
248
+ expect(submitted.model.name).toEqual("WBHQ");
249
+ // The regression: this used to be submitted as false.
250
+ expect(submitted.model.shouldAutoEnableProbeOnNewMonitors).toBe(true);
251
+ expect(submitted.model._id).toEqual(PROBE_ID.toString());
252
+ });
253
+
254
+ it("submits a toggle the user actually turned off", async () => {
255
+ getItemMock.mockResolvedValue(loadedProbe());
256
+
257
+ renderProbeCard();
258
+
259
+ await userEvent.click(
260
+ await screen.findByText("Edit Probe", {}, { timeout: WAIT_TIMEOUT }),
261
+ );
262
+
263
+ await waitFor(
264
+ () => {
265
+ expect(screen.getByDisplayValue("WBHQ")).toBeDefined();
266
+ },
267
+ { timeout: WAIT_TIMEOUT },
268
+ );
269
+
270
+ await userEvent.click(screen.getByTestId("auto-enable-toggle"));
271
+
272
+ await userEvent.click(screen.getByText("Save Changes"));
273
+
274
+ await waitFor(
275
+ () => {
276
+ expect(createOrUpdateMock).toHaveBeenCalled();
277
+ },
278
+ { timeout: WAIT_TIMEOUT },
279
+ );
280
+
281
+ const submitted: any = (createOrUpdateMock.mock.calls[0] as Array<any>)[0];
282
+
283
+ expect(submitted.model.shouldAutoEnableProbeOnNewMonitors).toBe(false);
284
+ });
285
+
286
+ it("confirms the save so a successful edit is not just a modal that vanished", async () => {
287
+ getItemMock.mockResolvedValue(loadedProbe());
288
+
289
+ renderProbeCard();
290
+
291
+ await userEvent.click(
292
+ await screen.findByText("Edit Probe", {}, { timeout: WAIT_TIMEOUT }),
293
+ );
294
+
295
+ await waitFor(
296
+ () => {
297
+ expect(screen.getByDisplayValue("WBHQ")).toBeDefined();
298
+ },
299
+ { timeout: WAIT_TIMEOUT },
300
+ );
301
+
302
+ await userEvent.click(screen.getByText("Save Changes"));
303
+
304
+ await waitFor(
305
+ () => {
306
+ expect(showToastMock).toHaveBeenCalled();
307
+ },
308
+ { timeout: WAIT_TIMEOUT },
309
+ );
310
+
311
+ const toast: any = (showToastMock.mock.calls[0] as Array<any>)[0];
312
+
313
+ expect(toast.title).toEqual("Changes saved");
314
+ });
315
+ });
@@ -0,0 +1,229 @@
1
+ import { describe, expect, it, jest, beforeEach } from "@jest/globals";
2
+ import { render, waitFor } from "@testing-library/react";
3
+ import * as React from "react";
4
+ import Select from "../../../Types/BaseDatabase/Select";
5
+ import ObjectID from "../../../Types/ObjectID";
6
+ import Permission, { UserPermission } from "../../../Types/Permission";
7
+ import getJestMockFunction, { MockFunction } from "../../MockType";
8
+ import FieldType from "../../../UI/Components/Types/FieldType";
9
+
10
+ /*
11
+ * ModelDetail builds the get-item `select` from the fields its card declares.
12
+ *
13
+ * Two things were wrong with that:
14
+ *
15
+ * 1. It never asked for _id, even though CardModelDetail derives the id its
16
+ * edit modal updates from the loaded record. Nothing else in the client
17
+ * guarantees the id comes back.
18
+ * 2. It did not filter by read permission, while the render path right below
19
+ * it does. Server-side, SelectPermission.checkSelectPermission rejects the
20
+ * WHOLE request when a single selected column is unreadable - so one
21
+ * privileged column (Probe.key is readable only by owners and admins)
22
+ * blanked the entire card for everyone else, instead of hiding one row.
23
+ */
24
+
25
+ const getItemMock: MockFunction = getJestMockFunction();
26
+
27
+ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
28
+ return {
29
+ __esModule: true,
30
+ default: {
31
+ getItem: (...args: Array<any>) => {
32
+ return getItemMock(...args);
33
+ },
34
+ },
35
+ };
36
+ });
37
+
38
+ let currentPermissions: Array<Permission> = [];
39
+ let isMasterAdmin: boolean = false;
40
+
41
+ jest.mock("../../../UI/Utils/Permission", () => {
42
+ return {
43
+ __esModule: true,
44
+ default: {
45
+ getAllPermissions: () => {
46
+ return currentPermissions;
47
+ },
48
+ getProjectPermissions: () => {
49
+ return {
50
+ permissions: currentPermissions.map((permission: Permission) => {
51
+ return {
52
+ permission,
53
+ labelIds: [],
54
+ _type: "UserPermission",
55
+ } as UserPermission;
56
+ }),
57
+ };
58
+ },
59
+ getGlobalPermissions: () => {
60
+ return { globalPermissions: currentPermissions };
61
+ },
62
+ },
63
+ };
64
+ });
65
+
66
+ jest.mock("../../../UI/Utils/User", () => {
67
+ return {
68
+ __esModule: true,
69
+ default: {
70
+ isMasterAdmin: () => {
71
+ return isMasterAdmin;
72
+ },
73
+ },
74
+ };
75
+ });
76
+
77
+ import ModelDetail from "../../../UI/Components/ModelDetail/ModelDetail";
78
+ import Probe from "../../../Models/DatabaseModels/Probe";
79
+
80
+ /*
81
+ * These render real components that fetch, so give the waits enough room to
82
+ * survive a loaded CI box - the testing-library default of 1s flakes there.
83
+ */
84
+ const WAIT_TIMEOUT: number = 20000;
85
+
86
+ const PROBE_ID: ObjectID = new ObjectID("11111111-1111-4111-8111-111111111111");
87
+
88
+ /*
89
+ * Signed-in users always carry Public/User/CurrentUser on top of their project
90
+ * role (AccessTokenService.refreshUserGlobalAccessPermission), and some Probe
91
+ * columns - name, description - are readable on Public alone. Tests mirror
92
+ * that, otherwise they would assert against a permission set no real user has.
93
+ */
94
+ type PermissionsForRoleFunction = (role: Permission) => Array<Permission>;
95
+
96
+ const permissionsForRole: PermissionsForRoleFunction = (
97
+ role: Permission,
98
+ ): Array<Permission> => {
99
+ return [Permission.Public, Permission.User, Permission.CurrentUser, role];
100
+ };
101
+
102
+ type RenderProbeDetailFunction = () => Promise<Select<Probe>>;
103
+
104
+ /*
105
+ * Renders the same card shape the Probe view page uses and hands back the
106
+ * select ModelDetail actually put on the wire.
107
+ */
108
+ const renderProbeDetail: RenderProbeDetailFunction = async (): Promise<
109
+ Select<Probe>
110
+ > => {
111
+ render(
112
+ <ModelDetail<Probe>
113
+ modelType={Probe}
114
+ id="probe-detail"
115
+ modelId={PROBE_ID}
116
+ fields={[
117
+ {
118
+ field: { name: true },
119
+ title: "Name",
120
+ },
121
+ {
122
+ field: { key: true },
123
+ title: "Probe Key",
124
+ fieldType: FieldType.HiddenText,
125
+ },
126
+ {
127
+ field: { shouldAutoEnableProbeOnNewMonitors: true },
128
+ title: "Enable Monitoring on New Monitors",
129
+ fieldType: FieldType.Boolean,
130
+ },
131
+ ]}
132
+ />,
133
+ );
134
+
135
+ await waitFor(
136
+ () => {
137
+ expect(getItemMock).toHaveBeenCalled();
138
+ },
139
+ { timeout: WAIT_TIMEOUT },
140
+ );
141
+
142
+ return (getItemMock.mock.calls[0] as Array<any>)[0].select as Select<Probe>;
143
+ };
144
+
145
+ describe("ModelDetail select", () => {
146
+ beforeEach(() => {
147
+ getItemMock.mockReset();
148
+ getItemMock.mockResolvedValue(new Probe());
149
+ isMasterAdmin = false;
150
+ currentPermissions = [];
151
+ });
152
+
153
+ it("always asks for _id so the edit modal knows which record it is updating", async () => {
154
+ currentPermissions = permissionsForRole(Permission.ProjectOwner);
155
+
156
+ const select: Select<Probe> = await renderProbeDetail();
157
+
158
+ expect((select as any)["_id"]).toBe(true);
159
+ });
160
+
161
+ it("selects every declared column for a user who can read them all", async () => {
162
+ currentPermissions = permissionsForRole(Permission.ProjectOwner);
163
+
164
+ const select: Select<Probe> = await renderProbeDetail();
165
+
166
+ expect((select as any)["name"]).toBe(true);
167
+ expect((select as any)["key"]).toBe(true);
168
+ expect((select as any)["shouldAutoEnableProbeOnNewMonitors"]).toBe(true);
169
+ });
170
+
171
+ it("drops a column the user cannot read instead of failing the whole request", async () => {
172
+ /*
173
+ * A SettingsMember can view probes but cannot read Probe.key. Asking for
174
+ * it anyway is what used to blank the card.
175
+ */
176
+ currentPermissions = permissionsForRole(Permission.SettingsMember);
177
+
178
+ const select: Select<Probe> = await renderProbeDetail();
179
+
180
+ expect((select as any)["key"]).toBeUndefined();
181
+ expect((select as any)["shouldAutoEnableProbeOnNewMonitors"]).toBe(true);
182
+ expect((select as any)["_id"]).toBe(true);
183
+ });
184
+
185
+ it("selects everything for a master admin", async () => {
186
+ isMasterAdmin = true;
187
+ currentPermissions = [];
188
+
189
+ const select: Select<Probe> = await renderProbeDetail();
190
+
191
+ expect((select as any)["key"]).toBe(true);
192
+ expect((select as any)["name"]).toBe(true);
193
+ });
194
+
195
+ it("drops unreadable selectMoreFields too", async () => {
196
+ currentPermissions = permissionsForRole(Permission.SettingsMember);
197
+
198
+ render(
199
+ <ModelDetail<Probe>
200
+ modelType={Probe}
201
+ id="probe-detail-more-fields"
202
+ modelId={PROBE_ID}
203
+ fields={[
204
+ {
205
+ field: { name: true },
206
+ title: "Name",
207
+ },
208
+ ]}
209
+ selectMoreFields={{
210
+ key: true,
211
+ shouldAutoEnableProbeOnNewMonitors: true,
212
+ }}
213
+ />,
214
+ );
215
+
216
+ await waitFor(
217
+ () => {
218
+ expect(getItemMock).toHaveBeenCalled();
219
+ },
220
+ { timeout: WAIT_TIMEOUT },
221
+ );
222
+
223
+ const select: Select<Probe> = (getItemMock.mock.calls[0] as Array<any>)[0]
224
+ .select as Select<Probe>;
225
+
226
+ expect((select as any)["key"]).toBeUndefined();
227
+ expect((select as any)["shouldAutoEnableProbeOnNewMonitors"]).toBe(true);
228
+ });
229
+ });