@oneuptime/common 8.0.5579 → 8.0.5581

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.
Files changed (181) hide show
  1. package/Models/DatabaseModels/AlertInternalNote.ts +58 -1
  2. package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +1 -0
  3. package/Models/DatabaseModels/File.ts +1 -1
  4. package/Models/DatabaseModels/IncidentInternalNote.ts +58 -1
  5. package/Models/DatabaseModels/IncidentPublicNote.ts +58 -1
  6. package/Models/DatabaseModels/ScheduledMaintenanceInternalNote.ts +58 -1
  7. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +58 -1
  8. package/Models/DatabaseModels/StatusPageAnnouncement.ts +49 -0
  9. package/Server/API/AlertInternalNoteAPI.ts +96 -0
  10. package/Server/API/IncidentInternalNoteAPI.ts +96 -0
  11. package/Server/API/IncidentPublicNoteAPI.ts +96 -0
  12. package/Server/API/ScheduledMaintenanceInternalNoteAPI.ts +100 -0
  13. package/Server/API/ScheduledMaintenancePublicNoteAPI.ts +100 -0
  14. package/Server/API/StatusPageAPI.ts +585 -59
  15. package/Server/API/StatusPageAnnouncementAPI.ts +98 -0
  16. package/Server/API/UserAPI.ts +95 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1763471659817-MigrationName.ts +79 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1763477560906-MigrationName.ts +81 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1763480947474-MigrationName.ts +79 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  21. package/Server/Middleware/ProjectAuthorization.ts +3 -1
  22. package/Server/Services/AlertInternalNoteService.ts +75 -2
  23. package/Server/Services/IncidentInternalNoteService.ts +76 -2
  24. package/Server/Services/IncidentPublicNoteService.ts +76 -2
  25. package/Server/Services/ScheduledMaintenanceInternalNoteService.ts +76 -2
  26. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +76 -2
  27. package/Server/Services/ScheduledMaintenanceService.ts +10 -7
  28. package/Server/Services/StatusPagePrivateUserService.ts +10 -7
  29. package/Server/Services/StatusPageService.ts +12 -7
  30. package/Server/Services/StatusPageSubscriberService.ts +19 -13
  31. package/Server/Utils/FileAttachmentMarkdownUtil.ts +98 -0
  32. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +9 -1
  33. package/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.ts +34 -0
  34. package/Server/Utils/Monitor/DataToProcess.ts +3 -1
  35. package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +13 -0
  36. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +13 -0
  37. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +20 -0
  38. package/Server/Utils/Monitor/MonitorResource.ts +18 -0
  39. package/Server/Utils/Response.ts +13 -0
  40. package/Server/Utils/Telemetry.ts +15 -0
  41. package/Types/File/MimeType.ts +18 -0
  42. package/Types/Monitor/CriteriaFilter.ts +3 -0
  43. package/Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse.ts +12 -0
  44. package/Types/Monitor/MonitorCriteriaInstance.ts +67 -0
  45. package/Types/Monitor/MonitorStep.ts +30 -0
  46. package/Types/Monitor/MonitorStepExceptionMonitor.ts +94 -0
  47. package/Types/Monitor/MonitorType.ts +10 -1
  48. package/Types/Telemetry/TelemetryQuery.ts +2 -1
  49. package/Types/Telemetry/TelemetryType.ts +1 -0
  50. package/UI/Components/AttachmentList/EventAttachmentList.tsx +121 -0
  51. package/UI/Components/EventItem/EventItem.tsx +22 -0
  52. package/UI/Components/Feed/FeedItem.tsx +9 -16
  53. package/UI/Components/FilePicker/FilePicker.tsx +441 -145
  54. package/UI/Components/Forms/Fields/FormField.tsx +32 -15
  55. package/UI/Components/Forms/FormSummary.tsx +168 -1
  56. package/UI/Components/Forms/ModelForm.tsx +46 -24
  57. package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
  58. package/UI/Components/Icon/Icon.tsx +1 -1
  59. package/UI/Utils/API/RequestOptions.ts +2 -0
  60. package/UI/Utils/ModelAPI/ModelAPI.ts +18 -0
  61. package/UI/Utils/User.ts +8 -0
  62. package/Utils/API.ts +11 -1
  63. package/build/dist/Models/DatabaseModels/AlertInternalNote.js +49 -1
  64. package/build/dist/Models/DatabaseModels/AlertInternalNote.js.map +1 -1
  65. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +1 -0
  66. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
  67. package/build/dist/Models/DatabaseModels/File.js +1 -1
  68. package/build/dist/Models/DatabaseModels/File.js.map +1 -1
  69. package/build/dist/Models/DatabaseModels/IncidentInternalNote.js +49 -1
  70. package/build/dist/Models/DatabaseModels/IncidentInternalNote.js.map +1 -1
  71. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +49 -1
  72. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  73. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceInternalNote.js +49 -1
  74. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceInternalNote.js.map +1 -1
  75. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +49 -1
  76. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  77. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +48 -0
  78. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  79. package/build/dist/Server/API/AlertInternalNoteAPI.js +68 -0
  80. package/build/dist/Server/API/AlertInternalNoteAPI.js.map +1 -0
  81. package/build/dist/Server/API/IncidentInternalNoteAPI.js +68 -0
  82. package/build/dist/Server/API/IncidentInternalNoteAPI.js.map +1 -0
  83. package/build/dist/Server/API/IncidentPublicNoteAPI.js +68 -0
  84. package/build/dist/Server/API/IncidentPublicNoteAPI.js.map +1 -0
  85. package/build/dist/Server/API/ScheduledMaintenanceInternalNoteAPI.js +68 -0
  86. package/build/dist/Server/API/ScheduledMaintenanceInternalNoteAPI.js.map +1 -0
  87. package/build/dist/Server/API/ScheduledMaintenancePublicNoteAPI.js +68 -0
  88. package/build/dist/Server/API/ScheduledMaintenancePublicNoteAPI.js.map +1 -0
  89. package/build/dist/Server/API/StatusPageAPI.js +488 -85
  90. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  91. package/build/dist/Server/API/StatusPageAnnouncementAPI.js +68 -0
  92. package/build/dist/Server/API/StatusPageAnnouncementAPI.js.map +1 -0
  93. package/build/dist/Server/API/UserAPI.js +66 -0
  94. package/build/dist/Server/API/UserAPI.js.map +1 -0
  95. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763471659817-MigrationName.js +34 -0
  96. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763471659817-MigrationName.js.map +1 -0
  97. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763477560906-MigrationName.js +34 -0
  98. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763477560906-MigrationName.js.map +1 -0
  99. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763480947474-MigrationName.js +34 -0
  100. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1763480947474-MigrationName.js.map +1 -0
  101. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  102. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  103. package/build/dist/Server/Middleware/ProjectAuthorization.js +4 -1
  104. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  105. package/build/dist/Server/Services/AlertInternalNoteService.js +54 -2
  106. package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -1
  107. package/build/dist/Server/Services/IncidentInternalNoteService.js +54 -2
  108. package/build/dist/Server/Services/IncidentInternalNoteService.js.map +1 -1
  109. package/build/dist/Server/Services/IncidentPublicNoteService.js +54 -2
  110. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  111. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js +54 -2
  112. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js.map +1 -1
  113. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +54 -2
  114. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  115. package/build/dist/Server/Services/ScheduledMaintenanceService.js +6 -5
  116. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  117. package/build/dist/Server/Services/StatusPagePrivateUserService.js +6 -4
  118. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  119. package/build/dist/Server/Services/StatusPageService.js +7 -4
  120. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  121. package/build/dist/Server/Services/StatusPageSubscriberService.js +11 -7
  122. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  123. package/build/dist/Server/Utils/FileAttachmentMarkdownUtil.js +67 -0
  124. package/build/dist/Server/Utils/FileAttachmentMarkdownUtil.js.map +1 -0
  125. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +6 -1
  126. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  127. package/build/dist/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.js +34 -0
  128. package/build/dist/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.js.map +1 -0
  129. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +6 -0
  130. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
  131. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +10 -0
  132. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  133. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +9 -0
  134. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  135. package/build/dist/Server/Utils/Monitor/MonitorResource.js +10 -0
  136. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  137. package/build/dist/Server/Utils/Response.js +8 -0
  138. package/build/dist/Server/Utils/Response.js.map +1 -1
  139. package/build/dist/Server/Utils/Telemetry.js +8 -1
  140. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  141. package/build/dist/Types/File/MimeType.js +18 -0
  142. package/build/dist/Types/File/MimeType.js.map +1 -1
  143. package/build/dist/Types/Monitor/CriteriaFilter.js +2 -0
  144. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  145. package/build/dist/Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse.js +2 -0
  146. package/build/dist/Types/Monitor/ExceptionMonitor/ExceptionMonitorResponse.js.map +1 -0
  147. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +62 -0
  148. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  149. package/build/dist/Types/Monitor/MonitorStep.js +20 -1
  150. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  151. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js +58 -0
  152. package/build/dist/Types/Monitor/MonitorStepExceptionMonitor.js.map +1 -0
  153. package/build/dist/Types/Monitor/MonitorType.js +9 -1
  154. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  155. package/build/dist/Types/Telemetry/TelemetryType.js +1 -0
  156. package/build/dist/Types/Telemetry/TelemetryType.js.map +1 -1
  157. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js +42 -0
  158. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js.map +1 -0
  159. package/build/dist/UI/Components/EventItem/EventItem.js +5 -1
  160. package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
  161. package/build/dist/UI/Components/Feed/FeedItem.js +6 -4
  162. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  163. package/build/dist/UI/Components/FilePicker/FilePicker.js +262 -77
  164. package/build/dist/UI/Components/FilePicker/FilePicker.js.map +1 -1
  165. package/build/dist/UI/Components/Forms/Fields/FormField.js +24 -12
  166. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  167. package/build/dist/UI/Components/Forms/FormSummary.js +77 -1
  168. package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
  169. package/build/dist/UI/Components/Forms/ModelForm.js +32 -18
  170. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  171. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
  172. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
  173. package/build/dist/UI/Components/Icon/Icon.js +1 -1
  174. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  175. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +30 -45
  176. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  177. package/build/dist/UI/Utils/User.js +7 -0
  178. package/build/dist/UI/Utils/User.js.map +1 -1
  179. package/build/dist/Utils/API.js +3 -0
  180. package/build/dist/Utils/API.js.map +1 -1
  181. package/package.json +6 -6
