@oneuptime/common 14.0.6 → 14.0.8

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 (556) hide show
  1. package/Models/DatabaseModels/Incident.ts +267 -1
  2. package/Models/DatabaseModels/IncidentCustomField.ts +202 -0
  3. package/Models/DatabaseModels/IncidentEpisode.ts +30 -0
  4. package/Models/DatabaseModels/IncidentTemplate.ts +126 -1
  5. package/Models/DatabaseModels/InventoryItem.ts +23 -12
  6. package/Models/DatabaseModels/StatusPage.ts +55 -0
  7. package/Models/DatabaseModels/StatusPageSubscriber.ts +128 -0
  8. package/Server/API/IncidentAPI.ts +162 -0
  9. package/Server/API/StatusPageAPI.ts +487 -171
  10. package/Server/API/StatusPageSubscriberAPI.ts +63 -15
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.ts +217 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.ts +49 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.ts +108 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.ts +33 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.ts +51 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.ts +33 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.ts +168 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.ts +44 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +16 -0
  20. package/Server/Infrastructure/Semaphore.ts +10 -0
  21. package/Server/Middleware/IdentityRateLimit.ts +108 -3
  22. package/Server/Middleware/SubscriberNotificationPreviewRateLimit.ts +237 -0
  23. package/Server/Middleware/SubscriberNotificationTestSendRateLimit.ts +304 -0
  24. package/Server/Services/AlertService.ts +32 -36
  25. package/Server/Services/DatabaseService.ts +93 -10
  26. package/Server/Services/IncidentAlertService.ts +609 -2
  27. package/Server/Services/IncidentCustomFieldService.ts +276 -1
  28. package/Server/Services/IncidentEpisodePublicNoteService.ts +28 -0
  29. package/Server/Services/IncidentEpisodeService.ts +15 -0
  30. package/Server/Services/IncidentEpisodeStateTimelineService.ts +27 -1
  31. package/Server/Services/IncidentPublicNoteService.ts +30 -1
  32. package/Server/Services/IncidentService.ts +1663 -103
  33. package/Server/Services/IncidentStateTimelineService.ts +13 -0
  34. package/Server/Services/IncidentTemplateService.ts +109 -0
  35. package/Server/Services/InventoryItemService.ts +38 -0
  36. package/Server/Services/IoTDeviceCredentialService.ts +13 -4
  37. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +30 -1
  38. package/Server/Services/ScheduledMaintenanceService.ts +118 -64
  39. package/Server/Services/SmsService.ts +10 -0
  40. package/Server/Services/StatusPageService.ts +65 -8
  41. package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +299 -37
  42. package/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.ts +129 -0
  43. package/Server/Services/StatusPageSubscriberService.ts +1161 -64
  44. package/Server/Services/UserNotificationRuleService.ts +55 -53
  45. package/Server/Services/WorkspaceNotificationSummaryService.ts +38 -20
  46. package/Server/Types/Markdown.ts +153 -6
  47. package/Server/Types/Workflow/Components/Email.ts +61 -2
  48. package/Server/Utils/AffectedResources/LinkedAffectedResources.ts +576 -0
  49. package/Server/Utils/Alert/AlertStateChangeAuthorization.ts +129 -0
  50. package/Server/Utils/CustomField/CustomFieldRename.ts +378 -0
  51. package/Server/Utils/DataSource/EgressGuard.ts +66 -21
  52. package/Server/Utils/Inventory/InventoryOverviewAggregation.ts +111 -0
  53. package/Server/Utils/Mail/PinnedSmtpSocket.ts +130 -0
  54. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +10 -0
  55. package/Server/Utils/Response.ts +31 -0
  56. package/Server/Utils/SSRFProtection.ts +76 -16
  57. package/Server/Utils/StatusPage/IncidentStatusPageScope.ts +948 -0
  58. package/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.ts +656 -0
  59. package/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.ts +805 -0
  60. package/Server/Utils/StatusPage/StatusPageExclusion.ts +18 -0
  61. package/Server/Utils/StatusPage/StatusPageReadAccess.ts +125 -0
  62. package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.ts +151 -0
  63. package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.ts +70 -0
  64. package/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.ts +421 -0
  65. package/Server/Utils/StatusPage/SubscriberNotificationClaim.ts +107 -0
  66. package/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.ts +1049 -0
  67. package/Server/Utils/StatusPage/SubscriberNotificationFanOut.ts +180 -0
  68. package/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.ts +839 -0
  69. package/Server/Utils/StatusPage/SubscriberNotificationResendAccess.ts +393 -0
  70. package/Server/Utils/StatusPage/SubscriberNotificationRunLimit.ts +246 -0
  71. package/Server/Utils/StatusPage/SubscriberNotificationTiming.ts +133 -0
  72. package/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.ts +215 -0
  73. package/Server/Utils/StatusPageResource.ts +51 -20
  74. package/Server/Utils/Topology/TopologyConcurrencyLimiter.ts +229 -0
  75. package/Server/Utils/Topology/TopologyQueries.ts +1350 -0
  76. package/Server/Utils/Topology/TopologyRequest.ts +463 -0
  77. package/Server/Utils/Topology/TopologyResponseCache.ts +183 -0
  78. package/Server/Utils/Topology/TopologySql.ts +1024 -0
  79. package/Server/Utils/VM/VMAPI.ts +1 -0
  80. package/Server/Utils/VM/VMRunner.ts +10 -0
  81. package/Server/Utils/Workflow/OAuth2TokenClient.ts +10 -0
  82. package/Server/Views/Partials/SensitiveUrlToken.ejs +8 -5
  83. package/Tests/App/Accounts/RegisterVerifyEmail.test.tsx +748 -0
  84. package/Tests/App/Accounts/ResendVerificationEmail.test.tsx +1222 -0
  85. package/Tests/App/Accounts/VerificationEmailResendUtils.test.ts +797 -0
  86. package/Tests/App/Accounts/VerifyEmailPending.test.tsx +538 -0
  87. package/Tests/App/Accounts/VerifyEmailResend.test.tsx +779 -0
  88. package/Tests/App/Dashboard/AcknowledgeAlertsOnDeclare.test.ts +369 -0
  89. package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +1 -1
  90. package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +510 -123
  91. package/Tests/App/Dashboard/AlertsTableAffectedResources.test.tsx +490 -0
  92. package/Tests/App/Dashboard/ChangeAlertStateDeclareIncident.test.tsx +886 -0
  93. package/Tests/App/Dashboard/CreateReviewStepRoleSummary.test.tsx +1250 -0
  94. package/Tests/App/Dashboard/CreateReviewStepSelectionSummary.test.tsx +738 -0
  95. package/Tests/App/Dashboard/CustomFieldsSettingsIncidentOptions.test.tsx +357 -0
  96. package/Tests/App/Dashboard/DeclareIncidentFromAlert.test.ts +417 -0
  97. package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +1948 -229
  98. package/Tests/App/Dashboard/EntityDetailPanelLifecycle.test.tsx +493 -0
  99. package/Tests/App/Dashboard/EntityDetailPanelNavigation.test.tsx +439 -0
  100. package/Tests/App/Dashboard/EventNotes.test.tsx +776 -0
  101. package/Tests/App/Dashboard/EventNotesPages.test.tsx +119 -0
  102. package/Tests/App/Dashboard/EventNotesUtil.test.ts +116 -17
  103. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +534 -6
  104. package/Tests/App/Dashboard/EventStatusPanel.test.tsx +798 -2
  105. package/Tests/App/Dashboard/FetchStateAndSeverityElements.test.tsx +669 -0
  106. package/Tests/App/Dashboard/FetchUsers.test.tsx +230 -0
  107. package/Tests/App/Dashboard/IncidentChangeStateNotifyDefault.test.tsx +91 -1
  108. package/Tests/App/Dashboard/IncidentCreateAcknowledgeAlerts.test.tsx +1611 -0
  109. package/Tests/App/Dashboard/IncidentCreateDetailsStep.test.tsx +643 -0
  110. package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +8 -1
  111. package/Tests/App/Dashboard/IncidentCreateStatusPageScope.test.tsx +601 -0
  112. package/Tests/App/Dashboard/IncidentCustomFieldTemplateVariables.test.tsx +386 -0
  113. package/Tests/App/Dashboard/IncidentNoteTemplatePlaceholders.test.tsx +124 -0
  114. package/Tests/App/Dashboard/IncidentNoteTemplateVariablesLoader.test.ts +305 -0
  115. package/Tests/App/Dashboard/IncidentOverviewNotifyDefault.test.tsx +112 -0
  116. package/Tests/App/Dashboard/IncidentSettingsRenotifyOnPublish.test.tsx +674 -0
  117. package/Tests/App/Dashboard/IncidentSettingsStatusPageScope.test.tsx +1051 -0
  118. package/Tests/App/Dashboard/IncidentTemplateCustomFields.test.tsx +384 -0
  119. package/Tests/App/Dashboard/IncidentTemplateStatusPageScopeCard.test.tsx +215 -0
  120. package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +1365 -57
  121. package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +964 -23
  122. package/Tests/App/Dashboard/InventoryRelationships.test.tsx +885 -0
  123. package/Tests/App/Dashboard/PublicNotePagesNotifyDefault.test.tsx +113 -1
  124. package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +201 -15
  125. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +508 -36
  126. package/Tests/App/Dashboard/SubscriberAudienceSummary.test.tsx +512 -0
  127. package/Tests/App/Dashboard/SubscriberNotificationPreviewModal.test.tsx +837 -0
  128. package/Tests/App/Dashboard/SubscriberNotificationStatusLabel.test.tsx +88 -0
  129. package/Tests/App/Dashboard/SubscriberNotificationStatusResend.test.tsx +473 -0
  130. package/Tests/App/Dashboard/SubscriberTemplateLivePreview.test.tsx +196 -0
  131. package/Tests/App/Dashboard/TeamAddedSubscribersUnsubscribedNotice.test.tsx +248 -0
  132. package/Tests/App/Dashboard/TopologyDataLifecycle.test.tsx +583 -0
  133. package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +982 -218
  134. package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +818 -114
  135. package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +64 -3
  136. package/Tests/App/StatusPage/StatusPageUnsubscribePage.test.tsx +412 -0
  137. package/Tests/Models/IncidentCustomFieldApiSchemaContract.test.ts +217 -0
  138. package/Tests/Models/IncidentCustomFieldCreateSettingsColumns.test.ts +252 -0
  139. package/Tests/Models/StatusPageSubscriberUnsubscribeColumns.test.ts +218 -0
  140. package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +7 -0
  141. package/Tests/Server/API/IncidentSubscriberAudienceAPI.test.ts +1408 -0
  142. package/Tests/Server/API/StatusPageIncidentScope.test.ts +1868 -0
  143. package/Tests/Server/API/StatusPageIncidentScopePostgres.test.ts +790 -0
  144. package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +10 -1
  145. package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +206 -18
  146. package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +14 -2
  147. package/Tests/Server/API/StatusPageSubscriberCreateResponse.test.ts +217 -0
  148. package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +103 -2
  149. package/Tests/Server/API/StatusPageUnsubscribeAPI.test.ts +396 -0
  150. package/Tests/Server/Infrastructure/Postgres/AddIncidentStatusPageScopeMigration.test.ts +395 -0
  151. package/Tests/Server/Infrastructure/Postgres/AddIncidentTemplateStatusPageScopeFlagMigration.test.ts +150 -0
  152. package/Tests/Server/Infrastructure/Postgres/AddSubscriberNotificationClaimedAtMigration.test.ts +156 -0
  153. package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +90 -21
  154. package/Tests/Server/Infrastructure/Postgres/SkipHiddenIncidentCreatedNotificationsMigration.test.ts +410 -0
  155. package/Tests/Server/Middleware/IdentityRateLimit.test.ts +551 -1
  156. package/Tests/Server/Middleware/SubscriberNotificationPreviewRateLimit.test.ts +238 -0
  157. package/Tests/Server/Middleware/SubscriberNotificationTestSendRateLimit.test.ts +245 -0
  158. package/Tests/Server/Services/AddStatusPageSubscriberUnsubscribeTokenMigration.test.ts +152 -0
  159. package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +221 -36
  160. package/Tests/Server/Services/DatabaseServiceCompareAndSetColumns.test.ts +191 -0
  161. package/Tests/Server/Services/DomainService.test.ts +525 -0
  162. package/Tests/Server/Services/IncidentAlertAcknowledgeOnDeclare.test.ts +2630 -0
  163. package/Tests/Server/Services/IncidentAlertPostgres.test.ts +1625 -1
  164. package/Tests/Server/Services/IncidentCreatedRenotifyOnPublish.test.ts +681 -0
  165. package/Tests/Server/Services/IncidentCreatedResend.test.ts +775 -0
  166. package/Tests/Server/Services/IncidentCustomFieldRenamePostgres.test.ts +713 -0
  167. package/Tests/Server/Services/IncidentCustomFieldService.test.ts +751 -0
  168. package/Tests/Server/Services/IncidentCustomFieldValueValidation.test.ts +556 -0
  169. package/Tests/Server/Services/IncidentDeclareAcknowledgeAlerts.test.ts +2189 -0
  170. package/Tests/Server/Services/IncidentStatusPageScope.test.ts +2971 -0
  171. package/Tests/Server/Services/IncidentStatusPageScopeFeed.test.ts +131 -0
  172. package/Tests/Server/Services/IncidentStatusPageScopePostgres.test.ts +625 -0
  173. package/Tests/Server/Services/IncidentTemplateCustomFieldsCopy.test.ts +311 -0
  174. package/Tests/Server/Services/IncidentTemplateStatusPageScope.test.ts +363 -0
  175. package/Tests/Server/Services/InventoryItemServiceOverviewCounts.test.ts +345 -0
  176. package/Tests/Server/Services/InventoryOverviewPostgres.test.ts +254 -0
  177. package/Tests/Server/Services/IoTDeviceCredentialService.test.ts +819 -0
  178. package/Tests/Server/Services/LinkedAffectedResourcesCreatedFeed.test.ts +420 -0
  179. package/Tests/Server/Services/PublicNoteEditFeedEventType.test.ts +213 -0
  180. package/Tests/Server/Services/PublicNoteResendAccess.test.ts +994 -0
  181. package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +289 -9
  182. package/Tests/Server/Services/SloAffectedResourceCreatedFeed.test.ts +92 -36
  183. package/Tests/Server/Services/SmsServiceFailIfNotSent.test.ts +67 -0
  184. package/Tests/Server/Services/StatusPageReportIncidentCounts.test.ts +610 -0
  185. package/Tests/Server/Services/StatusPageSubscriberAudienceCounts.test.ts +201 -0
  186. package/Tests/Server/Services/StatusPageSubscriberAudienceCountsPostgres.test.ts +271 -0
  187. package/Tests/Server/Services/StatusPageSubscriberConfirmationTemplateEscaping.test.ts +200 -0
  188. package/Tests/Server/Services/StatusPageSubscriberNotificationLogRedaction.test.ts +54 -0
  189. package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateCompile.test.ts +37 -0
  190. package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateIncidentRecordAccess.test.ts +772 -0
  191. package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookup.test.ts +506 -0
  192. package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookupPostgres.test.ts +261 -0
  193. package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +21 -5
  194. package/Tests/Server/Services/StatusPageSubscriberUnsubscribe.test.ts +1618 -0
  195. package/Tests/Server/Services/StatusPageSubscriberUnsubscribeLinkSenders.test.ts +373 -0
  196. package/Tests/Server/Services/StatusPageSubscriberUnsubscribePostgres.test.ts +388 -0
  197. package/Tests/Server/Services/SubscriberNotificationInFlightRequeue.test.ts +500 -0
  198. package/Tests/Server/Types/MarkdownEmailLinks.test.ts +320 -0
  199. package/Tests/Server/Types/Workflow/Components/Email.test.ts +491 -1
  200. package/Tests/Server/Types/Workflow/Components/EmailSmtpPinning.test.ts +398 -0
  201. package/Tests/Server/Utils/AffectedResources/LinkedAffectedResources.test.ts +858 -0
  202. package/Tests/Server/Utils/Alert/AlertStateChangeAuthorization.test.ts +1172 -0
  203. package/Tests/Server/Utils/CustomField/CustomFieldRename.test.ts +586 -0
  204. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +246 -10
  205. package/Tests/Server/Utils/DataSource/EgressGuardDeploymentConfig.test.ts +226 -0
  206. package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +131 -0
  207. package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +4 -0
  208. package/Tests/Server/Utils/EgressPolicyEnvironment.ts +45 -0
  209. package/Tests/Server/Utils/Mail/PinnedSmtpSocket.test.ts +409 -0
  210. package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +23 -0
  211. package/Tests/Server/Utils/SSRFProtection.test.ts +4 -0
  212. package/Tests/Server/Utils/SSRFProtectionCloudServiceAddresses.test.ts +4 -0
  213. package/Tests/Server/Utils/SSRFProtectionPrivateNetwork.test.ts +4 -0
  214. package/Tests/Server/Utils/SSRFProtectionResolutionDetail.test.ts +314 -0
  215. package/Tests/Server/Utils/StatusPage/IncidentStatusPageScope.test.ts +1699 -0
  216. package/Tests/Server/Utils/StatusPage/IncidentStatusPageScopeQueriesPostgres.test.ts +508 -0
  217. package/Tests/Server/Utils/StatusPage/IncidentSubscriberAudienceCallerPermission.test.ts +246 -0
  218. package/Tests/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.test.ts +1348 -0
  219. package/Tests/Server/Utils/StatusPage/StatusPageReadAccess.test.ts +221 -0
  220. package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.test.ts +132 -0
  221. package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.test.ts +155 -0
  222. package/Tests/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.test.ts +708 -0
  223. package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaim.test.ts +255 -0
  224. package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaimPostgres.test.ts +528 -0
  225. package/Tests/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.test.ts +1238 -0
  226. package/Tests/Server/Utils/StatusPage/SubscriberNotificationFanOut.test.ts +472 -0
  227. package/Tests/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.test.ts +1168 -0
  228. package/Tests/Server/Utils/StatusPage/SubscriberNotificationRunLimit.test.ts +275 -0
  229. package/Tests/Server/Utils/StatusPage/SubscriberNotificationTiming.test.ts +131 -0
  230. package/Tests/Server/Utils/StatusPageResource.test.ts +98 -0
  231. package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigration.test.ts +386 -0
  232. package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigrationPostgres.test.ts +430 -0
  233. package/Tests/Server/Utils/Topology/TopologyActivityParityPostgres.test.ts +279 -0
  234. package/Tests/Server/Utils/Topology/TopologyConcurrencyLimiter.test.ts +534 -0
  235. package/Tests/Server/Utils/Topology/TopologyEstateGenerator.ts +624 -0
  236. package/Tests/Server/Utils/Topology/TopologyJsonResponse.test.ts +90 -0
  237. package/Tests/Server/Utils/Topology/TopologyQueries.test.ts +1634 -0
  238. package/Tests/Server/Utils/Topology/TopologyQueriesDifferentialPostgres.test.ts +683 -0
  239. package/Tests/Server/Utils/Topology/TopologyQueriesPostgres.test.ts +2624 -0
  240. package/Tests/Server/Utils/Topology/TopologyReference.ts +1018 -0
  241. package/Tests/Server/Utils/Topology/TopologyRequest.test.ts +643 -0
  242. package/Tests/Server/Utils/Topology/TopologyResponseCache.test.ts +305 -0
  243. package/Tests/Server/Utils/Topology/TopologySql.test.ts +973 -0
  244. package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +17 -0
  245. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +75 -0
  246. package/Tests/Types/CustomField/CustomFieldSavedViews.test.ts +247 -0
  247. package/Tests/Types/CustomField/CustomFieldTemplateValues.test.ts +186 -0
  248. package/Tests/Types/CustomField/CustomFieldTypeCorrespondence.test.ts +48 -0
  249. package/Tests/Types/CustomField/CustomFieldValueFormat.test.ts +215 -0
  250. package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +343 -0
  251. package/Tests/Types/CustomField/CustomFieldVariableKey.test.ts +364 -0
  252. package/Tests/Types/SafeHtml.test.ts +102 -0
  253. package/Tests/Types/StatusPage/IncidentCreatedRenotify.test.ts +419 -0
  254. package/Tests/Types/StatusPage/IncidentCreatedResend.test.ts +118 -0
  255. package/Tests/Types/StatusPage/IncidentScopeAddedPagesNotification.test.ts +558 -0
  256. package/Tests/Types/StatusPage/IncidentSubscriberAudience.test.ts +284 -0
  257. package/Tests/Types/StatusPage/StatusPageSubscriberUnsubscribe.test.ts +341 -0
  258. package/Tests/Types/StatusPage/SubscriberNotificationPreview.test.ts +196 -0
  259. package/Tests/Types/StatusPage/SubscriberNotificationResend.test.ts +201 -0
  260. package/Tests/Types/StatusPage/SubscriberNotificationTemplateCompiler.test.ts +277 -0
  261. package/Tests/Types/StatusPage/SubscriberNotificationTemplatePreview.test.ts +179 -0
  262. package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +324 -0
  263. package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +60 -13
  264. package/Tests/Types/Topology/TopologyTypeRules.test.ts +176 -0
  265. package/Tests/UI/Components/CustomFields/CustomFieldFormFields.test.ts +432 -0
  266. package/Tests/UI/Components/CustomFields/CustomFieldModelFormFields.test.tsx +685 -0
  267. package/Tests/UI/Components/CustomFields/CustomFieldsDetailOrder.test.tsx +469 -0
  268. package/Tests/UI/Components/Forms/ModelFormCustomFieldInputs.test.tsx +325 -0
  269. package/Tests/UI/Components/Forms/ModelFormDropdownOptionsRefused.test.tsx +358 -0
  270. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +22 -0
  271. package/Tests/UI/Monitor/NetworkPathView.test.tsx +289 -0
  272. package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +302 -0
  273. package/Tests/Utils/Incident/IncidentNoteTemplateVariables.test.ts +623 -0
  274. package/Tests/Utils/Markdown/MarkdownEscape.test.ts +89 -0
  275. package/Tests/Utils/ProbeNetworkFailureUtil.test.ts +992 -0
  276. package/Tests/Utils/RequestFailedDetails.test.ts +575 -0
  277. package/Types/CustomField/CustomFieldOrder.ts +55 -0
  278. package/Types/CustomField/CustomFieldSavedViews.ts +225 -0
  279. package/Types/CustomField/CustomFieldTemplateMerge.ts +71 -0
  280. package/Types/CustomField/CustomFieldType.ts +14 -0
  281. package/Types/CustomField/CustomFieldValueFormat.ts +161 -0
  282. package/Types/CustomField/CustomFieldValueValidator.ts +488 -0
  283. package/Types/CustomField/CustomFieldVariableKey.ts +211 -0
  284. package/Types/Incident/IncidentAlertLink.ts +19 -0
  285. package/Types/SafeHtml.ts +93 -0
  286. package/Types/StatusPage/IncidentCreatedRenotify.ts +224 -0
  287. package/Types/StatusPage/IncidentCreatedResend.ts +108 -0
  288. package/Types/StatusPage/IncidentScopeAddedPagesNotification.ts +343 -0
  289. package/Types/StatusPage/IncidentSubscriberAudience.ts +332 -0
  290. package/Types/StatusPage/StatusPageSubscriberUnsubscribe.ts +405 -0
  291. package/Types/StatusPage/SubscriberNotificationInterruption.ts +32 -0
  292. package/Types/StatusPage/SubscriberNotificationPreview.ts +322 -0
  293. package/Types/StatusPage/SubscriberNotificationResend.ts +132 -0
  294. package/Types/StatusPage/SubscriberNotificationTemplateCompiler.ts +180 -0
  295. package/Types/StatusPage/SubscriberNotificationTemplatePreview.ts +301 -0
  296. package/Types/StatusPage/SubscriberNotificationTemplateVariables.ts +217 -4
  297. package/Types/StatusPage/SubscriberUpdateNotification.ts +32 -11
  298. package/Types/Telemetry/InventoryLiveness.ts +26 -0
  299. package/Types/Topology/TopologyApi.ts +428 -0
  300. package/Types/Topology/TopologyTypeRules.ts +191 -0
  301. package/UI/Components/CustomFields/CustomFieldFormFields.ts +317 -0
  302. package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +395 -0
  303. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +95 -55
  304. package/UI/Components/Forms/ModelForm.tsx +70 -8
  305. package/UI/Components/Forms/Validation.ts +1 -1
  306. package/UI/Components/ModelFormModal/ModelFormModal.tsx +2 -4
  307. package/UI/Components/ModelTable/AnalyticsModelTable.tsx +2 -6
  308. package/UI/Components/ModelTable/BaseModelTable.tsx +9 -8
  309. package/UI/Components/ModelTable/CustomFieldColumns.tsx +14 -1
  310. package/UI/Components/ModelTable/ModelTable.tsx +6 -7
  311. package/UI/Utils/SensitiveUrlToken.ts +10 -5
  312. package/Utils/API.ts +247 -2
  313. package/Utils/Incident/IncidentFromAlerts.ts +78 -0
  314. package/Utils/Incident/IncidentNoteTemplateVariables.ts +304 -0
  315. package/Utils/Markdown/MarkdownEscape.ts +65 -0
  316. package/Utils/ProbeNetworkFailureUtil.ts +673 -0
  317. package/build/dist/Models/DatabaseModels/Incident.js +267 -1
  318. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  319. package/build/dist/Models/DatabaseModels/IncidentCustomField.js +207 -1
  320. package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
  321. package/build/dist/Models/DatabaseModels/IncidentEpisode.js +31 -0
  322. package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
  323. package/build/dist/Models/DatabaseModels/IncidentTemplate.js +124 -1
  324. package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
  325. package/build/dist/Models/DatabaseModels/InventoryItem.js +20 -11
  326. package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -1
  327. package/build/dist/Models/DatabaseModels/StatusPage.js +56 -0
  328. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  329. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +131 -0
  330. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
  331. package/build/dist/Server/API/IncidentAPI.js +100 -1
  332. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  333. package/build/dist/Server/API/StatusPageAPI.js +417 -176
  334. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  335. package/build/dist/Server/API/StatusPageSubscriberAPI.js +52 -13
  336. package/build/dist/Server/API/StatusPageSubscriberAPI.js.map +1 -1
  337. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js +165 -0
  338. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js.map +1 -0
  339. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js +41 -0
  340. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js.map +1 -0
  341. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js +57 -0
  342. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js.map +1 -0
  343. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js +23 -0
  344. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js.map +1 -0
  345. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js +40 -0
  346. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js.map +1 -0
  347. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js +26 -0
  348. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js.map +1 -0
  349. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js +89 -0
  350. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js.map +1 -0
  351. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js +29 -0
  352. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js.map +1 -0
  353. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +16 -0
  354. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  355. package/build/dist/Server/Infrastructure/Semaphore.js +3 -0
  356. package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
  357. package/build/dist/Server/Middleware/IdentityRateLimit.js +89 -3
  358. package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
  359. package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js +149 -0
  360. package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js.map +1 -0
  361. package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js +190 -0
  362. package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js.map +1 -0
  363. package/build/dist/Server/Services/AlertService.js +21 -33
  364. package/build/dist/Server/Services/AlertService.js.map +1 -1
  365. package/build/dist/Server/Services/DatabaseService.js +56 -7
  366. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  367. package/build/dist/Server/Services/IncidentAlertService.js +457 -3
  368. package/build/dist/Server/Services/IncidentAlertService.js.map +1 -1
  369. package/build/dist/Server/Services/IncidentCustomFieldService.js +204 -8
  370. package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
  371. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +24 -0
  372. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
  373. package/build/dist/Server/Services/IncidentEpisodeService.js +14 -0
  374. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  375. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +26 -0
  376. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
  377. package/build/dist/Server/Services/IncidentPublicNoteService.js +26 -1
  378. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  379. package/build/dist/Server/Services/IncidentService.js +1148 -42
  380. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  381. package/build/dist/Server/Services/IncidentStateTimelineService.js +12 -0
  382. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  383. package/build/dist/Server/Services/IncidentTemplateService.js +83 -0
  384. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  385. package/build/dist/Server/Services/InventoryItemService.js +31 -0
  386. package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
  387. package/build/dist/Server/Services/IoTDeviceCredentialService.js +12 -5
  388. package/build/dist/Server/Services/IoTDeviceCredentialService.js.map +1 -1
  389. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +26 -1
  390. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  391. package/build/dist/Server/Services/ScheduledMaintenanceService.js +84 -57
  392. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  393. package/build/dist/Server/Services/SmsService.js +2 -22
  394. package/build/dist/Server/Services/SmsService.js.map +1 -1
  395. package/build/dist/Server/Services/StatusPageService.js +47 -9
  396. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  397. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +237 -32
  398. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
  399. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js +109 -0
  400. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js.map +1 -1
  401. package/build/dist/Server/Services/StatusPageSubscriberService.js +925 -99
  402. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  403. package/build/dist/Server/Services/UserNotificationRuleService.js +55 -51
  404. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  405. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +42 -25
  406. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
  407. package/build/dist/Server/Types/Markdown.js +110 -6
  408. package/build/dist/Server/Types/Markdown.js.map +1 -1
  409. package/build/dist/Server/Types/Workflow/Components/Email.js +55 -6
  410. package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
  411. package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js +405 -0
  412. package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js.map +1 -0
  413. package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js +112 -0
  414. package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js.map +1 -0
  415. package/build/dist/Server/Utils/CustomField/CustomFieldRename.js +211 -0
  416. package/build/dist/Server/Utils/CustomField/CustomFieldRename.js.map +1 -0
  417. package/build/dist/Server/Utils/DataSource/EgressGuard.js +41 -12
  418. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
  419. package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js +81 -0
  420. package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js.map +1 -0
  421. package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js +101 -0
  422. package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js.map +1 -0
  423. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +9 -0
  424. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  425. package/build/dist/Server/Utils/Response.js +30 -0
  426. package/build/dist/Server/Utils/Response.js.map +1 -1
  427. package/build/dist/Server/Utils/SSRFProtection.js +48 -6
  428. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  429. package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js +631 -0
  430. package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js.map +1 -0
  431. package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js +403 -0
  432. package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js.map +1 -0
  433. package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js +451 -0
  434. package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js.map +1 -0
  435. package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js +13 -0
  436. package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js.map +1 -0
  437. package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js +91 -0
  438. package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js.map +1 -0
  439. package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js +101 -0
  440. package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js.map +1 -0
  441. package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js +47 -0
  442. package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js.map +1 -0
  443. package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js +273 -0
  444. package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js.map +1 -0
  445. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js +73 -0
  446. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js.map +1 -0
  447. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js +722 -0
  448. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js.map +1 -0
  449. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js +102 -0
  450. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js.map +1 -0
  451. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js +527 -0
  452. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js.map +1 -0
  453. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js +278 -0
  454. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js.map +1 -0
  455. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js +137 -0
  456. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js.map +1 -0
  457. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js +103 -0
  458. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js.map +1 -0
  459. package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js +114 -0
  460. package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js.map +1 -0
  461. package/build/dist/Server/Utils/StatusPageResource.js +39 -7
  462. package/build/dist/Server/Utils/StatusPageResource.js.map +1 -1
  463. package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js +178 -0
  464. package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js.map +1 -0
  465. package/build/dist/Server/Utils/Topology/TopologyQueries.js +884 -0
  466. package/build/dist/Server/Utils/Topology/TopologyQueries.js.map +1 -0
  467. package/build/dist/Server/Utils/Topology/TopologyRequest.js +275 -0
  468. package/build/dist/Server/Utils/Topology/TopologyRequest.js.map +1 -0
  469. package/build/dist/Server/Utils/Topology/TopologyResponseCache.js +146 -0
  470. package/build/dist/Server/Utils/Topology/TopologyResponseCache.js.map +1 -0
  471. package/build/dist/Server/Utils/Topology/TopologySql.js +688 -0
  472. package/build/dist/Server/Utils/Topology/TopologySql.js.map +1 -0
  473. package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
  474. package/build/dist/Server/Utils/VM/VMRunner.js +1 -0
  475. package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
  476. package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js +3 -0
  477. package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js.map +1 -1
  478. package/build/dist/Types/CustomField/CustomFieldOrder.js +36 -0
  479. package/build/dist/Types/CustomField/CustomFieldOrder.js.map +1 -0
  480. package/build/dist/Types/CustomField/CustomFieldSavedViews.js +135 -0
  481. package/build/dist/Types/CustomField/CustomFieldSavedViews.js.map +1 -0
  482. package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js +27 -0
  483. package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js.map +1 -0
  484. package/build/dist/Types/CustomField/CustomFieldType.js +12 -0
  485. package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
  486. package/build/dist/Types/CustomField/CustomFieldValueFormat.js +126 -0
  487. package/build/dist/Types/CustomField/CustomFieldValueFormat.js.map +1 -0
  488. package/build/dist/Types/CustomField/CustomFieldValueValidator.js +280 -0
  489. package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -0
  490. package/build/dist/Types/CustomField/CustomFieldVariableKey.js +150 -0
  491. package/build/dist/Types/CustomField/CustomFieldVariableKey.js.map +1 -0
  492. package/build/dist/Types/Incident/IncidentAlertLink.js +17 -0
  493. package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -1
  494. package/build/dist/Types/SafeHtml.js +84 -0
  495. package/build/dist/Types/SafeHtml.js.map +1 -0
  496. package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js +117 -0
  497. package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js.map +1 -0
  498. package/build/dist/Types/StatusPage/IncidentCreatedResend.js +86 -0
  499. package/build/dist/Types/StatusPage/IncidentCreatedResend.js.map +1 -0
  500. package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js +246 -0
  501. package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js.map +1 -0
  502. package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js +183 -0
  503. package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js.map +1 -0
  504. package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js +277 -0
  505. package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js.map +1 -0
  506. package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js +27 -0
  507. package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js.map +1 -0
  508. package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js +190 -0
  509. package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js.map +1 -0
  510. package/build/dist/Types/StatusPage/SubscriberNotificationResend.js +102 -0
  511. package/build/dist/Types/StatusPage/SubscriberNotificationResend.js.map +1 -0
  512. package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js +97 -0
  513. package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js.map +1 -0
  514. package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js +175 -0
  515. package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js.map +1 -0
  516. package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js +144 -4
  517. package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js.map +1 -1
  518. package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js +29 -9
  519. package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js.map +1 -1
  520. package/build/dist/Types/Telemetry/InventoryLiveness.js +23 -0
  521. package/build/dist/Types/Telemetry/InventoryLiveness.js.map +1 -1
  522. package/build/dist/Types/Topology/TopologyApi.js +55 -0
  523. package/build/dist/Types/Topology/TopologyApi.js.map +1 -0
  524. package/build/dist/Types/Topology/TopologyTypeRules.js +165 -0
  525. package/build/dist/Types/Topology/TopologyTypeRules.js.map +1 -0
  526. package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js +169 -0
  527. package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js.map +1 -0
  528. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +212 -0
  529. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -0
  530. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +64 -49
  531. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  532. package/build/dist/UI/Components/Forms/ModelForm.js +39 -5
  533. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  534. package/build/dist/UI/Components/Forms/Validation.js +1 -1
  535. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  536. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
  537. package/build/dist/UI/Components/ModelTable/AnalyticsModelTable.js.map +1 -1
  538. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +2 -2
  539. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  540. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +13 -1
  541. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
  542. package/build/dist/UI/Components/ModelTable/ModelTable.js +1 -1
  543. package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
  544. package/build/dist/UI/Utils/SensitiveUrlToken.js +10 -5
  545. package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -1
  546. package/build/dist/Utils/API.js +177 -1
  547. package/build/dist/Utils/API.js.map +1 -1
  548. package/build/dist/Utils/Incident/IncidentFromAlerts.js +38 -0
  549. package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -1
  550. package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js +155 -0
  551. package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js.map +1 -0
  552. package/build/dist/Utils/Markdown/MarkdownEscape.js +48 -0
  553. package/build/dist/Utils/Markdown/MarkdownEscape.js.map +1 -1
  554. package/build/dist/Utils/ProbeNetworkFailureUtil.js +460 -0
  555. package/build/dist/Utils/ProbeNetworkFailureUtil.js.map +1 -0
  556. package/package.json +1 -1
