@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
@@ -19,6 +19,23 @@ export default interface Columns<
19
19
  field: SelectEntityField<TEntity>;
20
20
  selectedProperty?: string | undefined;
21
21
  title: string;
22
+ /*
23
+ * Stable identity for this column, used to persist the viewer's show/hide
24
+ * and ordering choices. Leave it unset and one is derived from the declared
25
+ * field (see ColumnPreference.getColumnIds) - set it only when the derived
26
+ * id would be unstable, e.g. a cell rendered entirely through `getElement`
27
+ * off a placeholder `field: { _id: true }` whose title is likely to change.
28
+ */
29
+ id?: string | undefined;
30
+ /*
31
+ * Keep this column out of the "Customize Columns" picker: it is always
32
+ * shown and can never be moved. Use it for the column that identifies the
33
+ * row (usually the name), so a table can never be customized into
34
+ * anonymity.
35
+ */
36
+ isNotCustomizable?: boolean | undefined;
37
+ // Start hidden. The viewer can still switch it on from the picker.
38
+ isHiddenByDefault?: boolean | undefined;
22
39
  contentClassName?: string | undefined;
23
40
  colSpan?: number | undefined;
24
41
  disableSort?: boolean;
@@ -29,6 +46,18 @@ export default interface Columns<
29
46
  alignItem?: AlignItem | undefined;
30
47
  noValueMessage?: string | undefined;
31
48
  hideOnMobile?: boolean | undefined; // Hide column on mobile devices
49
+ /*
50
+ * Exact text for this column's CSV cell (the text twin of getElement, and
51
+ * it receives the same item). Set it when the cell renders from something
52
+ * the row does not carry under this column's own `field` - data fetched
53
+ * alongside the table, or a phrase composed from several fields. Columns
54
+ * that render entirely through getElement off a placeholder
55
+ * `field: { _id: true }` are left out of the CSV unless they set this,
56
+ * because their only exportable value is a raw UUID.
57
+ */
58
+ getExportValue?: ((item: TEntity) => string) | undefined;
59
+ // Leave this column out of the CSV export entirely.
60
+ disableCsvExport?: boolean | undefined;
32
61
  getElement?:
33
62
  | ((item: TEntity, onBeforeFetchData?: TEntity | undefined) => ReactElement)
34
63
  | undefined;