@@ -0,0 +1,94 @@
1
+ import ExceptionInstance from "../../Models/AnalyticsModels/ExceptionInstance";
2
+ import InBetween from "../BaseDatabase/InBetween";
3
+ import Includes from "../BaseDatabase/Includes";
4
+ import Query from "../BaseDatabase/Query";
5
+ import Search from "../BaseDatabase/Search";
6
+ import OneUptimeDate from "../Date";
7
+ import { JSONObject } from "../JSON";
8
+ import ObjectID from "../ObjectID";
9
+
10
+ export default interface MonitorStepExceptionMonitor {
11
+ telemetryServiceIds: Array<ObjectID>;
12
+ exceptionTypes: Array<string>;
13
+ message: string;
14
+ includeResolved: boolean;
15
+ includeArchived: boolean;
16
+ lastXSecondsOfExceptions: number;
17
+ }
18
+
19
+ export class MonitorStepExceptionMonitorUtil {
20
+ public static toAnalyticsQuery(
21
+ monitorStepExceptionMonitor: MonitorStepExceptionMonitor,
22
+ ): Query<ExceptionInstance> {
23
+ const query: Query<ExceptionInstance> = {};
24
+
25
+ if (
26
+ monitorStepExceptionMonitor.telemetryServiceIds &&
27
+ monitorStepExceptionMonitor.telemetryServiceIds.length > 0
28
+ ) {
29
+ query.serviceId = new Includes(
30
+ monitorStepExceptionMonitor.telemetryServiceIds,
31
+ );
32
+ }
33
+
34
+ if (
35
+ monitorStepExceptionMonitor.exceptionTypes &&
36
+ monitorStepExceptionMonitor.exceptionTypes.length > 0
37
+ ) {
38
+ query.exceptionType = new Includes(
39
+ monitorStepExceptionMonitor.exceptionTypes,
40
+ );
41
+ }
42
+
43
+ if (monitorStepExceptionMonitor.message) {
44
+ query.message = new Search(monitorStepExceptionMonitor.message);
45
+ }
46
+
47
+ if (monitorStepExceptionMonitor.lastXSecondsOfExceptions) {
48
+ const endDate: Date = OneUptimeDate.getCurrentDate();
49
+ const startDate: Date = OneUptimeDate.addRemoveSeconds(
50
+ endDate,
51
+ monitorStepExceptionMonitor.lastXSecondsOfExceptions * -1,
52
+ );
53
+ query.time = new InBetween(startDate, endDate);
54
+ }
55
+
56
+ return query;
57
+ }
58
+
59
+ public static getDefault(): MonitorStepExceptionMonitor {
60
+ return {
61
+ telemetryServiceIds: [],
62
+ exceptionTypes: [],
63
+ message: "",
64
+ includeResolved: false,
65
+ includeArchived: false,
66
+ lastXSecondsOfExceptions: 60,
67
+ };
68
+ }
69
+
70
+ public static fromJSON(json: JSONObject): MonitorStepExceptionMonitor {
71
+ return {
72
+ telemetryServiceIds: ObjectID.fromJSONArray(
73
+ (json["telemetryServiceIds"] as Array<JSONObject>) || [],
74
+ ),
75
+ exceptionTypes: (json["exceptionTypes"] as Array<string>) || [],
76
+ message: (json["message"] as string) || "",
77
+ includeResolved: Boolean(json["includeResolved"]) || false,
78
+ includeArchived: Boolean(json["includeArchived"]) || false,
79
+ lastXSecondsOfExceptions:
80
+ (json["lastXSecondsOfExceptions"] as number | undefined) || 60,
81
+ };
82
+ }
83
+
84
+ public static toJSON(monitor: MonitorStepExceptionMonitor): JSONObject {
85
+ return {
86
+ telemetryServiceIds: ObjectID.toJSONArray(monitor.telemetryServiceIds),
87
+ exceptionTypes: monitor.exceptionTypes,
88
+ message: monitor.message,
89
+ includeResolved: monitor.includeResolved,
90
+ includeArchived: monitor.includeArchived,
91
+ lastXSecondsOfExceptions: monitor.lastXSecondsOfExceptions,
92
+ };
93
+ }
94
+ }
@@ -20,6 +20,7 @@ enum MonitorType {
20
20
  Logs = "Logs",
21
21
  Metrics = "Metrics",
22
22
  Traces = "Traces",
23
+ Exceptions = "Exceptions",
23
24
  }
