@oneuptime/common 10.4.14 → 10.4.16

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 (152) hide show
  1. package/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +49 -0
  2. package/Models/AnalyticsModels/AuditLog.ts +8 -0
  3. package/Models/AnalyticsModels/ExceptionInstance.ts +1 -0
  4. package/Models/AnalyticsModels/Log.ts +1 -0
  5. package/Models/AnalyticsModels/Metric.ts +10 -0
  6. package/Models/AnalyticsModels/MonitorLog.ts +1 -0
  7. package/Models/AnalyticsModels/Profile.ts +1 -0
  8. package/Models/AnalyticsModels/ProfileSample.ts +1 -0
  9. package/Models/AnalyticsModels/Span.ts +1 -0
  10. package/Models/DatabaseModels/AlertCustomField.ts +37 -0
  11. package/Models/DatabaseModels/IncidentCustomField.ts +37 -0
  12. package/Models/DatabaseModels/IncidentMember.ts +9 -0
  13. package/Models/DatabaseModels/MonitorCustomField.ts +37 -0
  14. package/Models/DatabaseModels/OnCallDutyPolicyCustomField.ts +37 -0
  15. package/Models/DatabaseModels/ScheduledMaintenanceCustomField.ts +37 -0
  16. package/Models/DatabaseModels/StatusPageCustomField.ts +37 -0
  17. package/Models/DatabaseModels/TableView.ts +40 -0
  18. package/Models/DatabaseModels/TeamMemberCustomField.ts +37 -0
  19. package/Server/API/BaseAnalyticsAPI.ts +128 -20
  20. package/Server/API/MetricAPI.ts +5 -138
  21. package/Server/API/StatusAPI.ts +103 -7
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.ts +13 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.ts +34 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.ts +67 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  26. package/Server/Services/AccessTokenService.ts +1 -1
  27. package/Server/Services/AnalyticsDatabaseService.ts +24 -4
  28. package/Server/Services/MetricService.ts +113 -0
  29. package/Server/Services/ProjectService.ts +21 -1
  30. package/Server/Utils/Response.ts +4 -1
  31. package/Server/Utils/UserPermission/UserPermission.ts +17 -1
  32. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +2 -2
  33. package/Types/API/HTTPResponse.ts +16 -0
  34. package/Types/BaseDatabase/ListResult.ts +6 -0
  35. package/Types/CustomField/CustomFieldType.ts +2 -0
  36. package/Types/Date.ts +9 -1
  37. package/Types/ListData.ts +14 -0
  38. package/Types/Monitor/DnsMonitor/DnsMonitorResponse.ts +3 -0
  39. package/Types/Monitor/DnssecMonitor/DnssecMonitorResponse.ts +5 -0
  40. package/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts +4 -0
  41. package/Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse.ts +4 -0
  42. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +3 -0
  43. package/Types/Probe/ProbeAttempt.ts +9 -0
  44. package/Types/Probe/ProbeMonitorResponse.ts +3 -0
  45. package/UI/Components/BulkUpdate/BulkOwnerActions.tsx +504 -0
  46. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +64 -54
  47. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +38 -0
  48. package/UI/Components/CustomFields/DropdownOptionsInput.tsx +150 -0
  49. package/UI/Components/Detail/Detail.tsx +78 -11
  50. package/UI/Components/List/List.tsx +6 -0
  51. package/UI/Components/ModelTable/BaseModelTable.tsx +74 -2
  52. package/UI/Components/ModelTable/TableView.tsx +74 -30
  53. package/UI/Components/Pagination/Pagination.tsx +75 -33
  54. package/UI/Components/Table/Table.tsx +6 -0
  55. package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +1 -0
  56. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +33 -0
  57. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
  58. package/build/dist/Models/AnalyticsModels/AuditLog.js +8 -0
  59. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  60. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js +1 -0
  61. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js.map +1 -1
  62. package/build/dist/Models/AnalyticsModels/Log.js +1 -0
  63. package/build/dist/Models/AnalyticsModels/Log.js.map +1 -1
  64. package/build/dist/Models/AnalyticsModels/Metric.js +10 -0
  65. package/build/dist/Models/AnalyticsModels/Metric.js.map +1 -1
  66. package/build/dist/Models/AnalyticsModels/MonitorLog.js +1 -0
  67. package/build/dist/Models/AnalyticsModels/MonitorLog.js.map +1 -1
  68. package/build/dist/Models/AnalyticsModels/Profile.js +1 -0
  69. package/build/dist/Models/AnalyticsModels/Profile.js.map +1 -1
  70. package/build/dist/Models/AnalyticsModels/ProfileSample.js +1 -0
  71. package/build/dist/Models/AnalyticsModels/ProfileSample.js.map +1 -1
  72. package/build/dist/Models/AnalyticsModels/Span.js +1 -0
  73. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  74. package/build/dist/Models/DatabaseModels/AlertCustomField.js +38 -0
  75. package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -1
  76. package/build/dist/Models/DatabaseModels/IncidentCustomField.js +38 -0
  77. package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
  78. package/build/dist/Models/DatabaseModels/IncidentMember.js +11 -1
  79. package/build/dist/Models/DatabaseModels/IncidentMember.js.map +1 -1
  80. package/build/dist/Models/DatabaseModels/MonitorCustomField.js +38 -0
  81. package/build/dist/Models/DatabaseModels/MonitorCustomField.js.map +1 -1
  82. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js +38 -0
  83. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js.map +1 -1
  84. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js +38 -0
  85. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js.map +1 -1
  86. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js +38 -0
  87. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js.map +1 -1
  88. package/build/dist/Models/DatabaseModels/TableView.js +40 -0
  89. package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
  90. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js +38 -0
  91. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js.map +1 -1
  92. package/build/dist/Server/API/BaseAnalyticsAPI.js +105 -18
  93. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  94. package/build/dist/Server/API/MetricAPI.js +5 -113
  95. package/build/dist/Server/API/MetricAPI.js.map +1 -1
  96. package/build/dist/Server/API/StatusAPI.js +75 -8
  97. package/build/dist/Server/API/StatusAPI.js.map +1 -1
  98. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.js +12 -0
  99. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.js.map +1 -0
  100. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.js +27 -0
  101. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.js.map +1 -0
  102. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.js +28 -0
  103. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.js.map +1 -0
  104. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  105. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  106. package/build/dist/Server/Services/AccessTokenService.js +1 -1
  107. package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
  108. package/build/dist/Server/Services/AnalyticsDatabaseService.js +22 -3
  109. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  110. package/build/dist/Server/Services/MetricService.js +89 -0
  111. package/build/dist/Server/Services/MetricService.js.map +1 -1
  112. package/build/dist/Server/Services/ProjectService.js +19 -1
  113. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  114. package/build/dist/Server/Utils/Response.js +6 -5
  115. package/build/dist/Server/Utils/Response.js.map +1 -1
  116. package/build/dist/Server/Utils/UserPermission/UserPermission.js +13 -1
  117. package/build/dist/Server/Utils/UserPermission/UserPermission.js.map +1 -1
  118. package/build/dist/Tests/Server/Services/AnalyticsDatabaseService.test.js +2 -2
  119. package/build/dist/Tests/Server/Services/AnalyticsDatabaseService.test.js.map +1 -1
  120. package/build/dist/Types/API/HTTPResponse.js +15 -0
  121. package/build/dist/Types/API/HTTPResponse.js.map +1 -1
  122. package/build/dist/Types/CustomField/CustomFieldType.js +2 -0
  123. package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
  124. package/build/dist/Types/Date.js +10 -1
  125. package/build/dist/Types/Date.js.map +1 -1
  126. package/build/dist/Types/ListData.js +4 -0
  127. package/build/dist/Types/ListData.js.map +1 -1
  128. package/build/dist/Types/Probe/ProbeAttempt.js +2 -0
  129. package/build/dist/Types/Probe/ProbeAttempt.js.map +1 -0
  130. package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js +376 -0
  131. package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js.map +1 -0
  132. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +32 -25
  133. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  134. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +32 -0
  135. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  136. package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js +84 -0
  137. package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js.map +1 -0
  138. package/build/dist/UI/Components/Detail/Detail.js +34 -3
  139. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  140. package/build/dist/UI/Components/List/List.js +1 -1
  141. package/build/dist/UI/Components/List/List.js.map +1 -1
  142. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +45 -5
  143. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  144. package/build/dist/UI/Components/ModelTable/TableView.js +44 -19
  145. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  146. package/build/dist/UI/Components/Pagination/Pagination.js +62 -36
  147. package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
  148. package/build/dist/UI/Components/Table/Table.js +1 -1
  149. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  150. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +1 -0
  151. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
  152. package/package.json +1 -1
