@oneuptime/common 11.7.0 → 11.7.2
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/DashboardDomain.ts +1 -0
- package/Models/DatabaseModels/Incident.ts +2 -0
- package/Models/DatabaseModels/IncidentEpisode.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentPublicNote.ts +1 -0
- package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
- package/Models/DatabaseModels/Monitor.ts +1 -0
- package/Models/DatabaseModels/MonitorStatusTimeline.ts +1 -0
- package/Models/DatabaseModels/NetworkSite.ts +1 -0
- package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +1 -0
- package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +1 -0
- package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +2 -0
- package/Models/DatabaseModels/Probe.ts +13 -13
- package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +1 -0
- package/Models/DatabaseModels/StatusPage.ts +1 -0
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +1 -0
- package/Models/DatabaseModels/StatusPageDomain.ts +1 -0
- package/Models/DatabaseModels/WorkspaceNotificationSummary.ts +1 -0
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +11 -0
- package/Server/API/BaseAPI.ts +17 -1
- package/Server/API/CommonAPI.ts +32 -0
- package/Server/API/MicrosoftTeamsAPI.ts +99 -2
- package/Server/API/ProbeAPI.ts +2 -0
- package/Server/API/SlackAPI.ts +62 -0
- package/Server/API/StatusPageAPI.ts +157 -192
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.ts +89 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.ts +61 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.ts +280 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Services/DatabaseService.ts +11 -3
- package/Server/Services/MonitorGroupService.ts +145 -0
- package/Server/Services/MonitorService.ts +231 -30
- package/Server/Services/ProbeService.ts +319 -16
- package/Server/Services/StatusPageService.ts +72 -42
- package/Server/Services/WorkspaceNotificationRuleService.ts +232 -2
- package/Server/Utils/Database/PostgresErrorTranslator.ts +131 -0
- package/Server/Utils/Monitor/MonitorResource.ts +88 -35
- package/Server/Utils/Monitor/MonitorStatusTimeline.ts +21 -1
- package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +158 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +706 -6
- package/Tests/Models/DatabaseModels/ProbeColumnAccessControl.test.ts +103 -0
- package/Tests/Server/API/BaseAPIUpdateNoOp.test.ts +135 -0
- package/Tests/Server/API/CommonAPIAuthGuard.test.ts +317 -0
- package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +228 -0
- package/Tests/Server/API/ProbeAPI.test.ts +6 -0
- package/Tests/Server/API/ZZVerifyChatsAuth.test.ts +167 -0
- package/Tests/Server/Services/AddHotQueryIndexesMigration.test.ts +255 -0
- package/Tests/Server/Services/AddHotQueryIndexesSecondPassMigration.test.ts +258 -0
- package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +1 -1
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +121 -0
- package/Tests/Server/Services/HeartbeatWriteFastPathSafety.test.ts +200 -0
- package/Tests/Server/Services/HookFreeWriteSafetySecondPass.test.ts +181 -0
- package/Tests/Server/Services/MonitorGroupServiceBatchedStatuses.test.ts +513 -0
- package/Tests/Server/Services/MonitorResourceProbeAgreementReuse.test.ts +492 -0
- package/Tests/Server/Services/MonitorServiceProbeSelection.test.ts +401 -0
- package/Tests/Server/Services/MonitorStatusTimelineFastPath.test.ts +453 -0
- package/Tests/Server/Services/ProbeAuthKeyCacheAndHeartbeat.test.ts +679 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +3 -3
- package/Tests/Server/Services/StatusPageDomainResolutionCache.test.ts +245 -0
- package/Tests/Server/Services/StatusPageOverviewTimelineWindow.test.ts +283 -0
- package/Tests/Server/Services/StatusPageServiceMcp.test.ts +17 -1
- package/Tests/Server/Services/StatusPageServiceMonitorGroupBatching.test.ts +331 -0
- package/Tests/Server/Services/UserOnCallLogClaimNotificationRule.test.ts +12 -12
- package/Tests/Server/Services/WorkspaceNotificationRuleChats.test.ts +1390 -0
- package/Tests/Server/Utils/AI/Insights/InsightFixRouting.test.ts +4 -4
- package/Tests/Server/Utils/AI/Insights/InsightScanner.test.ts +2 -2
- package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +1 -3
- package/Tests/Server/Utils/AI/Insights/InsightStoreHardening.test.ts +1 -3
- package/Tests/Server/Utils/AI/Insights/InsightTriage.test.ts +1 -1
- package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +5 -5
- package/Tests/Server/Utils/Alert/AlertPrivacyFilter.test.ts +187 -0
- package/Tests/Server/Utils/AlertEpisode/AlertEpisodePrivacyFilter.test.ts +170 -0
- package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +125 -0
- package/Tests/Server/Utils/Incident/IncidentPrivacyFilter.test.ts +264 -0
- package/Tests/Server/Utils/IncidentEpisode/IncidentEpisodePrivacyFilter.test.ts +175 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +181 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +1 -1
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +2 -2
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +341 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +2175 -0
- package/Tests/Server/Utils/Workspace/SlackChannelsList.test.ts +585 -0
- package/Tests/Types/Billing/MeteredPlan.test.ts +46 -0
- package/Tests/Types/DateUserTimezone.test.ts +205 -0
- package/Tests/Types/DateUserTimezoneOverridesBrowser.test.ts +73 -0
- package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +219 -1
- package/Tests/UI/Components/BulkUpdateForm.test.tsx +174 -0
- package/Tests/UI/Components/CardModelDetailEdit.test.tsx +315 -0
- package/Tests/UI/Components/ModelDetailSelect.test.tsx +229 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1258 -0
- package/Tests/UI/Components/ModelTableExportFromColumns.test.ts +153 -0
- package/Tests/UI/Components/MonacoLoader.test.ts +67 -0
- package/Tests/UI/Components/MonacoRuntime.test.ts +121 -0
- package/Tests/UI/Components/TableBulkCsvExport.test.tsx +212 -3
- package/Tests/UI/Components/TimePicker/TimePicker.test.tsx +11 -0
- package/Tests/UI/Utils/Project.test.ts +809 -0
- package/Tests/UI/Utils/TableColumnsToCsv.test.ts +360 -0
- package/Tests/Utils/Alerts/AlertMetricType.test.ts +143 -0
- package/Tests/Utils/Dashboard/VariableUrlState.test.ts +219 -0
- package/Tests/Utils/Incident/IncidentMetricType.test.ts +174 -0
- package/Tests/Utils/Monitor/MonitorProbeSelectionUtil.test.ts +145 -0
- package/Tests/Utils/StatusPage/ResourceUptime.test.ts +263 -0
- package/Types/Date.ts +119 -50
- package/Types/Workspace/NotificationRules/BaseNotificationRule.ts +4 -0
- package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +25 -10
- package/Types/Workspace/WorkspaceMessagePayload.ts +1 -0
- package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +63 -8
- package/UI/Components/CodeEditor/CodeEditor.tsx +3 -0
- package/UI/Components/CodeEditor/MonacoLoader.ts +36 -0
- package/UI/Components/Forms/Fields/FormField.tsx +13 -3
- package/UI/Components/Forms/ModelForm.tsx +41 -18
- package/UI/Components/Input/Input.tsx +6 -1
- package/UI/Components/ModelDetail/CardModelDetail.tsx +23 -1
- package/UI/Components/ModelDetail/ModelDetail.tsx +46 -1
- package/UI/Components/ModelTable/BaseModelTable.tsx +300 -30
- package/UI/Components/ModelTable/Column.ts +12 -0
- package/UI/Components/ModelTable/ExportFromColumns.ts +57 -0
- package/UI/Components/Navbar/NavBar.tsx +66 -1
- package/UI/Components/Table/Table.tsx +52 -13
- package/UI/Components/Table/Types/Column.ts +18 -0
- package/UI/Components/TimePicker/TimePicker.tsx +8 -4
- package/UI/Utils/Project.ts +214 -18
- package/UI/Utils/TableColumnsToCsv.ts +86 -6
- package/UI/Utils/User.ts +19 -0
- package/UI/esbuild-config.js +34 -0
- package/Utils/Monitor/MonitorProbeSelectionUtil.ts +72 -0
- package/build/dist/Models/DatabaseModels/DashboardDomain.js +1 -0
- package/build/dist/Models/DatabaseModels/DashboardDomain.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +2 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +1 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSite.js +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +1 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +2 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Probe.js +13 -13
- package/build/dist/Models/DatabaseModels/Probe.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +1 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageDomain.js +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceNotificationSummary.js +1 -0
- package/build/dist/Models/DatabaseModels/WorkspaceNotificationSummary.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +12 -1
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/CommonAPI.js +21 -0
- package/build/dist/Server/API/CommonAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +72 -2
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ProbeAPI.js +2 -0
- package/build/dist/Server/API/ProbeAPI.js.map +1 -1
- package/build/dist/Server/API/SlackAPI.js +44 -0
- package/build/dist/Server/API/SlackAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +98 -152
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.js +254 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.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/Services/DatabaseService.js +10 -2
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/MonitorGroupService.js +118 -0
- package/build/dist/Server/Services/MonitorGroupService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +198 -24
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/ProbeService.js +238 -9
- package/build/dist/Server/Services/ProbeService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +46 -39
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +178 -3
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +80 -0
- package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +67 -29
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js +31 -14
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +117 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +549 -7
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/Date.js +106 -35
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +17 -7
- package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +37 -11
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +2 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +34 -0
- package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +1 -0
- package/build/dist/UI/Components/Forms/Fields/FormField.js +11 -3
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +37 -17
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +6 -1
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +22 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js +31 -1
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +234 -21
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ExportFromColumns.js +30 -0
- package/build/dist/UI/Components/ModelTable/ExportFromColumns.js.map +1 -0
- package/build/dist/UI/Components/Navbar/NavBar.js +39 -1
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +31 -11
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/TimePicker/TimePicker.js +4 -4
- package/build/dist/UI/Components/TimePicker/TimePicker.js.map +1 -1
- package/build/dist/UI/Utils/Project.js +161 -15
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/build/dist/UI/Utils/TableColumnsToCsv.js +67 -6
- package/build/dist/UI/Utils/TableColumnsToCsv.js.map +1 -1
- package/build/dist/UI/Utils/User.js +19 -0
- package/build/dist/UI/Utils/User.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorProbeSelectionUtil.js +52 -0
- package/build/dist/Utils/Monitor/MonitorProbeSelectionUtil.js.map +1 -0
- package/package.json +4 -3
- package/Server/Infrastructure/Postgres/SchemaMigrations/1773414578773-MigrationName.ts +0 -79
- package/Server/Infrastructure/Postgres/SchemaMigrations/1773500000000-MigrationName.ts +0 -41
- package/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.ts +0 -17
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1773414578773-MigrationName.js +0 -34
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1773414578773-MigrationName.js.map +0 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1773500000000-MigrationName.js +0 -22
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1773500000000-MigrationName.js.map +0 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.js +0 -12
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.js.map +0 -1
|
@@ -67,6 +67,21 @@ export interface ComponentProps<T extends GenericObject> {
|
|
|
67
67
|
onActionStart?: (() => void) | undefined;
|
|
68
68
|
onActionEnd?: (() => void) | undefined;
|
|
69
69
|
itemToString?: ((item: T) => string) | undefined;
|
|
70
|
+
/*
|
|
71
|
+
* Selecting everything is a multi-request fetch that can fail. Surfacing it
|
|
72
|
+
* here - next to the button the user pressed - keeps the message alive; the
|
|
73
|
+
* table body's own error is wiped by the next refresh.
|
|
74
|
+
*/
|
|
75
|
+
errorMessage?: string | undefined;
|
|
76
|
+
isSelectingAllItems?: boolean | undefined;
|
|
77
|
+
/*
|
|
78
|
+
* Set when the selection hit the per-selection ceiling and there are more
|
|
79
|
+
* matching rows than were selected. `totalMatchingItemsCount` is how many
|
|
80
|
+
* rows actually matched, so the warning can name real numbers instead of
|
|
81
|
+
* inferring truncation from the selected count.
|
|
82
|
+
*/
|
|
83
|
+
isSelectionTruncated?: boolean | undefined;
|
|
84
|
+
totalMatchingItemsCount?: number | undefined;
|
|
70
85
|
}
|
|
71
86
|
|
|
72
87
|
const isDangerStyle: (style: ButtonStyleType) => boolean = (
|
|
@@ -317,9 +332,16 @@ const BulkUpdateForm: <T extends GenericObject>(
|
|
|
317
332
|
menuChildren.push(renderMenuItem(button, safeButtons.length + index));
|
|
318
333
|
});
|
|
319
334
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
335
|
+
/*
|
|
336
|
+
* Driven by what the fetch actually reported rather than by
|
|
337
|
+
* `selectedItems.length === LIMIT_PER_PROJECT`, which both cried wolf on a
|
|
338
|
+
* project holding exactly the ceiling and stayed silent whenever a partial
|
|
339
|
+
* selection came back one row short of it.
|
|
340
|
+
*/
|
|
341
|
+
const showLimitWarning: boolean = Boolean(props.isSelectionTruncated);
|
|
342
|
+
|
|
343
|
+
const totalMatchingItemsCount: number =
|
|
344
|
+
props.totalMatchingItemsCount || props.selectedItems.length;
|
|
323
345
|
|
|
324
346
|
return (
|
|
325
347
|
<div>
|
|
@@ -345,13 +367,33 @@ const BulkUpdateForm: <T extends GenericObject>(
|
|
|
345
367
|
{!props.isAllItemsSelected && (
|
|
346
368
|
<button
|
|
347
369
|
type="button"
|
|
370
|
+
disabled={props.isSelectingAllItems}
|
|
348
371
|
onClick={() => {
|
|
372
|
+
if (props.isSelectingAllItems) {
|
|
373
|
+
// the fetch is paged, so it must not be re-entrant.
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
349
376
|
props.onSelectAllClick();
|
|
350
377
|
}}
|
|
351
|
-
className=
|
|
378
|
+
className={`inline-flex items-center gap-1.5 rounded-lg border border-gray-300 bg-white px-3 py-1.5 text-sm font-medium text-gray-700 shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-all duration-150 select-none ${
|
|
379
|
+
props.isSelectingAllItems
|
|
380
|
+
? "opacity-50 cursor-not-allowed"
|
|
381
|
+
: "cursor-pointer hover:bg-indigo-50 hover:border-indigo-300 hover:text-indigo-700"
|
|
382
|
+
}`}
|
|
352
383
|
>
|
|
353
|
-
<Icon
|
|
354
|
-
|
|
384
|
+
<Icon
|
|
385
|
+
icon={
|
|
386
|
+
props.isSelectingAllItems
|
|
387
|
+
? IconProp.Spinner
|
|
388
|
+
: IconProp.CheckCircle
|
|
389
|
+
}
|
|
390
|
+
className="h-3.5 w-3.5"
|
|
391
|
+
/>
|
|
392
|
+
<span>
|
|
393
|
+
{props.isSelectingAllItems
|
|
394
|
+
? `Selecting All ${props.pluralLabel}...`
|
|
395
|
+
: `Select All ${props.pluralLabel}`}
|
|
396
|
+
</span>
|
|
355
397
|
</button>
|
|
356
398
|
)}
|
|
357
399
|
|
|
@@ -393,8 +435,21 @@ const BulkUpdateForm: <T extends GenericObject>(
|
|
|
393
435
|
|
|
394
436
|
{showLimitWarning && (
|
|
395
437
|
<div className="mt-2 text-xs text-gray-500">
|
|
396
|
-
|
|
397
|
-
|
|
438
|
+
Selected {props.selectedItems.length.toLocaleString()} of{" "}
|
|
439
|
+
{totalMatchingItemsCount.toLocaleString()} matching{" "}
|
|
440
|
+
{props.pluralLabel}. You can only select{" "}
|
|
441
|
+
{LIMIT_PER_PROJECT.toLocaleString()} {props.pluralLabel} at a
|
|
442
|
+
time, for performance reasons, so bulk actions will apply to the
|
|
443
|
+
selected {props.selectedItems.length.toLocaleString()} only.
|
|
444
|
+
</div>
|
|
445
|
+
)}
|
|
446
|
+
|
|
447
|
+
{props.errorMessage && (
|
|
448
|
+
<div
|
|
449
|
+
role="alert"
|
|
450
|
+
className="mt-2 rounded-lg bg-red-50 p-3 text-sm text-red-800"
|
|
451
|
+
>
|
|
452
|
+
{props.errorMessage}
|
|
398
453
|
</div>
|
|
399
454
|
)}
|
|
400
455
|
</div>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Editor from "@monaco-editor/react";
|
|
2
|
+
import configureMonacoLoader from "./MonacoLoader";
|
|
2
3
|
import CodeType from "../../../Types/Code/CodeType";
|
|
3
4
|
import MarkdownUtil from "../../Utils/Markdown";
|
|
4
5
|
import { Theme, useTheme } from "../../Utils/Theme";
|
|
@@ -10,6 +11,8 @@ import React, {
|
|
|
10
11
|
useState,
|
|
11
12
|
} from "react";
|
|
12
13
|
|
|
14
|
+
configureMonacoLoader();
|
|
15
|
+
|
|
13
16
|
export interface ComponentProps {
|
|
14
17
|
initialValue?: undefined | string;
|
|
15
18
|
onClick?: undefined | (() => void);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { loader } from "@monaco-editor/react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Points Monaco at the copy of its runtime that ships with the app.
|
|
5
|
+
*
|
|
6
|
+
* @monaco-editor/loader otherwise fetches it from cdn.jsdelivr.net at runtime,
|
|
7
|
+
* which never resolves on an air-gapped install and leaves every code editor
|
|
8
|
+
* stuck on "Loading...". The path is baked in by the build, which is the only
|
|
9
|
+
* place that knows where this service is mounted.
|
|
10
|
+
*
|
|
11
|
+
* The path has to be absolute. Monaco loads its language services in a worker
|
|
12
|
+
* spun up from a blob: URL, and a blob worker has no base to resolve a
|
|
13
|
+
* root-relative path against - it fetches "/dashboard/assets/monaco/vs/..." and
|
|
14
|
+
* throws "Failed to parse URL". The editor still renders, so the only visible
|
|
15
|
+
* symptom is that JSON/TypeScript validation and IntelliSense quietly stop
|
|
16
|
+
* working. The CDN default never hit this because it was already absolute.
|
|
17
|
+
*
|
|
18
|
+
* The monaco-editor version in Common/package.json is pinned exactly, because
|
|
19
|
+
* the loader resolves init() with whatever the AMD module `vs/editor/editor.main`
|
|
20
|
+
* exports and that shape is not stable across releases - 0.53 and 0.54 nest the
|
|
21
|
+
* API under `exports.m`, which leaves `monaco.editor` undefined and makes every
|
|
22
|
+
* editor throw instead of mount. MonacoRuntime.test.ts guards the pin.
|
|
23
|
+
*/
|
|
24
|
+
export default function configureMonacoLoader(): void {
|
|
25
|
+
const assetPath: string | undefined = process.env["MONACO_ASSET_PATH"];
|
|
26
|
+
|
|
27
|
+
if (!assetPath) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
loader.config({
|
|
32
|
+
paths: {
|
|
33
|
+
vs: new URL(assetPath, window.location.origin).href,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -291,9 +291,19 @@ const FormField: <T extends GenericObject>(
|
|
|
291
291
|
fieldDescription = "";
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
294
|
+
/*
|
|
295
|
+
* Name the zone in full. The abbreviation on its own ("EDT") is not
|
|
296
|
+
* enough to tell whether the field is following the timezone picked in
|
|
297
|
+
* User Settings or the one the browser reports.
|
|
298
|
+
*/
|
|
299
|
+
fieldDescription = (
|
|
300
|
+
fieldDescription +
|
|
301
|
+
" This is in your timezone - " +
|
|
302
|
+
OneUptimeDate.getCurrentTimezoneString() +
|
|
303
|
+
" (" +
|
|
304
|
+
OneUptimeDate.getCurrentTimezone().toString() +
|
|
305
|
+
")."
|
|
306
|
+
).trim();
|
|
297
307
|
}
|
|
298
308
|
|
|
299
309
|
type GetFieldDescriptionFunction = () => ReactElement | string;
|
|
@@ -641,27 +641,50 @@ const ModelForm: <TBaseModel extends BaseModel>(
|
|
|
641
641
|
return fields;
|
|
642
642
|
};
|
|
643
643
|
|
|
644
|
+
/*
|
|
645
|
+
* Keyed on the id (as a string - ObjectID identity changes every render)
|
|
646
|
+
* so a form that mounts before its id is known still fetches once it
|
|
647
|
+
* arrives. It used to run only on mount, which left an Update form showing
|
|
648
|
+
* blank defaults: submitting that silently wrote empty values - and false
|
|
649
|
+
* for every Toggle, since BasicForm defaults untouched toggles to false -
|
|
650
|
+
* over the real record.
|
|
651
|
+
*/
|
|
644
652
|
useAsyncEffect(async () => {
|
|
645
|
-
if (
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
) {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
653
|
+
if (props.formType !== FormType.Update || props.doNotFetchExistingModel) {
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
if (!props.modelIdToEdit) {
|
|
658
|
+
/*
|
|
659
|
+
* Without an id there is nothing to prefill and nothing to update, so
|
|
660
|
+
* say so rather than rendering an empty form that looks editable.
|
|
661
|
+
*
|
|
662
|
+
* Deliberately not props.onError: ModelFormModal unmounts the form on
|
|
663
|
+
* that, and this state is recoverable - the effect re-runs and clears
|
|
664
|
+
* the message as soon as the id arrives.
|
|
665
|
+
*/
|
|
666
|
+
setError(
|
|
667
|
+
`Cannot edit this ${(
|
|
668
|
+
model.singularName || "item"
|
|
669
|
+
).toLowerCase()} yet because it is still loading. Please try again in a moment.`,
|
|
670
|
+
);
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
660
673
|
|
|
661
|
-
|
|
662
|
-
|
|
674
|
+
// get item.
|
|
675
|
+
setLoading(true);
|
|
676
|
+
setIsFetching(true);
|
|
677
|
+
setError("");
|
|
678
|
+
try {
|
|
679
|
+
await fetchItem();
|
|
680
|
+
} catch (err) {
|
|
681
|
+
setError(API.getFriendlyMessage(err));
|
|
682
|
+
props.onError?.(API.getFriendlyMessage(err));
|
|
663
683
|
}
|
|
664
|
-
|
|
684
|
+
|
|
685
|
+
setLoading(false);
|
|
686
|
+
setIsFetching(false);
|
|
687
|
+
}, [props.modelIdToEdit?.toString()]);
|
|
665
688
|
|
|
666
689
|
type GetMiscDataPropsFunction = (
|
|
667
690
|
values: FormValues<JSONObject>,
|
|
@@ -174,7 +174,12 @@ const Input: FunctionComponent<ComponentProps> = (
|
|
|
174
174
|
props.type === InputType.DATETIME_LOCAL) &&
|
|
175
175
|
value
|
|
176
176
|
) {
|
|
177
|
-
|
|
177
|
+
/*
|
|
178
|
+
* The input hands back a bare wall-clock with no offset. Resolve
|
|
179
|
+
* it in the user's configured timezone rather than letting the
|
|
180
|
+
* browser assume its own zone.
|
|
181
|
+
*/
|
|
182
|
+
const date: Date = OneUptimeDate.fromDateTimeLocalString(value);
|
|
178
183
|
const dateString: string = OneUptimeDate.toString(date);
|
|
179
184
|
setValue(dateString);
|
|
180
185
|
if (props.onChange) {
|
|
@@ -12,6 +12,8 @@ import Fields from "../Forms/Types/Fields";
|
|
|
12
12
|
import { FormStep } from "../Forms/Types/FormStep";
|
|
13
13
|
import { ModalWidth } from "../Modal/Modal";
|
|
14
14
|
import ModelFormModal from "../ModelFormModal/ModelFormModal";
|
|
15
|
+
import { ToastType } from "../Toast/Toast";
|
|
16
|
+
import { ShowToastNotification } from "../Toast/ToastInit";
|
|
15
17
|
import ModelDetail, { ComponentProps as ModeDetailProps } from "./ModelDetail";
|
|
16
18
|
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
17
19
|
import IconProp from "../../../Types/Icon/IconProp";
|
|
@@ -165,6 +167,16 @@ const CardModelDetail: <TBaseModel extends BaseModel>(
|
|
|
165
167
|
onSuccess={(item: TBaseModel) => {
|
|
166
168
|
setShowModal(false);
|
|
167
169
|
setRefresher(!refresher);
|
|
170
|
+
/*
|
|
171
|
+
* The modal just disappears otherwise, which reads as "nothing
|
|
172
|
+
* happened" - especially on cards that do not display every field
|
|
173
|
+
* the edit form exposes.
|
|
174
|
+
*/
|
|
175
|
+
ShowToastNotification({
|
|
176
|
+
title: "Changes saved",
|
|
177
|
+
description: `${model.singularName || "Item"} updated successfully.`,
|
|
178
|
+
type: ToastType.SUCCESS,
|
|
179
|
+
});
|
|
168
180
|
if (props.onSaveSuccess) {
|
|
169
181
|
props.onSaveSuccess(item);
|
|
170
182
|
}
|
|
@@ -180,7 +192,17 @@ const CardModelDetail: <TBaseModel extends BaseModel>(
|
|
|
180
192
|
steps: props.formSteps || [],
|
|
181
193
|
createOrUpdateApiUrl: props.createOrUpdateApiUrl,
|
|
182
194
|
}}
|
|
183
|
-
|
|
195
|
+
/*
|
|
196
|
+
* Prefer the id the caller already handed us. Deriving it purely
|
|
197
|
+
* from the loaded item meant that opening the modal before (or
|
|
198
|
+
* without) a successful detail fetch produced an Update form with
|
|
199
|
+
* no id: ModelForm silently skipped its fetch, rendered defaults,
|
|
200
|
+
* and BasicForm coerced every untouched Toggle to false - so
|
|
201
|
+
* saving quietly wrote blank values over the real record.
|
|
202
|
+
*/
|
|
203
|
+
modelIdToEdit={
|
|
204
|
+
props.modelDetailProps.modelId || item?.id || undefined
|
|
205
|
+
}
|
|
184
206
|
/>
|
|
185
207
|
) : (
|
|
186
208
|
<></>
|
|
@@ -51,15 +51,55 @@ const ModelDetail: <TBaseModel extends BaseModel>(
|
|
|
51
51
|
JSONObject | undefined
|
|
52
52
|
>(undefined);
|
|
53
53
|
|
|
54
|
+
type HasPermissionToReadFieldFunction = (fieldName: string) => boolean;
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* The server rejects the WHOLE get-item request when the select names a
|
|
58
|
+
* single column the caller cannot read (SelectPermission.checkSelectPermission
|
|
59
|
+
* throws NotAuthorizedException), which blanks the entire card instead of
|
|
60
|
+
* hiding one row. setDetailFields() below already drops unreadable fields
|
|
61
|
+
* from the render, so the fetch has to drop them too - the same thing
|
|
62
|
+
* BaseModelTable does for its selectMoreFields.
|
|
63
|
+
*/
|
|
64
|
+
const hasPermissionToReadField: HasPermissionToReadFieldFunction = (
|
|
65
|
+
fieldName: string,
|
|
66
|
+
): boolean => {
|
|
67
|
+
if (User.isMasterAdmin()) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const accessControl: Dictionary<ColumnAccessControl> =
|
|
72
|
+
new props.modelType().getColumnAccessControlForAllColumns() || {};
|
|
73
|
+
|
|
74
|
+
const fieldPermissions: Array<Permission> =
|
|
75
|
+
accessControl[fieldName]?.read || [];
|
|
76
|
+
|
|
77
|
+
return PermissionHelper.doesPermissionsIntersect(
|
|
78
|
+
PermissionUtil.getAllPermissions(),
|
|
79
|
+
fieldPermissions,
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
54
83
|
type GetSelectFields = () => Select<TBaseModel>;
|
|
55
84
|
|
|
56
85
|
const getSelectFields: GetSelectFields = (): Select<TBaseModel> => {
|
|
57
86
|
const select: Select<TBaseModel> = {};
|
|
87
|
+
|
|
88
|
+
/*
|
|
89
|
+
* _id is never a declared field on most cards, but CardModelDetail needs
|
|
90
|
+
* it to know which record its edit modal is updating. It is exempt from
|
|
91
|
+
* select permission checks server-side, so it is always safe to ask for.
|
|
92
|
+
*/
|
|
93
|
+
(select as Dictionary<boolean>)["_id"] = true;
|
|
94
|
+
|
|
58
95
|
for (const field of props.fields) {
|
|
59
96
|
if (!field.field) {
|
|
60
97
|
continue;
|
|
61
98
|
}
|
|
62
99
|
for (const key of Object.keys(field.field)) {
|
|
100
|
+
if (!hasPermissionToReadField(key)) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
63
103
|
select[key as keyof TBaseModel] = true;
|
|
64
104
|
}
|
|
65
105
|
}
|
|
@@ -70,7 +110,8 @@ const ModelDetail: <TBaseModel extends BaseModel>(
|
|
|
70
110
|
typeof field === "string" &&
|
|
71
111
|
field &&
|
|
72
112
|
props.selectMoreFields &&
|
|
73
|
-
(props.selectMoreFields as Select<TBaseModel>)[keyofField]
|
|
113
|
+
(props.selectMoreFields as Select<TBaseModel>)[keyofField] &&
|
|
114
|
+
hasPermissionToReadField(field)
|
|
74
115
|
) {
|
|
75
116
|
select[keyofField] = props.selectMoreFields[keyofField] as JSONObject;
|
|
76
117
|
}
|
|
@@ -91,6 +132,10 @@ const ModelDetail: <TBaseModel extends BaseModel>(
|
|
|
91
132
|
continue;
|
|
92
133
|
}
|
|
93
134
|
for (const key of Object.keys(field.field)) {
|
|
135
|
+
if (!hasPermissionToReadField(key)) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
|
|
94
139
|
if (model.isFileColumn(key)) {
|
|
95
140
|
(relationSelect as JSONObject)[key] = {
|
|
96
141
|
file: true,
|