24
25
 
25
26
  export default MonitorType;
@@ -35,7 +36,8 @@ export class MonitorTypeHelper {
35
36
  return (
36
37
  monitorType === MonitorType.Logs ||
37
38
  monitorType === MonitorType.Metrics ||
38
- monitorType === MonitorType.Traces
39
+ monitorType === MonitorType.Traces ||
40
+ monitorType === MonitorType.Exceptions
39
41
  );
40
42
  }
41
43
 
@@ -123,6 +125,12 @@ export class MonitorTypeHelper {
123
125
  title: "Logs",
124
126
  description: "This monitor type lets you monitor logs from any source.",
125
127
  },
128
+ {
129
+ monitorType: MonitorType.Exceptions,
130
+ title: "Exceptions",
131
+ description:
132
+ "This monitor type lets you monitor exceptions and error groups from any source.",
133
+ },
126
134
  {
127
135
  monitorType: MonitorType.Traces,
128
136
  title: "Traces",
@@ -198,6 +206,7 @@ export class MonitorTypeHelper {
198
206
  MonitorType.Logs,
199
207
  MonitorType.Metrics,
200
208
  MonitorType.Traces,
209
+ MonitorType.Exceptions,
201
210
  ];
202
211
  }
203
212
 
@@ -3,9 +3,10 @@ import Span from "../../Models/AnalyticsModels/Span";
3
3
  import Query from "../BaseDatabase/Query";