@@ -0,0 +1,395 @@
1
+ import Detail from "../Detail/Detail";
2
+ import { ModelField } from "../Forms/ModelForm";
3
+ import Field from "../Forms/Types/Field";
4
+ import FormValues from "../Forms/Types/FormValues";
5
+ import FieldType from "../Types/FieldType";
6
+ import {
7
+ buildCustomFieldFormFields,
8
+ CUSTOM_FIELD_NO_VALUE_PLACEHOLDER,
9
+ CustomFieldFormDefinition,
10
+ getCustomFieldDetailContentClassName,
11
+ getCustomFieldDisplayValue,
12
+ getCustomFieldDropdownOptions,
13
+ } from "./CustomFieldFormFields";
14
+
15
+ export { CUSTOM_FIELD_NO_VALUE_PLACEHOLDER } from "./CustomFieldFormFields";
16
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
17
+ import {
18
+ CustomFieldMappingSourceInfo,
19
+ getCustomFieldMappingSource,
20
+ hasCustomFieldMappingSource,
21
+ } from "../../../Types/CustomField/CustomFieldMappingCatalog";
22
+ import CustomFieldType from "../../../Types/CustomField/CustomFieldType";
23
+ import { isCustomFieldValueEmpty } from "../../../Types/CustomField/CustomFieldValueMapping";
24
+ import { JSONObject } from "../../../Types/JSON";
25
+ import React, { FunctionComponent, ReactElement } from "react";
26
+
27
+ /*
28
+ * Custom field inputs inside a record's OWN create form, next to its columns:
29
+ * the Details step of declaring an incident, and the Custom Fields step of a
30
+ * new incident template. (The Custom Fields card of a record that exists
31
+ * edits the values on their own, through CustomFieldsDetail.)
32
+ *
33
+ * A ModelForm only knows its model's columns, and the values live in one of
34
+ * them, `customFields`, a JSON bag keyed by each field's name. So each input
35
+ * here:
36
+ *
37
+ * - is held under its own form key, "customFields:<name>", never under the
38
+ * field's bare name: a field called "title" must not become the title
39
+ * input's value;
40
+ * - is permission-checked against the model's `customFields` column
41
+ * (overrideField), so nobody is shown inputs they may not fill in;
42
+ * - is packed back into `customFields` by the page's onBeforeCreate, from
43
+ * the values the form submitted (packCustomFieldFormValues). Never from
44
+ * the request's misc data, which keeps only truthy values - a Number of 0
45
+ * and a switch left off would be dropped there.
46
+ */
47
+
48
+ export const CUSTOM_FIELD_FORM_KEY_PREFIX: string = "customFields:";
49
+
50
+ export type GetCustomFieldFormKeyFunction = (fieldName: string) => string;
51
+
52
+ // Where the form holds one field's value.
53
+ export const getCustomFieldFormKey: GetCustomFieldFormKeyFunction = (
54
+ fieldName: string,
55
+ ): string => {
56
+ return `${CUSTOM_FIELD_FORM_KEY_PREFIX}${fieldName}`;
57
+ };
58
+
59
+ export type IsCustomFieldInheritedFunction = (data: {
60
+ // The definition table, e.g. "IncidentCustomField".
61
+ definitionTableName: string;
62
+ definition: CustomFieldFormDefinition;
63
+ // The record as the form stands: its relations decide.
64
+ values: JSONObject;
65
+ }) => boolean;
66
+
67
+ /**
68
+ * Whether a field's value will be copied from a related resource rather than
69
+ * typed: it is mapped (an incident field from a monitor field) and the record
70
+ * is attached to something to copy from (the incident has a monitor). The
71
+ * server re-applies the mapping on create, so asking for such a value would
72
+ * only have it replaced. The same rule the Custom Fields card uses.
73
+ */
74
+ export const isCustomFieldInherited: IsCustomFieldInheritedFunction = (data: {
75
+ definitionTableName: string;
76
+ definition: CustomFieldFormDefinition;
77
+ values: JSONObject;
78
+ }): boolean => {
79
+ if (
80
+ !data.definition.mapFromResourceType ||
81
+ !data.definition.mapFromCustomFieldName
82
+ ) {
83
+ return false;
84
+ }
85
+
86
+ const source: CustomFieldMappingSourceInfo | undefined =
87
+ getCustomFieldMappingSource({
88
+ definitionTableName: data.definitionTableName,
89
+ resource: data.definition.mapFromResourceType,
90
+ });
91
+
92
+ if (!source) {
93
+ return false;
94
+ }
95
+
96
+ return hasCustomFieldMappingSource({
97
+ source: source,
98
+ record: data.values as Record<string, unknown>,
99
+ });
100
+ };
101
+
102
+ export interface CustomFieldValueSummaryProps {
103
+ definition: CustomFieldFormDefinition;
104
+ value: unknown;
105
+ }
106
+
107
+ /*
108
+ * One field's value on a form's review step, drawn the way the Custom Fields
109
+ * card draws it: Yes or No, the option's label, the date in the viewer's
110
+ * time, a text field's number or yes/no as text, a Long text value's lines.
111
+ */
112
+ export const CustomFieldValueSummary: FunctionComponent<
113
+ CustomFieldValueSummaryProps
114
+ > = (props: CustomFieldValueSummaryProps): ReactElement => {
115
+ const type: CustomFieldType | undefined = props.definition.customFieldType;
116
+ const isDropdown: boolean =
117
+ type === CustomFieldType.Dropdown ||
118
+ type === CustomFieldType.MultiSelectDropdown;
119
+
120
+ return (
121
+ <Detail<JSONObject>
122
+ item={{
123
+ value: isCustomFieldValueEmpty(props.value)
124
+ ? null
125
+ : (getCustomFieldDisplayValue({
126
+ customFieldType: type,
127
+ value: props.value,
128
+ }) as JSONObject["value"]),
129
+ }}
130
+ fields={[
131
+ {
132
+ key: "value",
133
+ // CustomFieldType names a FieldType by value (see CustomFieldType).
134
+ fieldType: (type as unknown as FieldType) || FieldType.Text,
135
+ contentClassName: getCustomFieldDetailContentClassName(type),
136
+ placeholder: CUSTOM_FIELD_NO_VALUE_PLACEHOLDER,
137
+ dropdownOptions: isDropdown
138
+ ? getCustomFieldDropdownOptions(props.definition.dropdownOptions)
139
+ : undefined,
140
+ },
141
+ ]}
142
+ />
143
+ );
144
+ };
145
+
146
+ export type BuildCustomFieldModelFormFieldsFunction = <
147
+ TBaseModel extends BaseModel,
148
+ >(data: {
149
+ definitions: Array<CustomFieldFormDefinition>;
150
+ // Honour "Required on create" (the Details step of declaring an incident).
151
+ enforceRequiredOnCreate?: boolean | undefined;
152
+ stepId?: string | undefined;
153
+ /*
154
+ * Whether to ask for a field given the form as it stands. A field not asked
155
+ * for is neither validated nor packed: the record keeps whatever it would
156
+ * otherwise start with.
157
+ */
158
+ isShown?:
159
+ | ((definition: CustomFieldFormDefinition, values: JSONObject) => boolean)
160
+ | undefined;
161
+ }) => Array<ModelField<TBaseModel>>;
162
+
163
+ /**
164
+ * One ModelForm input per definition, in the order given, built by the same
165
+ * builder as every other custom field form (buildCustomFieldFormFields).
166
+ */
167
+ export const buildCustomFieldModelFormFields: BuildCustomFieldModelFormFieldsFunction =
168
+ <TBaseModel extends BaseModel>(data: {
169
+ definitions: Array<CustomFieldFormDefinition>;
170
+ enforceRequiredOnCreate?: boolean | undefined;
171
+ stepId?: string | undefined;
172
+ isShown?:
173
+ | ((definition: CustomFieldFormDefinition, values: JSONObject) => boolean)
174
+ | undefined;
175
+ }): Array<ModelField<TBaseModel>> => {
176
+ const fields: Array<Field<JSONObject>> = buildCustomFieldFormFields({
177
+ definitions: data.definitions,
178
+ enforceRequiredOnCreate: data.enforceRequiredOnCreate,
179
+ stepId: data.stepId,
180
+ getFormKey: getCustomFieldFormKey,
181
+ });
182
+
183
+ return fields.map(
184
+ (
185
+ builtField: Field<JSONObject>,
186
+ index: number,
187
+ ): ModelField<TBaseModel> => {
188
+ const definition: CustomFieldFormDefinition = data.definitions[index]!;
189
+ const formKey: string = getCustomFieldFormKey(definition.name);
190
+
191
+ /*
192
+ * The builder names the field after its name (`field`). Here the
193
+ * value is not a column, so that goes: the permission check and the
194
+ * dedupe read `overrideField` and the form key instead.
195
+ */
196
+ const rest: Field<JSONObject> = { ...builtField };
197
+ delete rest.field;
198
+
199
+ const modelField: ModelField<TBaseModel> = {
200
+ ...(rest as unknown as ModelField<TBaseModel>),
201
+ overrideField: {
202
+ customFields: true,
203
+ },
204
+ overrideFieldKey: formKey,
205
+ getSummaryElement: (values: FormValues<TBaseModel>): ReactElement => {
206
+ return (
207
+ <CustomFieldValueSummary
208
+ definition={definition}
209
+ value={(values as JSONObject)[formKey]}
210
+ />
211
+ );
212
+ },
213
+ };
214
+
215
+ if (data.isShown) {
216
+ const isShown: (
217
+ definition: CustomFieldFormDefinition,
218
+ values: JSONObject,
219
+ ) => boolean = data.isShown;
220
+
221
+ modelField.showIf = (values: FormValues<TBaseModel>): boolean => {
222
+ return isShown(definition, (values || {}) as JSONObject);
223
+ };
224
+ }
225
+
226
+ return modelField;
227
+ },
228
+ );
229
+ };
230
+
231
+ export type GetCustomFieldFormInitialValuesFunction = (data: {
232
+ definitions: Array<CustomFieldFormDefinition>;
233
+ // The values the record starts with, keyed by field name.
234
+ customFields: unknown;
235
+ }) => JSONObject;
236
+
237
+ /**
238
+ * The form's starting values for these fields, taken from a bag keyed by
239
+ * field name (an incident template's values), under their form keys.
240
+ */
241
+ export const getCustomFieldFormInitialValues: GetCustomFieldFormInitialValuesFunction =
242
+ (data: {
243
+ definitions: Array<CustomFieldFormDefinition>;
244
+ customFields: unknown;
245
+ }): JSONObject => {
246
+ const initialValues: JSONObject = {};
247
+
248
+ if (!isPlainObject(data.customFields)) {
249
+ return initialValues;
250
+ }
251
+
252
+ const bag: JSONObject = data.customFields;
253
+
254
+ for (const definition of data.definitions) {
255
+ if (!Object.prototype.hasOwnProperty.call(bag, definition.name)) {
256
+ continue;
257
+ }
258
+
259
+ const value: unknown = bag[definition.name];
260
+
261
+ if (isCustomFieldValueEmpty(value)) {
262
+ continue;
263
+ }
264
+
265
+ // A text field's number or yes/no as text: its input takes a string.
266
+ initialValues[getCustomFieldFormKey(definition.name)] =
267
+ getCustomFieldDisplayValue({
268
+ customFieldType: definition.customFieldType,
269
+ value: value,
270
+ }) as JSONObject["value"];
271
+ }
272
+
273
+ return initialValues;
274
+ };
275
+
276
+ type IsPlainObjectFunction = (value: unknown) => value is JSONObject;
277
+
278
+ const isPlainObject: IsPlainObjectFunction = (
279
+ value: unknown,
280
+ ): value is JSONObject => {
281
+ return (
282
+ value !== null &&
283
+ typeof value === "object" &&
284
+ !Array.isArray(value) &&
285
+ !(value instanceof Date)
286
+ );
287
+ };
288
+
289
+ type NormalizeFormValueFunction = (value: unknown) => unknown;
290
+
291
+ /*
292
+ * A dropdown can still hold the option object it was picked as ({label,
293
+ * value}) rather than its value; the value is what is stored.
294
+ */
295
+ const normalizeFormValue: NormalizeFormValueFunction = (
296
+ value: unknown,
297
+ ): unknown => {
298
+ const unwrap: (entry: unknown) => unknown = (entry: unknown): unknown => {
299
+ if (
300
+ isPlainObject(entry) &&
301
+ Object.prototype.hasOwnProperty.call(entry, "value") &&
302
+ Object.prototype.hasOwnProperty.call(entry, "label")
303
+ ) {
304
+ return entry["value"];
305
+ }
306
+
307
+ return entry;
308
+ };
309
+
310
+ if (Array.isArray(value)) {
311
+ return value.map(unwrap);
312
+ }
313
+
314
+ return unwrap(value);
315
+ };
316
+
317
+ export type PackCustomFieldFormValuesFunction = (data: {
318
+ // The fields the form asked for.
319
+ definitions: Array<CustomFieldFormDefinition>;
320
+ // Every value the form submitted (ModelForm's onBeforeCreate hands it over).
321
+ formValues: JSONObject | null | undefined;
322
+ /*
323
+ * The values the record starts with, keyed by field name - an incident
324
+ * template's. They are kept for every field the form did not ask about.
325
+ */
326
+ startingCustomFields?: unknown;
327
+ // As buildCustomFieldModelFormFields: a field not shown is not the form's.
328
+ isShown?:
329
+ | ((definition: CustomFieldFormDefinition, values: JSONObject) => boolean)
330
+ | undefined;
331
+ }) => JSONObject | undefined;
332
+
333
+ /**
334
+ * The record's `customFields` bag: the starting values, with each field the
335
+ * form asked for set to what it holds. 0 and false are answers and are kept;
336
+ * a field emptied on the form is removed, so clearing a value a template
337
+ * filled in sticks. Undefined when there is nothing to store.
338
+ */
339
+ export const packCustomFieldFormValues: PackCustomFieldFormValuesFunction =
340
+ (data: {
341
+ definitions: Array<CustomFieldFormDefinition>;
342
+ formValues: JSONObject | null | undefined;
343
+ startingCustomFields?: unknown;
344
+ isShown?:
345
+ | ((definition: CustomFieldFormDefinition, values: JSONObject) => boolean)
346
+ | undefined;
347
+ }): JSONObject | undefined => {
348
+ const formValues: JSONObject = data.formValues || {};
349
+
350
+ const result: JSONObject = isPlainObject(data.startingCustomFields)
351
+ ? { ...data.startingCustomFields }
352
+ : {};
353
+
354
+ for (const definition of data.definitions) {
355
+ if (data.isShown && !data.isShown(definition, formValues)) {
356
+ continue;
357
+ }
358
+
359
+ const formKey: string = getCustomFieldFormKey(definition.name);
360
+
361
+ // The form never held a value for it, so it has nothing to say.
362
+ if (!Object.prototype.hasOwnProperty.call(formValues, formKey)) {
363
+ continue;
364
+ }
365
+
366
+ const value: unknown = normalizeFormValue(formValues[formKey]);
367
+
368
+ if (isCustomFieldValueEmpty(value)) {
369
+ delete result[definition.name];
370
+ continue;
371
+ }
372
+
373
+ result[definition.name] = value as JSONObject["value"];
374
+ }
375
+
376
+ return Object.keys(result).length > 0 ? result : undefined;
377
+ };
378
+
379
+ export type RemoveCustomFieldFormKeysFunction = (
380
+ miscDataProps: JSONObject,
381
+ ) => void;
382
+
383
+ /**
384
+ * Takes the inputs' values out of a request's misc data, where ModelForm puts
385
+ * every form-only value: they travel in `customFields`, and nowhere else.
386
+ */
387
+ export const removeCustomFieldFormKeys: RemoveCustomFieldFormKeysFunction = (
388
+ miscDataProps: JSONObject,
389
+ ): void => {
390
+ for (const key of Object.keys(miscDataProps)) {
391
+ if (key.startsWith(CUSTOM_FIELD_FORM_KEY_PREFIX)) {
392
+ delete miscDataProps[key];
393
+ }
394
+ }
395
+ };
@@ -8,24 +8,28 @@ import { ButtonStyleType } from "../Button/Button";
8
8
  import Card, { CardButtonSchema, CardHeaderLayout } from "../Card/Card";
