@oneuptime/common 12.0.13 → 12.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
- package/Models/DatabaseModels/UserCall.ts +94 -3
- package/Models/DatabaseModels/UserEmail.ts +94 -3
- package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
- package/Models/DatabaseModels/UserPush.ts +37 -0
- package/Models/DatabaseModels/UserSMS.ts +94 -3
- package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
- package/Server/API/BaseAPI.ts +79 -14
- package/Server/API/UserCallAPI.ts +53 -45
- package/Server/API/UserEmailAPI.ts +53 -44
- package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
- package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
- package/Server/API/UserPushAPI.ts +126 -2
- package/Server/API/UserSmsAPI.ts +53 -44
- package/Server/API/UserWhatsAppAPI.ts +53 -50
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
- package/Server/Services/AnalyticsDatabaseService.ts +169 -0
- package/Server/Services/DatabaseService.ts +101 -0
- package/Server/Services/LogAggregationService.ts +5 -0
- package/Server/Services/PushNotificationService.ts +127 -12
- package/Server/Services/TeamMemberService.ts +53 -13
- package/Server/Services/UserCallService.ts +55 -24
- package/Server/Services/UserEmailService.ts +83 -17
- package/Server/Services/UserIncomingCallNumberService.ts +49 -85
- package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
- package/Server/Services/UserNotificationRuleService.ts +26 -0
- package/Server/Services/UserPushService.ts +89 -0
- package/Server/Services/UserSmsService.ts +50 -17
- package/Server/Services/UserWhatsAppService.ts +48 -15
- package/Server/Types/Database/QueryHelper.ts +30 -0
- package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
- package/Server/Utils/ChannelVerification.ts +510 -0
- package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +13 -16
- package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
- package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
- package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
- package/Server/Utils/TotpAuth.ts +137 -9
- package/Server/Utils/UserRegistrationToken.ts +182 -0
- package/Server/Utils/VerificationCode.ts +134 -0
- package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
- package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
- package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +28 -0
- package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
- package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
- package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
- package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
- package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
- package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
- package/Tests/Server/API/UserSmsApi.test.ts +107 -14
- package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
- package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +315 -0
- package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
- package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +10 -62
- package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
- package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
- package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
- package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
- package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
- package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
- package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
- package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
- package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
- package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
- package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
- package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
- package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
- package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
- package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
- package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
- package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
- package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
- package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
- package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
- package/Tests/Server/Utils/Browser.test.ts +162 -0
- package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
- package/Tests/Server/Utils/Express.test.ts +371 -0
- package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
- package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
- package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
- package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
- package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
- package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
- package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
- package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
- package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
- package/Tests/Types/Call/CallRequest.test.ts +189 -0
- package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
- package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
- package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
- package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
- package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
- package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
- package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
- package/Tests/Types/TextRandomGeneration.test.ts +211 -0
- package/Tests/UI/Components/Button.test.tsx +175 -1
- package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
- package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
- package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
- package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
- package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
- package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
- package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
- package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
- package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
- package/Tests/UI/Components/List.test.tsx +9 -2
- package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
- package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
- package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
- package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
- package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
- package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
- package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
- package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
- package/Tests/UI/Components/Skeleton.test.tsx +71 -0
- package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
- package/Tests/UI/Components/Tabs.test.tsx +24 -0
- package/Tests/UI/Components/Toast.test.tsx +130 -7
- package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
- package/Tests/UI/Utils/Dropdown.test.ts +423 -0
- package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
- package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
- package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
- package/Tests/Utils/API.test.ts +16 -2
- package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
- package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
- package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
- package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
- package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
- package/Types/Permission.ts +35 -0
- package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
- package/Types/PushNotification/PushNotificationMessage.ts +15 -0
- package/Types/PushNotification/PushNotificationRequest.ts +8 -16
- package/Types/Service/ServiceLanguage.ts +144 -0
- package/Types/Text.ts +111 -19
- package/UI/Components/Button/Button.tsx +27 -14
- package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
- package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
- package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
- package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
- package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
- package/UI/Components/CommandPalette/Types.ts +49 -0
- package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
- package/UI/Components/Dropdown/Dropdown.tsx +6 -1
- package/UI/Components/Feed/FeedItem.tsx +1 -1
- package/UI/Components/List/List.tsx +37 -5
- package/UI/Components/List/ListSkeleton.tsx +54 -0
- package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +6 -1
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
- package/UI/Components/Modal/Modal.tsx +2 -2
- package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
- package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
- package/UI/Components/Navbar/NavBar.tsx +14 -1
- package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
- package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
- package/UI/Components/SideOver/SideOver.tsx +37 -2
- package/UI/Components/Skeleton/Skeleton.tsx +53 -0
- package/UI/Components/Table/Table.tsx +74 -44
- package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
- package/UI/Components/Tabs/Tab.tsx +1 -1
- package/UI/Components/Toast/Toast.tsx +118 -53
- package/UI/Components/Toast/ToastInit.tsx +82 -32
- package/UI/Styles/Theme.css +40 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
- package/UI/Utils/ModelListCache.ts +188 -0
- package/UI/Utils/Project.ts +29 -0
- package/Utils/API.ts +6 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
- package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
- package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
- package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
- package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +69 -13
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/UserCallAPI.js +42 -38
- package/build/dist/Server/API/UserCallAPI.js.map +1 -1
- package/build/dist/Server/API/UserEmailAPI.js +42 -38
- package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
- package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
- package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
- package/build/dist/Server/API/UserPushAPI.js +95 -2
- package/build/dist/Server/API/UserPushAPI.js.map +1 -1
- package/build/dist/Server/API/UserSmsAPI.js +42 -38
- package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
- package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
- package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
- package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +74 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +5 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/PushNotificationService.js +69 -30
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +43 -7
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/UserCallService.js +54 -22
- package/build/dist/Server/Services/UserCallService.js.map +1 -1
- package/build/dist/Server/Services/UserEmailService.js +78 -17
- package/build/dist/Server/Services/UserEmailService.js.map +1 -1
- package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
- package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
- package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserPushService.js +77 -0
- package/build/dist/Server/Services/UserPushService.js.map +1 -1
- package/build/dist/Server/Services/UserSmsService.js +50 -17
- package/build/dist/Server/Services/UserSmsService.js.map +1 -1
- package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
- package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
- package/build/dist/Server/Utils/ChannelVerification.js +348 -0
- package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +13 -12
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/TotpAuth.js +127 -8
- package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
- package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
- package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
- package/build/dist/Server/Utils/VerificationCode.js +120 -0
- package/build/dist/Server/Utils/VerificationCode.js.map +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
- package/build/dist/Types/Permission.js +33 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
- package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
- package/build/dist/Types/Service/ServiceLanguage.js +96 -0
- package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
- package/build/dist/Types/Text.js +82 -17
- package/build/dist/Types/Text.js.map +1 -1
- package/build/dist/UI/Components/Button/Button.js +22 -14
- package/build/dist/UI/Components/Button/Button.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
- package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
- package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
- package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
- package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
- package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
- package/build/dist/UI/Components/List/List.js +19 -5
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
- package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +2 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
- package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
- package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +35 -24
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
- package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
- package/build/dist/UI/Components/Tabs/Tab.js +1 -1
- package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
- package/build/dist/UI/Components/Toast/Toast.js +77 -23
- package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
- package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
- package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/ModelListCache.js +126 -0
- package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
- package/build/dist/UI/Utils/Project.js +24 -1
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/build/dist/Utils/API.js +6 -1
- package/build/dist/Utils/API.js.map +1 -1
- package/jest.config.json +1 -1
- package/package.json +2 -3
- package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
- package/Tests/__mocks__/otpauth.js +0 -30
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { GetReactElementFunction } from "../../Types/FunctionTypes";
|
|
2
2
|
import ActionButtonSchema from "../ActionButton/ActionButtonSchema";
|
|
3
|
-
import ComponentLoader from "../ComponentLoader/ComponentLoader";
|
|
4
3
|
import Field from "../Detail/Field";
|
|
5
4
|
import ErrorMessage from "../ErrorMessage/ErrorMessage";
|
|
6
5
|
import FilterViewer from "../Filters/FilterViewer";
|
|
@@ -8,6 +7,7 @@ import FilterType from "../Filters/Types/Filter";
|
|
|
8
7
|
import FilterData from "../Filters/Types/FilterData";
|
|
9
8
|
import Pagination from "../Pagination/Pagination";
|
|
10
9
|
import ListBody from "./ListBody";
|
|
10
|
+
import ListSkeleton from "./ListSkeleton";
|
|
11
11
|
import { ListDetailProps } from "./ListRow";
|
|
12
12
|
import GenericObject from "../../../Types/GenericObject";
|
|
13
13
|
import React, { ReactElement } from "react";
|
|
@@ -67,12 +67,30 @@ type ListFunction = <T extends GenericObject>(
|
|
|
67
67
|
const List: ListFunction = <T extends GenericObject>(
|
|
68
68
|
props: ComponentProps<T>,
|
|
69
69
|
): ReactElement => {
|
|
70
|
+
/*
|
|
71
|
+
* A refetch with cards already on screen (pagination, sort, refresh - the
|
|
72
|
+
* parent never clears `data` while fetching) keeps those cards visible and
|
|
73
|
+
* dims them; skeletons are only for a load with nothing to show yet.
|
|
74
|
+
*/
|
|
75
|
+
const isRefetchingWithData: boolean =
|
|
76
|
+
props.isLoading && props.data.length > 0;
|
|
77
|
+
|
|
70
78
|
const getListbody: GetReactElementFunction = (): ReactElement => {
|
|
71
|
-
if (props.isLoading) {
|
|
72
|
-
return
|
|
79
|
+
if (props.isLoading && props.data.length === 0) {
|
|
80
|
+
return (
|
|
81
|
+
<ListSkeleton
|
|
82
|
+
fieldsCount={props.fields.length}
|
|
83
|
+
itemsOnPage={props.itemsOnPage}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
73
86
|
}
|
|
74
87
|
|
|
75
|
-
|
|
88
|
+
/*
|
|
89
|
+
* Loading still wins over error and empty (same priority as before the
|
|
90
|
+
* skeletons): while a refetch is in flight the stale cards render, never
|
|
91
|
+
* a stale error or a premature "no items".
|
|
92
|
+
*/
|
|
93
|
+
if (!props.isLoading && props.error) {
|
|
76
94
|
return (
|
|
77
95
|
<div className="p-6">
|
|
78
96
|
<ErrorMessage
|
|
@@ -145,7 +163,21 @@ const List: ListFunction = <T extends GenericObject>(
|
|
|
145
163
|
}
|
|
146
164
|
}}
|
|
147
165
|
>
|
|
148
|
-
{
|
|
166
|
+
{/*
|
|
167
|
+
* Dims the stale cards while a refetch is in flight and blocks
|
|
168
|
+
* clicks on them - actions against data about to be replaced
|
|
169
|
+
* are a race.
|
|
170
|
+
*/}
|
|
171
|
+
<div
|
|
172
|
+
data-testid="list-content"
|
|
173
|
+
className={
|
|
174
|
+
isRefetchingWithData
|
|
175
|
+
? "opacity-60 pointer-events-none transition-opacity duration-150"
|
|
176
|
+
: "transition-opacity duration-150"
|
|
177
|
+
}
|
|
178
|
+
>
|
|
179
|
+
{getListbody()}
|
|
180
|
+
</div>
|
|
149
181
|
</DragDropContext>
|
|
150
182
|
{!props.disablePagination && (
|
|
151
183
|
<div className="mt-5 -mb-6">
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import Skeleton from "../Skeleton/Skeleton";
|
|
2
|
+
import React, { FunctionComponent, ReactElement } from "react";
|
|
3
|
+
|
|
4
|
+
export interface ComponentProps {
|
|
5
|
+
/*
|
|
6
|
+
* One placeholder line per field the real ListRow will render, so the
|
|
7
|
+
* cards are the right height before the data arrives.
|
|
8
|
+
*/
|
|
9
|
+
fieldsCount: number;
|
|
10
|
+
itemsOnPage: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* Card-shaped placeholders for the list's first load, matching ListBody's
|
|
15
|
+
* wrapper (space-y-6 p-6 border-t) so nothing shifts when real rows land.
|
|
16
|
+
*/
|
|
17
|
+
const ListSkeleton: FunctionComponent<ComponentProps> = (
|
|
18
|
+
props: ComponentProps,
|
|
19
|
+
): ReactElement => {
|
|
20
|
+
// Enough cards to look like a page without painting offscreen ones.
|
|
21
|
+
const cardCount: number = Math.max(1, Math.min(props.itemsOnPage || 0, 6));
|
|
22
|
+
const cardIndexes: Array<number> = Array.from(Array(cardCount).keys());
|
|
23
|
+
const lineIndexes: Array<number> = Array.from(
|
|
24
|
+
Array(Math.max(1, props.fieldsCount)).keys(),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
data-testid="list-skeleton-loader"
|
|
30
|
+
role="status"
|
|
31
|
+
aria-live="polite"
|
|
32
|
+
className="space-y-6 p-6 border-t border-gray-200"
|
|
33
|
+
>
|
|
34
|
+
<span className="sr-only">Loading...</span>
|
|
35
|
+
{cardIndexes.map((cardIndex: number) => {
|
|
36
|
+
return (
|
|
37
|
+
<div key={cardIndex} className="space-y-3">
|
|
38
|
+
{lineIndexes.map((lineIndex: number) => {
|
|
39
|
+
return (
|
|
40
|
+
<Skeleton
|
|
41
|
+
key={lineIndex}
|
|
42
|
+
className="h-4"
|
|
43
|
+
widthVariantIndex={cardIndex + lineIndex}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
})}
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
})}
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default ListSkeleton;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Type-only on purpose: the sole static edge to MarkdownViewer must be
|
|
3
|
+
* erasable, so the viewer (and the mermaid chunk it lazily pulls) stays out
|
|
4
|
+
* of every eager bundle that imports this wrapper.
|
|
5
|
+
*/
|
|
6
|
+
import type { ComponentProps } from "./MarkdownViewer";
|
|
2
7
|
import React, {
|
|
3
8
|
FunctionComponent,
|
|
4
9
|
LazyExoticComponent,
|
|
@@ -76,7 +76,6 @@ SyntaxHighlighter.registerLanguage("ruby", ruby);
|
|
|
76
76
|
SyntaxHighlighter.registerLanguage("php", php);
|
|
77
77
|
SyntaxHighlighter.registerLanguage("graphql", graphql);
|
|
78
78
|
SyntaxHighlighter.registerLanguage("http", http);
|
|
79
|
-
import mermaid from "mermaid";
|
|
80
79
|
import DOMPurify from "dompurify";
|
|
81
80
|
import OneUptimeDate from "../../../Types/Date";
|
|
82
81
|
import { Theme, useTheme } from "../../Utils/Theme";
|
|
@@ -90,7 +89,48 @@ import { Theme, useTheme } from "../../Utils/Theme";
|
|
|
90
89
|
const ISO_8601_REGEX: RegExp =
|
|
91
90
|
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?Z$/;
|
|
92
91
|
|
|
93
|
-
|
|
92
|
+
/*
|
|
93
|
+
* mermaid's pre-bundled build is ~4.5MB — by far the heaviest dependency of
|
|
94
|
+
* this component — so it is loaded on demand the first time a mermaid fence
|
|
95
|
+
* actually renders. Plain markdown (the overwhelmingly common case) never
|
|
96
|
+
* pays for it: there is no static import and no module-scope initialization.
|
|
97
|
+
* The promise is cached module-wide so multiple diagrams share one load, and
|
|
98
|
+
* theme setup runs only after the load resolves.
|
|
99
|
+
*/
|
|
100
|
+
type MermaidApi = typeof import("mermaid").default;
|
|
101
|
+
|
|
102
|
+
let mermaidLoadPromise: Promise<MermaidApi> | null = null;
|
|
103
|
+
|
|
104
|
+
const loadMermaid: () => Promise<MermaidApi> = (): Promise<MermaidApi> => {
|
|
105
|
+
if (!mermaidLoadPromise) {
|
|
106
|
+
const loadPromise: Promise<MermaidApi> = import("mermaid").then(
|
|
107
|
+
(mermaidModule: { default: MermaidApi }): MermaidApi => {
|
|
108
|
+
return mermaidModule.default;
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
mermaidLoadPromise = loadPromise;
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
* A failed chunk load (flaky network, deploy rotating hashed chunk
|
|
116
|
+
* names) must not be cached forever — clear the slot so the next
|
|
117
|
+
* diagram retries the import. The reset rides a side branch of the
|
|
118
|
+
* promise: the original is still returned below, so the caller that
|
|
119
|
+
* triggered this load sees the rejection through its own error path.
|
|
120
|
+
*/
|
|
121
|
+
loadPromise.catch((): void => {
|
|
122
|
+
if (mermaidLoadPromise === loadPromise) {
|
|
123
|
+
mermaidLoadPromise = null;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return mermaidLoadPromise;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const initializeMermaid: (mermaid: MermaidApi, theme: Theme) => void = (
|
|
131
|
+
mermaid: MermaidApi,
|
|
132
|
+
theme: Theme,
|
|
133
|
+
): void => {
|
|
94
134
|
const isDark: boolean = theme === Theme.Dark;
|
|
95
135
|
|
|
96
136
|
mermaid.initialize({
|
|
@@ -120,10 +160,8 @@ const initializeMermaid: (theme: Theme) => void = (theme: Theme): void => {
|
|
|
120
160
|
});
|
|
121
161
|
};
|
|
122
162
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
// Mermaid diagram component
|
|
126
|
-
const MermaidDiagram: FunctionComponent<{ chart: string }> = ({
|
|
163
|
+
// Mermaid diagram component (exported so tests can exercise the lazy load directly)
|
|
164
|
+
export const MermaidDiagram: FunctionComponent<{ chart: string }> = ({
|
|
127
165
|
chart,
|
|
128
166
|
}: {
|
|
129
167
|
chart: string;
|
|
@@ -136,27 +174,34 @@ const MermaidDiagram: FunctionComponent<{ chart: string }> = ({
|
|
|
136
174
|
let isCancelled: boolean = false;
|
|
137
175
|
|
|
138
176
|
const renderDiagram: () => Promise<void> = async (): Promise<void> => {
|
|
139
|
-
|
|
177
|
+
try {
|
|
178
|
+
/*
|
|
179
|
+
* Dynamic load first; a failed chunk load surfaces through the same
|
|
180
|
+
* error path as a failed render. Theme setup MUST follow the load —
|
|
181
|
+
* there is deliberately no module-scope initialization any more.
|
|
182
|
+
*/
|
|
183
|
+
const mermaid: MermaidApi = await loadMermaid();
|
|
184
|
+
if (!containerRef.current || isCancelled) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
140
187
|
containerRef.current.innerHTML = "";
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
containerRef.current.appendChild(errorEl);
|
|
159
|
-
}
|
|
188
|
+
initializeMermaid(mermaid, theme);
|
|
189
|
+
const id: string = `mermaid-${Math.random().toString(36).substr(2, 9)}`;
|
|
190
|
+
const { svg } = await mermaid.render(id, chart);
|
|
191
|
+
if (containerRef.current && !isCancelled) {
|
|
192
|
+
containerRef.current.innerHTML = DOMPurify.sanitize(svg, {
|
|
193
|
+
USE_PROFILES: { svg: true, svgFilters: true },
|
|
194
|
+
ADD_TAGS: ["foreignObject"],
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
} catch (error) {
|
|
198
|
+
if (containerRef.current && !isCancelled) {
|
|
199
|
+
const errorMessage: string = String(error);
|
|
200
|
+
const errorEl: HTMLPreElement = document.createElement("pre");
|
|
201
|
+
errorEl.className = "text-red-500";
|
|
202
|
+
errorEl.textContent = `Error rendering diagram: ${errorMessage}`;
|
|
203
|
+
containerRef.current.innerHTML = "";
|
|
204
|
+
containerRef.current.appendChild(errorEl);
|
|
160
205
|
}
|
|
161
206
|
}
|
|
162
207
|
};
|
|
@@ -413,7 +413,7 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
413
413
|
return (
|
|
414
414
|
<div className="relative z-50">
|
|
415
415
|
<div
|
|
416
|
-
className={`fixed inset-0 bg-gray-950/45 backdrop-blur-[2px] transition-opacity duration-
|
|
416
|
+
className={`fixed inset-0 bg-gray-950/45 backdrop-blur-[2px] transition-opacity duration-150 ease-out motion-reduce:transition-none ${
|
|
417
417
|
hasEntered ? "opacity-100" : "opacity-0"
|
|
418
418
|
}`}
|
|
419
419
|
data-testid="modal-backdrop"
|
|
@@ -429,7 +429,7 @@ const Modal: FunctionComponent<ComponentProps> = (
|
|
|
429
429
|
<div className="flex min-h-full items-end justify-center p-0 text-center sm:items-center sm:p-6">
|
|
430
430
|
<div
|
|
431
431
|
ref={modalRef}
|
|
432
|
-
className={`relative flex max-h-[calc(100dvh-1rem)] w-full flex-col rounded-t-2xl border border-gray-200/80 bg-white text-left shadow-2xl ring-1 ring-black/5 transition duration-
|
|
432
|
+
className={`relative flex max-h-[calc(100dvh-1rem)] w-full flex-col rounded-t-2xl border border-gray-200/80 bg-white text-left shadow-2xl ring-1 ring-black/5 transition duration-150 ease-out focus:outline-none motion-reduce:transition-none sm:my-8 sm:max-h-[calc(100dvh-4rem)] sm:rounded-xl ${modalWidthClassName} ${panelTransitionClassName}`}
|
|
433
433
|
data-testid="modal"
|
|
434
434
|
aria-labelledby={titleId}
|
|
435
435
|
aria-describedby={translatedDescription ? descriptionId : undefined}
|
|
@@ -47,7 +47,7 @@ import List from "../List/List";
|
|
|
47
47
|
import { ListDetailProps } from "../List/ListRow";
|
|
48
48
|
import ConfirmModal from "../Modal/ConfirmModal";
|
|
49
49
|
import Modal, { ModalWidth } from "../Modal/Modal";
|
|
50
|
-
import MarkdownViewer from "../Markdown.tsx/
|
|
50
|
+
import MarkdownViewer from "../Markdown.tsx/LazyMarkdownViewer";
|
|
51
51
|
import Icon from "../Icon/Icon";
|
|
52
52
|
import Filter from "../ModelFilter/Filter";
|
|
53
53
|
import { DropdownOption, DropdownOptionLabel } from "../Dropdown/Dropdown";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getCustomFieldColumns,
|
|
5
5
|
getCustomFieldDefinitions,
|
|
6
6
|
} from "./CustomFieldColumns";
|
|
7
|
-
import
|
|
7
|
+
import ModelListCache from "../../Utils/ModelListCache";
|
|
8
8
|
import ProjectUtil from "../../Utils/Project";
|
|
9
9
|
import { Logger } from "../../Utils/Logger";
|
|
10
10
|
import AnalyticsBaseModel from "../../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
|
|
@@ -96,8 +96,14 @@ const useCustomFieldColumns: UseCustomFieldColumnsFunction = <
|
|
|
96
96
|
setError("");
|
|
97
97
|
|
|
98
98
|
try {
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
/*
|
|
100
|
+
* Through ModelListCache rather than ModelAPI: a table mounts two
|
|
101
|
+
* instances of this hook (the facet bar and the column set), and both
|
|
102
|
+
* want the same definition list - the cache turns that into one
|
|
103
|
+
* request, shared for the next minute.
|
|
104
|
+
*/
|
|
105
|
+
const result: ListResult<BaseModel> =
|
|
106
|
+
await ModelListCache.getList<BaseModel>({
|
|
101
107
|
modelType: customFieldsModelType,
|
|
102
108
|
query: {
|
|
103
109
|
projectId: projectId,
|
|
@@ -113,8 +119,8 @@ const useCustomFieldColumns: UseCustomFieldColumnsFunction = <
|
|
|
113
119
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
114
120
|
} as any,
|
|
115
121
|
sort: {},
|
|
116
|
-
|
|
117
|
-
|
|
122
|
+
projectId: projectId,
|
|
123
|
+
});
|
|
118
124
|
|
|
119
125
|
if (isCancelled) {
|
|
120
126
|
return;
|
|
@@ -114,6 +114,13 @@ const MoreMenu: React.ForwardRefExoticComponent<
|
|
|
114
114
|
|
|
115
115
|
const [isDropdownVisible, setDropdownVisible] = useState<boolean>(false);
|
|
116
116
|
|
|
117
|
+
/*
|
|
118
|
+
* The menu is mounted in its closed state (faded, slightly shrunk towards
|
|
119
|
+
* origin-top-right) and flipped open one frame later so the browser has
|
|
120
|
+
* something to transition from — the same pattern Modal uses.
|
|
121
|
+
*/
|
|
122
|
+
const [hasMenuEntered, setHasMenuEntered] = useState<boolean>(false);
|
|
123
|
+
|
|
117
124
|
useEffect(() => {
|
|
118
125
|
setDropdownVisible(isComponentVisible);
|
|
119
126
|
if (isComponentVisible) {
|
|
@@ -123,6 +130,30 @@ const MoreMenu: React.ForwardRefExoticComponent<
|
|
|
123
130
|
}
|
|
124
131
|
}, [isComponentVisible]);
|
|
125
132
|
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
if (!isComponentVisible) {
|
|
135
|
+
setHasMenuEntered(false);
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const open: () => void = (): void => {
|
|
140
|
+
setHasMenuEntered(true);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const frame: number = requestAnimationFrame(open);
|
|
144
|
+
|
|
145
|
+
/*
|
|
146
|
+
* A hidden or throttled tab never runs an animation frame; the timer
|
|
147
|
+
* skips the transition rather than leaving the menu at zero opacity.
|
|
148
|
+
*/
|
|
149
|
+
const fallbackTimer: ReturnType<typeof setTimeout> = setTimeout(open, 80);
|
|
150
|
+
|
|
151
|
+
return () => {
|
|
152
|
+
cancelAnimationFrame(frame);
|
|
153
|
+
clearTimeout(fallbackTimer);
|
|
154
|
+
};
|
|
155
|
+
}, [isComponentVisible]);
|
|
156
|
+
|
|
126
157
|
useEffect(() => {
|
|
127
158
|
if (props.isDisabled && isComponentVisible) {
|
|
128
159
|
setIsComponentVisible(false);
|
|
@@ -427,7 +458,14 @@ const MoreMenu: React.ForwardRefExoticComponent<
|
|
|
427
458
|
<div
|
|
428
459
|
ref={ref}
|
|
429
460
|
id={menuId}
|
|
430
|
-
|
|
461
|
+
/*
|
|
462
|
+
* Once settled the menu carries no transform class at all: a
|
|
463
|
+
* lingering scale would make it the containing block for any
|
|
464
|
+
* position:fixed descendant (the Modal invariant).
|
|
465
|
+
*/
|
|
466
|
+
className={`absolute right-0 z-50 mt-2 w-56 origin-top-right rounded-lg bg-white shadow-xl ring-1 ring-gray-200 focus:outline-none py-1 transition duration-150 ease-out motion-reduce:transition-none ${
|
|
467
|
+
hasMenuEntered ? "opacity-100" : "opacity-0 scale-95"
|
|
468
|
+
}`}
|
|
431
469
|
role="menu"
|
|
432
470
|
aria-orientation="vertical"
|
|
433
471
|
aria-labelledby={buttonId}
|
|
@@ -65,6 +65,14 @@ export interface ComponentProps {
|
|
|
65
65
|
description: string;
|
|
66
66
|
link: URL;
|
|
67
67
|
};
|
|
68
|
+
/*
|
|
69
|
+
* When true, the document-level Cmd/Ctrl+K shortcut that toggles the
|
|
70
|
+
* products menu is not registered — for apps where another surface (e.g. a
|
|
71
|
+
* command palette) owns that shortcut. The menu itself stays fully usable
|
|
72
|
+
* via its trigger button. Defaults to false: existing consumers keep the
|
|
73
|
+
* shortcut.
|
|
74
|
+
*/
|
|
75
|
+
disableCommandKShortcut?: boolean | undefined;
|
|
68
76
|
className?: string;
|
|
69
77
|
// Legacy support for children-based usage
|
|
70
78
|
children?: ReactElement | Array<ReactElement>;
|
|
@@ -165,6 +173,11 @@ const Navbar: FunctionComponent<ComponentProps> = (
|
|
|
165
173
|
|
|
166
174
|
// Open/close the products menu with Cmd/Ctrl + K from anywhere.
|
|
167
175
|
useEffect(() => {
|
|
176
|
+
if (props.disableCommandKShortcut) {
|
|
177
|
+
// Another surface (e.g. a command palette) owns Cmd/Ctrl+K.
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
168
181
|
const handleGlobalKeyDown: (event: KeyboardEvent) => void = (
|
|
169
182
|
event: KeyboardEvent,
|
|
170
183
|
): void => {
|
|
@@ -180,7 +193,7 @@ const Navbar: FunctionComponent<ComponentProps> = (
|
|
|
180
193
|
return () => {
|
|
181
194
|
document.removeEventListener("keydown", handleGlobalKeyDown);
|
|
182
195
|
};
|
|
183
|
-
}, []);
|
|
196
|
+
}, [props.disableCommandKShortcut]);
|
|
184
197
|
|
|
185
198
|
// More menu open/close.
|
|
186
199
|
const openMoreMenu: () => void = (): void => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import ActionButtonSchema from "../ActionButton/ActionButtonSchema";
|
|
2
|
-
import ComponentLoader from "../ComponentLoader/ComponentLoader";
|
|
3
2
|
import ErrorMessage from "../ErrorMessage/ErrorMessage";
|
|
4
3
|
import Icon, { SizeProp } from "../Icon/Icon";
|
|
5
4
|
import Item from "./Item";
|
|
5
|
+
import Skeleton from "../Skeleton/Skeleton";
|
|
6
6
|
import GenericObject from "../../../Types/GenericObject";
|
|
7
7
|
import IconProp from "../../../Types/Icon/IconProp";
|
|
8
8
|
import React, { ReactElement } from "react";
|
|
@@ -33,11 +33,49 @@ type OrderedStatesListFunction = <T extends GenericObject>(
|
|
|
33
33
|
const OrderedStatesList: OrderedStatesListFunction = <T extends GenericObject>(
|
|
34
34
|
props: ComponentProps<T>,
|
|
35
35
|
): ReactElement => {
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
/*
|
|
37
|
+
* A refetch with states already on screen keeps them visible and dims
|
|
38
|
+
* them; the skeleton stack is only for a load with nothing to show yet.
|
|
39
|
+
*/
|
|
40
|
+
const isRefetchingWithData: boolean =
|
|
41
|
+
Boolean(props.isLoading) && props.data.length > 0;
|
|
42
|
+
|
|
43
|
+
if (props.isLoading && props.data.length === 0) {
|
|
44
|
+
/*
|
|
45
|
+
* Three card-shaped placeholders where the ordered state cards will
|
|
46
|
+
* land (matching Item's rounded bordered card), so the page keeps its
|
|
47
|
+
* shape instead of collapsing to a centered spinner.
|
|
48
|
+
*/
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
data-testid="ordered-states-list-skeleton-loader"
|
|
52
|
+
role="status"
|
|
53
|
+
aria-live="polite"
|
|
54
|
+
className="m-32 text-center"
|
|
55
|
+
>
|
|
56
|
+
<span className="sr-only">Loading...</span>
|
|
57
|
+
{[0, 1, 2].map((index: number) => {
|
|
58
|
+
return (
|
|
59
|
+
<div key={index} className="w-fit m-auto">
|
|
60
|
+
<Skeleton className="h-32 w-64 rounded p-10" />
|
|
61
|
+
{index < 2 && (
|
|
62
|
+
<div className="items-center m-10">
|
|
63
|
+
<Skeleton className="m-auto h-5 w-5" />
|
|
64
|
+
</div>
|
|
65
|
+
)}
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
})}
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
38
71
|
}
|
|
39
72
|
|
|
40
|
-
|
|
73
|
+
/*
|
|
74
|
+
* Loading still wins over error and empty (same priority as before the
|
|
75
|
+
* skeletons): while a refetch is in flight the stale states render, never
|
|
76
|
+
* a stale error or a premature "no items".
|
|
77
|
+
*/
|
|
78
|
+
if (!props.isLoading && props.error) {
|
|
41
79
|
return (
|
|
42
80
|
<ErrorMessage
|
|
43
81
|
message={props.error}
|
|
@@ -82,7 +120,14 @@ const OrderedStatesList: OrderedStatesListFunction = <T extends GenericObject>(
|
|
|
82
120
|
}
|
|
83
121
|
|
|
84
122
|
return (
|
|
85
|
-
<div
|
|
123
|
+
<div
|
|
124
|
+
data-testid="ordered-states-list-content"
|
|
125
|
+
className={`m-32 text-center${
|
|
126
|
+
isRefetchingWithData
|
|
127
|
+
? " opacity-60 pointer-events-none transition-opacity duration-150"
|
|
128
|
+
: " transition-opacity duration-150"
|
|
129
|
+
}`}
|
|
130
|
+
>
|
|
86
131
|
{props.error && <p>{props.error}</p>}
|
|
87
132
|
{!props.error &&
|
|
88
133
|
props.data &&
|
|
@@ -7,7 +7,14 @@ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/Database
|
|
|
7
7
|
import { PromiseVoidFunction } from "../../../Types/FunctionTypes";
|
|
8
8
|
import IconProp from "../../../Types/Icon/IconProp";
|
|
9
9
|
import Link from "../../../Types/Link";
|
|
10
|
-
import React, {
|
|
10
|
+
import React, {
|
|
11
|
+
MutableRefObject,
|
|
12
|
+
ReactElement,
|
|
13
|
+
useEffect,
|
|
14
|
+
useRef,
|
|
15
|
+
useState,
|
|
16
|
+
useCallback,
|
|
17
|
+
} from "react";
|
|
11
18
|
import GlobalEvents from "../../Utils/GlobalEvents";
|
|
12
19
|
|
|
13
20
|
export const REFRESH_SIDEBAR_COUNT_EVENT: string = "REFRESH_SIDEBAR_COUNTS";
|
|
@@ -70,7 +77,39 @@ const CountModelSideMenuItem: <TBaseModel extends BaseModel>(
|
|
|
70
77
|
props.onCountFetchInit,
|
|
71
78
|
]);
|
|
72
79
|
|
|
80
|
+
/*
|
|
81
|
+
* Side menus rebuild `countQuery` / `requestOptions` as fresh object
|
|
82
|
+
* literals on every render, so their identity changes on every parent
|
|
83
|
+
* re-render (which happens on every in-section navigation). Guard the fetch
|
|
84
|
+
* with a value-level compare - the same JSON.stringify-in-a-ref pattern
|
|
85
|
+
* BaseModelTable uses for its `props.query` - so only a real change
|
|
86
|
+
* re-issues the count request. The global refresh event below still forces
|
|
87
|
+
* a refetch regardless of this guard.
|
|
88
|
+
*/
|
|
89
|
+
const lastFetchedModelTypeRef: MutableRefObject<
|
|
90
|
+
{ new (): TBaseModel } | undefined
|
|
91
|
+
> = useRef<{ new (): TBaseModel } | undefined>(undefined);
|
|
92
|
+
const lastFetchedQueryJsonRef: MutableRefObject<string | null> = useRef<
|
|
93
|
+
string | null
|
|
94
|
+
>(null);
|
|
95
|
+
|
|
73
96
|
useEffect(() => {
|
|
97
|
+
const queryJson: string = JSON.stringify({
|
|
98
|
+
countQuery: props.countQuery || null,
|
|
99
|
+
requestOptions: props.requestOptions || null,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// only fetch if the query has changed by value (or on first mount).
|
|
103
|
+
if (
|
|
104
|
+
lastFetchedModelTypeRef.current === props.modelType &&
|
|
105
|
+
lastFetchedQueryJsonRef.current === queryJson
|
|
106
|
+
) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
lastFetchedModelTypeRef.current = props.modelType;
|
|
111
|
+
lastFetchedQueryJsonRef.current = queryJson;
|
|
112
|
+
|
|
74
113
|
fetchCount().catch((err: Error) => {
|
|
75
114
|
setError(API.getFriendlyMessage(err));
|
|
76
115
|
});
|
|
@@ -80,6 +80,32 @@ const SideOver: FunctionComponent<ComponentProps> = (
|
|
|
80
80
|
const titleId: string = useId();
|
|
81
81
|
const descriptionId: string = useId();
|
|
82
82
|
|
|
83
|
+
/*
|
|
84
|
+
* The panel is mounted parked off the right edge and flipped into place one
|
|
85
|
+
* frame later so the browser has something to transition from — the same
|
|
86
|
+
* pattern Modal uses for its entrance.
|
|
87
|
+
*/
|
|
88
|
+
const [hasEntered, setHasEntered] = useState<boolean>(false);
|
|
89
|
+
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
const open: () => void = (): void => {
|
|
92
|
+
setHasEntered(true);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const frame: number = requestAnimationFrame(open);
|
|
96
|
+
|
|
97
|
+
/*
|
|
98
|
+
* A hidden or throttled tab never runs an animation frame; the timer
|
|
99
|
+
* skips the transition rather than leaving the panel offscreen.
|
|
100
|
+
*/
|
|
101
|
+
const fallbackTimer: ReturnType<typeof setTimeout> = setTimeout(open, 80);
|
|
102
|
+
|
|
103
|
+
return () => {
|
|
104
|
+
cancelAnimationFrame(frame);
|
|
105
|
+
clearTimeout(fallbackTimer);
|
|
106
|
+
};
|
|
107
|
+
}, []);
|
|
108
|
+
|
|
83
109
|
const [portalTarget, setPortalTarget] = useState<HTMLElement | null>(
|
|
84
110
|
getPortalTarget,
|
|
85
111
|
);
|
|
@@ -148,7 +174,16 @@ const SideOver: FunctionComponent<ComponentProps> = (
|
|
|
148
174
|
className="pointer-events-none fixed inset-0 flex justify-end"
|
|
149
175
|
data-testid="side-over-layer"
|
|
150
176
|
>
|
|
151
|
-
|
|
177
|
+
{/*
|
|
178
|
+
* Settled state carries no transform class at all: a lingering
|
|
179
|
+
* translate would make the panel the containing block for
|
|
180
|
+
* position:fixed descendants (the Modal invariant).
|
|
181
|
+
*/}
|
|
182
|
+
<div
|
|
183
|
+
className={`pointer-events-auto w-full ${widthClass} transition-transform duration-200 ease-out motion-reduce:transition-none ${
|
|
184
|
+
hasEntered ? "" : "translate-x-full"
|
|
185
|
+
}`}
|
|
186
|
+
>
|
|
152
187
|
<div className="flex h-full flex-col bg-white shadow-xl">
|
|
153
188
|
<div className="flex-shrink-0 flex flex-col bg-gray-50 px-4 py-6 sm:px-6">
|
|
154
189
|
<div className="flex items-start justify-between space-x-3">
|
|
@@ -176,7 +211,7 @@ const SideOver: FunctionComponent<ComponentProps> = (
|
|
|
176
211
|
type="button"
|
|
177
212
|
title="Close panel"
|
|
178
213
|
data-testid="close-button"
|
|
179
|
-
className="text-gray-400 hover:text-gray-500"
|
|
214
|
+
className="rounded-md text-gray-400 transition-colors duration-150 ease-out hover:text-gray-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2"
|
|
180
215
|
>
|
|
181
216
|
<span className="sr-only">Close panel</span>
|
|
182
217
|
|