4
4
  import MetricViewData from "../Metrics/MetricViewData";
5
5
  import TelemetryType from "./TelemetryType";
6
+ import ExceptionInstance from "../../Models/AnalyticsModels/ExceptionInstance";
6
7
 
7
8
  export interface TelemetryQuery {
8
9
  telemetryType: TelemetryType;
9
- telemetryQuery: Query<Log> | Query<Span> | null;
10
+ telemetryQuery: Query<Log> | Query<Span> | Query<ExceptionInstance> | null;
10
11
  metricViewData: MetricViewData | null;
11
12
  }
@@ -2,6 +2,7 @@ enum TelemetryType {
2
2
  Metric = "Metric",
3
3
  Trace = "Trace",
4
4
  Log = "Log",
5
+ Exception = "Exception",
5
6
  }
6
7
 
7
8
  export default TelemetryType;
@@ -0,0 +1,121 @@
1
+ import React, { FunctionComponent, ReactElement } from "react";
2
+
3
+ export interface EventAttachment {
4
+ name: string;
5
+ downloadUrl: string;
6
+ }
7
+
8
+ export interface EventAttachmentListProps {
9
+ attachments: Array<EventAttachment>;
10
+ title?: string;
11
+ variant?: "section" | "inline";
12
+ showHeader?: boolean;
13
+ showCount?: boolean;
14
+ className?: string;
15
+ }
16
+
17
+ function getAttachmentExtensionLabel(fileName?: string | null): string | null {
18
+ if (!fileName) {
19
+ return null;
20
+ }
21
+
22
+ const trimmedName: string = fileName.trim();
23
+ const lastDotIndex: number = trimmedName.lastIndexOf(".");
24
+
25
+ if (lastDotIndex === -1 || lastDotIndex === trimmedName.length - 1) {
26
+ return null;
27
+ }
28
+
29
+ return trimmedName.substring(lastDotIndex + 1).toUpperCase();
30
+ }
31
+
32
+ type AttachmentCardProps = {
33
+ attachment: EventAttachment;
34
+ };
35
+
36
+ const AttachmentCard: FunctionComponent<AttachmentCardProps> = (
37
+ props: AttachmentCardProps,
38
+ ): ReactElement => {
39
+ const { attachment } = props;
40
+ const extensionLabel: string | null = getAttachmentExtensionLabel(
41
+ attachment.name,
42
+ );
43
+
44
+ return (
45
+ <li>
46
+ <a
47
+ href={attachment.downloadUrl}
48
+ target="_blank"
49
+ rel="noopener noreferrer"
50
+ title={attachment.name}
51
+ className="group flex items-center justify-between gap-3 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm text-gray-900 transition hover:border-gray-300 hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-200"
52
+ >
53
+ <span className="flex items-center gap-3 min-w-0">
54
+ <span className="flex flex-col min-w-0">
55
+ <span className="text-sm font-medium text-gray-900 truncate">
56
+ {attachment.name || "Attachment"}
57
+ </span>
58
+ {extensionLabel && (
59
+ <span className="text-[11px] font-semibold uppercase tracking-wide text-gray-400">
60
+ {extensionLabel}
61
+ </span>
62
+ )}
63
+ </span>
64
+ </span>
65
+
66
+ <span className="flex flex-shrink-0 items-center text-gray-500 text-xs font-semibold uppercase tracking-wide">
67
+ Download
68
+ </span>
69
+ </a>
70
+ </li>
71
+ );
72
+ };
73
+
74
+ const EventAttachmentList: FunctionComponent<EventAttachmentListProps> = (
75
+ props: EventAttachmentListProps,
76
+ ): ReactElement | null => {
77
+ const {
78
+ attachments,
79
+ title = "Attachments",
80
+ variant = "section",
81
+ showHeader = true,
82
+ showCount = true,
83
+ className = "",
84
+ } = props;
85
+
86
+ if (!attachments || attachments.length === 0) {
87
+ return null;
88
+ }
89
+
90
+ const attachmentsList: ReactElement = (
91
+ <ul className="space-y-2">
92
+ {attachments.map((attachment: EventAttachment, index: number) => {
93
+ return <AttachmentCard attachment={attachment} key={index} />;
94
+ })}
95
+ </ul>
96
+ );
97
+
98
+ if (variant === "inline") {
99
+ return <div className={className}>{attachmentsList}</div>;
100
+ }
101
+
102
+ return (
103
+ <div
104
+ className={`mt-4 rounded-2xl border border-gray-100 bg-gray-50/80 p-4 ${className}`.trim()}
105
+ >
106
+ {showHeader && (
107
+ <div className="flex items-center justify-between text-xs font-semibold uppercase tracking-wide text-gray-500">
108
+ <span>{title}</span>
109
+ {showCount && (
110
+ <span className="rounded-full bg-white px-2 py-0.5 text-[11px] font-semibold text-gray-600">
111
+ {attachments.length}
112
+ </span>
113
+ )}
114
+ </div>
115
+ )}
116
+ <div className="mt-3">{attachmentsList}</div>
117
+ </div>
118
+ );
119
+ };
120
+
121
+ export default EventAttachmentList;
@@ -2,6 +2,7 @@ import Icon from "../Icon/Icon";
2
2
  import Link from "../Link/Link";