9
9
  import ComponentLoader from "../ComponentLoader/ComponentLoader";
10
10
  import Detail from "../Detail/Detail";
11
- import { DropdownOption } from "../Dropdown/Dropdown";
12
11
  import ErrorMessage from "../ErrorMessage/ErrorMessage";
13
12
  import BasicFormModal from "../FormModal/BasicFormModal";
13
+ import {
14
+ buildCustomFieldFormFields,
15
+ CustomFieldFormDefinition,
16
+ getCustomFieldDetailContentClassName,
17
+ getCustomFieldDisplayValue,
18
+ getCustomFieldDropdownOptions,
19
+ sortCustomFieldDefinitions,
20
+ toCustomFieldFormDefinition,
21
+ } from "./CustomFieldFormFields";
14
22
  import BaseModel, {
15
23
  DatabaseBaseModelType,
16
24
  } from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
25
+ import SortOrder from "../../../Types/BaseDatabase/SortOrder";
17
26
  import CustomFieldType from "../../../Types/CustomField/CustomFieldType";
18
- import {
19
- CustomFieldDropdownOption,
20
- parseCustomFieldDropdownOptions,
21
- } from "../../../Types/CustomField/CustomFieldDropdownOption";
22
27
  import {
23
28
  CustomFieldMappingSourceInfo,
24
29
  getCustomFieldMappingRelationSelect,
25
30
  getCustomFieldMappingSources,
26
31
  hasCustomFieldMappingSource,
27
32
  } from "../../../Types/CustomField/CustomFieldMappingCatalog";
