@oneuptime/common 11.5.12 → 11.6.0
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/AIInsight.ts +30 -0
- package/Models/DatabaseModels/EnterpriseLicense.ts +21 -0
- package/Models/DatabaseModels/EnterpriseLicenseInstance.ts +25 -0
- package/Models/DatabaseModels/GlobalConfig.ts +76 -0
- package/Models/DatabaseModels/Project.ts +30 -0
- package/Models/DatabaseModels/TelemetryException.ts +128 -0
- package/Server/API/AIAgentDataAPI.ts +129 -5
- package/Server/API/AIInvestigationAPI.ts +87 -0
- package/Server/API/EnterpriseLicenseAPI.ts +57 -0
- package/Server/API/GlobalConfigAPI.ts +62 -1
- package/Server/EnvironmentConfig.ts +22 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784640000000-AddExceptionTriageAndPrivacyColumns.ts +56 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.ts +38 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Services/AIRunService.ts +8 -0
- package/Server/Services/AnalyticsDatabaseService.ts +48 -45
- package/Server/Services/DatabaseService.ts +66 -1
- package/Server/Services/TelemetryExceptionService.ts +320 -24
- package/Server/Services/WorkflowService.ts +100 -39
- package/Server/Types/Workflow/Components/Schedule.ts +57 -32
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +15 -4
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +15 -4
- package/Server/Utils/AI/SRE/Insights/InsightScanner.ts +222 -24
- package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +225 -9
- package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +39 -0
- package/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.ts +114 -0
- package/Server/Utils/AnalyticsDatabase/InsertDedupContext.ts +59 -0
- package/Server/Utils/Express.ts +13 -0
- package/Server/Utils/Telemetry/ExceptionSanitizer.ts +222 -0
- package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +799 -0
- package/Server/Utils/Telemetry/TelemetryWriterClient.ts +263 -0
- package/Server/Utils/Telemetry/TelemetryWriterServer.ts +240 -0
- package/Server/Utils/Telemetry/TelemetryWriterShedMetrics.ts +93 -0
- package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +232 -0
- package/Tests/Server/Services/TelemetryExceptionCodeFixRun.test.ts +205 -1
- package/Tests/Server/Services/UpdateOneByIdKeepsRowId.test.ts +107 -0
- package/Tests/Server/Services/WorkflowService.test.ts +308 -0
- package/Tests/Server/Utils/AI/Insights/InsightScanner.test.ts +150 -141
- package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +277 -1
- package/Tests/Server/Utils/Attribution.test.ts +203 -0
- package/Tests/Server/Utils/ExceptionSanitizer.test.ts +70 -0
- package/Tests/Server/Utils/InsightTriageClassification.test.ts +57 -0
- package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +183 -0
- package/Tests/Server/Utils/Marketing/GoogleAds.test.ts +340 -0
- package/Tests/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.test.ts +87 -0
- package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +165 -0
- package/Tests/Server/Utils/Monitor/Criteria/TraceMonitorCriteria.test.ts +86 -0
- package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +1565 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterClient.test.ts +313 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterServer.test.ts +270 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterShedMetrics.test.ts +127 -0
- package/Tests/Server/Utils/TelemetryImprovementTaskTrigger.test.ts +141 -0
- package/Tests/Types/AI/CodeFixTaskType.test.ts +3 -0
- package/Tests/Types/Monitor/MonitorCriteriaMetricVariables.test.ts +228 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +169 -0
- package/Tests/Types/Monitor/MonitorStepExceptionMonitor.test.ts +289 -0
- package/Tests/Types/Monitor/MonitorStepLogMonitor.test.ts +231 -0
- package/Tests/Types/Monitor/MonitorStepMetricViewConfigUtil.test.ts +245 -0
- package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +155 -0
- package/Tests/Types/Monitor/MonitorStepTelemetrySerialization.test.ts +141 -0
- package/Tests/Types/Monitor/MonitorStepTraceMonitor.test.ts +137 -0
- package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +311 -0
- package/Tests/UI/Components/ModelTableSelectFromColumns.test.ts +259 -0
- package/Tests/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.test.ts +461 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +2852 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +758 -0
- package/Tests/UI/Utils/NotificationMethodUtil.test.ts +564 -0
- package/Tests/Utils/Array.test.ts +156 -0
- package/Tests/Utils/CronTab.test.ts +199 -0
- package/Tests/Utils/ModelImportExport.test.ts +101 -0
- package/Tests/Utils/Number.test.ts +179 -0
- package/Tests/Utils/VersionUtil.test.ts +348 -0
- package/Tests/jest.setup.ts +1 -0
- package/Types/AI/CodeFixTaskContext.ts +6 -0
- package/Types/AI/CodeFixTaskType.ts +38 -1
- package/Types/AI/ExceptionAIClassification.ts +27 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +6 -0
- package/Types/Log/LogScrubPatternType.ts +7 -0
- package/Types/Monitor/MonitorStep.ts +24 -4
- package/Types/Monitor/MonitorStepMetricViewConfigUtil.ts +105 -0
- package/Types/Trace/TraceScrubPatternType.ts +7 -0
- package/UI/Components/EditionLabel/EditionLabel.tsx +445 -12
- package/UI/Components/ModelTable/BaseModelTable.tsx +15 -46
- package/UI/Components/ModelTable/SelectFromColumns.ts +129 -0
- package/UI/Components/Workflow/ArgumentsForm.tsx +68 -30
- package/UI/Components/Workflow/CronScheduleField.tsx +411 -0
- package/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.ts +176 -0
- package/UI/Utils/NotificationMethodUtil.ts +310 -0
- package/Utils/CronTab.ts +823 -0
- package/Utils/ModelImportExport.ts +21 -6
- package/Utils/VersionUtil.ts +260 -0
- package/build/dist/Models/DatabaseModels/AIInsight.js +31 -0
- package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +22 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js +26 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +81 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +31 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +134 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +97 -8
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +55 -0
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +47 -0
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +52 -1
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +17 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784640000000-AddExceptionTriageAndPrivacyColumns.js +33 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784640000000-AddExceptionTriageAndPrivacyColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.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/AIRunService.js +9 -2
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +44 -16
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +53 -1
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryExceptionService.js +263 -22
- package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowService.js +80 -30
- package/build/dist/Server/Services/WorkflowService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Schedule.js +44 -19
- package/build/dist/Server/Types/Workflow/Components/Schedule.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +12 -4
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +12 -4
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightScanner.js +193 -22
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightScanner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +178 -9
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +37 -0
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js +98 -0
- package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js +24 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js.map +1 -0
- package/build/dist/Server/Utils/Express.js +12 -0
- package/build/dist/Server/Utils/Express.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js +149 -0
- package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js +496 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterClient.js +165 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterClient.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterServer.js +136 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterServer.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterShedMetrics.js +76 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterShedMetrics.js.map +1 -0
- package/build/dist/Types/AI/CodeFixTaskType.js +38 -1
- package/build/dist/Types/AI/CodeFixTaskType.js.map +1 -1
- package/build/dist/Types/AI/ExceptionAIClassification.js +28 -0
- package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -0
- package/build/dist/Types/Log/LogScrubPatternType.js +7 -0
- package/build/dist/Types/Log/LogScrubPatternType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +20 -4
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js +73 -0
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js.map +1 -0
- package/build/dist/Types/Trace/TraceScrubPatternType.js +7 -0
- package/build/dist/Types/Trace/TraceScrubPatternType.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +261 -13
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +12 -37
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/SelectFromColumns.js +82 -0
- package/build/dist/UI/Components/ModelTable/SelectFromColumns.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +30 -6
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/CronScheduleField.js +209 -0
- package/build/dist/UI/Components/Workflow/CronScheduleField.js.map +1 -0
- package/build/dist/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.js +129 -0
- package/build/dist/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.js.map +1 -0
- package/build/dist/UI/Utils/NotificationMethodUtil.js +189 -0
- package/build/dist/UI/Utils/NotificationMethodUtil.js.map +1 -0
- package/build/dist/Utils/CronTab.js +609 -0
- package/build/dist/Utils/CronTab.js.map +1 -0
- package/build/dist/Utils/ModelImportExport.js +20 -6
- package/build/dist/Utils/ModelImportExport.js.map +1 -1
- package/build/dist/Utils/VersionUtil.js +193 -0
- package/build/dist/Utils/VersionUtil.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { DropdownOption } from "../Components/Dropdown/Dropdown";
|
|
2
|
+
import Select from "../../Types/BaseDatabase/Select";
|
|
3
|
+
import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
4
|
+
import UserCall from "../../Models/DatabaseModels/UserCall";
|
|
5
|
+
import UserEmail from "../../Models/DatabaseModels/UserEmail";
|
|
6
|
+
import UserNotificationRule from "../../Models/DatabaseModels/UserNotificationRule";
|
|
7
|
+
import UserPush from "../../Models/DatabaseModels/UserPush";
|
|
8
|
+
import UserSMS from "../../Models/DatabaseModels/UserSMS";
|
|
9
|
+
import UserTelegram from "../../Models/DatabaseModels/UserTelegram";
|
|
10
|
+
import UserWebhook from "../../Models/DatabaseModels/UserWebhook";
|
|
11
|
+
import UserWhatsApp from "../../Models/DatabaseModels/UserWhatsApp";
|
|
12
|
+
import ObjectID from "../../Types/ObjectID";
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* The four on-call rule pages (alert, incident, alert episode, incident
|
|
16
|
+
* episode) each let a user pick one of their notification methods from a single
|
|
17
|
+
* dropdown. Every method lives in its own model, so building the dropdown and
|
|
18
|
+
* mapping the chosen option back onto the rule used to be ~140 lines duplicated
|
|
19
|
+
* verbatim across all four pages. Adding a method meant four identical edits,
|
|
20
|
+
* and missing one silently dropped that method from a rule type.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* Anything that exposes column values by name. DatabaseBaseModel satisfies
|
|
25
|
+
* this; keeping the surface this small is what makes the display helpers
|
|
26
|
+
* testable without constructing decorated model instances.
|
|
27
|
+
*/
|
|
28
|
+
export interface ColumnValueReader {
|
|
29
|
+
getColumnValue: (columnName: string) => unknown;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* The per-user notification methods a rule can point at. */
|
|
33
|
+
export interface NotificationMethodModels {
|
|
34
|
+
userCalls: Array<UserCall>;
|
|
35
|
+
userEmails: Array<UserEmail>;
|
|
36
|
+
userSMSs: Array<UserSMS>;
|
|
37
|
+
userPush: Array<UserPush>;
|
|
38
|
+
userWhatsApps: Array<UserWhatsApp>;
|
|
39
|
+
userTelegrams: Array<UserTelegram>;
|
|
40
|
+
userWebhooks: Array<UserWebhook>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* One rendered "Notification Method" line, e.g. `Email: jane@example.com`. */
|
|
44
|
+
export interface NotificationMethodDisplayItem {
|
|
45
|
+
/* The method name shown before the colon, e.g. "Email". */
|
|
46
|
+
title: string;
|
|
47
|
+
/* The identifier of the method itself, e.g. the address or device name. */
|
|
48
|
+
value: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
* A relation on UserNotificationRule / UserOnCallLogTimeline, and how to turn
|
|
53
|
+
* it into a display line. `columns` is tried in order so a method can fall back
|
|
54
|
+
* to a secondary identifier (a Telegram chat id when the handle is unknown).
|
|
55
|
+
*/
|
|
56
|
+
interface NotificationMethodRelation {
|
|
57
|
+
relationName: string;
|
|
58
|
+
title: string;
|
|
59
|
+
columns: Array<string>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/*
|
|
63
|
+
* Display order for the "Notification Method" table cell. A rule only ever has
|
|
64
|
+
* one method set, so this order is cosmetic, but it is kept stable so the cell
|
|
65
|
+
* reads identically wherever it is rendered.
|
|
66
|
+
*/
|
|
67
|
+
const NOTIFICATION_METHOD_RELATIONS: Array<NotificationMethodRelation> = [
|
|
68
|
+
{ relationName: "userEmail", title: "Email", columns: ["email"] },
|
|
69
|
+
{ relationName: "userCall", title: "Call", columns: ["phone"] },
|
|
70
|
+
{ relationName: "userSms", title: "SMS", columns: ["phone"] },
|
|
71
|
+
{ relationName: "userWhatsApp", title: "WhatsApp", columns: ["phone"] },
|
|
72
|
+
{
|
|
73
|
+
relationName: "userTelegram",
|
|
74
|
+
title: "Telegram",
|
|
75
|
+
columns: ["telegramUserHandle", "telegramChatId"],
|
|
76
|
+
},
|
|
77
|
+
/*
|
|
78
|
+
* Only `name` is read here. A webhook URL is a bearer credential for
|
|
79
|
+
* Slack/Discord/Teams style hooks, so it is deliberately never selected into
|
|
80
|
+
* the browser or rendered. `name` is NOT NULL on UserWebhook.
|
|
81
|
+
*/
|
|
82
|
+
{ relationName: "userWebhook", title: "Webhook", columns: ["name"] },
|
|
83
|
+
{ relationName: "userPush", title: "Push", columns: ["deviceName"] },
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
export default class NotificationMethodUtil {
|
|
87
|
+
/*
|
|
88
|
+
* The relation -> column selection the on-call rule tables need in order to
|
|
89
|
+
* render the "Notification Method" cell. Shared so every table that renders
|
|
90
|
+
* NotificationMethodView selects the same fields; a table that under-selects
|
|
91
|
+
* silently renders a blank cell.
|
|
92
|
+
*/
|
|
93
|
+
public static getSelectForNotificationMethods<
|
|
94
|
+
TBaseModel extends BaseModel,
|
|
95
|
+
>(): Select<TBaseModel> {
|
|
96
|
+
const select: Record<string, Record<string, boolean>> = {};
|
|
97
|
+
|
|
98
|
+
for (const relation of NOTIFICATION_METHOD_RELATIONS) {
|
|
99
|
+
const columns: Record<string, boolean> = {};
|
|
100
|
+
|
|
101
|
+
for (const column of relation.columns) {
|
|
102
|
+
columns[column] = true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
select[relation.relationName] = columns;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return select as Select<TBaseModel>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/*
|
|
112
|
+
* Turns a rule (or an on-call log timeline entry) into the lines to render in
|
|
113
|
+
* the "Notification Method" column. Returns an empty array when no method
|
|
114
|
+
* relation was loaded or populated.
|
|
115
|
+
*/
|
|
116
|
+
public static getDisplayItems(
|
|
117
|
+
item: ColumnValueReader,
|
|
118
|
+
): Array<NotificationMethodDisplayItem> {
|
|
119
|
+
const displayItems: Array<NotificationMethodDisplayItem> = [];
|
|
120
|
+
|
|
121
|
+
for (const relation of NOTIFICATION_METHOD_RELATIONS) {
|
|
122
|
+
const relationValue: unknown = item.getColumnValue(relation.relationName);
|
|
123
|
+
|
|
124
|
+
if (!relationValue || typeof relationValue !== "object") {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const value: string | undefined = NotificationMethodUtil.firstNonEmpty(
|
|
129
|
+
relationValue as Record<string, unknown>,
|
|
130
|
+
relation.columns,
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
if (value) {
|
|
134
|
+
displayItems.push({ title: relation.title, value: value });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return displayItems;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/*
|
|
142
|
+
* The dropdown shown on the on-call rule create form. Every method the user
|
|
143
|
+
* has configured becomes one option, prefixed with the method name so a phone
|
|
144
|
+
* number used for both SMS and WhatsApp stays distinguishable.
|
|
145
|
+
*/
|
|
146
|
+
public static getDropdownOptions(
|
|
147
|
+
models: NotificationMethodModels,
|
|
148
|
+
): Array<DropdownOption> {
|
|
149
|
+
return NotificationMethodUtil.toOrderedList(models).map(
|
|
150
|
+
(model: BaseModel) => {
|
|
151
|
+
return {
|
|
152
|
+
label: NotificationMethodUtil.getLabel(model),
|
|
153
|
+
value: model.id!.toString(),
|
|
154
|
+
};
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/*
|
|
160
|
+
* The label for a single method, e.g. `SMS: +15550100`. Exported separately so
|
|
161
|
+
* the dropdown and any future surface stay in agreement.
|
|
162
|
+
*/
|
|
163
|
+
public static getLabel(model: BaseModel): string {
|
|
164
|
+
if (model instanceof UserWebhook) {
|
|
165
|
+
return (
|
|
166
|
+
"Webhook: " +
|
|
167
|
+
(NotificationMethodUtil.readColumn(model, "name") || "Unknown Webhook")
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (model instanceof UserPush) {
|
|
172
|
+
return (
|
|
173
|
+
"Push: " +
|
|
174
|
+
(NotificationMethodUtil.readColumn(model, "deviceName") ||
|
|
175
|
+
"Unknown Device")
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (model instanceof UserTelegram) {
|
|
180
|
+
return (
|
|
181
|
+
"Telegram: " +
|
|
182
|
+
(NotificationMethodUtil.readColumn(model, "telegramUserHandle") ||
|
|
183
|
+
NotificationMethodUtil.readColumn(model, "telegramChatId") ||
|
|
184
|
+
"Unknown Chat")
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const identifier: string =
|
|
189
|
+
NotificationMethodUtil.readColumn(model, "phone") ||
|
|
190
|
+
NotificationMethodUtil.readColumn(model, "email") ||
|
|
191
|
+
"";
|
|
192
|
+
|
|
193
|
+
if (model instanceof UserCall) {
|
|
194
|
+
return "Call: " + identifier;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (model instanceof UserSMS) {
|
|
198
|
+
return "SMS: " + identifier;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (model instanceof UserWhatsApp) {
|
|
202
|
+
return "WhatsApp: " + identifier;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return "Email: " + identifier;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/*
|
|
209
|
+
* Maps the id chosen in the dropdown back onto the rule being created. The
|
|
210
|
+
* dropdown is single-select, so at most one of the seven foreign keys is set.
|
|
211
|
+
* An id that matches nothing leaves the rule untouched, and the server then
|
|
212
|
+
* rejects the create as having no notification method.
|
|
213
|
+
*/
|
|
214
|
+
public static setSelectedMethodOnRule(
|
|
215
|
+
rule: UserNotificationRule,
|
|
216
|
+
selectedValue: unknown,
|
|
217
|
+
models: NotificationMethodModels,
|
|
218
|
+
): UserNotificationRule {
|
|
219
|
+
if (!selectedValue) {
|
|
220
|
+
return rule;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const selectedId: string = selectedValue.toString();
|
|
224
|
+
|
|
225
|
+
const assignById: (
|
|
226
|
+
candidates: Array<BaseModel>,
|
|
227
|
+
assign: (id: ObjectID) => void,
|
|
228
|
+
) => void = (
|
|
229
|
+
candidates: Array<BaseModel>,
|
|
230
|
+
assign: (id: ObjectID) => void,
|
|
231
|
+
): void => {
|
|
232
|
+
const match: BaseModel | undefined = candidates.find(
|
|
233
|
+
(candidate: BaseModel) => {
|
|
234
|
+
return candidate.id?.toString() === selectedId;
|
|
235
|
+
},
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
if (match) {
|
|
239
|
+
assign(match.id!);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
assignById(models.userEmails, (id: ObjectID) => {
|
|
244
|
+
rule.userEmailId = id;
|
|
245
|
+
});
|
|
246
|
+
assignById(models.userSMSs, (id: ObjectID) => {
|
|
247
|
+
rule.userSmsId = id;
|
|
248
|
+
});
|
|
249
|
+
assignById(models.userCalls, (id: ObjectID) => {
|
|
250
|
+
rule.userCallId = id;
|
|
251
|
+
});
|
|
252
|
+
assignById(models.userPush, (id: ObjectID) => {
|
|
253
|
+
rule.userPushId = id;
|
|
254
|
+
});
|
|
255
|
+
assignById(models.userWhatsApps, (id: ObjectID) => {
|
|
256
|
+
rule.userWhatsAppId = id;
|
|
257
|
+
});
|
|
258
|
+
assignById(models.userTelegrams, (id: ObjectID) => {
|
|
259
|
+
rule.userTelegramId = id;
|
|
260
|
+
});
|
|
261
|
+
assignById(models.userWebhooks, (id: ObjectID) => {
|
|
262
|
+
rule.userWebhookId = id;
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
return rule;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/*
|
|
269
|
+
* Dropdown ordering: methods are grouped by type in a fixed order so the list
|
|
270
|
+
* does not reshuffle between page loads.
|
|
271
|
+
*/
|
|
272
|
+
private static toOrderedList(
|
|
273
|
+
models: NotificationMethodModels,
|
|
274
|
+
): Array<BaseModel> {
|
|
275
|
+
return [
|
|
276
|
+
...models.userCalls,
|
|
277
|
+
...models.userEmails,
|
|
278
|
+
...models.userSMSs,
|
|
279
|
+
...models.userPush,
|
|
280
|
+
...models.userWhatsApps,
|
|
281
|
+
...models.userTelegrams,
|
|
282
|
+
...models.userWebhooks,
|
|
283
|
+
];
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private static readColumn(model: BaseModel, columnName: string): string {
|
|
287
|
+
const value: unknown = model.getColumnValue(columnName);
|
|
288
|
+
|
|
289
|
+
if (value === undefined || value === null || value === "") {
|
|
290
|
+
return "";
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return value.toString();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private static firstNonEmpty(
|
|
297
|
+
source: Record<string, unknown>,
|
|
298
|
+
columns: Array<string>,
|
|
299
|
+
): string | undefined {
|
|
300
|
+
for (const column of columns) {
|
|
301
|
+
const value: unknown = source[column];
|
|
302
|
+
|
|
303
|
+
if (value !== undefined && value !== null && value !== "") {
|
|
304
|
+
return value.toString();
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return undefined;
|
|
309
|
+
}
|
|
310
|
+
}
|