@oneuptime/common 14.0.7 → 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.
- package/Models/DatabaseModels/Incident.ts +267 -1
- package/Models/DatabaseModels/IncidentCustomField.ts +202 -0
- package/Models/DatabaseModels/IncidentEpisode.ts +30 -0
- package/Models/DatabaseModels/IncidentTemplate.ts +126 -1
- package/Models/DatabaseModels/StatusPage.ts +55 -0
- package/Models/DatabaseModels/StatusPageSubscriber.ts +128 -0
- package/Server/API/IncidentAPI.ts +162 -0
- package/Server/API/StatusPageAPI.ts +487 -171
- package/Server/API/StatusPageSubscriberAPI.ts +63 -15
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.ts +49 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.ts +108 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.ts +51 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.ts +168 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.ts +44 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
- package/Server/Infrastructure/Semaphore.ts +10 -0
- package/Server/Middleware/IdentityRateLimit.ts +108 -3
- package/Server/Middleware/SubscriberNotificationPreviewRateLimit.ts +237 -0
- package/Server/Middleware/SubscriberNotificationTestSendRateLimit.ts +304 -0
- package/Server/Services/DatabaseService.ts +93 -10
- package/Server/Services/IncidentCustomFieldService.ts +276 -1
- package/Server/Services/IncidentEpisodePublicNoteService.ts +28 -0
- package/Server/Services/IncidentEpisodeService.ts +15 -0
- package/Server/Services/IncidentEpisodeStateTimelineService.ts +27 -1
- package/Server/Services/IncidentPublicNoteService.ts +30 -1
- package/Server/Services/IncidentService.ts +1535 -65
- package/Server/Services/IncidentStateTimelineService.ts +13 -0
- package/Server/Services/IncidentTemplateService.ts +109 -0
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +30 -1
- package/Server/Services/ScheduledMaintenanceService.ts +68 -18
- package/Server/Services/SmsService.ts +10 -0
- package/Server/Services/StatusPageService.ts +65 -8
- package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +299 -37
- package/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.ts +129 -0
- package/Server/Services/StatusPageSubscriberService.ts +1161 -64
- package/Server/Types/Markdown.ts +153 -6
- package/Server/Types/Workflow/Components/Email.ts +61 -2
- package/Server/Utils/CustomField/CustomFieldRename.ts +378 -0
- package/Server/Utils/DataSource/EgressGuard.ts +66 -21
- package/Server/Utils/Mail/PinnedSmtpSocket.ts +130 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +10 -0
- package/Server/Utils/SSRFProtection.ts +76 -16
- package/Server/Utils/StatusPage/IncidentStatusPageScope.ts +948 -0
- package/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.ts +656 -0
- package/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.ts +805 -0
- package/Server/Utils/StatusPage/StatusPageExclusion.ts +18 -0
- package/Server/Utils/StatusPage/StatusPageReadAccess.ts +125 -0
- package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.ts +151 -0
- package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.ts +70 -0
- package/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.ts +421 -0
- package/Server/Utils/StatusPage/SubscriberNotificationClaim.ts +107 -0
- package/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.ts +1049 -0
- package/Server/Utils/StatusPage/SubscriberNotificationFanOut.ts +180 -0
- package/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.ts +839 -0
- package/Server/Utils/StatusPage/SubscriberNotificationResendAccess.ts +393 -0
- package/Server/Utils/StatusPage/SubscriberNotificationRunLimit.ts +246 -0
- package/Server/Utils/StatusPage/SubscriberNotificationTiming.ts +133 -0
- package/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.ts +215 -0
- package/Server/Utils/StatusPageResource.ts +51 -20
- package/Server/Utils/VM/VMAPI.ts +1 -0
- package/Server/Utils/VM/VMRunner.ts +10 -0
- package/Server/Utils/Workflow/OAuth2TokenClient.ts +10 -0
- package/Server/Views/Partials/SensitiveUrlToken.ejs +8 -5
- package/Tests/App/Accounts/RegisterVerifyEmail.test.tsx +748 -0
- package/Tests/App/Accounts/ResendVerificationEmail.test.tsx +1222 -0
- package/Tests/App/Accounts/VerificationEmailResendUtils.test.ts +797 -0
- package/Tests/App/Accounts/VerifyEmailPending.test.tsx +538 -0
- package/Tests/App/Accounts/VerifyEmailResend.test.tsx +779 -0
- package/Tests/App/Dashboard/CustomFieldsSettingsIncidentOptions.test.tsx +357 -0
- package/Tests/App/Dashboard/EventNotes.test.tsx +776 -0
- package/Tests/App/Dashboard/EventNotesPages.test.tsx +119 -0
- package/Tests/App/Dashboard/EventNotesUtil.test.ts +116 -17
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +242 -5
- package/Tests/App/Dashboard/IncidentChangeStateNotifyDefault.test.tsx +91 -1
- package/Tests/App/Dashboard/IncidentCreateDetailsStep.test.tsx +643 -0
- package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +8 -1
- package/Tests/App/Dashboard/IncidentCreateStatusPageScope.test.tsx +601 -0
- package/Tests/App/Dashboard/IncidentCustomFieldTemplateVariables.test.tsx +386 -0
- package/Tests/App/Dashboard/IncidentNoteTemplatePlaceholders.test.tsx +124 -0
- package/Tests/App/Dashboard/IncidentNoteTemplateVariablesLoader.test.ts +305 -0
- package/Tests/App/Dashboard/IncidentOverviewNotifyDefault.test.tsx +112 -0
- package/Tests/App/Dashboard/IncidentSettingsRenotifyOnPublish.test.tsx +674 -0
- package/Tests/App/Dashboard/IncidentSettingsStatusPageScope.test.tsx +1051 -0
- package/Tests/App/Dashboard/IncidentTemplateCustomFields.test.tsx +384 -0
- package/Tests/App/Dashboard/IncidentTemplateStatusPageScopeCard.test.tsx +215 -0
- package/Tests/App/Dashboard/PublicNotePagesNotifyDefault.test.tsx +113 -1
- package/Tests/App/Dashboard/SubscriberAudienceSummary.test.tsx +512 -0
- package/Tests/App/Dashboard/SubscriberNotificationPreviewModal.test.tsx +837 -0
- package/Tests/App/Dashboard/SubscriberNotificationStatusLabel.test.tsx +88 -0
- package/Tests/App/Dashboard/SubscriberNotificationStatusResend.test.tsx +473 -0
- package/Tests/App/Dashboard/SubscriberTemplateLivePreview.test.tsx +196 -0
- package/Tests/App/Dashboard/TeamAddedSubscribersUnsubscribedNotice.test.tsx +248 -0
- package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +64 -3
- package/Tests/App/StatusPage/StatusPageUnsubscribePage.test.tsx +412 -0
- package/Tests/Models/IncidentCustomFieldApiSchemaContract.test.ts +217 -0
- package/Tests/Models/IncidentCustomFieldCreateSettingsColumns.test.ts +252 -0
- package/Tests/Models/StatusPageSubscriberUnsubscribeColumns.test.ts +218 -0
- package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +7 -0
- package/Tests/Server/API/IncidentSubscriberAudienceAPI.test.ts +1408 -0
- package/Tests/Server/API/StatusPageIncidentScope.test.ts +1868 -0
- package/Tests/Server/API/StatusPageIncidentScopePostgres.test.ts +790 -0
- package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +10 -1
- package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +206 -18
- package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +14 -2
- package/Tests/Server/API/StatusPageSubscriberCreateResponse.test.ts +217 -0
- package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +103 -2
- package/Tests/Server/API/StatusPageUnsubscribeAPI.test.ts +396 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentStatusPageScopeMigration.test.ts +395 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentTemplateStatusPageScopeFlagMigration.test.ts +150 -0
- package/Tests/Server/Infrastructure/Postgres/AddSubscriberNotificationClaimedAtMigration.test.ts +156 -0
- package/Tests/Server/Infrastructure/Postgres/SkipHiddenIncidentCreatedNotificationsMigration.test.ts +410 -0
- package/Tests/Server/Middleware/IdentityRateLimit.test.ts +551 -1
- package/Tests/Server/Middleware/SubscriberNotificationPreviewRateLimit.test.ts +238 -0
- package/Tests/Server/Middleware/SubscriberNotificationTestSendRateLimit.test.ts +245 -0
- package/Tests/Server/Services/AddStatusPageSubscriberUnsubscribeTokenMigration.test.ts +152 -0
- package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +221 -36
- package/Tests/Server/Services/DatabaseServiceCompareAndSetColumns.test.ts +191 -0
- package/Tests/Server/Services/IncidentCreatedRenotifyOnPublish.test.ts +681 -0
- package/Tests/Server/Services/IncidentCreatedResend.test.ts +775 -0
- package/Tests/Server/Services/IncidentCustomFieldRenamePostgres.test.ts +713 -0
- package/Tests/Server/Services/IncidentCustomFieldService.test.ts +751 -0
- package/Tests/Server/Services/IncidentCustomFieldValueValidation.test.ts +556 -0
- package/Tests/Server/Services/IncidentStatusPageScope.test.ts +2971 -0
- package/Tests/Server/Services/IncidentStatusPageScopeFeed.test.ts +131 -0
- package/Tests/Server/Services/IncidentStatusPageScopePostgres.test.ts +625 -0
- package/Tests/Server/Services/IncidentTemplateCustomFieldsCopy.test.ts +311 -0
- package/Tests/Server/Services/IncidentTemplateStatusPageScope.test.ts +363 -0
- package/Tests/Server/Services/PublicNoteEditFeedEventType.test.ts +213 -0
- package/Tests/Server/Services/PublicNoteResendAccess.test.ts +994 -0
- package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +289 -9
- package/Tests/Server/Services/SmsServiceFailIfNotSent.test.ts +67 -0
- package/Tests/Server/Services/StatusPageReportIncidentCounts.test.ts +610 -0
- package/Tests/Server/Services/StatusPageSubscriberAudienceCounts.test.ts +201 -0
- package/Tests/Server/Services/StatusPageSubscriberAudienceCountsPostgres.test.ts +271 -0
- package/Tests/Server/Services/StatusPageSubscriberConfirmationTemplateEscaping.test.ts +200 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationLogRedaction.test.ts +54 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateCompile.test.ts +37 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateIncidentRecordAccess.test.ts +772 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookup.test.ts +506 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookupPostgres.test.ts +261 -0
- package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +21 -5
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribe.test.ts +1618 -0
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribeLinkSenders.test.ts +373 -0
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribePostgres.test.ts +388 -0
- package/Tests/Server/Services/SubscriberNotificationInFlightRequeue.test.ts +500 -0
- package/Tests/Server/Types/MarkdownEmailLinks.test.ts +320 -0
- package/Tests/Server/Types/Workflow/Components/Email.test.ts +491 -1
- package/Tests/Server/Types/Workflow/Components/EmailSmtpPinning.test.ts +398 -0
- package/Tests/Server/Utils/CustomField/CustomFieldRename.test.ts +586 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +246 -10
- package/Tests/Server/Utils/DataSource/EgressGuardDeploymentConfig.test.ts +226 -0
- package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +131 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +4 -0
- package/Tests/Server/Utils/EgressPolicyEnvironment.ts +45 -0
- package/Tests/Server/Utils/Mail/PinnedSmtpSocket.test.ts +409 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +23 -0
- package/Tests/Server/Utils/SSRFProtection.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionCloudServiceAddresses.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionPrivateNetwork.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionResolutionDetail.test.ts +314 -0
- package/Tests/Server/Utils/StatusPage/IncidentStatusPageScope.test.ts +1699 -0
- package/Tests/Server/Utils/StatusPage/IncidentStatusPageScopeQueriesPostgres.test.ts +508 -0
- package/Tests/Server/Utils/StatusPage/IncidentSubscriberAudienceCallerPermission.test.ts +246 -0
- package/Tests/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.test.ts +1348 -0
- package/Tests/Server/Utils/StatusPage/StatusPageReadAccess.test.ts +221 -0
- package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.test.ts +132 -0
- package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.test.ts +155 -0
- package/Tests/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.test.ts +708 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaim.test.ts +255 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaimPostgres.test.ts +528 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.test.ts +1238 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationFanOut.test.ts +472 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.test.ts +1168 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationRunLimit.test.ts +275 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationTiming.test.ts +131 -0
- package/Tests/Server/Utils/StatusPageResource.test.ts +98 -0
- package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +17 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +75 -0
- package/Tests/Types/CustomField/CustomFieldSavedViews.test.ts +247 -0
- package/Tests/Types/CustomField/CustomFieldTemplateValues.test.ts +186 -0
- package/Tests/Types/CustomField/CustomFieldTypeCorrespondence.test.ts +48 -0
- package/Tests/Types/CustomField/CustomFieldValueFormat.test.ts +215 -0
- package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +343 -0
- package/Tests/Types/CustomField/CustomFieldVariableKey.test.ts +364 -0
- package/Tests/Types/SafeHtml.test.ts +102 -0
- package/Tests/Types/StatusPage/IncidentCreatedRenotify.test.ts +419 -0
- package/Tests/Types/StatusPage/IncidentCreatedResend.test.ts +118 -0
- package/Tests/Types/StatusPage/IncidentScopeAddedPagesNotification.test.ts +558 -0
- package/Tests/Types/StatusPage/IncidentSubscriberAudience.test.ts +284 -0
- package/Tests/Types/StatusPage/StatusPageSubscriberUnsubscribe.test.ts +341 -0
- package/Tests/Types/StatusPage/SubscriberNotificationPreview.test.ts +196 -0
- package/Tests/Types/StatusPage/SubscriberNotificationResend.test.ts +201 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateCompiler.test.ts +277 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplatePreview.test.ts +179 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +324 -0
- package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +60 -13
- package/Tests/UI/Components/CustomFields/CustomFieldFormFields.test.ts +432 -0
- package/Tests/UI/Components/CustomFields/CustomFieldModelFormFields.test.tsx +685 -0
- package/Tests/UI/Components/CustomFields/CustomFieldsDetailOrder.test.tsx +469 -0
- package/Tests/UI/Components/Forms/ModelFormCustomFieldInputs.test.tsx +325 -0
- package/Tests/UI/Components/Forms/ModelFormDropdownOptionsRefused.test.tsx +358 -0
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +22 -0
- package/Tests/UI/Monitor/NetworkPathView.test.tsx +289 -0
- package/Tests/Utils/Incident/IncidentNoteTemplateVariables.test.ts +623 -0
- package/Tests/Utils/Markdown/MarkdownEscape.test.ts +89 -0
- package/Tests/Utils/ProbeNetworkFailureUtil.test.ts +992 -0
- package/Tests/Utils/RequestFailedDetails.test.ts +575 -0
- package/Types/CustomField/CustomFieldOrder.ts +55 -0
- package/Types/CustomField/CustomFieldSavedViews.ts +225 -0
- package/Types/CustomField/CustomFieldTemplateMerge.ts +71 -0
- package/Types/CustomField/CustomFieldType.ts +14 -0
- package/Types/CustomField/CustomFieldValueFormat.ts +161 -0
- package/Types/CustomField/CustomFieldValueValidator.ts +488 -0
- package/Types/CustomField/CustomFieldVariableKey.ts +211 -0
- package/Types/SafeHtml.ts +93 -0
- package/Types/StatusPage/IncidentCreatedRenotify.ts +224 -0
- package/Types/StatusPage/IncidentCreatedResend.ts +108 -0
- package/Types/StatusPage/IncidentScopeAddedPagesNotification.ts +343 -0
- package/Types/StatusPage/IncidentSubscriberAudience.ts +332 -0
- package/Types/StatusPage/StatusPageSubscriberUnsubscribe.ts +405 -0
- package/Types/StatusPage/SubscriberNotificationInterruption.ts +32 -0
- package/Types/StatusPage/SubscriberNotificationPreview.ts +322 -0
- package/Types/StatusPage/SubscriberNotificationResend.ts +132 -0
- package/Types/StatusPage/SubscriberNotificationTemplateCompiler.ts +180 -0
- package/Types/StatusPage/SubscriberNotificationTemplatePreview.ts +301 -0
- package/Types/StatusPage/SubscriberNotificationTemplateVariables.ts +217 -4
- package/Types/StatusPage/SubscriberUpdateNotification.ts +32 -11
- package/UI/Components/CustomFields/CustomFieldFormFields.ts +317 -0
- package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +395 -0
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +95 -55
- package/UI/Components/Forms/ModelForm.tsx +70 -8
- package/UI/Components/Forms/Validation.ts +1 -1
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +2 -4
- package/UI/Components/ModelTable/AnalyticsModelTable.tsx +2 -6
- package/UI/Components/ModelTable/BaseModelTable.tsx +9 -8
- package/UI/Components/ModelTable/CustomFieldColumns.tsx +14 -1
- package/UI/Components/ModelTable/ModelTable.tsx +6 -7
- package/UI/Utils/SensitiveUrlToken.ts +10 -5
- package/Utils/API.ts +247 -2
- package/Utils/Incident/IncidentNoteTemplateVariables.ts +304 -0
- package/Utils/Markdown/MarkdownEscape.ts +65 -0
- package/Utils/ProbeNetworkFailureUtil.ts +673 -0
- package/build/dist/Models/DatabaseModels/Incident.js +267 -1
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js +207 -1
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +31 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +124 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +56 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +131 -0
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +100 -1
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +417 -176
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageSubscriberAPI.js +52 -13
- package/build/dist/Server/API/StatusPageSubscriberAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js +57 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js +89 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js +29 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +3 -0
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Middleware/IdentityRateLimit.js +89 -3
- package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
- package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js +149 -0
- package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js +190 -0
- package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js.map +1 -0
- package/build/dist/Server/Services/DatabaseService.js +56 -7
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentCustomFieldService.js +204 -8
- package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +24 -0
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +14 -0
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +26 -0
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +26 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +1052 -0
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +12 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +83 -0
- package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +26 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +47 -17
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/SmsService.js +2 -22
- package/build/dist/Server/Services/SmsService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +47 -9
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +237 -32
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js +109 -0
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +925 -99
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +110 -6
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Email.js +55 -6
- package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
- package/build/dist/Server/Utils/CustomField/CustomFieldRename.js +211 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldRename.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +41 -12
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js +101 -0
- package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +9 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +48 -6
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js +631 -0
- package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js +403 -0
- package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js +451 -0
- package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js +13 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js +91 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js +101 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js +47 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js +273 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js +73 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js +722 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js +102 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js +527 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js +278 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js +137 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js +103 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js +114 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPageResource.js +39 -7
- package/build/dist/Server/Utils/StatusPageResource.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +1 -0
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js +3 -0
- package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldOrder.js +36 -0
- package/build/dist/Types/CustomField/CustomFieldOrder.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldSavedViews.js +135 -0
- package/build/dist/Types/CustomField/CustomFieldSavedViews.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js +27 -0
- package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldType.js +12 -0
- package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldValueFormat.js +126 -0
- package/build/dist/Types/CustomField/CustomFieldValueFormat.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js +280 -0
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldVariableKey.js +150 -0
- package/build/dist/Types/CustomField/CustomFieldVariableKey.js.map +1 -0
- package/build/dist/Types/SafeHtml.js +84 -0
- package/build/dist/Types/SafeHtml.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js +117 -0
- package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentCreatedResend.js +86 -0
- package/build/dist/Types/StatusPage/IncidentCreatedResend.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js +246 -0
- package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js +183 -0
- package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js +277 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js +27 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js +190 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationResend.js +102 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationResend.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js +97 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js +175 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js +144 -4
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js.map +1 -1
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js +29 -9
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js +169 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js.map +1 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +212 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +64 -49
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +39 -5
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Validation.js +1 -1
- package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/AnalyticsModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +2 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +13 -1
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
- package/build/dist/UI/Utils/SensitiveUrlToken.js +10 -5
- package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -1
- package/build/dist/Utils/API.js +177 -1
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js +155 -0
- package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js.map +1 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js +48 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js.map +1 -1
- package/build/dist/Utils/ProbeNetworkFailureUtil.js +460 -0
- package/build/dist/Utils/ProbeNetworkFailureUtil.js.map +1 -0
- 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
|
-
|
|
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={(
|
|
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
|
-
?
|
|
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: (
|
|
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
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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
|
-
|
|
450
|
-
|
|
451
|
-
|
|
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
|
)}
|