@@ -52,6 +52,16 @@ export default class AnalyticsBaseModel extends CommonModel {
52
52
  materializedViews?: Array<MaterializedView> | undefined;
53
53
  enableMCP?: boolean | undefined;
54
54
  ttlExpression?: string | undefined; // e.g. "retentionDate DELETE"
55
+ /*
56
+ * Column that `findBy` falls back to when the caller doesn't
57
+ * specify a `sort`. Defaults to `createdAt` (matching the legacy
58
+ * behavior), but heavy analytics tables should override this to
59
+ * a column that participates in their ClickHouse sort key so the
60
+ * default list query streams from the index instead of doing a
61
+ * full sort. Examples: Log/MonitorLog/ExceptionInstance => "time",
62
+ * Span/Profile => "startTime", AuditLog => "createdAt".
63
+ */
64
+ defaultSortColumn?: string | undefined;
55
65
  }) {
56
66
  super({
57
67
  tableColumns: data.tableColumns,
@@ -156,6 +166,29 @@ export default class AnalyticsBaseModel extends CommonModel {
156
166
  this.materializedViews = data.materializedViews || [];
157
167
  this.enableMCP = data.enableMCP || false;
158
168
  this.ttlExpression = data.ttlExpression || "";
169
+
170
+ /*
171
+ * Validate the override matches the schema. We deliberately do
172
+ * NOT require the column to be in `sortKeys` — it must just
173
+ * exist on the table; the caller picks a column they know is
174
+ * indexed (typically the timestamp column at position 2 of the
175
+ * sort key, after `projectId`).
176
+ */
177
+ if (data.defaultSortColumn) {
178
+ const column: AnalyticsTableColumn | undefined = columns.find(
179
+ (column: AnalyticsTableColumn) => {
180
+ return column.key === data.defaultSortColumn;
181
+ },
182
+ );
183
+ if (!column) {
184
+ throw new BadDataException(
185
+ "defaultSortColumn " +
186
+ data.defaultSortColumn +
187
+ " is not part of tableColumns",
188
+ );
189
+ }
190
+ this.defaultSortColumn = data.defaultSortColumn;
191
+ }
159
192
  }
160
193
 
161
194
  private _enableWorkflowOn: EnableWorkflowOn | undefined;
@@ -214,6 +247,22 @@ export default class AnalyticsBaseModel extends CommonModel {
214
247
  this._sortKeys = v;
215
248
  }
216
249
 
250
+ /*
251
+ * Column that `AnalyticsDatabaseService._findBy` falls back to
252
+ * when the caller didn't pass a `sort`. `createdAt` (the historical
253
+ * default) is not part of the ClickHouse sort key on heavy
254
+ * analytics tables (Log/Span/Metric/...), so a default list query
255
+ * over those tables triggers a full sort. Per-model overrides
256
+ * point at a column that participates in the sort key.
257
+ */
258
+ private _defaultSortColumn: string = "createdAt";
259
+ public get defaultSortColumn(): string {
260
+ return this._defaultSortColumn;
261
+ }
262
+ public set defaultSortColumn(v: string) {
263
+ this._defaultSortColumn = v;
264
+ }
265
+
217
266
  private _singularName: string = "";
218
267
  public get singularName(): string {
219
268
  return this._singularName;
@@ -287,6 +287,14 @@ export default class AuditLog extends AnalyticsBaseModel {
287
287
  primaryKeys: ["projectId", "createdAt"],
288
288
  partitionKey: "sipHash64(projectId) % 16",
289
289
  ttlExpression: "retentionDate DELETE",
290
+ /*
291
+ * `createdAt` already participates in the AuditLog sort key
292
+ * (position 2 after `projectId`), so the legacy `createdAt
293
+ * DESC` default was already efficient here. Set it explicitly
294
+ * so the choice is intentional rather than inherited from the
295
+ * base class.
296
+ */
297
+ defaultSortColumn: "createdAt",
290
298
  });
291
299
  }
292
300
 
@@ -667,6 +667,7 @@ export default class ExceptionInstance extends AnalyticsBaseModel {
667
667
  primaryKeys: ["projectId", "time", "serviceId", "fingerprint"],
668
668
  partitionKey: "sipHash64(projectId) % 16",
669
669
  ttlExpression: "retentionDate DELETE",
670
+ defaultSortColumn: "time",
670
671
  });
671
672
  }
