diff --git a/Common/Models/DatabaseModels/Index.ts b/Common/Models/DatabaseModels/Index.ts index 4fe4f8ef7e..aaaa60e3b9 100644 --- a/Common/Models/DatabaseModels/Index.ts +++ b/Common/Models/DatabaseModels/Index.ts @@ -103,6 +103,7 @@ import SmsLog from "./SmsLog"; // Status Page import StatusPage from "./StatusPage"; import StatusPageAnnouncement from "./StatusPageAnnouncement"; +import StatusPageAnnouncementTemplate from "./StatusPageAnnouncementTemplate"; import StatusPageCustomField from "./StatusPageCustomField"; import StatusPageDomain from "./StatusPageDomain"; import StatusPageFooterLink from "./StatusPageFooterLink"; @@ -247,6 +248,7 @@ const AllModelTypes: Array<{ StatusPageResource, StatusPageAnnouncement, + StatusPageAnnouncementTemplate, StatusPageSubscriber, StatusPageFooterLink, StatusPageHeaderLink, diff --git a/Common/Models/DatabaseModels/StatusPageAnnouncementTemplate.ts b/Common/Models/DatabaseModels/StatusPageAnnouncementTemplate.ts new file mode 100644 index 0000000000..cc13342bca --- /dev/null +++ b/Common/Models/DatabaseModels/StatusPageAnnouncementTemplate.ts @@ -0,0 +1,468 @@ +import Project from "./Project"; +import StatusPage from "./StatusPage"; +import User from "./User"; +import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel"; +import Route from "../../Types/API/Route"; +import { PlanType } from "../../Types/Billing/SubscriptionPlan"; +import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl"; +import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl"; +import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl"; +import CanAccessIfCanReadOn from "../../Types/Database/CanAccessIfCanReadOn"; +import ColumnLength from "../../Types/Database/ColumnLength"; +import ColumnType from "../../Types/Database/ColumnType"; +import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint"; +import EnableDocumentation from "../../Types/Database/EnableDocumentation"; +import EnableWorkflow from "../../Types/Database/EnableWorkflow"; +import SlugifyColumn from "../../Types/Database/SlugifyColumn"; +import TableColumn from "../../Types/Database/TableColumn"; +import TableColumnType from "../../Types/Database/TableColumnType"; +import TableMetadata from "../../Types/Database/TableMetadata"; +import TenantColumn from "../../Types/Database/TenantColumn"; +import IconProp from "../../Types/Icon/IconProp"; +import ObjectID from "../../Types/ObjectID"; +import Permission from "../../Types/Permission"; +import { + Column, + Entity, + Index, + JoinColumn, + JoinTable, + ManyToMany, + ManyToOne, +} from "typeorm"; + +@EnableDocumentation() +@TenantColumn("projectId") +@CanAccessIfCanReadOn("statusPages") +@TableBillingAccessControl({ + create: PlanType.Growth, + read: PlanType.Growth, + update: PlanType.Growth, + delete: PlanType.Growth, +}) +@TableAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.CreateStatusPageAnnouncementTemplate, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + delete: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.DeleteStatusPageAnnouncementTemplate, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.EditStatusPageAnnouncementTemplate, + ], +}) +@EnableWorkflow({ + create: true, + delete: true, + update: true, + read: true, +}) +@CrudApiEndpoint(new Route("/status-page-announcement-template")) +@SlugifyColumn("templateName", "slug") +@TableMetadata({ + tableName: "StatusPageAnnouncementTemplate", + singularName: "Status Page Announcement Template", + pluralName: "Status Page Announcement Templates", + icon: IconProp.Announcement, + tableDescription: "Manage announcement templates for your status page", +}) +@Entity({ + name: "StatusPageAnnouncementTemplate", +}) +export default class StatusPageAnnouncementTemplate extends BaseModel { + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.CreateStatusPageAnnouncementTemplate, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "projectId", + type: TableColumnType.Entity, + modelType: Project, + title: "Project", + description: "Relation to Project Resource in which this object belongs", + }) + @ManyToOne( + () => { + return Project; + }, + { + eager: false, + nullable: true, + onDelete: "CASCADE", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "projectId" }) + public project?: Project = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.CreateStatusPageAnnouncementTemplate, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [], + }) + @Index() + @TableColumn({ + type: TableColumnType.ObjectID, + required: true, + canReadOnRelationQuery: true, + title: "Project ID", + description: "ID of your OneUptime Project in which this object belongs", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: false, + transformer: ObjectID.getDatabaseTransformer(), + }) + public projectId?: ObjectID = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.CreateStatusPageAnnouncementTemplate, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.EditStatusPageAnnouncementTemplate, + ], + }) + @TableColumn({ + required: true, + type: TableColumnType.ShortText, + title: "Template Name", + description: "Name of the announcement template", + }) + @Column({ + nullable: false, + type: ColumnType.ShortText, + length: ColumnLength.ShortText, + }) + public templateName?: string = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.CreateStatusPageAnnouncementTemplate, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.EditStatusPageAnnouncementTemplate, + ], + }) + @TableColumn({ + required: false, + type: TableColumnType.LongText, + title: "Template Description", + description: "Description of the announcement template", + }) + @Column({ + nullable: true, + type: ColumnType.LongText, + length: ColumnLength.LongText, + }) + public templateDescription?: string = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.CreateStatusPageAnnouncementTemplate, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.EditStatusPageAnnouncementTemplate, + ], + }) + @TableColumn({ + required: true, + type: TableColumnType.ShortText, + title: "Announcement Title", + description: "Title of the announcement", + }) + @Column({ + nullable: false, + type: ColumnType.ShortText, + length: ColumnLength.ShortText, + }) + public title?: string = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.CreateStatusPageAnnouncementTemplate, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.EditStatusPageAnnouncementTemplate, + ], + }) + @TableColumn({ + required: true, + type: TableColumnType.Markdown, + title: "Announcement Description", + description: "Text of the announcement. This is in Markdown.", + }) + @Column({ + nullable: false, + type: ColumnType.Markdown, + }) + public description?: string = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.CreateStatusPageAnnouncementTemplate, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.EditStatusPageAnnouncementTemplate, + ], + }) + @TableColumn({ + required: false, + type: TableColumnType.EntityArray, + modelType: StatusPage, + title: "Status Pages", + description: "Status Pages to show this announcement on.", + }) + @ManyToMany( + () => { + return StatusPage; + }, + { eager: false }, + ) + @JoinTable({ + name: "AnnouncementTemplateStatusPage", + inverseJoinColumn: { + name: "statusPageId", + referencedColumnName: "_id", + }, + joinColumn: { + name: "announcementTemplateId", + referencedColumnName: "_id", + }, + }) + public statusPages?: Array = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.CreateStatusPageAnnouncementTemplate, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [], + }) + @TableColumn({ + isDefaultValueColumn: true, + type: TableColumnType.Boolean, + title: "Should subscribers be notified?", + description: + "Should subscribers be notified about announcements created from this template?", + }) + @Column({ + type: ColumnType.Boolean, + default: true, + }) + public shouldStatusPageSubscribersBeNotified?: boolean = undefined; + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "createdByUserId", + type: TableColumnType.Entity, + modelType: User, + title: "Created by User", + description: + "Relation to User who created this object (if this object was created by a User)", + }) + @ManyToOne( + () => { + return User; + }, + { + eager: false, + nullable: true, + onDelete: "SET NULL", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "createdByUserId" }) + public createdByUser?: User = undefined; + + @ColumnAccessControl({ + create: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.CreateStatusPageAnnouncementTemplate, + ], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [], + }) + @TableColumn({ + type: TableColumnType.ObjectID, + title: "Created by User ID", + description: + "User ID who created this object (if this object was created by a User)", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: true, + transformer: ObjectID.getDatabaseTransformer(), + }) + public createdByUserId?: ObjectID = undefined; + + @ColumnAccessControl({ + create: [], + read: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.ReadStatusPageAnnouncementTemplate, + ], + update: [], + }) + @TableColumn({ + manyToOneRelationColumn: "deletedByUserId", + type: TableColumnType.Entity, + title: "Deleted by User", + description: + "Relation to User who deleted this object (if this object was deleted by a User)", + }) + @ManyToOne( + () => { + return User; + }, + { + cascade: false, + eager: false, + nullable: true, + onDelete: "SET NULL", + orphanedRowAction: "nullify", + }, + ) + @JoinColumn({ name: "deletedByUserId" }) + public deletedByUser?: User = undefined; + + @ColumnAccessControl({ + create: [], + read: [], + update: [], + }) + @TableColumn({ + type: TableColumnType.ObjectID, + title: "Deleted by User ID", + description: + "User ID who deleted this object (if this object was deleted by a User)", + }) + @Column({ + type: ColumnType.ObjectID, + nullable: true, + transformer: ObjectID.getDatabaseTransformer(), + }) + public deletedByUserId?: ObjectID = undefined; +} diff --git a/Common/Server/Services/Index.ts b/Common/Server/Services/Index.ts index 60038abfa3..ea32d52197 100644 --- a/Common/Server/Services/Index.ts +++ b/Common/Server/Services/Index.ts @@ -94,6 +94,7 @@ import SmsLogService from "./SmsLogService"; import SmsService from "./SmsService"; import SpanService from "./SpanService"; import StatusPageAnnouncementService from "./StatusPageAnnouncementService"; +import StatusPageAnnouncementTemplateService from "./StatusPageAnnouncementTemplateService"; import StatusPageCustomFieldService from "./StatusPageCustomFieldService"; import StatusPageDomainService from "./StatusPageDomainService"; import StatusPageFooterLinkService from "./StatusPageFooterLinkService"; @@ -249,6 +250,7 @@ const services: Array = [ SmsService, StatusPageAnnouncementService, + StatusPageAnnouncementTemplateService, StatusPageCustomFieldService, StatusPageDomainService, StatusPageFooterLinkService, diff --git a/Common/Server/Services/StatusPageAnnouncementTemplateService.ts b/Common/Server/Services/StatusPageAnnouncementTemplateService.ts new file mode 100644 index 0000000000..6f6430a711 --- /dev/null +++ b/Common/Server/Services/StatusPageAnnouncementTemplateService.ts @@ -0,0 +1,10 @@ +import DatabaseService from "./DatabaseService"; +import Model from "../../Models/DatabaseModels/StatusPageAnnouncementTemplate"; + +export class Service extends DatabaseService { + public constructor() { + super(Model); + } +} + +export default new Service(); diff --git a/Common/Types/Permission.ts b/Common/Types/Permission.ts index 056e221883..06d7e19cd8 100644 --- a/Common/Types/Permission.ts +++ b/Common/Types/Permission.ts @@ -468,6 +468,12 @@ enum Permission { ReadStatusPageAnnouncement = "ReadStatusPageAnnouncement", DeleteStatusPageAnnouncement = "DeleteStatusPageAnnouncement", + // Status Page Announcement Template Permissions (Owner + Admin Permission by default) + CreateStatusPageAnnouncementTemplate = "CreateStatusPageAnnouncementTemplate", + EditStatusPageAnnouncementTemplate = "EditStatusPageAnnouncementTemplate", + ReadStatusPageAnnouncementTemplate = "ReadStatusPageAnnouncementTemplate", + DeleteStatusPageAnnouncementTemplate = "DeleteStatusPageAnnouncementTemplate", + // Resource Permissions (Team Permission) CreateIncidentInternalNote = "CreateIncidentInternalNote", EditIncidentInternalNote = "EditIncidentInternalNote", @@ -1395,34 +1401,100 @@ export class PermissionHelper { }, { - permission: Permission.CreateStatusPageAnnouncement, - title: "Create Monitor Status", + permission: Permission.CreateStatusPageAnnouncementTemplate, + title: "Create Status Page Announcement Template", description: - "This permission can create monitor statuses this project.", + "This permission can create Status Page Announcement Templates in this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + { + permission: Permission.DeleteStatusPageAnnouncementTemplate, + title: "Delete Status Page Announcement Template", + description: + "This permission can delete Status Page Announcement Templates of this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + { + permission: Permission.EditStatusPageAnnouncementTemplate, + title: "Edit Status Page Announcement Template", + description: + "This permission can edit Status Page Announcement Templates of this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + { + permission: Permission.ReadStatusPageAnnouncementTemplate, + title: "Read Status Page Announcement Template", + description: + "This permission can read Status Page Announcement Templates of this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + + { + permission: Permission.CreateStatusPageAnnouncement, + title: "Create Status Page Announcement", + description: + "This permission can create Status Page Announcements in this project.", isAssignableToTenant: true, isAccessControlPermission: false, }, { permission: Permission.DeleteStatusPageAnnouncement, - title: "Delete Monitor Status", + title: "Delete Status Page Announcement", description: - "This permission can delete monitor statuses of this project.", + "This permission can delete Status Page Announcements of this project.", isAssignableToTenant: true, isAccessControlPermission: false, }, { permission: Permission.EditStatusPageAnnouncement, - title: "Edit Monitor Status", + title: "Edit Status Page Announcement", description: - "This permission can edit monitor statuses of this project.", + "This permission can edit Status Page Announcements of this project.", isAssignableToTenant: true, isAccessControlPermission: false, }, { permission: Permission.ReadStatusPageAnnouncement, - title: "Read Monitor Status", + title: "Read Status Page Announcement", description: - "This permission can read monitor statuses of this project.", + "This permission can read Status Page Announcements of this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + + { + permission: Permission.CreateStatusPageAnnouncementTemplate, + title: "Create Status Page Announcement Template", + description: + "This permission can create Status Page Announcement Templates in this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + { + permission: Permission.DeleteStatusPageAnnouncementTemplate, + title: "Delete Status Page Announcement Template", + description: + "This permission can delete Status Page Announcement Templates of this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + { + permission: Permission.EditStatusPageAnnouncementTemplate, + title: "Edit Status Page Announcement Template", + description: + "This permission can edit Status Page Announcement Templates of this project.", + isAssignableToTenant: true, + isAccessControlPermission: false, + }, + { + permission: Permission.ReadStatusPageAnnouncementTemplate, + title: "Read Status Page Announcement Template", + description: + "This permission can read Status Page Announcement Templates of this project.", isAssignableToTenant: true, isAccessControlPermission: false, }, diff --git a/Common/Utils/Schema/ModelSchema.ts b/Common/Utils/Schema/ModelSchema.ts index f7a1f4dc67..f5ab53cb10 100644 --- a/Common/Utils/Schema/ModelSchema.ts +++ b/Common/Utils/Schema/ModelSchema.ts @@ -272,7 +272,6 @@ export class ModelSchema extends BaseSchema { const entityArrayType: (new () => DatabaseBaseModel) | undefined = column.modelType; if (!entityArrayType) { - continue; } zodType = z @@ -306,7 +305,6 @@ export class ModelSchema extends BaseSchema { column.modelType; if (!entityType) { - continue; } @@ -358,7 +356,6 @@ export class ModelSchema extends BaseSchema { const schema: ModelSchemaType = z.object(shape); - return schema; } @@ -1013,7 +1010,6 @@ export class ModelSchema extends BaseSchema { } if (column.hideColumnInDocumentation) { - continue; } @@ -1088,7 +1084,6 @@ export class ModelSchema extends BaseSchema { additionalProperties: false, }); - return schema; } @@ -1265,7 +1260,6 @@ export class ModelSchema extends BaseSchema { const entityArrayType: (new () => DatabaseBaseModel) | undefined = column.modelType; if (!entityArrayType) { - return z.any().openapi({ type: "null", example: null }); } @@ -1309,7 +1303,6 @@ export class ModelSchema extends BaseSchema { column.modelType; if (!entityType) { - return z.any().openapi({ type: "null", example: null }); } diff --git a/Dashboard/src/Pages/Settings/SideMenu.tsx b/Dashboard/src/Pages/Settings/SideMenu.tsx index dbf76f7607..61acb51990 100644 --- a/Dashboard/src/Pages/Settings/SideMenu.tsx +++ b/Dashboard/src/Pages/Settings/SideMenu.tsx @@ -85,6 +85,17 @@ const DashboardSideMenu: () => JSX.Element = (): ReactElement => { /> + = ( + _props: PageComponentProps, +): ReactElement => { + return ( + + + modelType={StatusPageAnnouncementTemplate} + id="status-page-announcement-templates-table" + userPreferencesKey="status-page-announcement-templates-table" + name="Settings > Status Page Announcement Templates" + isDeleteable={true} + isEditable={true} + isCreateable={true} + isViewable={true} + cardProps={{ + title: "Status Page Announcement Templates", + description: + "Here is a list of all the status page announcement templates in this project.", + }} + noItemsMessage={"No status page announcement templates found."} + query={{ + projectId: ProjectUtil.getCurrentProjectId()!, + }} + showViewIdButton={true} + formSteps={[ + { + title: "Template Info", + id: "template-info", + }, + { + title: "Announcement Details", + id: "announcement-details", + }, + { + title: "Status Pages", + id: "status-pages", + }, + { + title: "Notification Settings", + id: "notification-settings", + }, + ]} + formFields={[ + { + field: { + templateName: true, + }, + title: "Template Name", + stepId: "template-info", + description: "Name of the announcement template", + fieldType: FormFieldSchemaType.Text, + required: true, + placeholder: "Template Name", + }, + { + field: { + templateDescription: true, + }, + title: "Template Description", + stepId: "template-info", + description: "Description of the announcement template", + fieldType: FormFieldSchemaType.LongText, + required: false, + placeholder: "Template Description", + }, + { + field: { + title: true, + }, + title: "Announcement Title", + stepId: "announcement-details", + description: "Title of announcement", + fieldType: FormFieldSchemaType.Text, + required: true, + placeholder: "Title", + }, + { + field: { + description: true, + }, + title: "Description", + stepId: "announcement-details", + fieldType: FormFieldSchemaType.Markdown, + required: false, + description: "Add an announcement note. This is in Markdown.", + }, + { + field: { + statusPages: true, + }, + title: "Show announcement on these status pages ", + stepId: "status-pages", + description: "Select status pages to show this announcement on", + fieldType: FormFieldSchemaType.MultiSelectDropdown, + dropdownModal: { + type: StatusPage, + labelField: "name", + valueField: "_id", + }, + required: false, + placeholder: "Select Status Pages", + overrideFieldKey: "statusPages", + }, + { + field: { + shouldStatusPageSubscribersBeNotified: true, + }, + title: "Notify Subscribers", + stepId: "notification-settings", + description: + "Should status page subscribers be notified when this announcement is created?", + fieldType: FormFieldSchemaType.Toggle, + required: false, + }, + ]} + showRefreshButton={true} + filters={[ + { + field: { + templateName: true, + }, + title: "Template Name", + type: FieldType.Text, + }, + { + field: { + title: true, + }, + title: "Announcement Title", + type: FieldType.Text, + }, + { + field: { + createdAt: true, + }, + title: "Created", + type: FieldType.Date, + }, + ]} + columns={[ + { + field: { + templateName: true, + }, + title: "Template Name", + type: FieldType.Text, + }, + { + field: { + title: true, + }, + title: "Announcement Title", + type: FieldType.Text, + }, + { + field: { + statusPages: true, + }, + title: "Status Pages", + type: FieldType.Element, + getElement: ( + item: StatusPageAnnouncementTemplate, + ): ReactElement => { + return ( + + ); + }, + }, + { + field: { + createdAt: true, + }, + title: "Created", + type: FieldType.DateTime, + }, + ]} + /> + + ); +}; + +export default StatusPageAnnouncementTemplates; diff --git a/Dashboard/src/Routes/SettingsRoutes.tsx b/Dashboard/src/Routes/SettingsRoutes.tsx index 036e127f62..9d462a8116 100644 --- a/Dashboard/src/Routes/SettingsRoutes.tsx +++ b/Dashboard/src/Routes/SettingsRoutes.tsx @@ -154,6 +154,13 @@ const IncidentTemplatesView: LazyExoticComponent< > = lazy(() => { return import("../Pages/Settings/IncidentTemplatesView"); }); + +const StatusPageAnnouncementTemplates: LazyExoticComponent< + FunctionComponent +> = lazy(() => { + return import("../Pages/Settings/StatusPageAnnouncementTemplates"); +}); + const IncidentNoteTemplates: LazyExoticComponent< FunctionComponent > = lazy(() => { @@ -326,6 +333,24 @@ const SettingsRoutes: FunctionComponent = ( } /> + + + + } + /> + = { [PageMap.SETTINGS_INCIDENT_NOTE_TEMPLATES]: "incident-note-templates", [PageMap.SETTINGS_INCIDENT_NOTE_TEMPLATES_VIEW]: `incident-note-templates/${RouteParams.ModelID}`, + [PageMap.SETTINGS_STATUS_PAGE_ANNOUNCEMENT_TEMPLATES]: + "status-page-announcement-templates", + [PageMap.SETTINGS_STATUS_PAGE_ANNOUNCEMENT_TEMPLATES_VIEW]: `status-page-announcement-templates/${RouteParams.ModelID}`, + [PageMap.SETTINGS_ALERT_CUSTOM_FIELDS]: "alert-custom-fields", [PageMap.SETTINGS_ALERTS_STATE]: "alerts-state", [PageMap.SETTINGS_ALERTS_SEVERITY]: "alerts-severity",