feat: add Status Page Announcement Template functionality with permissions and UI integration

This commit is contained in:
Simon Larsen
2025-06-13 12:09:13 +01:00
parent 3234f730fe
commit d74be2e23a
11 changed files with 799 additions and 16 deletions

View File

@@ -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,

View File

@@ -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<StatusPage> = 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;
}

View File

@@ -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<BaseService> = [
SmsService,
StatusPageAnnouncementService,
StatusPageAnnouncementTemplateService,
StatusPageCustomFieldService,
StatusPageDomainService,
StatusPageFooterLinkService,

View File

@@ -0,0 +1,10 @@
import DatabaseService from "./DatabaseService";
import Model from "../../Models/DatabaseModels/StatusPageAnnouncementTemplate";
export class Service extends DatabaseService<Model> {
public constructor() {
super(Model);
}
}
export default new Service();

View File

@@ -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,
},

View File

@@ -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 });
}

View File

@@ -85,6 +85,17 @@ const DashboardSideMenu: () => JSX.Element = (): ReactElement => {
/>
</SideMenuSection>
<SideMenuSection title="Status Pages">
<SideMenuItem
link={{
title: "Announcement Templates",
to: RouteUtil.populateRouteParams(
RouteMap[
PageMap.SETTINGS_STATUS_PAGE_ANNOUNCEMENT_TEMPLATES
] as Route,
),
}}
icon={IconProp.Template}
/>
<SideMenuItem
link={{
title: "Custom Fields",

View File

@@ -0,0 +1,192 @@
import ProjectUtil from "Common/UI/Utils/Project";
import PageComponentProps from "../PageComponentProps";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import ModelTable from "Common/UI/Components/ModelTable/ModelTable";
import FieldType from "Common/UI/Components/Types/FieldType";
import StatusPageAnnouncementTemplate from "Common/Models/DatabaseModels/StatusPageAnnouncementTemplate";
import StatusPage from "Common/Models/DatabaseModels/StatusPage";
import React, { Fragment, FunctionComponent, ReactElement } from "react";
import StatusPagesElement from "../../Components/StatusPage/StatusPagesElement";
const StatusPageAnnouncementTemplates: FunctionComponent<PageComponentProps> = (
_props: PageComponentProps,
): ReactElement => {
return (
<Fragment>
<ModelTable<StatusPageAnnouncementTemplate>
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 (
<StatusPagesElement statusPages={item.statusPages || []} />
);
},
},
{
field: {
createdAt: true,
},
title: "Created",
type: FieldType.DateTime,
},
]}
/>
</Fragment>
);
};
export default StatusPageAnnouncementTemplates;

View File

@@ -154,6 +154,13 @@ const IncidentTemplatesView: LazyExoticComponent<
> = lazy(() => {
return import("../Pages/Settings/IncidentTemplatesView");
});
const StatusPageAnnouncementTemplates: LazyExoticComponent<
FunctionComponent<ComponentProps>
> = lazy(() => {
return import("../Pages/Settings/StatusPageAnnouncementTemplates");
});
const IncidentNoteTemplates: LazyExoticComponent<
FunctionComponent<ComponentProps>
> = lazy(() => {
@@ -326,6 +333,24 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
}
/>
<PageRoute
path={RouteUtil.getLastPathForKey(
PageMap.SETTINGS_STATUS_PAGE_ANNOUNCEMENT_TEMPLATES,
)}
element={
<Suspense fallback={Loader}>
<StatusPageAnnouncementTemplates
{...props}
pageRoute={
RouteMap[
PageMap.SETTINGS_STATUS_PAGE_ANNOUNCEMENT_TEMPLATES
] as Route
}
/>
</Suspense>
}
/>
<PageRoute
path={RouteUtil.getLastPathForKey(
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_TEMPLATES,

View File

@@ -304,6 +304,10 @@ enum PageMap {
SETTINGS_SCHEDULED_MAINTENANCE_TEMPLATES = "SETTINGS_SCHEDULED_MAINTENANCE_TEMPLATES",
SETTINGS_SCHEDULED_MAINTENANCE_TEMPLATES_VIEW = "SETTINGS_SCHEDULED_MAINTENANCE_TEMPLATES_VIEW",
// status page announcement templates
SETTINGS_STATUS_PAGE_ANNOUNCEMENT_TEMPLATES = "SETTINGS_STATUS_PAGE_ANNOUNCEMENT_TEMPLATES",
SETTINGS_STATUS_PAGE_ANNOUNCEMENT_TEMPLATES_VIEW = "SETTINGS_STATUS_PAGE_ANNOUNCEMENT_TEMPLATES_VIEW",
// incident note templates
SETTINGS_INCIDENT_NOTE_TEMPLATES = "SETTINGS_INCIDENT_NOTE_TEMPLATES",
SETTINGS_INCIDENT_NOTE_TEMPLATES_VIEW = "SETTINGS_INCIDENT_NOTE_TEMPLATES_VIEW",

View File

@@ -221,6 +221,10 @@ export const SettingsRoutePath: Dictionary<string> = {
[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",