672
673
 
@@ -569,6 +569,7 @@ export default class Log extends AnalyticsBaseModel {
569
569
  primaryKeys: ["projectId", "time", "serviceId"],
570
570
  partitionKey: "sipHash64(projectId) % 16",
571
571
  ttlExpression: "retentionDate DELETE",
572
+ defaultSortColumn: "time",
572
573
  });
573
574
  }
574
575
 
@@ -1046,6 +1046,16 @@ export default class Metric extends AnalyticsBaseModel {
1046
1046
  primaryKeys: ["projectId", "name", "serviceId", "time"],
1047
1047
  partitionKey: "sipHash64(projectId) % 16",
1048
1048
  ttlExpression: "retentionDate DELETE",
1049
+ /*
1050
+ * `time` is the 4th column of the Metric sort key (after
1051
+ * projectId + name + serviceId). A list query that filters
1052
+ * by name (the typical "metric detail" drilldown) can still
1053
+ * stream from the index when sorting by `time DESC`. With
1054
+ * no name filter the sort is less efficient but still far
1055
+ * better than the legacy `createdAt DESC` fallback, which
1056
+ * isn't in the sort key at all.
1057
+ */
1058
+ defaultSortColumn: "time",
1049
1059
  });
1050
1060
  }
1051
1061
 