28
- import Color from "../../../Types/Color";
29
33
  import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
30
34
  import { PromiseVoidFunction } from "../../../Types/FunctionTypes";
31
35
  import IconProp from "../../../Types/Icon/IconProp";
@@ -34,25 +38,6 @@ import ObjectID from "../../../Types/ObjectID";
34
38
  import React, { FunctionComponent, ReactElement, useState } from "react";
35
39
  import useAsyncEffect from "use-async-effect";
36
40
 
37
- const parseDropdownOptions: (value: unknown) => Array<DropdownOption> = (
38
- value: unknown,
39
- ): Array<DropdownOption> => {
40
- return parseCustomFieldDropdownOptions(value).map(
41
- (option: CustomFieldDropdownOption): DropdownOption => {
42
- const dropdownOption: DropdownOption = {
43
- label: option.value,
44
- value: option.value,
45
- };
46
-
47
- if (option.color) {
48
- dropdownOption.color = Color.fromString(option.color);
49
- }
50
-
51
- return dropdownOption;
52
- },
53
- );
54
- };
55
-
56
41
  export interface ComponentProps {
57
42
  title: string;
58
43
  description: string;
@@ -126,6 +111,16 @@ const CustomFieldsDetail: FunctionComponent<ComponentProps> = (
126
111
  const mappingSources: Array<CustomFieldMappingSourceInfo> =
127
112
  getCustomFieldMappingSources(new props.customFieldType().tableName!);
128
113
 
114
+ /*
115
+ * Only incident fields have an order today. The column is asked for only
116
+ * where the definition model has it: this card issues one select for
117
+ * whichever definition model it is handed, and a column missing from the
118
+ * model would fail that read for every other resource.
119
+ */
120
+ const hasSortOrder: boolean = new props.customFieldType().hasColumn(
121
+ "sortOrder",
122
+ );
123
+
129
124
  /*
130
125
  * A mapped field is a derived value, so it is shown rather than edited — but
131
126
  * only on records that actually have a source to derive it from. On a record
@@ -207,8 +202,9 @@ const CustomFieldsDetail: FunctionComponent<ComponentProps> = (
207
202
  dropdownOptions: true,
208
203
  mapFromResourceType: true,
209
204
  mapFromCustomFieldName: true,
205
+ ...(hasSortOrder ? { sortOrder: true } : {}),
210
206
  } as any,
211
- sort: {},
207
+ sort: (hasSortOrder ? { sortOrder: SortOrder.Ascending } : {}) as any,
212
208
  });
213
209
 
214
210
  /*
@@ -234,7 +230,19 @@ const CustomFieldsDetail: FunctionComponent<ComponentProps> = (
234
230
  select: itemSelect as any,
235
231
  });
236
232
 
237
- setSchemaList(schemaList.data);
233
+ /*
234
+ * Sorted here as well as by the query: the order has to hold for fields
235
+ * with no order too (last, in the order the server listed them).
236
+ */
237
+ setSchemaList(
238
+ hasSortOrder
239
+ ? sortCustomFieldDefinitions(
240
+ schemaList.data as Array<
241
+ BaseModel & { sortOrder?: number | null | undefined }
242
+ >,
243
+ )
244
+ : schemaList.data,
245
+ );
238
246
  setModel(item);
239
247
 
240
248
  if (props.onValuesLoaded) {
@@ -359,6 +367,36 @@ const CustomFieldsDetail: FunctionComponent<ComponentProps> = (
359
367
  ...(props.additionalButtons || []),
360
368
  ];
361
369
 
370
+ /*
371
+ * The stored values as the card draws them and the edit form starts from
372
+ * them: a text field's number or yes/no as text
373
+ * (getCustomFieldDisplayValue). The Markdown viewer draws nothing for a
374
+ * value that is not a string, and the Rich text editor fails on one, so a
375
+ * field switched from Number to Rich text could be neither seen nor
376
+ * edited. Every other value, and every key no field has, is as stored.
377
+ */
378
+ const getDisplayValues: () => JSONObject = (): JSONObject => {
379
+ const stored: JSONObject = ((model as any)?.["customFields"] ||
380
+ {}) as JSONObject;
381
+ const displayed: JSONObject = { ...stored };
382
+
383
+ for (const schemaItem of schemaList) {
384
+ const name: unknown = (schemaItem as any).name;
385
+
386
+ if (
387
+ typeof name === "string" &&
388
+ Object.prototype.hasOwnProperty.call(stored, name)
389
+ ) {
390
+ displayed[name] = getCustomFieldDisplayValue({
391
+ customFieldType: (schemaItem as any).customFieldType,
392
+ value: stored[name],
393
+ }) as JSONObject[string];
394
+ }
395
+ }
396
+
397
+ return displayed;
398
+ };
399
+
362
400
  return (
363
401
  <Card
364
402
  title={props.title}
@@ -389,7 +427,7 @@ const CustomFieldsDetail: FunctionComponent<ComponentProps> = (
389
427
  {!isLoading && !loadError && schemaList.length > 0 && model && (
390
428
  <Detail
391
429
  id={props.name}
392
- item={(model as any)["customFields"] || {}}
430
+ item={getDisplayValues()}
393
431
  fields={schemaList.map((schemaItem: BaseModel) => {
394
432
  const isDropdown: boolean =
395
433
  (schemaItem as any).customFieldType ===
@@ -401,9 +439,14 @@ const CustomFieldsDetail: FunctionComponent<ComponentProps> = (
401
439
  title: (schemaItem as any).name,
402
440
  description: getMappedDescription(schemaItem) as string,
403
441
  fieldType: (schemaItem as any).customFieldType,
442
+ contentClassName: getCustomFieldDetailContentClassName(
443
+ (schemaItem as any).customFieldType,
444
+ ),
404
445
  placeholder: "No data entered",
405
446
  dropdownOptions: isDropdown
406
- ? parseDropdownOptions((schemaItem as any).dropdownOptions)
447
+ ? getCustomFieldDropdownOptions(
448
+ (schemaItem as any).dropdownOptions,
449
+ )
407
450
  : undefined,
408
451
  };
409
452
  })}
@@ -421,7 +464,7 @@ const CustomFieldsDetail: FunctionComponent<ComponentProps> = (
421
464
  await onSave(data).catch();
422
465
  }}
423
466
  formProps={{
424
- initialValues: (model as any)?.["customFields"] || {},
467
+ initialValues: getDisplayValues(),
425
468
  /*
426
469
  * Mapped fields are left OUT of the form rather than rendered
427
470
  * disabled: `Field.disabled` is honoured by only three of the
@@ -432,32 +475,29 @@ const CustomFieldsDetail: FunctionComponent<ComponentProps> = (
432
475
  * from the record's existing bag — and the server re-applies the
433
476
  * mapping on update either way.
434
477
  */
435
- fields: schemaList
436
- .filter((schemaItem: BaseModel) => {
437
- return !isMappedAndInherited(schemaItem);
438
- })
439
- .map((schemaItem: BaseModel) => {
440
- const isDropdown: boolean =
441
- (schemaItem as any).customFieldType ===
442
- CustomFieldType.Dropdown ||
443
- (schemaItem as any).customFieldType ===
444
- CustomFieldType.MultiSelectDropdown;
445
- return {
446
- field: {
447
- [(schemaItem as any).name]: true,
478
+ /*
479
+ * Every field optional, "Required on create" included: that
480
+ * applies when an incident is declared, and fixing one field on
481
+ * an incident a monitor opened mid-outage must not demand all
482
+ * the others first.
483
+ */
484
+ fields: buildCustomFieldFormFields({
485
+ definitions: schemaList
486
+ .filter((schemaItem: BaseModel) => {
487
+ return !isMappedAndInherited(schemaItem);
488
+ })
489
+ .map((schemaItem: BaseModel) => {
490
+ return toCustomFieldFormDefinition(schemaItem);
491
+ })
492
+ .filter(
493
+ (
494
+ definition: CustomFieldFormDefinition | null,
495
+ ): definition is CustomFieldFormDefinition => {
496
+ return definition !== null;
448
497
  },
449
- title: (schemaItem as any).name,
450
- description: (schemaItem as any).description,
451
- fieldType: (schemaItem as any).customFieldType,
452
- required: false,
453
- placeholder: "",
454
- dropdownOptions: isDropdown
455
- ? parseDropdownOptions(
456
- (schemaItem as any).dropdownOptions,
457
- )
458
- : undefined,
459
- };
460
- }),
498
+ ),
499
+ enforceRequiredOnCreate: false,
500
+ }),
461
501
  }}
462
502
  />
463
503
  )}