3
3
  import MarkdownViewer from "../Markdown.tsx/LazyMarkdownViewer";
4
4
  import Pill from "../Pill/Pill";
5
+ import EventAttachmentList from "../AttachmentList/EventAttachmentList";
5
6
  import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
6
7
  import Route from "../../../Types/API/Route";
7
8
  import URL from "../../../Types/API/URL";
@@ -16,6 +17,11 @@ export enum TimelineItemType {
16
17
  Note = "Note",
17
18
  }
18
19
 
20
+ export interface TimelineAttachment {
21
+ name: string;
22
+ downloadUrl: string;
23
+ }
24
+
19
25
  export interface TimelineItem {
20
26
  date: Date;
21
27
  note?: string;
@@ -23,6 +29,7 @@ export interface TimelineItem {
23
29
  state?: BaseModel;
24
30
  icon: IconProp;
25
31
  iconColor: Color;
32
+ attachments?: Array<TimelineAttachment>;
26
33
  }
27
34
 
28
35
  export interface EventItemLabel {
@@ -46,6 +53,7 @@ export interface ComponentProps {
46
53
  anotherStatusColor?: Color | undefined;
47
54
  eventSecondDescription: string;
48
55
  labels?: Array<EventItemLabel> | undefined;
56
+ eventAttachments?: Array<TimelineAttachment> | undefined;
49
57
  }
50
58
 
51
59
  const EventItem: FunctionComponent<ComponentProps> = (
@@ -102,6 +110,10 @@ const EventItem: FunctionComponent<ComponentProps> = (
102
110
  </div>
103
111
  )}
104
112
 
113
+ {props.eventAttachments && props.eventAttachments.length > 0 && (
114
+ <EventAttachmentList attachments={props.eventAttachments} />
115
+ )}
116
+
105
117
  {props.eventSecondDescription && (
106
118
  <div className="mt-3 text-gray-500 text-sm active-event-box-body-second-description">
107
119
  {props.eventSecondDescription}
@@ -278,6 +290,16 @@ const EventItem: FunctionComponent<ComponentProps> = (
278
290
  <p>
279
291
  <MarkdownViewer text={item.note || ""} />
280
292
  </p>
293
+ {item.attachments &&
294
+ item.attachments.length > 0 && (
295
+ <EventAttachmentList
296
+ attachments={item.attachments}
297
+ variant="inline"
298
+ showHeader={false}
299
+ showCount={false}
300
+ className="mt-3"
301
+ />
302
+ )}
281
303
  </div>
282
304
  </div>
283
305
  </div>
@@ -4,7 +4,7 @@ import { GetReactElementFunction } from "../../Types/FunctionTypes";
4
4
  import Image from "../Image/Image";
5
5
  import Route from "../../../Types/API/Route";
6
6
  import BlankProfilePic from "../../Images/users/blank-profile.svg";
7
- import FileUtil from "../../Utils/File";
7
+ import UserUtil from "../../Utils/User";
8
8
  import ObjectID from "../../../Types/ObjectID";
9
9
  import OneUptimeDate from "../../../Types/Date";
10
10
  import Tooltip from "../Tooltip/Tooltip";
@@ -60,23 +60,16 @@ const FeedItem: FunctionComponent<ComponentProps> = (
60
60
  };
61
61
 
62
62
  const getUserIcon: GetReactElementFunction = (): ReactElement => {
63
+ const userImageRoute: Route = props.user?.id
64
+ ? UserUtil.getProfilePictureRoute(props.user.id as ObjectID)
65
+ : Route.fromString(`${BlankProfilePic}`);
66
+
63
67
  return (
64
68
  <div>
65
- {!props.user?.profilePictureId && (
66
- <Image
67
- className="h-10 w-10 rounded-full"
68
- imageUrl={Route.fromString(`${BlankProfilePic}`)}
69
- />
70
- )}
71
-
72
- {props.user?.profilePictureId && (
73
- <Image
74
- className="flex size-10 items-center justify-center rounded-full bg-gray-400 ring-8 ring-white"
75
- imageUrl={FileUtil.getFileRoute(
76
- props.user!.profilePictureId as ObjectID,
77
- )}
78
- />
79
- )}
69
+ <Image
70
+ className="flex size-10 items-center justify-center rounded-full bg-gray-400 ring-8 ring-white"
71
+ imageUrl={userImageRoute}
72
+ />
80
73
 
81
74
  {props.icon && (
82
75
  <span className="absolute -bottom-0.5 -right-1 rounded-tl bg-white px-0.5 py-px">