@@ -188,6 +188,7 @@ export default class MonitorLog extends AnalyticsBaseModel {
188
188
  primaryKeys: ["projectId", "time", "monitorId"],
189
189
  partitionKey: "sipHash64(projectId) % 16",
190
190
  ttlExpression: "retentionDate DELETE",
191
+ defaultSortColumn: "time",
191
192
  });
192
193
  }
193
194
 
@@ -673,6 +673,7 @@ export default class Profile extends AnalyticsBaseModel {
673
673
  primaryKeys: ["projectId", "startTime", "serviceId", "profileType"],
674
674
  partitionKey: "sipHash64(projectId) % 16",
675
675
  ttlExpression: "retentionDate DELETE",
676
+ defaultSortColumn: "startTime",
676
677
  });
677
678
  }
678
679
 
@@ -542,6 +542,7 @@ export default class ProfileSample extends AnalyticsBaseModel {
542
542
  ],
543
543
  partitionKey: "sipHash64(projectId) % 16",
544
544
  ttlExpression: "retentionDate DELETE",
545
+ defaultSortColumn: "time",
545
546
  });
546
547
  }
547
548
 
@@ -846,6 +846,7 @@ export default class Span extends AnalyticsBaseModel {
846
846
  primaryKeys: ["projectId", "startTime", "serviceId", "traceId"],
847
847
  partitionKey: "sipHash64(projectId) % 16",
848
848
  ttlExpression: "retentionDate DELETE",
849
+ defaultSortColumn: "startTime",
849
850
  });
850
851
  }
851
852
 
@@ -249,6 +249,43 @@ export default class AlertCustomField extends BaseModel {
249
249
  })
250
250
  public customFieldType?: CustomFieldType = undefined;
251
251
 
