@oneuptime/common 10.4.3 → 10.4.5
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/Server/Services/UserCallService.ts +20 -0
- package/Server/Services/UserIncomingCallNumberService.ts +22 -0
- package/Server/Services/UserSmsService.ts +20 -0
- package/Types/Dashboard/DashboardComponents/DashboardHostMetricChartComponent.ts +2 -0
- package/Types/Dashboard/DashboardTemplates.ts +290 -0
- package/Utils/Dashboard/Components/DashboardHostMetricChartComponent.ts +29 -0
- package/Utils/Dashboard/ModelQueryVariableInterpolation.ts +98 -0
- package/build/dist/Server/Services/UserCallService.js +14 -2
- package/build/dist/Server/Services/UserCallService.js.map +1 -1
- package/build/dist/Server/Services/UserIncomingCallNumberService.js +15 -2
- package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
- package/build/dist/Server/Services/UserSmsService.js +14 -2
- package/build/dist/Server/Services/UserSmsService.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardHostMetricChartComponent.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +259 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardHostMetricChartComponent.js +28 -0
- package/build/dist/Utils/Dashboard/Components/DashboardHostMetricChartComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/ModelQueryVariableInterpolation.js +66 -0
- package/build/dist/Utils/Dashboard/ModelQueryVariableInterpolation.js.map +1 -0
- package/package.json +1 -1
|
@@ -91,7 +91,17 @@ export class Service extends DatabaseService<Model> {
|
|
|
91
91
|
);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
/*
|
|
95
|
+
* If the project has its own default Twilio config, OneUptime does not
|
|
96
|
+
* charge the project's Call/SMS balance, so the low-balance check does not apply.
|
|
97
|
+
*/
|
|
98
|
+
const projectTwilioConfig: TwilioConfig | undefined =
|
|
99
|
+
await ProjectCallSMSConfigService.getProjectDefaultTwilioConfig(
|
|
100
|
+
createBy.data.projectId!,
|
|
101
|
+
);
|
|
102
|
+
|
|
94
103
|
if (
|
|
104
|
+
!projectTwilioConfig &&
|
|
95
105
|
(project.smsOrCallCurrentBalanceInUSDCents as number) <= 100 &&
|
|
96
106
|
IsBillingEnabled
|
|
97
107
|
) {
|
|
@@ -161,7 +171,17 @@ export class Service extends DatabaseService<Model> {
|
|
|
161
171
|
);
|
|
162
172
|
}
|
|
163
173
|
|
|
174
|
+
/*
|
|
175
|
+
* If the project has its own default Twilio config, OneUptime does not
|
|
176
|
+
* charge the project's Call/SMS balance, so the low-balance check does not apply.
|
|
177
|
+
*/
|
|
178
|
+
const projectTwilioConfig: TwilioConfig | undefined =
|
|
179
|
+
await ProjectCallSMSConfigService.getProjectDefaultTwilioConfig(
|
|
180
|
+
item.projectId!,
|
|
181
|
+
);
|
|
182
|
+
|
|
164
183
|
if (
|
|
184
|
+
!projectTwilioConfig &&
|
|
165
185
|
(project.smsOrCallCurrentBalanceInUSDCents as number) <= 100 &&
|
|
166
186
|
IsBillingEnabled
|
|
167
187
|
) {
|
|
@@ -3,8 +3,10 @@ import CreateBy from "../Types/Database/CreateBy";
|
|
|
3
3
|
import { OnCreate } from "../Types/Database/Hooks";
|
|
4
4
|
import logger from "../Utils/Logger";
|
|
5
5
|
import DatabaseService from "./DatabaseService";
|
|
6
|
+
import ProjectCallSMSConfigService from "./ProjectCallSMSConfigService";
|
|
6
7
|
import ProjectService from "./ProjectService";
|
|
7
8
|
import SmsService from "./SmsService";
|
|
9
|
+
import TwilioConfig from "../../Types/CallAndSMS/TwilioConfig";
|
|
8
10
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
9
11
|
import ObjectID from "../../Types/ObjectID";
|
|
10
12
|
import Text from "../../Types/Text";
|
|
@@ -48,7 +50,17 @@ export class Service extends DatabaseService<Model> {
|
|
|
48
50
|
);
|
|
49
51
|
}
|
|
50
52
|
|
|
53
|
+
/*
|
|
54
|
+
* If the project has its own default Twilio config, OneUptime does not
|
|
55
|
+
* charge the project's SMS balance, so the low-balance check does not apply.
|
|
56
|
+
*/
|
|
57
|
+
const projectTwilioConfig: TwilioConfig | undefined =
|
|
58
|
+
await ProjectCallSMSConfigService.getProjectDefaultTwilioConfig(
|
|
59
|
+
createBy.data.projectId!,
|
|
60
|
+
);
|
|
61
|
+
|
|
51
62
|
if (
|
|
63
|
+
!projectTwilioConfig &&
|
|
52
64
|
(project.smsOrCallCurrentBalanceInUSDCents as number) <= 100 &&
|
|
53
65
|
IsBillingEnabled
|
|
54
66
|
) {
|
|
@@ -141,7 +153,17 @@ export class Service extends DatabaseService<Model> {
|
|
|
141
153
|
);
|
|
142
154
|
}
|
|
143
155
|
|
|
156
|
+
/*
|
|
157
|
+
* If the project has its own default Twilio config, OneUptime does not
|
|
158
|
+
* charge the project's SMS balance, so the low-balance check does not apply.
|
|
159
|
+
*/
|
|
160
|
+
const projectTwilioConfig: TwilioConfig | undefined =
|
|
161
|
+
await ProjectCallSMSConfigService.getProjectDefaultTwilioConfig(
|
|
162
|
+
item.projectId!,
|
|
163
|
+
);
|
|
164
|
+
|
|
144
165
|
if (
|
|
166
|
+
!projectTwilioConfig &&
|
|
145
167
|
(project.smsOrCallCurrentBalanceInUSDCents as number) <= 100 &&
|
|
146
168
|
IsBillingEnabled
|
|
147
169
|
) {
|
|
@@ -90,7 +90,17 @@ export class Service extends DatabaseService<Model> {
|
|
|
90
90
|
);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
/*
|
|
94
|
+
* If the project has its own default Twilio config, OneUptime does not
|
|
95
|
+
* charge the project's SMS balance, so the low-balance check does not apply.
|
|
96
|
+
*/
|
|
97
|
+
const projectTwilioConfig: TwilioConfig | undefined =
|
|
98
|
+
await ProjectCallSMSConfigService.getProjectDefaultTwilioConfig(
|
|
99
|
+
createBy.data.projectId!,
|
|
100
|
+
);
|
|
101
|
+
|
|
93
102
|
if (
|
|
103
|
+
!projectTwilioConfig &&
|
|
94
104
|
(project.smsOrCallCurrentBalanceInUSDCents as number) <= 100 &&
|
|
95
105
|
IsBillingEnabled
|
|
96
106
|
) {
|
|
@@ -161,7 +171,17 @@ export class Service extends DatabaseService<Model> {
|
|
|
161
171
|
);
|
|
162
172
|
}
|
|
163
173
|
|
|
174
|
+
/*
|
|
175
|
+
* If the project has its own default Twilio config, OneUptime does not
|
|
176
|
+
* charge the project's SMS balance, so the low-balance check does not apply.
|
|
177
|
+
*/
|
|
178
|
+
const projectTwilioConfig: TwilioConfig | undefined =
|
|
179
|
+
await ProjectCallSMSConfigService.getProjectDefaultTwilioConfig(
|
|
180
|
+
item.projectId!,
|
|
181
|
+
);
|
|
182
|
+
|
|
164
183
|
if (
|
|
184
|
+
!projectTwilioConfig &&
|
|
165
185
|
(project.smsOrCallCurrentBalanceInUSDCents as number) <= 100 &&
|
|
166
186
|
IsBillingEnabled
|
|
167
187
|
) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import ObjectID from "../../ObjectID";
|
|
2
|
+
import DashboardChartType from "../Chart/ChartType";
|
|
2
3
|
import DashboardComponentType from "../DashboardComponentType";
|
|
3
4
|
import BaseComponent from "./DashboardBaseComponent";
|
|
4
5
|
|
|
@@ -21,5 +22,6 @@ export default interface DashboardHostMetricChartComponent
|
|
|
21
22
|
description?: string | undefined;
|
|
22
23
|
metricKind?: HostMetricKind | undefined;
|
|
23
24
|
hostIdentifier?: string | undefined;
|
|
25
|
+
chartType?: DashboardChartType | undefined;
|
|
24
26
|
};
|
|
25
27
|
}
|
|
@@ -11,6 +11,7 @@ import IncidentMetricType from "../Incident/IncidentMetricType";
|
|
|
11
11
|
import MonitorMetricType from "../Monitor/MonitorMetricType";
|
|
12
12
|
import MetricDashboardMetricType from "../Metrics/MetricDashboardMetricType";
|
|
13
13
|
import { DashboardValueTrendDirection } from "./DashboardComponents/DashboardValueComponent";
|
|
14
|
+
import { HostMetricKind } from "./DashboardComponents/DashboardHostMetricChartComponent";
|
|
14
15
|
|
|
15
16
|
/*
|
|
16
17
|
* Trace / Exception / Profiles entries are intentionally not in this
|
|
@@ -25,6 +26,7 @@ export enum DashboardTemplateType {
|
|
|
25
26
|
Monitor = "Monitor",
|
|
26
27
|
Incident = "Incident",
|
|
27
28
|
Kubernetes = "Kubernetes",
|
|
29
|
+
Host = "Host",
|
|
28
30
|
Metrics = "Metrics",
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -63,6 +65,13 @@ export const DashboardTemplates: Array<DashboardTemplate> = [
|
|
|
63
65
|
"Pod/node CPU and memory averages, utilization gauges, live pod and node lists, network I/O, restarts, and cluster logs.",
|
|
64
66
|
icon: IconProp.Kubernetes,
|
|
65
67
|
},
|
|
68
|
+
{
|
|
69
|
+
type: DashboardTemplateType.Host,
|
|
70
|
+
name: "Hosts Dashboard",
|
|
71
|
+
description:
|
|
72
|
+
"Per-host CPU, memory, disk and network charts, a live host inventory, CPU utilization gauge, process counts, and recent logs.",
|
|
73
|
+
icon: IconProp.Server,
|
|
74
|
+
},
|
|
66
75
|
{
|
|
67
76
|
type: DashboardTemplateType.Metrics,
|
|
68
77
|
name: "Metrics Dashboard",
|
|
@@ -374,6 +383,62 @@ function createKubernetesNodeListComponent(data: {
|
|
|
374
383
|
};
|
|
375
384
|
}
|
|
376
385
|
|
|
386
|
+
function createHostListComponent(data: {
|
|
387
|
+
title: string;
|
|
388
|
+
top: number;
|
|
389
|
+
left: number;
|
|
390
|
+
width: number;
|
|
391
|
+
height: number;
|
|
392
|
+
maxRows?: number;
|
|
393
|
+
statusFilter?: string;
|
|
394
|
+
osTypeFilter?: string;
|
|
395
|
+
}): DashboardBaseComponent {
|
|
396
|
+
return {
|
|
397
|
+
_type: ObjectType.DashboardComponent,
|
|
398
|
+
componentType: DashboardComponentType.HostList,
|
|
399
|
+
componentId: ObjectID.generate(),
|
|
400
|
+
topInDashboardUnits: data.top,
|
|
401
|
+
leftInDashboardUnits: data.left,
|
|
402
|
+
widthInDashboardUnits: data.width,
|
|
403
|
+
heightInDashboardUnits: data.height,
|
|
404
|
+
minHeightInDashboardUnits: 3,
|
|
405
|
+
minWidthInDashboardUnits: 6,
|
|
406
|
+
arguments: {
|
|
407
|
+
title: data.title,
|
|
408
|
+
maxRows: data.maxRows ?? 25,
|
|
409
|
+
statusFilter: data.statusFilter,
|
|
410
|
+
osTypeFilter: data.osTypeFilter,
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function createHostMetricChartComponent(data: {
|
|
416
|
+
title: string;
|
|
417
|
+
description?: string;
|
|
418
|
+
metricKind: HostMetricKind;
|
|
419
|
+
top: number;
|
|
420
|
+
left: number;
|
|
421
|
+
width: number;
|
|
422
|
+
height: number;
|
|
423
|
+
}): DashboardBaseComponent {
|
|
424
|
+
return {
|
|
425
|
+
_type: ObjectType.DashboardComponent,
|
|
426
|
+
componentType: DashboardComponentType.HostMetricChart,
|
|
427
|
+
componentId: ObjectID.generate(),
|
|
428
|
+
topInDashboardUnits: data.top,
|
|
429
|
+
leftInDashboardUnits: data.left,
|
|
430
|
+
widthInDashboardUnits: data.width,
|
|
431
|
+
heightInDashboardUnits: data.height,
|
|
432
|
+
minHeightInDashboardUnits: 3,
|
|
433
|
+
minWidthInDashboardUnits: 6,
|
|
434
|
+
arguments: {
|
|
435
|
+
title: data.title,
|
|
436
|
+
description: data.description,
|
|
437
|
+
metricKind: data.metricKind,
|
|
438
|
+
},
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
|
|
377
442
|
// -- Dashboard configs --
|
|
378
443
|
|
|
379
444
|
function createMonitorDashboardConfig(): DashboardViewConfig {
|
|
@@ -1384,6 +1449,229 @@ function createMetricsDashboardConfig(): DashboardViewConfig {
|
|
|
1384
1449
|
};
|
|
1385
1450
|
}
|
|
1386
1451
|
|
|
1452
|
+
function createHostDashboardConfig(): DashboardViewConfig {
|
|
1453
|
+
/*
|
|
1454
|
+
* Layout notes:
|
|
1455
|
+
*
|
|
1456
|
+
* - The HostMetricChart widget groups by `host.name` and plots one
|
|
1457
|
+
* series per host (or a single series when filtered to one host).
|
|
1458
|
+
* The OTel host receiver emits `system.cpu.utilization` and
|
|
1459
|
+
* `system.memory.utilization` as [0, 1] ratios, which Value/Gauge
|
|
1460
|
+
* widgets auto-scale to percent at render time (see
|
|
1461
|
+
* splitFormattedValue / isFractionScale).
|
|
1462
|
+
*
|
|
1463
|
+
* - The Value widget for "Avg Memory" uses `system.memory.usage`
|
|
1464
|
+
* (bytes) and is auto-formatted to MB/GB by ValueFormatter, since
|
|
1465
|
+
* `system.memory.utilization` is not always emitted by default OTel
|
|
1466
|
+
* host metrics.
|
|
1467
|
+
*
|
|
1468
|
+
* - Disk and Network I/O Value widgets aggregate the raw byte counters
|
|
1469
|
+
* with Sum. HostMetricChart turns these into per-second rates for
|
|
1470
|
+
* the chart view; the Value tile shows the unrated total so users
|
|
1471
|
+
* reading "Disk I/O" against the time window get an absolute byte
|
|
1472
|
+
* figure rather than a noisy snapshot.
|
|
1473
|
+
*/
|
|
1474
|
+
const components: Array<DashboardBaseComponent> = [
|
|
1475
|
+
// Row 0: Title
|
|
1476
|
+
createTextComponent({
|
|
1477
|
+
text: "Hosts Dashboard",
|
|
1478
|
+
top: 0,
|
|
1479
|
+
left: 0,
|
|
1480
|
+
width: 12,
|
|
1481
|
+
height: 1,
|
|
1482
|
+
isBold: true,
|
|
1483
|
+
}),
|
|
1484
|
+
|
|
1485
|
+
// Row 1: Key host metrics
|
|
1486
|
+
createValueComponent({
|
|
1487
|
+
title: "Avg CPU",
|
|
1488
|
+
top: 1,
|
|
1489
|
+
left: 0,
|
|
1490
|
+
width: 3,
|
|
1491
|
+
metricConfig: {
|
|
1492
|
+
metricName: MetricDashboardMetricType.SystemCpuUtilization,
|
|
1493
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
1494
|
+
},
|
|
1495
|
+
trendDirection: DashboardValueTrendDirection.HigherIsWorse,
|
|
1496
|
+
}),
|
|
1497
|
+
createValueComponent({
|
|
1498
|
+
title: "Avg Memory",
|
|
1499
|
+
top: 1,
|
|
1500
|
+
left: 3,
|
|
1501
|
+
width: 3,
|
|
1502
|
+
metricConfig: {
|
|
1503
|
+
metricName: MetricDashboardMetricType.SystemMemoryUsage,
|
|
1504
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
1505
|
+
},
|
|
1506
|
+
trendDirection: DashboardValueTrendDirection.HigherIsWorse,
|
|
1507
|
+
}),
|
|
1508
|
+
createValueComponent({
|
|
1509
|
+
title: "Disk I/O",
|
|
1510
|
+
top: 1,
|
|
1511
|
+
left: 6,
|
|
1512
|
+
width: 3,
|
|
1513
|
+
metricConfig: {
|
|
1514
|
+
metricName: MetricDashboardMetricType.SystemDiskIo,
|
|
1515
|
+
aggregationType: MetricsAggregationType.Sum,
|
|
1516
|
+
},
|
|
1517
|
+
trendDirection: DashboardValueTrendDirection.HigherIsBetter,
|
|
1518
|
+
}),
|
|
1519
|
+
createValueComponent({
|
|
1520
|
+
title: "Network I/O",
|
|
1521
|
+
top: 1,
|
|
1522
|
+
left: 9,
|
|
1523
|
+
width: 3,
|
|
1524
|
+
metricConfig: {
|
|
1525
|
+
metricName: MetricDashboardMetricType.SystemNetworkIo,
|
|
1526
|
+
aggregationType: MetricsAggregationType.Sum,
|
|
1527
|
+
},
|
|
1528
|
+
trendDirection: DashboardValueTrendDirection.HigherIsBetter,
|
|
1529
|
+
}),
|
|
1530
|
+
|
|
1531
|
+
// Row 2-4: Per-host CPU and Memory charts
|
|
1532
|
+
createHostMetricChartComponent({
|
|
1533
|
+
title: "CPU Utilization by Host",
|
|
1534
|
+
metricKind: HostMetricKind.CpuUtilization,
|
|
1535
|
+
top: 2,
|
|
1536
|
+
left: 0,
|
|
1537
|
+
width: 6,
|
|
1538
|
+
height: 3,
|
|
1539
|
+
}),
|
|
1540
|
+
createHostMetricChartComponent({
|
|
1541
|
+
title: "Memory Usage by Host",
|
|
1542
|
+
metricKind: HostMetricKind.MemoryUsage,
|
|
1543
|
+
top: 2,
|
|
1544
|
+
left: 6,
|
|
1545
|
+
width: 6,
|
|
1546
|
+
height: 3,
|
|
1547
|
+
}),
|
|
1548
|
+
|
|
1549
|
+
// Row 5: Section header
|
|
1550
|
+
createTextComponent({
|
|
1551
|
+
text: "Hosts",
|
|
1552
|
+
top: 5,
|
|
1553
|
+
left: 0,
|
|
1554
|
+
width: 12,
|
|
1555
|
+
height: 1,
|
|
1556
|
+
isBold: true,
|
|
1557
|
+
}),
|
|
1558
|
+
|
|
1559
|
+
/*
|
|
1560
|
+
* Row 6-9: Live host inventory. The widget reads the Postgres host
|
|
1561
|
+
* snapshot, so the header shows the true current count and rows
|
|
1562
|
+
* link to per-host detail pages.
|
|
1563
|
+
*/
|
|
1564
|
+
createHostListComponent({
|
|
1565
|
+
title: "All Hosts",
|
|
1566
|
+
top: 6,
|
|
1567
|
+
left: 0,
|
|
1568
|
+
width: 12,
|
|
1569
|
+
height: 4,
|
|
1570
|
+
maxRows: 25,
|
|
1571
|
+
}),
|
|
1572
|
+
|
|
1573
|
+
// Row 10: Section header
|
|
1574
|
+
createTextComponent({
|
|
1575
|
+
text: "Resource Health",
|
|
1576
|
+
top: 10,
|
|
1577
|
+
left: 0,
|
|
1578
|
+
width: 12,
|
|
1579
|
+
height: 1,
|
|
1580
|
+
isBold: true,
|
|
1581
|
+
}),
|
|
1582
|
+
|
|
1583
|
+
/*
|
|
1584
|
+
* Row 11-13: CPU gauge (auto-scaled from [0,1] ratio to percent),
|
|
1585
|
+
* alongside the filesystem-usage chart so capacity pressure is
|
|
1586
|
+
* visible per host.
|
|
1587
|
+
*/
|
|
1588
|
+
createGaugeComponent({
|
|
1589
|
+
title: "Avg CPU Utilization",
|
|
1590
|
+
top: 11,
|
|
1591
|
+
left: 0,
|
|
1592
|
+
width: 4,
|
|
1593
|
+
height: 3,
|
|
1594
|
+
minValue: 0,
|
|
1595
|
+
maxValue: 100,
|
|
1596
|
+
warningThreshold: 70,
|
|
1597
|
+
criticalThreshold: 90,
|
|
1598
|
+
metricConfig: {
|
|
1599
|
+
metricName: MetricDashboardMetricType.SystemCpuUtilization,
|
|
1600
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
1601
|
+
},
|
|
1602
|
+
}),
|
|
1603
|
+
createHostMetricChartComponent({
|
|
1604
|
+
title: "Filesystem Usage by Host",
|
|
1605
|
+
metricKind: HostMetricKind.Filesystem,
|
|
1606
|
+
top: 11,
|
|
1607
|
+
left: 4,
|
|
1608
|
+
width: 8,
|
|
1609
|
+
height: 3,
|
|
1610
|
+
}),
|
|
1611
|
+
|
|
1612
|
+
// Row 14: Section header
|
|
1613
|
+
createTextComponent({
|
|
1614
|
+
text: "I/O Activity",
|
|
1615
|
+
top: 14,
|
|
1616
|
+
left: 0,
|
|
1617
|
+
width: 12,
|
|
1618
|
+
height: 1,
|
|
1619
|
+
isBold: true,
|
|
1620
|
+
}),
|
|
1621
|
+
|
|
1622
|
+
// Row 15-17: Disk and network I/O rates per host
|
|
1623
|
+
createHostMetricChartComponent({
|
|
1624
|
+
title: "Disk I/O by Host",
|
|
1625
|
+
metricKind: HostMetricKind.DiskIo,
|
|
1626
|
+
top: 15,
|
|
1627
|
+
left: 0,
|
|
1628
|
+
width: 6,
|
|
1629
|
+
height: 3,
|
|
1630
|
+
}),
|
|
1631
|
+
createHostMetricChartComponent({
|
|
1632
|
+
title: "Network I/O by Host",
|
|
1633
|
+
metricKind: HostMetricKind.NetworkIo,
|
|
1634
|
+
top: 15,
|
|
1635
|
+
left: 6,
|
|
1636
|
+
width: 6,
|
|
1637
|
+
height: 3,
|
|
1638
|
+
}),
|
|
1639
|
+
|
|
1640
|
+
// Row 18: Section header
|
|
1641
|
+
createTextComponent({
|
|
1642
|
+
text: "Processes & Logs",
|
|
1643
|
+
top: 18,
|
|
1644
|
+
left: 0,
|
|
1645
|
+
width: 12,
|
|
1646
|
+
height: 1,
|
|
1647
|
+
isBold: true,
|
|
1648
|
+
}),
|
|
1649
|
+
|
|
1650
|
+
// Row 19-21: Process count chart and recent logs
|
|
1651
|
+
createHostMetricChartComponent({
|
|
1652
|
+
title: "Process Count by Host",
|
|
1653
|
+
metricKind: HostMetricKind.ProcessCount,
|
|
1654
|
+
top: 19,
|
|
1655
|
+
left: 0,
|
|
1656
|
+
width: 6,
|
|
1657
|
+
height: 3,
|
|
1658
|
+
}),
|
|
1659
|
+
createLogStreamComponent({
|
|
1660
|
+
title: "Recent Logs",
|
|
1661
|
+
top: 19,
|
|
1662
|
+
left: 6,
|
|
1663
|
+
width: 6,
|
|
1664
|
+
height: 3,
|
|
1665
|
+
}),
|
|
1666
|
+
];
|
|
1667
|
+
|
|
1668
|
+
return {
|
|
1669
|
+
_type: ObjectType.DashboardViewConfig,
|
|
1670
|
+
components,
|
|
1671
|
+
heightInDashboardUnits: Math.max(DashboardSize.heightInDashboardUnits, 22),
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1387
1675
|
export function getTemplateConfig(
|
|
1388
1676
|
type: DashboardTemplateType,
|
|
1389
1677
|
): DashboardViewConfig | null {
|
|
@@ -1394,6 +1682,8 @@ export function getTemplateConfig(
|
|
|
1394
1682
|
return createIncidentDashboardConfig();
|
|
1395
1683
|
case DashboardTemplateType.Kubernetes:
|
|
1396
1684
|
return createKubernetesDashboardConfig();
|
|
1685
|
+
case DashboardTemplateType.Host:
|
|
1686
|
+
return createHostDashboardConfig();
|
|
1397
1687
|
case DashboardTemplateType.Metrics:
|
|
1398
1688
|
return createMetricsDashboardConfig();
|
|
1399
1689
|
case DashboardTemplateType.Blank:
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
ComponentInputType,
|
|
11
11
|
} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
|
|
12
12
|
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
13
|
+
import DashboardChartType from "../../../Types/Dashboard/Chart/ChartType";
|
|
13
14
|
|
|
14
15
|
const DataSection: ComponentArgumentSection = {
|
|
15
16
|
name: "Data Source",
|
|
@@ -38,6 +39,7 @@ export default class DashboardHostMetricChartComponentUtil extends DashboardBase
|
|
|
38
39
|
minWidthInDashboardUnits: 6,
|
|
39
40
|
arguments: {
|
|
40
41
|
metricKind: HostMetricKind.CpuUtilization,
|
|
42
|
+
chartType: DashboardChartType.Line,
|
|
41
43
|
},
|
|
42
44
|
};
|
|
43
45
|
}
|
|
@@ -80,6 +82,33 @@ export default class DashboardHostMetricChartComponentUtil extends DashboardBase
|
|
|
80
82
|
section: DataSection,
|
|
81
83
|
});
|
|
82
84
|
|
|
85
|
+
args.push({
|
|
86
|
+
name: "Chart Type",
|
|
87
|
+
description: "How the data will be visualized",
|
|
88
|
+
required: false,
|
|
89
|
+
type: ComponentInputType.Dropdown,
|
|
90
|
+
id: "chartType",
|
|
91
|
+
section: DisplaySection,
|
|
92
|
+
dropdownOptions: [
|
|
93
|
+
{
|
|
94
|
+
label: "Line Chart",
|
|
95
|
+
value: DashboardChartType.Line,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
label: "Bar Chart",
|
|
99
|
+
value: DashboardChartType.Bar,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
label: "Area Chart",
|
|
103
|
+
value: DashboardChartType.Area,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
label: "Stacked Area Chart",
|
|
107
|
+
value: DashboardChartType.StackedArea,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
});
|
|
111
|
+
|
|
83
112
|
args.push({
|
|
84
113
|
name: "Title",
|
|
85
114
|
description: "Displayed above the chart",
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import Includes from "../../Types/BaseDatabase/Includes";
|
|
2
|
+
import DashboardVariable, {
|
|
3
|
+
DashboardVariableType,
|
|
4
|
+
} from "../../Types/Dashboard/DashboardVariable";
|
|
5
|
+
import DashboardVariableInterpolation, {
|
|
6
|
+
ResolvedVariableValue,
|
|
7
|
+
} from "./VariableInterpolation";
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* Maps a dashboard variable's OpenTelemetry attribute key (e.g.
|
|
11
|
+
* "host.name", "k8s.namespace.name") to the Postgres model column
|
|
12
|
+
* that should be filtered for a given list widget. Each list widget
|
|
13
|
+
* declares the subset of attribute keys it understands.
|
|
14
|
+
*/
|
|
15
|
+
export type AttributeToColumnMap = Record<string, string>;
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* Applies dashboard variables to a Postgres model query at render time.
|
|
19
|
+
*
|
|
20
|
+
* Companion to `DashboardVariableInterpolation`, which targets OTel
|
|
21
|
+
* attribute filters used by metric/log widgets. Resource list widgets
|
|
22
|
+
* (Host, Kubernetes resources, Docker resources) query the model store
|
|
23
|
+
* by column instead, so this helper translates the variable's bound
|
|
24
|
+
* OTel attribute key into the matching column name before writing the
|
|
25
|
+
* predicate. An empty/unset selection removes any prior filter on that
|
|
26
|
+
* column so the list falls back to its widget-default view.
|
|
27
|
+
*/
|
|
28
|
+
export default class DashboardModelQueryInterpolation {
|
|
29
|
+
public static applyToQuery(
|
|
30
|
+
query: Record<string, unknown>,
|
|
31
|
+
variables: Array<DashboardVariable> | undefined,
|
|
32
|
+
attributeToColumn: AttributeToColumnMap,
|
|
33
|
+
): Record<string, unknown> {
|
|
34
|
+
if (!variables || variables.length === 0) {
|
|
35
|
+
return query;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const mappedAttributeKeys: Array<string> = Object.keys(attributeToColumn);
|
|
39
|
+
if (mappedAttributeKeys.length === 0) {
|
|
40
|
+
return query;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const relevantVariables: Array<DashboardVariable> = variables.filter(
|
|
44
|
+
(v: DashboardVariable) => {
|
|
45
|
+
return (
|
|
46
|
+
v.type === DashboardVariableType.TelemetryAttribute &&
|
|
47
|
+
Boolean(v.attributeKey) &&
|
|
48
|
+
mappedAttributeKeys.includes(v.attributeKey as string)
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
if (relevantVariables.length === 0) {
|
|
54
|
+
return query;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let next: Record<string, unknown> = query;
|
|
58
|
+
let changed: boolean = false;
|
|
59
|
+
|
|
60
|
+
for (const variable of relevantVariables) {
|
|
61
|
+
const column: string = attributeToColumn[
|
|
62
|
+
variable.attributeKey as string
|
|
63
|
+
] as string;
|
|
64
|
+
const resolved: ResolvedVariableValue | undefined =
|
|
65
|
+
DashboardVariableInterpolation.resolveValue(variable);
|
|
66
|
+
|
|
67
|
+
if (!resolved) {
|
|
68
|
+
if (column in next) {
|
|
69
|
+
if (!changed) {
|
|
70
|
+
next = { ...query };
|
|
71
|
+
changed = true;
|
|
72
|
+
}
|
|
73
|
+
delete next[column];
|
|
74
|
+
}
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (resolved.multi && resolved.multi.length > 0) {
|
|
79
|
+
if (!changed) {
|
|
80
|
+
next = { ...query };
|
|
81
|
+
changed = true;
|
|
82
|
+
}
|
|
83
|
+
next[column] = new Includes(resolved.multi);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (resolved.scalar !== undefined && next[column] !== resolved.scalar) {
|
|
88
|
+
if (!changed) {
|
|
89
|
+
next = { ...query };
|
|
90
|
+
changed = true;
|
|
91
|
+
}
|
|
92
|
+
next[column] = resolved.scalar;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return changed ? next : query;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -76,7 +76,13 @@ export class Service extends DatabaseService {
|
|
|
76
76
|
if (!project.enableCallNotifications) {
|
|
77
77
|
throw new BadDataException("Call notifications are disabled for this project. Please enable them in Project Settings > Notification Settings.");
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
/*
|
|
80
|
+
* If the project has its own default Twilio config, OneUptime does not
|
|
81
|
+
* charge the project's Call/SMS balance, so the low-balance check does not apply.
|
|
82
|
+
*/
|
|
83
|
+
const projectTwilioConfig = await ProjectCallSMSConfigService.getProjectDefaultTwilioConfig(createBy.data.projectId);
|
|
84
|
+
if (!projectTwilioConfig &&
|
|
85
|
+
project.smsOrCallCurrentBalanceInUSDCents <= 100 &&
|
|
80
86
|
IsBillingEnabled) {
|
|
81
87
|
throw new BadDataException("Your SMS balance is low. Please recharge your SMS balance in Project Settings > Notification Settings.");
|
|
82
88
|
}
|
|
@@ -124,7 +130,13 @@ export class Service extends DatabaseService {
|
|
|
124
130
|
if (!project.enableCallNotifications) {
|
|
125
131
|
throw new BadDataException("Call notifications are disabled for this project. Please enable them in Project Settings > Notification Settings.");
|
|
126
132
|
}
|
|
127
|
-
|
|
133
|
+
/*
|
|
134
|
+
* If the project has its own default Twilio config, OneUptime does not
|
|
135
|
+
* charge the project's Call/SMS balance, so the low-balance check does not apply.
|
|
136
|
+
*/
|
|
137
|
+
const projectTwilioConfig = await ProjectCallSMSConfigService.getProjectDefaultTwilioConfig(item.projectId);
|
|
138
|
+
if (!projectTwilioConfig &&
|
|
139
|
+
project.smsOrCallCurrentBalanceInUSDCents <= 100 &&
|
|
128
140
|
IsBillingEnabled) {
|
|
129
141
|
throw new BadDataException("Your SMS balance is low. Please recharge your SMS balance in Project Settings > Notification Settings.");
|
|
130
142
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserCallService.js","sourceRoot":"","sources":["../../../../Server/Services/UserCallService.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAIxD,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAChD,OAAO,2BAA2B,MAAM,+BAA+B,CAAC;AACxE,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,2BAA2B,MAAM,+BAA+B,CAAC;AAExE,OAAO,SAAS,MAAM,+BAA+B,CAAC;AAEtD,OAAO,gBAAgB,MAAM,wCAAwC,CAAC;AACtE,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAC5C,OAAO,IAAI,MAAM,kBAAkB,CAAC;AAEpC,OAAO,KAAK,MAAM,sCAAsC,CAAC;AACzD,OAAO,WAAW,MAAM,gCAAgC,CAAC;AAEzD,MAAM,OAAO,OAAQ,SAAQ,eAAsB;IACjD;QACE,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAGwB,AAAN,KAAK,CAAC,cAAc,CACrC,QAAyB;QAEzB,MAAM,aAAa,GAAiB,MAAM,IAAI,CAAC,MAAM,CAAC;YACpD,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,MAAM,EAAE;gBACN,GAAG,EAAE,IAAI;gBACT,SAAS,EAAE,IAAI;aAChB;YACD,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI;aACb;SACF,CAAC,CAAC;QAEH,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,MAAM,2BAA2B,CAAC,QAAQ,CAAC;gBACzC,KAAK,EAAE;oBACL,UAAU,EAAE,IAAI,CAAC,EAAG;oBACpB,SAAS,EAAE,IAAI,CAAC,SAAU;iBAC3B;gBACD,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE;oBACL,MAAM,EAAE,IAAI;iBACb;aACF,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,QAAQ;YACR,YAAY,EAAE,IAAI;SACnB,CAAC;IACJ,CAAC;IAGwB,AAAN,KAAK,CAAC,cAAc,CACrC,QAAyB;QAEzB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACvD,MAAM,IAAI,gBAAgB,CAAC,kCAAkC,CAAC,CAAC;QACjE,CAAC;QAED,mDAAmD;QAEnD,MAAM,OAAO,GAAmB,MAAM,cAAc,CAAC,WAAW,CAAC;YAC/D,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAU;YAC5B,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI;aACb;YACD,MAAM,EAAE;gBACN,uBAAuB,EAAE,IAAI;gBAC7B,iCAAiC,EAAE,IAAI;aACxC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC;YACrC,MAAM,IAAI,gBAAgB,CACxB,mHAAmH,CACpH,CAAC;QACJ,CAAC;QAED,
|
|
1
|
+
{"version":3,"file":"UserCallService.js","sourceRoot":"","sources":["../../../../Server/Services/UserCallService.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAIxD,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAChD,OAAO,2BAA2B,MAAM,+BAA+B,CAAC;AACxE,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,2BAA2B,MAAM,+BAA+B,CAAC;AAExE,OAAO,SAAS,MAAM,+BAA+B,CAAC;AAEtD,OAAO,gBAAgB,MAAM,wCAAwC,CAAC;AACtE,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAC5C,OAAO,IAAI,MAAM,kBAAkB,CAAC;AAEpC,OAAO,KAAK,MAAM,sCAAsC,CAAC;AACzD,OAAO,WAAW,MAAM,gCAAgC,CAAC;AAEzD,MAAM,OAAO,OAAQ,SAAQ,eAAsB;IACjD;QACE,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAGwB,AAAN,KAAK,CAAC,cAAc,CACrC,QAAyB;QAEzB,MAAM,aAAa,GAAiB,MAAM,IAAI,CAAC,MAAM,CAAC;YACpD,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,MAAM,EAAE;gBACN,GAAG,EAAE,IAAI;gBACT,SAAS,EAAE,IAAI;aAChB;YACD,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI;aACb;SACF,CAAC,CAAC;QAEH,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,MAAM,2BAA2B,CAAC,QAAQ,CAAC;gBACzC,KAAK,EAAE;oBACL,UAAU,EAAE,IAAI,CAAC,EAAG;oBACpB,SAAS,EAAE,IAAI,CAAC,SAAU;iBAC3B;gBACD,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE;oBACL,MAAM,EAAE,IAAI;iBACb;aACF,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,QAAQ;YACR,YAAY,EAAE,IAAI;SACnB,CAAC;IACJ,CAAC;IAGwB,AAAN,KAAK,CAAC,cAAc,CACrC,QAAyB;QAEzB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACvD,MAAM,IAAI,gBAAgB,CAAC,kCAAkC,CAAC,CAAC;QACjE,CAAC;QAED,mDAAmD;QAEnD,MAAM,OAAO,GAAmB,MAAM,cAAc,CAAC,WAAW,CAAC;YAC/D,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAU;YAC5B,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI;aACb;YACD,MAAM,EAAE;gBACN,uBAAuB,EAAE,IAAI;gBAC7B,iCAAiC,EAAE,IAAI;aACxC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC;YACrC,MAAM,IAAI,gBAAgB,CACxB,mHAAmH,CACpH,CAAC;QACJ,CAAC;QAED;;;WAGG;QACH,MAAM,mBAAmB,GACvB,MAAM,2BAA2B,CAAC,6BAA6B,CAC7D,QAAQ,CAAC,IAAI,CAAC,SAAU,CACzB,CAAC;QAEJ,IACE,CAAC,mBAAmB;YACnB,OAAO,CAAC,iCAA4C,IAAI,GAAG;YAC5D,gBAAgB,EAChB,CAAC;YACD,MAAM,IAAI,gBAAgB,CACxB,wGAAwG,CACzG,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC1C,CAAC;IAGwB,AAAN,KAAK,CAAC,eAAe,CACtC,SAA0B,EAC1B,WAAkB;QAElB,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;YAC5B,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IAGY,AAAN,KAAK,CAAC,sBAAsB,CAAC,MAAgB;QAClD,MAAM,IAAI,GAAiB,MAAM,IAAI,CAAC,WAAW,CAAC;YAChD,EAAE,EAAE,MAAM;YACV,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI;aACb;YACD,MAAM,EAAE;gBACN,KAAK,EAAE,IAAI;gBACX,gBAAgB,EAAE,IAAI;gBACtB,UAAU,EAAE,IAAI;gBAChB,SAAS,EAAE,IAAI;aAChB;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,gBAAgB,CACxB,eAAe,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,YAAY,CACnD,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,gBAAgB,CAAC,+BAA+B,CAAC,CAAC;QAC9D,CAAC;QAED,2DAA2D;QAC3D,MAAM,OAAO,GAAmB,MAAM,cAAc,CAAC,WAAW,CAAC;YAC/D,EAAE,EAAE,IAAI,CAAC,SAAU;YACnB,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI;aACb;YACD,MAAM,EAAE;gBACN,uBAAuB,EAAE,IAAI;gBAC7B,iCAAiC,EAAE,IAAI;aACxC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC;YACrC,MAAM,IAAI,gBAAgB,CACxB,mHAAmH,CACpH,CAAC;QACJ,CAAC;QAED;;;WAGG;QACH,MAAM,mBAAmB,GACvB,MAAM,2BAA2B,CAAC,6BAA6B,CAC7D,IAAI,CAAC,SAAU,CAChB,CAAC;QAEJ,IACE,CAAC,mBAAmB;YACnB,OAAO,CAAC,iCAA4C,IAAI,GAAG;YAC5D,gBAAgB,EAChB,CAAC;YACD,MAAM,IAAI,gBAAgB,CACxB,wGAAwG,CACzG,CAAC;QACJ,CAAC;QAED,iCAAiC;QACjC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;QAErD,MAAM,IAAI,CAAC,aAAa,CAAC;YACvB,EAAE,EAAE,IAAI,CAAC,EAAG;YACZ,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI;aACb;YACD,IAAI,EAAE;gBACJ,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;aACxC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAEM,oBAAoB,CAAC,IAAW;;QACrC,MAAM,WAAW,GAAgB;YAC/B,EAAE,EAAE,IAAI,CAAC,KAAM;YACf,IAAI,EAAE;gBACJ;oBACE,UAAU,EAAE,+BAA+B;iBAC5C;gBACD;oBACE,UAAU,EACR,4BAA4B;yBAC5B,MAAA,IAAI,CAAC,gBAAgB,0CAAE,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA,EAAE,4DAA4D;iBAC5G;gBACD;oBACE,UAAU,EACR,4BAA4B;yBAC5B,MAAA,IAAI,CAAC,gBAAgB,0CAAE,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA,EAAE,4DAA4D;iBAC5G;gBACD;oBACE,UAAU,EACR,4BAA4B;yBAC5B,MAAA,IAAI,CAAC,gBAAgB,0CAAE,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA,EAAE,4DAA4D;iBAC5G;gBACD;oBACE,UAAU,EAAE,0CAA0C;iBACvD;aACF;SACF,CAAC;QAEF,0BAA0B;QAC1B,CAAC,KAAK,IAAI,EAAE;YACV,MAAM,mBAAmB,GACvB,MAAM,2BAA2B,CAAC,6BAA6B,CAC7D,IAAI,CAAC,SAAS,CACf,CAAC;YAEJ,MAAM,WAAW,CAAC,QAAQ,CAAC,WAAW,EAAE;gBACtC,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,kBAAkB,EAAE,mBAAmB;gBACvC,WAAW,EAAE,IAAI;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAO;aACrB,CAAC,CAAC;QACL,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;YACxB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAnO0B;IADxB,WAAW,EAAE;;;;6CAmCb;AAGwB;IADxB,WAAW,EAAE;;;;6CAmDb;AAGwB;IADxB,WAAW,EAAE;;6CAGC,KAAK;;8CAMnB;AAGY;IADZ,WAAW,EAAE;;qCAC8B,QAAQ;;qDA+EnD;AAiDH,eAAe,IAAI,OAAO,EAAE,CAAC"}
|