@oneuptime/common 11.7.1 → 11.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/KubernetesCostAllocation.ts +103 -0
- 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/TableView.ts +40 -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/1785241000000-AddColumnsToTableView.ts +13 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -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/AnalyticsModels/KubernetesCostAllocation.test.ts +16 -0
- 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/JSONFunctions.test.ts +103 -1
- 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/ModelTable/BaseModelTableColumnCustomization.test.tsx +679 -0
- package/Tests/UI/Components/ModelTable/ColumnCustomizationModal.test.tsx +572 -0
- package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +1678 -0
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1094 -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/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/Tests/Utils/UserPreferences.test.ts +563 -0
- package/Types/JSONFunctions.ts +7 -2
- package/Types/Kubernetes/KubernetesCostIngest.ts +37 -1
- 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/ModelForm.tsx +41 -18
- package/UI/Components/MasterPage/MasterPage.tsx +65 -0
- package/UI/Components/ModelDetail/CardModelDetail.tsx +23 -1
- package/UI/Components/ModelDetail/ModelDetail.tsx +46 -1
- package/UI/Components/ModelTable/BaseModelTable.tsx +687 -34
- package/UI/Components/ModelTable/Column.ts +29 -0
- package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +420 -0
- package/UI/Components/ModelTable/ColumnPreference.ts +482 -0
- package/UI/Components/ModelTable/CustomFieldColumns.tsx +326 -0
- package/UI/Components/ModelTable/ExportFromColumns.ts +57 -0
- package/UI/Components/ModelTable/TableView.tsx +24 -2
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +150 -0
- package/UI/Components/Navbar/NavBar.tsx +66 -1
- package/UI/Components/SideMenu/SideMenu.tsx +24 -4
- package/UI/Components/Table/Table.tsx +66 -14
- package/UI/Components/Table/TableRow.tsx +180 -175
- package/UI/Components/Table/Types/Column.ts +20 -0
- package/UI/Utils/Project.ts +214 -18
- package/UI/Utils/TableColumnsToCsv.ts +86 -6
- package/UI/esbuild-config.js +34 -0
- package/Utils/Monitor/MonitorProbeSelectionUtil.ts +72 -0
- package/Utils/UserPreferences.ts +53 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +86 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -1
- 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/TableView.js +40 -0
- package/build/dist/Models/DatabaseModels/TableView.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/1785241000000-AddColumnsToTableView.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -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/JSONFunctions.js +8 -3
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.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/ModelForm.js +37 -17
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.js +50 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.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 +472 -27
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +189 -0
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js +258 -0
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +168 -0
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -0
- 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/ModelTable/TableView.js +13 -2
- package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +84 -0
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.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/SideMenu/SideMenu.js +15 -5
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +46 -13
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +11 -6
- package/build/dist/UI/Components/Table/TableRow.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/Utils/Monitor/MonitorProbeSelectionUtil.js +52 -0
- package/build/dist/Utils/Monitor/MonitorProbeSelectionUtil.js.map +1 -0
- package/build/dist/Utils/UserPreferences.js +33 -0
- package/build/dist/Utils/UserPreferences.js.map +1 -1
- package/package.json +4 -3
|
@@ -9,7 +9,7 @@ import ScheduledMaintenanceState from "../../../Models/DatabaseModels/ScheduledM
|
|
|
9
9
|
import { DropdownOption } from "../../../UI/Components/Dropdown/Dropdown";
|
|
10
10
|
import DropdownUtil from "../../../UI/Utils/Dropdown";
|
|
11
11
|
import MonitorType from "../../Monitor/MonitorType";
|
|
12
|
-
import WorkspaceType from "../WorkspaceType";
|
|
12
|
+
import WorkspaceType, { getWorkspaceTypeDisplayName } from "../WorkspaceType";
|
|
13
13
|
import NotificationRuleEventType from "./EventType";
|
|
14
14
|
import IncidentNotificationRule from "./NotificationRuleTypes/IncidentNotificationRule";
|
|
15
15
|
|
|
@@ -108,32 +108,47 @@ export class NotificationRuleConditionUtil {
|
|
|
108
108
|
eventType === NotificationRuleEventType.IncidentEpisode ||
|
|
109
109
|
eventType === NotificationRuleEventType.ScheduledMaintenance
|
|
110
110
|
) {
|
|
111
|
-
// either create
|
|
111
|
+
// either create a channel, post to an existing channel, or post to a chat.
|
|
112
|
+
|
|
113
|
+
const workspaceDisplayName: string =
|
|
114
|
+
getWorkspaceTypeDisplayName(workspaceType);
|
|
112
115
|
|
|
113
116
|
if (
|
|
114
117
|
!notificationRule.shouldCreateNewChannel &&
|
|
115
|
-
!notificationRule.shouldPostToExistingChannel
|
|
118
|
+
!notificationRule.shouldPostToExistingChannel &&
|
|
119
|
+
!notificationRule.shouldPostToExistingChat
|
|
116
120
|
) {
|
|
117
|
-
return
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
" channel"
|
|
121
|
-
);
|
|
121
|
+
return workspaceType === WorkspaceType.MicrosoftTeams
|
|
122
|
+
? `Please select a destination: create a ${workspaceDisplayName} channel, post to an existing ${workspaceDisplayName} channel, or post to an existing ${workspaceDisplayName} chat`
|
|
123
|
+
: `Please select a destination: create a ${workspaceDisplayName} channel or post to an existing ${workspaceDisplayName} channel`;
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
if (notificationRule.shouldPostToExistingChannel) {
|
|
125
127
|
if (!notificationRule.existingChannelNames?.trim()) {
|
|
126
|
-
return
|
|
128
|
+
return (
|
|
129
|
+
"Existing " + workspaceDisplayName + " channel name is required"
|
|
130
|
+
);
|
|
127
131
|
}
|
|
128
132
|
}
|
|
129
133
|
|
|
130
134
|
if (notificationRule.shouldCreateNewChannel) {
|
|
131
135
|
if (!notificationRule.newChannelTemplateName?.trim()) {
|
|
132
|
-
return "New " +
|
|
136
|
+
return "New " + workspaceDisplayName + " channel name is required";
|
|
133
137
|
}
|
|
134
138
|
}
|
|
135
139
|
}
|
|
136
140
|
|
|
141
|
+
if (notificationRule.shouldPostToExistingChat) {
|
|
142
|
+
if (
|
|
143
|
+
!notificationRule.existingChatIds ||
|
|
144
|
+
notificationRule.existingChatIds.length === 0
|
|
145
|
+
) {
|
|
146
|
+
const workspaceDisplayName: string =
|
|
147
|
+
getWorkspaceTypeDisplayName(workspaceType);
|
|
148
|
+
return `Please select at least one ${workspaceDisplayName} chat to post to. If no chats are listed, add the OneUptime app to a chat in ${workspaceDisplayName} first.`;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
137
152
|
return null;
|
|
138
153
|
}
|
|
139
154
|
|
|
@@ -106,4 +106,5 @@ export default interface WorkspaceMessagePayload {
|
|
|
106
106
|
messageBlocks: Array<WorkspaceMessageBlock>; // Message to add to blocks.
|
|
107
107
|
workspaceType: WorkspaceType;
|
|
108
108
|
teamId?: string | undefined; // Team ID for Microsoft Teams
|
|
109
|
+
chatIds?: Array<string> | undefined; // Microsoft Teams chat ids (group / personal chats) to send message to.
|
|
109
110
|
}
|
|
@@ -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
|
+
}
|
|
@@ -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>,
|
|
@@ -27,6 +27,70 @@ const MasterPage: FunctionComponent<ComponentProps> = (
|
|
|
27
27
|
props: ComponentProps,
|
|
28
28
|
): ReactElement => {
|
|
29
29
|
const [isOnline, setIsOnline] = React.useState(true);
|
|
30
|
+
const topSectionRef: React.RefObject<HTMLDivElement> =
|
|
31
|
+
React.useRef<HTMLDivElement>(null);
|
|
32
|
+
|
|
33
|
+
/*
|
|
34
|
+
* Publish the sticky top section's height as --app-header-height so anything
|
|
35
|
+
* that sticks underneath it (the side menu, for example) can offset itself by
|
|
36
|
+
* the real header instead of guessing and ending up tucked behind it. The
|
|
37
|
+
* height is not a constant — it changes when the navbar is hidden, when the
|
|
38
|
+
* header wraps on narrow viewports and when top alerts appear — so keep it in
|
|
39
|
+
* sync rather than measuring once.
|
|
40
|
+
*/
|
|
41
|
+
React.useLayoutEffect(() => {
|
|
42
|
+
const setHeaderHeight: (height: number) => void = (
|
|
43
|
+
height: number,
|
|
44
|
+
): void => {
|
|
45
|
+
document.documentElement.style.setProperty(
|
|
46
|
+
"--app-header-height",
|
|
47
|
+
`${height}px`,
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const element: HTMLDivElement | null = topSectionRef.current;
|
|
52
|
+
|
|
53
|
+
if (!element || props.makeTopSectionUnstick) {
|
|
54
|
+
// Nothing is overlaying the content, so no offset is needed.
|
|
55
|
+
setHeaderHeight(0);
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const measure: () => void = (): void => {
|
|
60
|
+
setHeaderHeight(element.offsetHeight);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
measure();
|
|
64
|
+
|
|
65
|
+
/*
|
|
66
|
+
* ResizeObserver is missing in jsdom and in older browsers, so fall back to
|
|
67
|
+
* resize events there — less precise, but the header only really changes
|
|
68
|
+
* height when the viewport does.
|
|
69
|
+
*/
|
|
70
|
+
if (typeof ResizeObserver === "undefined") {
|
|
71
|
+
window.addEventListener("resize", measure);
|
|
72
|
+
|
|
73
|
+
return () => {
|
|
74
|
+
window.removeEventListener("resize", measure);
|
|
75
|
+
document.documentElement.style.removeProperty("--app-header-height");
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const observer: ResizeObserver = new ResizeObserver(measure);
|
|
80
|
+
observer.observe(element);
|
|
81
|
+
|
|
82
|
+
return () => {
|
|
83
|
+
observer.disconnect();
|
|
84
|
+
document.documentElement.style.removeProperty("--app-header-height");
|
|
85
|
+
};
|
|
86
|
+
}, [
|
|
87
|
+
props.makeTopSectionUnstick,
|
|
88
|
+
props.hideHeader,
|
|
89
|
+
props.isLoading,
|
|
90
|
+
props.error,
|
|
91
|
+
props.disableMainContentWrapper,
|
|
92
|
+
isOnline,
|
|
93
|
+
]);
|
|
30
94
|
|
|
31
95
|
if (props.isLoading) {
|
|
32
96
|
return (
|
|
@@ -62,6 +126,7 @@ const MasterPage: FunctionComponent<ComponentProps> = (
|
|
|
62
126
|
</a>
|
|
63
127
|
)}
|
|
64
128
|
<div
|
|
129
|
+
ref={topSectionRef}
|
|
65
130
|
className={props.makeTopSectionUnstick ? "" : "sticky top-0 z-10"}
|
|
66
131
|
>
|
|
67
132
|
<TopSection
|
|
@@ -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,
|