252
+ @ColumnAccessControl({
253
+ create: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.CreateAlertCustomField,
257
+ ],
258
+ read: [
259
+ Permission.ProjectOwner,
260
+ Permission.ProjectAdmin,
261
+ Permission.ProjectMember,
262
+ Permission.Viewer,
263
+ Permission.AlertAdmin,
264
+ Permission.AlertMember,
265
+ Permission.AlertViewer,
266
+ Permission.ReadAlertCustomField,
267
+ ],
268
+ update: [
269
+ Permission.ProjectOwner,
270
+ Permission.ProjectAdmin,
271
+ Permission.EditAlertCustomField,
272
+ ],
273
+ })
274
+ @TableColumn({
275
+ required: false,
276
+ type: TableColumnType.LongText,
277
+ title: "Dropdown Options",
278
+ description:
279
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
280
+ example: "Option 1\nOption 2\nOption 3",
281
+ })
282
+ @Column({
283
+ nullable: true,
284
+ type: ColumnType.LongText,
285
+ length: ColumnLength.LongText,
286
+ })
287
+ public dropdownOptions?: string = undefined;
288
+
252
289
  @ColumnAccessControl({
253
290
  create: [
254
291
  Permission.ProjectOwner,
@@ -249,6 +249,43 @@ export default class IncidentCustomField extends BaseModel {
249
249
  })
250
250
  public customFieldType?: CustomFieldType = undefined;
251
251
 
252
+ @ColumnAccessControl({
253
+ create: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.CreateIncidentCustomField,
257
+ ],
258
+ read: [
259
+ Permission.ProjectOwner,
260
+ Permission.ProjectAdmin,
261
+ Permission.ProjectMember,
262
+ Permission.Viewer,
263
+ Permission.IncidentAdmin,
264
+ Permission.IncidentMember,
265
+ Permission.IncidentViewer,
266
+ Permission.ReadIncidentCustomField,
267
+ ],
268
+ update: [
269
+ Permission.ProjectOwner,
270
+ Permission.ProjectAdmin,
271
+ Permission.EditIncidentCustomField,
272
+ ],
273
+ })
274
+ @TableColumn({
275
+ required: false,
276
+ type: TableColumnType.LongText,
277
+ title: "Dropdown Options",
278
+ description:
279
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
280
+ example: "Option 1\nOption 2\nOption 3",
281
+ })
282
+ @Column({
283
+ nullable: true,
284
+ type: ColumnType.LongText,
285
+ length: ColumnLength.LongText,
286
+ })
287
+ public dropdownOptions?: string = undefined;
288
+
252
289
  @ColumnAccessControl({
253
290
  create: [
254
291
  Permission.ProjectOwner,
@@ -605,6 +605,15 @@ export default class IncidentMember extends BaseModel {
605
605
  read: [],
606
606
  update: [],
607
607
  })
608
+ /*
609
+ * Indexed because `IncidentMembers/SendMemberAddedNotification`
610
+ * cron polls `WHERE isMemberNotified = false` every minute. Without
611
+ * the index the cron does a full table scan that grows with every
612
+ * incident-member assignment ever made. Matches the indexing
613
+ * pattern used by the sibling `isOwnerNotified` flag on state
614
+ * timeline tables.
615
+ */
616
+ @Index()
608
617
  @TableColumn({
609
618
  isDefaultValueColumn: true,
610
619
  type: TableColumnType.Boolean,
@@ -249,6 +249,43 @@ export default class MonitorCustomField extends BaseModel {
249
249
  })
250
250
  public customFieldType?: CustomFieldType = undefined;
251
251
 
252
+ @ColumnAccessControl({
253
+ create: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.CreateMonitorCustomField,
257
+ ],
258
+ read: [
259
+ Permission.ProjectOwner,
260
+ Permission.ProjectAdmin,
261
+ Permission.ProjectMember,
262
+ Permission.Viewer,
263
+ Permission.MonitorAdmin,
264
+ Permission.MonitorMember,
265
+ Permission.MonitorViewer,
266
+ Permission.ReadMonitorCustomField,
267
+ ],
268
+ update: [
269
+ Permission.ProjectOwner,
270
+ Permission.ProjectAdmin,
271
+ Permission.EditMonitorCustomField,
272
+ ],
273
+ })
274
+ @TableColumn({
275
+ required: false,
276
+ type: TableColumnType.LongText,
277
+ title: "Dropdown Options",
278
+ description:
279
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
280
+ example: "Option 1\nOption 2\nOption 3",
281
+ })
282
+ @Column({
283
+ nullable: true,
284
+ type: ColumnType.LongText,
285
+ length: ColumnLength.LongText,
286
+ })
287
+ public dropdownOptions?: string = undefined;
288
+
252
289
  @ColumnAccessControl({
253
290
  create: [
254
291
  Permission.ProjectOwner,
@@ -244,6 +244,43 @@ export default class OnCallDutyPolicyCustomField extends BaseModel {
244
244
  })
245
245
  public customFieldType?: CustomFieldType = undefined;
246
246
 
247
+ @ColumnAccessControl({
248
+ create: [
249
+ Permission.ProjectOwner,
250
+ Permission.ProjectAdmin,
251
+ Permission.CreateOnCallDutyPolicyCustomField,
252
+ ],
253
+ read: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.ProjectMember,
257
+ Permission.Viewer,
258
+ Permission.OnCallAdmin,
259
+ Permission.OnCallMember,
260
+ Permission.OnCallViewer,
261
+ Permission.ReadOnCallDutyPolicyCustomField,
262
+ ],
263
+ update: [
264
+ Permission.ProjectOwner,
265
+ Permission.ProjectAdmin,
266
+ Permission.EditOnCallDutyPolicyCustomField,
267
+ ],
268
+ })
269
+ @TableColumn({
270
+ required: false,
271
+ type: TableColumnType.LongText,
272
+ title: "Dropdown Options",
273
+ description:
274
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
275
+ example: "Option 1\nOption 2\nOption 3",
276
+ })
277
+ @Column({
278
+ nullable: true,
279
+ type: ColumnType.LongText,
280
+ length: ColumnLength.LongText,
281
+ })
282
+ public dropdownOptions?: string = undefined;
283
+
247
284
  @ColumnAccessControl({
248
285
  create: [
249
286
  Permission.ProjectOwner,
@@ -249,6 +249,43 @@ export default class ScheduledMaintenanceCustomField extends BaseModel {
249
249
  })
250
250
  public customFieldType?: CustomFieldType = undefined;
251
251
 
252
+ @ColumnAccessControl({
253
+ create: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.CreateScheduledMaintenanceCustomField,
257
+ ],
258
+ read: [
259
+ Permission.ProjectOwner,
260
+ Permission.ProjectAdmin,
261
+ Permission.ProjectMember,
262
+ Permission.Viewer,
263
+ Permission.ScheduledMaintenanceAdmin,
264
+ Permission.ScheduledMaintenanceMember,
265
+ Permission.ScheduledMaintenanceViewer,
266
+ Permission.ReadScheduledMaintenanceCustomField,
267
+ ],
268
+ update: [
269
+ Permission.ProjectOwner,
270
+ Permission.ProjectAdmin,
271
+ Permission.EditScheduledMaintenanceCustomField,
272
+ ],
273
+ })
274
+ @TableColumn({
275
+ required: false,
276
+ type: TableColumnType.LongText,
277
+ title: "Dropdown Options",
278
+ description:
279
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
280
+ example: "Option 1\nOption 2\nOption 3",
281
+ })
282
+ @Column({
283
+ nullable: true,
284
+ type: ColumnType.LongText,
285
+ length: ColumnLength.LongText,
286
+ })
287
+ public dropdownOptions?: string = undefined;
288
+
252
289
  @ColumnAccessControl({
253
290
  create: [
254
291
  Permission.ProjectOwner,
@@ -244,6 +244,43 @@ export default class StatusPageCustomField extends BaseModel {
244
244
  })
245
245
  public customFieldType?: CustomFieldType = undefined;
246
246
 
247
+ @ColumnAccessControl({
248
+ create: [
249
+ Permission.ProjectOwner,
250
+ Permission.ProjectAdmin,
251
+ Permission.CreateStatusPageCustomField,
252
+ ],
253
+ read: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.ProjectMember,
257
+ Permission.Viewer,
258
+ Permission.StatusPageAdmin,
259
+ Permission.StatusPageMember,
260
+ Permission.StatusPageViewer,
261
+ Permission.ReadStatusPageCustomField,
262
+ ],
263
+ update: [
264
+ Permission.ProjectOwner,
265
+ Permission.ProjectAdmin,
266
+ Permission.EditStatusPageCustomField,
267
+ ],
268
+ })
269
+ @TableColumn({
270
+ required: false,
271
+ type: TableColumnType.LongText,
272
+ title: "Dropdown Options",
273
+ description:
274
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
275
+ example: "Option 1\nOption 2\nOption 3",
276
+ })
277
+ @Column({
278
+ nullable: true,
279
+ type: ColumnType.LongText,
280
+ length: ColumnLength.LongText,
281
+ })
282
+ public dropdownOptions?: string = undefined;
283
+
247
284
  @ColumnAccessControl({
248
285
  create: [
249
286
  Permission.ProjectOwner,
@@ -22,6 +22,7 @@ import Query from "../../Types/BaseDatabase/Query";
22
22
  import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
23
23
  import Sort from "../../Types/BaseDatabase/Sort";
24
24
  import AnalyticsBaseModel from "../AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
25
+ import { JSONObject } from "../../Types/JSON";
25
26
 
26
27
  @TableBillingAccessControl({
27
28
  create: PlanType.Growth,
@@ -515,4 +516,43 @@ export default class TableView extends BaseModel {
515
516
  default: 10,
516
517
  })
517
518
  public itemsOnPage?: number = undefined;
519
+
520
+ @ColumnAccessControl({
521
+ create: [
522
+ Permission.ProjectOwner,
523
+ Permission.ProjectAdmin,
524
+ Permission.CreateTableView,
525
+ ],
526
+ read: [
527
+ Permission.ProjectOwner,
528
+ Permission.ProjectAdmin,
529
+ Permission.ProjectMember,
530
+ Permission.Viewer,
531
+ Permission.SettingsAdmin,
532
+ Permission.SettingsMember,
533
+ Permission.SettingsViewer,
534
+ Permission.ReadTableView,
535
+ ],
536
+ update: [
537
+ Permission.ProjectOwner,
538
+ Permission.ProjectAdmin,
539
+ Permission.EditTableView,
540
+ ],
541
+ })
542
+ @TableColumn({
543
+ title: "Facets",
544
+ required: false,
545
+ unique: false,
546
+ type: TableColumnType.JSON,
547
+ canReadOnRelationQuery: true,
548
+ description:
549
+ "Facet selections (owner, labels, status, etc.) for this table view",
550
+ example: '{"selectedOwnerKeys": ["user:abc"], "facetSelections": {}}',
551
+ })
552
+ @Column({
553
+ type: ColumnType.JSON,
554
+ unique: false,
555
+ nullable: true,
556
+ })
557
+ public facets?: JSONObject = undefined;
518
558
  }
@@ -248,6 +248,43 @@ export default class TeamMemberCustomField extends BaseModel {
248
248
  })
249
249
  public customFieldType?: CustomFieldType = undefined;
250
250
 
251
+ @ColumnAccessControl({
252
+ create: [
253
+ Permission.ProjectOwner,
254
+ Permission.ProjectAdmin,
255
+ Permission.CreateTeamMemberCustomField,
256
+ ],
257
+ read: [
258
+ Permission.ProjectOwner,
259
+ Permission.ProjectAdmin,
260
+ Permission.ProjectMember,
261
+ Permission.Viewer,
262
+ Permission.SettingsAdmin,
263
+ Permission.SettingsMember,
264
+ Permission.SettingsViewer,
265
+ Permission.ReadTeamMemberCustomField,
266
+ ],
267
+ update: [
268
+ Permission.ProjectOwner,
269
+ Permission.ProjectAdmin,
270
+ Permission.EditTeamMemberCustomField,
271
+ ],
272
+ })
273
+ @TableColumn({
274
+ required: false,
275
+ type: TableColumnType.LongText,
276
+ title: "Dropdown Options",
277
+ description:
278
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
279
+ example: "Option 1\nOption 2\nOption 3",
280
+ })
281
+ @Column({
282
+ nullable: true,
283
+ type: ColumnType.LongText,
284
+ length: ColumnLength.LongText,
285
+ })
286
+ public dropdownOptions?: string = undefined;
287
+
251
288
  @ColumnAccessControl({
252
289
  create: [
253
290
  Permission.ProjectOwner,