@@ -0,0 +1,420 @@
1
+ import { CustomizableColumn } from "./ColumnPreference";
2
+ import Button, { ButtonSize, ButtonStyleType } from "../Button/Button";
3
+ import CheckboxElement from "../Checkbox/Checkbox";
4
+ import Icon from "../Icon/Icon";
5
+ import Input, { InputType } from "../Input/Input";
6
+ import Modal, { ModalWidth } from "../Modal/Modal";
7
+ import AnalyticsBaseModel from "../../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
8
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
9
+ import IconProp from "../../../Types/Icon/IconProp";
10
+ import React, { ReactElement, useMemo, useState } from "react";
11
+ import {
12
+ DragDropContext,
13
+ Draggable,
14
+ DraggableProvided,
15
+ Droppable,
16
+ DroppableProvided,
17
+ DropResult,
18
+ } from "react-beautiful-dnd";
19
+
20
+ export interface ComponentProps<
21
+ TBaseModel extends BaseModel | AnalyticsBaseModel,
22
+ > {
23
+ // Every customizable column, already in the order the table renders them.
24
+ columns: Array<CustomizableColumn<TBaseModel>>;
25
+ onSave: (columns: Array<CustomizableColumn<TBaseModel>>) => void;
26
+ onClose: () => void;
27
+ // Drop the stored layout and go back to what the table ships with.
28
+ onReset: () => void;
29
+ title?: string | undefined;
30
+ description?: string | undefined;
31
+ /*
32
+ * False once the viewer has customized anything, which is when Reset earns
33
+ * its place in the footer.
34
+ */
35
+ isDefaultLayout?: boolean | undefined;
36
+ }
37
+
38
+ type ColumnCustomizationModalFunction = <
39
+ TBaseModel extends BaseModel | AnalyticsBaseModel,
40
+ >(
41
+ props: ComponentProps<TBaseModel>,
42
+ ) => ReactElement;
43
+
44
+ /*
45
+ * The "Customize Columns" picker: a checkbox and a drag handle per column.
46
+ *
47
+ * Two constraints shape it:
48
+ *
49
+ * - The last visible column cannot be switched off. A table with no columns
50
+ * renders as an empty shell with no header row, and the only control that
51
+ * could undo that is the one the viewer just closed.
52
+ *
53
+ * - Reordering is offered through Up/Down buttons as well as drag. Drag alone
54
+ * is unusable with a keyboard or a screen reader, and pointer-only
55
+ * reordering is also the part that cannot be exercised in tests.
56
+ *
57
+ * Changes are staged locally and only handed back on Save, so Cancel really
58
+ * does cancel.
59
+ */
60
+ const ColumnCustomizationModal: ColumnCustomizationModalFunction = <
61
+ TBaseModel extends BaseModel | AnalyticsBaseModel,
62
+ >(
63
+ props: ComponentProps<TBaseModel>,
64
+ ): ReactElement => {
65
+ const [entries, setEntries] = useState<Array<CustomizableColumn<TBaseModel>>>(
66
+ [...props.columns],
67
+ );
68
+ const [searchText, setSearchText] = useState<string>("");
69
+
70
+ const visibleCount: number = useMemo(() => {
71
+ return entries.filter((entry: CustomizableColumn<TBaseModel>) => {
72
+ return entry.isVisible;
73
+ }).length;
74
+ }, [entries]);
75
+
76
+ const normalizedSearch: string = searchText.trim().toLowerCase();
77
+ const isSearching: boolean = normalizedSearch.length > 0;
78
+
79
+ const shownEntries: Array<CustomizableColumn<TBaseModel>> = useMemo(() => {
80
+ if (!isSearching) {
81
+ return entries;
82
+ }
83
+
84
+ return entries.filter((entry: CustomizableColumn<TBaseModel>) => {
85
+ return (entry.column.title || "")
86
+ .toLowerCase()
87
+ .includes(normalizedSearch);
88
+ });
89
+ }, [entries, normalizedSearch, isSearching]);
90
+
91
+ type ToggleFunction = (id: string, isVisible: boolean) => void;
92
+
93
+ const toggleColumn: ToggleFunction = (
94
+ id: string,
95
+ isVisible: boolean,
96
+ ): void => {
97
+ setEntries((current: Array<CustomizableColumn<TBaseModel>>) => {
98
+ const isLastVisible: boolean =
99
+ !isVisible &&
100
+ current.filter((entry: CustomizableColumn<TBaseModel>) => {
101
+ return entry.isVisible;
102
+ }).length <= 1;
103
+
104
+ if (isLastVisible) {
105
+ // Refuse rather than render a table with nothing in it.
106
+ return current;
107
+ }
108
+
109
+ return current.map((entry: CustomizableColumn<TBaseModel>) => {
110
+ return entry.id === id ? { ...entry, isVisible } : entry;
111
+ });
112
+ });
113
+ };
114
+
115
+ type MoveFunction = (fromIndex: number, toIndex: number) => void;
116
+
117
+ const moveColumn: MoveFunction = (
118
+ fromIndex: number,
119
+ toIndex: number,
120
+ ): void => {
121
+ setEntries((current: Array<CustomizableColumn<TBaseModel>>) => {
122
+ if (
123
+ fromIndex === toIndex ||
124
+ fromIndex < 0 ||
125
+ toIndex < 0 ||
126
+ fromIndex >= current.length ||
127
+ toIndex >= current.length
128
+ ) {
129
+ return current;
130
+ }
131
+
132
+ const next: Array<CustomizableColumn<TBaseModel>> = [...current];
133
+ const [moved] = next.splice(fromIndex, 1);
134
+
135
+ if (!moved) {
136
+ return current;
137
+ }
138
+
139
+ next.splice(toIndex, 0, moved);
140
+
141
+ return next;
142
+ });
143
+ };
144
+
145
+ type OnDragEndFunction = (result: DropResult) => void;
146
+
147
+ const onDragEnd: OnDragEndFunction = (result: DropResult): void => {
148
+ /*
149
+ * Guard on the object, not on the index: a drop into the first slot has
150
+ * `index === 0`, which a truthiness check would throw away.
151
+ */
152
+ if (!result.destination) {
153
+ return;
154
+ }
155
+
156
+ moveColumn(result.source.index, result.destination.index);
157
+ };
158
+
159
+ type SetAllVisibleFunction = (isVisible: boolean) => void;
160
+
161
+ const setAllVisible: SetAllVisibleFunction = (isVisible: boolean): void => {
162
+ setEntries((current: Array<CustomizableColumn<TBaseModel>>) => {
163
+ if (!isVisible) {
164
+ /*
165
+ * "Hide all" still has to leave one column standing, so it keeps the
166
+ * first one - the leftmost, which is normally the row's name.
167
+ */
168
+ let isFirstKept: boolean = false;
169
+
170
+ return current.map((entry: CustomizableColumn<TBaseModel>) => {
171
+ if (!isFirstKept) {
172
+ isFirstKept = true;
173
+ return { ...entry, isVisible: true };
174
+ }
175
+
176
+ return { ...entry, isVisible: false };
177
+ });
178
+ }
179
+
180
+ return current.map((entry: CustomizableColumn<TBaseModel>) => {
181
+ return { ...entry, isVisible: true };
182
+ });
183
+ });
184
+ };
185
+
186
+ type GetRowFunction = (data: {
187
+ entry: CustomizableColumn<TBaseModel>;
188
+ index: number;
189
+ dragHandle?: ReactElement | undefined;
190
+ }) => ReactElement;
191
+
192
+ const getRowContents: GetRowFunction = (data: {
193
+ entry: CustomizableColumn<TBaseModel>;
194
+ index: number;
195
+ dragHandle?: ReactElement | undefined;
196
+ }): ReactElement => {
197
+ const { entry, index } = data;
198
+
199
+ const isOnlyVisibleColumn: boolean = entry.isVisible && visibleCount <= 1;
200
+
201
+ return (
202
+ <div className="flex items-center gap-3 px-3 py-2">
203
+ {data.dragHandle || <div className="w-4" />}
204
+
205
+ <div className="flex-1 min-w-0">
206
+ <CheckboxElement
207
+ value={entry.isVisible}
208
+ disabled={isOnlyVisibleColumn}
209
+ dataTestId={`column-toggle-${entry.id}`}
210
+ title={entry.column.title}
211
+ onChange={(value: boolean) => {
212
+ toggleColumn(entry.id, value);
213
+ }}
214
+ />
215
+ </div>
216
+
217
+ <div className="flex flex-none items-center gap-1">
218
+ <Button
219
+ buttonSize={ButtonSize.Small}
220
+ buttonStyle={ButtonStyleType.ICON}
221
+ icon={IconProp.ChevronUp}
222
+ title=""
223
+ dataTestId={`column-move-up-${entry.id}`}
224
+ disabled={isSearching || index === 0}
225
+ onClick={() => {
226
+ moveColumn(index, index - 1);
227
+ }}
228
+ />
229
+ <Button
230
+ buttonSize={ButtonSize.Small}
231
+ buttonStyle={ButtonStyleType.ICON}
232
+ icon={IconProp.ChevronDown}
233
+ title=""
234
+ dataTestId={`column-move-down-${entry.id}`}
235
+ disabled={isSearching || index === entries.length - 1}
236
+ onClick={() => {
237
+ moveColumn(index, index + 1);
238
+ }}
239
+ />
240
+ </div>
241
+ </div>
242
+ );
243
+ };
244
+
245
+ type GetListFunction = () => ReactElement;
246
+
247
+ const getList: GetListFunction = (): ReactElement => {
248
+ if (shownEntries.length === 0) {
249
+ return (
250
+ <div
251
+ className="px-3 py-6 text-center text-sm text-gray-400"
252
+ data-testid="column-customization-no-results"
253
+ >
254
+ No columns match &quot;{searchText}&quot;.
255
+ </div>
256
+ );
257
+ }
258
+
259
+ /*
260
+ * Dragging a filtered list would move a column to a position that only
261
+ * makes sense inside the filter, so while a search is active the list is
262
+ * rendered plain and the reorder controls are disabled.
263
+ */
264
+ if (isSearching) {
265
+ return (
266
+ <div className="divide-y divide-gray-100">
267
+ {shownEntries.map((entry: CustomizableColumn<TBaseModel>) => {
268
+ return (
269
+ <div key={entry.id}>
270
+ {getRowContents({
271
+ entry,
272
+ index: entries.indexOf(entry),
273
+ })}
274
+ </div>
275
+ );
276
+ })}
277
+ </div>
278
+ );
279
+ }
280
+
281
+ return (
282
+ <DragDropContext onDragEnd={onDragEnd}>
283
+ <Droppable droppableId="model-table-columns">
284
+ {(droppableProvided: DroppableProvided) => {
285
+ return (
286
+ <div
287
+ ref={droppableProvided.innerRef}
288
+ {...droppableProvided.droppableProps}
289
+ className="divide-y divide-gray-100"
290
+ >
291
+ {shownEntries.map(
292
+ (entry: CustomizableColumn<TBaseModel>, index: number) => {
293
+ return (
294
+ <Draggable
295
+ draggableId={entry.id}
296
+ index={index}
297
+ key={entry.id}
298
+ >
299
+ {(draggableProvided: DraggableProvided) => {
300
+ return (
301
+ <div
302
+ ref={draggableProvided.innerRef}
303
+ {...draggableProvided.draggableProps}
304
+ className="bg-white"
305
+ >
306
+ {getRowContents({
307
+ entry,
308
+ index,
309
+ dragHandle: (
310
+ <div
311
+ {...draggableProvided.dragHandleProps}
312
+ className="flex-none cursor-grab text-gray-400 hover:text-gray-600 active:cursor-grabbing"
313
+ aria-label={`Drag to reorder ${entry.column.title}`}
314
+ title="Drag to reorder"
315
+ >
316
+ <Icon
317
+ icon={IconProp.GripVertical}
318
+ className="h-4 w-4"
319
+ />
320
+ </div>
321
+ ),
322
+ })}
323
+ </div>
324
+ );
325
+ }}
326
+ </Draggable>
327
+ );
328
+ },
329
+ )}
330
+ {droppableProvided.placeholder}
331
+ </div>
332
+ );
333
+ }}
334
+ </Droppable>
335
+ </DragDropContext>
336
+ );
337
+ };
338
+
339
+ return (
340
+ <Modal
341
+ title={props.title || "Customize Columns"}
342
+ description={
343
+ props.description ||
344
+ "Choose which columns to show and drag them into the order you want."
345
+ }
346
+ modalWidth={ModalWidth.Medium}
347
+ icon={IconProp.TableCells}
348
+ submitButtonText="Save"
349
+ closeButtonText="Cancel"
350
+ onClose={props.onClose}
351
+ onSubmit={() => {
352
+ props.onSave(entries);
353
+ }}
354
+ leftFooterElement={
355
+ props.isDefaultLayout ? (
356
+ <></>
357
+ ) : (
358
+ <Button
359
+ title="Reset to default"
360
+ buttonSize={ButtonSize.Normal}
361
+ buttonStyle={ButtonStyleType.OUTLINE}
362
+ dataTestId="column-customization-reset"
363
+ onClick={() => {
364
+ props.onReset();
365
+ }}
366
+ />
367
+ )
368
+ }
369
+ >
370
+ <div className="space-y-3" data-testid="column-customization-modal">
371
+ <div className="flex items-center justify-between gap-3">
372
+ <div className="flex-1">
373
+ <Input
374
+ type={InputType.TEXT}
375
+ placeholder="Search columns..."
376
+ value={searchText}
377
+ dataTestId="column-customization-search"
378
+ onChange={(value: string) => {
379
+ setSearchText(value);
380
+ }}
381
+ />
382
+ </div>
383
+ <div className="flex flex-none gap-2">
384
+ <Button
385
+ title="Show all"
386
+ buttonSize={ButtonSize.Small}
387
+ buttonStyle={ButtonStyleType.OUTLINE}
388
+ dataTestId="column-customization-show-all"
389
+ onClick={() => {
390
+ setAllVisible(true);
391
+ }}
392
+ />
393
+ <Button
394
+ title="Hide all"
395
+ buttonSize={ButtonSize.Small}
396
+ buttonStyle={ButtonStyleType.OUTLINE}
397
+ dataTestId="column-customization-hide-all"
398
+ onClick={() => {
399
+ setAllVisible(false);
400
+ }}
401
+ />
402
+ </div>
403
+ </div>
404
+
405
+ <div
406
+ className="text-xs text-gray-500"
407
+ data-testid="column-customization-count"
408
+ >
409
+ {visibleCount} of {entries.length} columns shown
410
+ </div>
411
+
412
+ <div className="rounded-md border border-gray-200 overflow-hidden">
413
+ {getList()}
414
+ </div>
415
+ </div>
416
+ </Modal>
417
+ );
418
+ };
419
+
420
+ export default ColumnCustomizationModal;