add email logs in project settings

This commit is contained in:
Simon Larsen
2023-07-21 17:10:46 +01:00
parent 2156c8f5d5
commit 7eb0b79d7b
11 changed files with 559 additions and 112 deletions

View File

@@ -0,0 +1,6 @@
enum MailStatus {
Success = 'Success',
Error = 'Error',
}
export default MailStatus;

View File

@@ -79,7 +79,7 @@ enum Permission {
CanReadMonitorProbe = 'CanReadMonitorProbe',
CanReadSmsLog = 'CanReadSmsLog',
CanReadEmailLog = 'CanReadEmailLog',
CanReadCallLog = 'CanReadCallLog',
CanCreateIncidentOwnerTeam = 'CanCreateIncidentOwnerTeam',

View File

@@ -5,6 +5,8 @@ import DatabaseService from './DatabaseService';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
this.hardDeleteItemsOlderThanInDays('createdAt', 30);
}
}
export default new Service();

View File

@@ -96,6 +96,7 @@ import SettingsBilling from './Pages/Settings/Billing';
import SettingsSSO from './Pages/Settings/SSO';
import SettingsSmsLog from './Pages/Settings/SmsLog';
import SettingsCallLog from './Pages/Settings/CallLog';
import SettingsEmailLog from './Pages/Settings/EmailLog';
import SettingsCallSms from './Pages/Settings/CallSms';
import SettingsInvoices from './Pages/Settings/Invoices';
import MonitorCustomFields from './Pages/Settings/MonitorCustomFields';
@@ -374,7 +375,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.HOME_NOT_OPERATIONAL_MONITORS
PageMap.HOME_NOT_OPERATIONAL_MONITORS
] as Route
}
/>
@@ -394,8 +395,8 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap
.HOME_ONGOING_SCHEDULED_MAINTENANCE_EVENTS
PageMap
.HOME_ONGOING_SCHEDULED_MAINTENANCE_EVENTS
] as Route
}
/>
@@ -423,7 +424,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.MONITORS_INOPERATIONAL
PageMap.MONITORS_INOPERATIONAL
] as Route
}
/>
@@ -506,7 +507,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.MONITOR_VIEW_STATUS_TIMELINE
PageMap.MONITOR_VIEW_STATUS_TIMELINE
] as Route
}
/>
@@ -538,7 +539,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.MONITOR_VIEW_INCIDENTS
PageMap.MONITOR_VIEW_INCIDENTS
] as Route
}
/>
@@ -556,7 +557,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.MONITOR_VIEW_CUSTOM_FIELDS
PageMap.MONITOR_VIEW_CUSTOM_FIELDS
] as Route
}
/>
@@ -736,7 +737,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_DELETE
PageMap.STATUS_PAGE_VIEW_DELETE
] as Route
}
/>
@@ -754,7 +755,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_BRANDING
PageMap.STATUS_PAGE_VIEW_BRANDING
] as Route
}
/>
@@ -772,7 +773,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_CUSTOM_HTML_CSS
PageMap.STATUS_PAGE_VIEW_CUSTOM_HTML_CSS
] as Route
}
/>
@@ -790,7 +791,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_ADVANCED_OPTIONS
PageMap.STATUS_PAGE_VIEW_ADVANCED_OPTIONS
] as Route
}
/>
@@ -808,7 +809,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_CUSTOM_FIELDS
PageMap.STATUS_PAGE_VIEW_CUSTOM_FIELDS
] as Route
}
/>
@@ -825,7 +826,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_OWNERS
PageMap.STATUS_PAGE_VIEW_OWNERS
] as Route
}
/>
@@ -857,7 +858,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_EMAIL_SUBSCRIBERS
PageMap.STATUS_PAGE_VIEW_EMAIL_SUBSCRIBERS
] as Route
}
/>
@@ -875,8 +876,8 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap
.STATUS_PAGE_VIEW_AUTHENTICATION_SETTINGS
PageMap
.STATUS_PAGE_VIEW_AUTHENTICATION_SETTINGS
] as Route
}
/>
@@ -894,7 +895,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_CUSTOM_SMTP
PageMap.STATUS_PAGE_VIEW_CUSTOM_SMTP
] as Route
}
/>
@@ -912,7 +913,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_SETTINGS
PageMap.STATUS_PAGE_VIEW_SETTINGS
] as Route
}
/>
@@ -930,7 +931,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_PRIVATE_USERS
PageMap.STATUS_PAGE_VIEW_PRIVATE_USERS
] as Route
}
/>
@@ -948,7 +949,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_SMS_SUBSCRIBERS
PageMap.STATUS_PAGE_VIEW_SMS_SUBSCRIBERS
] as Route
}
/>
@@ -966,7 +967,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_HEADER_STYLE
PageMap.STATUS_PAGE_VIEW_HEADER_STYLE
] as Route
}
/>
@@ -984,7 +985,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_FOOTER_STYLE
PageMap.STATUS_PAGE_VIEW_FOOTER_STYLE
] as Route
}
/>
@@ -1002,7 +1003,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_NAVBAR_STYLE
PageMap.STATUS_PAGE_VIEW_NAVBAR_STYLE
] as Route
}
/>
@@ -1020,7 +1021,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_WEBHOOK_SUBSCRIBERS
PageMap.STATUS_PAGE_VIEW_WEBHOOK_SUBSCRIBERS
] as Route
}
/>
@@ -1038,7 +1039,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_EMBEDDED
PageMap.STATUS_PAGE_VIEW_EMBEDDED
] as Route
}
/>
@@ -1056,7 +1057,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_RESOURCES
PageMap.STATUS_PAGE_VIEW_RESOURCES
] as Route
}
/>
@@ -1074,7 +1075,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_DOMAINS
PageMap.STATUS_PAGE_VIEW_DOMAINS
] as Route
}
/>
@@ -1091,7 +1092,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_GROUPS
PageMap.STATUS_PAGE_VIEW_GROUPS
] as Route
}
/>
@@ -1109,7 +1110,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_ANNOUNCEMENTS
PageMap.STATUS_PAGE_VIEW_ANNOUNCEMENTS
] as Route
}
/>
@@ -1177,7 +1178,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.INCIDENT_VIEW_STATE_TIMELINE
PageMap.INCIDENT_VIEW_STATE_TIMELINE
] as Route
}
/>
@@ -1194,7 +1195,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.INCIDENT_INTERNAL_NOTE
PageMap.INCIDENT_INTERNAL_NOTE
] as Route
}
/>
@@ -1212,7 +1213,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.INCIDENT_VIEW_CUSTOM_FIELDS
PageMap.INCIDENT_VIEW_CUSTOM_FIELDS
] as Route
}
/>
@@ -1230,8 +1231,8 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap
.ON_CALL_DUTY_POLICY_VIEW_CUSTOM_FIELDS
PageMap
.ON_CALL_DUTY_POLICY_VIEW_CUSTOM_FIELDS
] as Route
}
/>
@@ -1279,7 +1280,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SCHEDULED_MAINTENANCE_EVENTS
PageMap.SCHEDULED_MAINTENANCE_EVENTS
] as Route
}
/>
@@ -1297,7 +1298,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.ONGOING_SCHEDULED_MAINTENANCE_EVENTS
PageMap.ONGOING_SCHEDULED_MAINTENANCE_EVENTS
] as Route
}
/>
@@ -1315,7 +1316,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SCHEDULED_MAINTENANCE_VIEW
PageMap.SCHEDULED_MAINTENANCE_VIEW
] as Route
}
/>
@@ -1333,8 +1334,8 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap
.SCHEDULED_MAINTENANCE_VIEW_CUSTOM_FIELDS
PageMap
.SCHEDULED_MAINTENANCE_VIEW_CUSTOM_FIELDS
] as Route
}
/>
@@ -1352,7 +1353,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SCHEDULED_MAINTENANCE_VIEW_DELETE
PageMap.SCHEDULED_MAINTENANCE_VIEW_DELETE
] as Route
}
/>
@@ -1370,7 +1371,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SCHEDULED_MAINTENANCE_VIEW_OWNERS
PageMap.SCHEDULED_MAINTENANCE_VIEW_OWNERS
] as Route
}
/>
@@ -1388,8 +1389,8 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap
.SCHEDULED_MAINTENANCE_VIEW_STATE_TIMELINE
PageMap
.SCHEDULED_MAINTENANCE_VIEW_STATE_TIMELINE
] as Route
}
/>
@@ -1407,7 +1408,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SCHEDULED_MAINTENANCE_INTERNAL_NOTE
PageMap.SCHEDULED_MAINTENANCE_INTERNAL_NOTE
] as Route
}
/>
@@ -1425,7 +1426,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SCHEDULED_MAINTENANCE_PUBLIC_NOTE
PageMap.SCHEDULED_MAINTENANCE_PUBLIC_NOTE
] as Route
}
/>
@@ -1482,6 +1483,21 @@ const App: FunctionComponent = () => {
}
/>
<PageRoute
path={
RouteMap[PageMap.SETTINGS_EMAIL_LOGS]?.toString() || ''
}
element={
<SettingsEmailLog
{...commonPageProps}
pageRoute={
RouteMap[PageMap.SETTINGS_EMAIL_LOGS] as Route
}
/>
}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS_CALL_SMS]?.toString() || ''}
element={
@@ -1525,7 +1541,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SETTINGS_MONITORS_STATUS
PageMap.SETTINGS_MONITORS_STATUS
] as Route
}
/>
@@ -1543,7 +1559,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SETTINGS_INCIDENTS_STATE
PageMap.SETTINGS_INCIDENTS_STATE
] as Route
}
/>
@@ -1561,7 +1577,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE
] as Route
}
/>
@@ -1589,7 +1605,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SETTINGS_INCIDENTS_SEVERITY
PageMap.SETTINGS_INCIDENTS_SEVERITY
] as Route
}
/>
@@ -1659,7 +1675,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SETTINGS_MONITOR_CUSTOM_FIELDS
PageMap.SETTINGS_MONITOR_CUSTOM_FIELDS
] as Route
}
/>
@@ -1677,7 +1693,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SETTINGS_STATUS_PAGE_CUSTOM_FIELDS
PageMap.SETTINGS_STATUS_PAGE_CUSTOM_FIELDS
] as Route
}
/>
@@ -1695,8 +1711,8 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap
.SETTINGS_SCHEDULED_MAINTENANCE_CUSTOM_FIELDS
PageMap
.SETTINGS_SCHEDULED_MAINTENANCE_CUSTOM_FIELDS
] as Route
}
/>
@@ -1714,7 +1730,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SETTINGS_INCIDENT_CUSTOM_FIELDS
PageMap.SETTINGS_INCIDENT_CUSTOM_FIELDS
] as Route
}
/>
@@ -1732,8 +1748,8 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap
.SETTINGS_ON_CALL_DUTY_POLICY_CUSTOM_FIELDS
PageMap
.SETTINGS_ON_CALL_DUTY_POLICY_CUSTOM_FIELDS
] as Route
}
/>
@@ -1763,7 +1779,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.SETTINGS_BILLING_INVOICES
PageMap.SETTINGS_BILLING_INVOICES
] as Route
}
/>
@@ -1843,7 +1859,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.ON_CALL_DUTY_EXECUTION_LOGS
PageMap.ON_CALL_DUTY_EXECUTION_LOGS
] as Route
}
/>
@@ -1861,7 +1877,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.ON_CALL_DUTY_EXECUTION_LOGS_TIMELINE
PageMap.ON_CALL_DUTY_EXECUTION_LOGS_TIMELINE
] as Route
}
/>
@@ -1894,7 +1910,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.ON_CALL_DUTY_POLICY_VIEW
PageMap.ON_CALL_DUTY_POLICY_VIEW
] as Route
}
/>
@@ -1912,7 +1928,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.ON_CALL_DUTY_POLICY_VIEW_DELETE
PageMap.ON_CALL_DUTY_POLICY_VIEW_DELETE
] as Route
}
/>
@@ -1930,7 +1946,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.ON_CALL_DUTY_POLICY_VIEW_ESCALATION
PageMap.ON_CALL_DUTY_POLICY_VIEW_ESCALATION
] as Route
}
/>
@@ -1948,8 +1964,8 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap
.ON_CALL_DUTY_POLICY_VIEW_EXECUTION_LOGS
PageMap
.ON_CALL_DUTY_POLICY_VIEW_EXECUTION_LOGS
] as Route
}
/>
@@ -1967,8 +1983,8 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap
.ON_CALL_DUTY_POLICY_VIEW_EXECUTION_LOG_VIEW
PageMap
.ON_CALL_DUTY_POLICY_VIEW_EXECUTION_LOG_VIEW
] as Route
}
/>
@@ -2080,7 +2096,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.USER_SETTINGS_ON_CALL_LOGS
PageMap.USER_SETTINGS_ON_CALL_LOGS
] as Route
}
/>
@@ -2098,7 +2114,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.USER_SETTINGS_ON_CALL_LOGS_TIMELINE
PageMap.USER_SETTINGS_ON_CALL_LOGS_TIMELINE
] as Route
}
/>
@@ -2116,7 +2132,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.USER_SETTINGS_NOTIFICATION_SETTINGS
PageMap.USER_SETTINGS_NOTIFICATION_SETTINGS
] as Route
}
/>
@@ -2134,7 +2150,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.USER_SETTINGS_NOTIFICATION_METHODS
PageMap.USER_SETTINGS_NOTIFICATION_METHODS
] as Route
}
/>
@@ -2152,7 +2168,7 @@ const App: FunctionComponent = () => {
{...commonPageProps}
pageRoute={
RouteMap[
PageMap.USER_SETTINGS_ON_CALL_RULES
PageMap.USER_SETTINGS_ON_CALL_RULES
] as Route
}
/>

View File

@@ -0,0 +1,204 @@
import Route from 'Common/Types/API/Route';
import React, { FunctionComponent, ReactElement, useState } from 'react';
import PageMap from '../../Utils/PageMap';
import RouteMap, { RouteUtil } from '../../Utils/RouteMap';
import PageComponentProps from '../PageComponentProps';
import FieldType from 'CommonUI/src/Components/Types/FieldType';
import IconProp from 'Common/Types/Icon/IconProp';
import EmailLog from 'Model/Models/EmailLog';
import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable';
import DashboardNavigation from '../../Utils/Navigation';
import { JSONObject } from 'Common/Types/JSON';
import { ButtonStyleType } from 'CommonUI/src/Components/Button/Button';
import DashboardSideMenu from './SideMenu';
import Page from 'CommonUI/src/Components/Page/Page';
import Pill from 'CommonUI/src/Components/Pill/Pill';
import EmailStatus from 'Common/Types/Mail/MailStatus';
import { Green, Red } from 'Common/Types/BrandColors';
import Columns from 'CommonUI/src/Components/ModelTable/Columns';
import ConfirmModal from 'CommonUI/src/Components/Modal/ConfirmModal';
const EmailLogs: FunctionComponent<PageComponentProps> = (
_props: PageComponentProps
): ReactElement => {
const [showViewEmailTextModal, setShowViewEmailTextModal] =
useState<boolean>(false);
const [EmailText, setEmailText] = useState<string>('');
const [EmailModelTitle, setEmailModalTitle] = useState<string>('');
const modelTableColumns: Columns<EmailLog> = [
{
field: {
_id: true,
},
title: 'Log ID',
type: FieldType.Text,
isFilterable: true,
},
{
field: {
toEmail: true,
},
isFilterable: true,
title: 'To Email',
type: FieldType.Email,
},
{
field: {
fromEmail: true,
},
isFilterable: true,
title: 'To Email',
type: FieldType.Email,
},
{
field: {
createdAt: true,
},
title: 'Sent at',
type: FieldType.DateTime,
isFilterable: true,
},
{
field: {
status: true,
},
title: 'Status',
type: FieldType.Text,
getElement: (item: JSONObject): ReactElement => {
if (item['status']) {
return (
<Pill
isMinimal={false}
color={
item['status'] === EmailStatus.Success
? Green
: Red
}
text={item['status'] as string}
/>
);
}
return <></>;
},
isFilterable: true,
},
];
return (
<Page
title={'Project Settings'}
breadcrumbLinks={[
{
title: 'Project',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.HOME] as Route
),
},
{
title: 'Settings',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS] as Route
),
},
{
title: 'Email Logs',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_EMAIL_LOGS] as Route
),
},
]}
sideMenu={<DashboardSideMenu />}
>
<>
<ModelTable<EmailLog>
modelType={EmailLog}
id="Email-logs-table"
isDeleteable={false}
isEditable={false}
isCreateable={false}
name="Email Logs"
query={{
projectId:
DashboardNavigation.getProjectId()?.toString(),
}}
selectMoreFields={{
subject: true,
statusMessage: true,
}}
actionButtons={[
{
title: 'View Email Text',
buttonStyleType: ButtonStyleType.NORMAL,
icon: IconProp.List,
onClick: async (
item: JSONObject,
onCompleteAction: Function
) => {
setEmailText(
JSON.stringify(item['subject']) as string
);
setEmailModalTitle('Subject of Email Message');
setShowViewEmailTextModal(true);
onCompleteAction();
},
},
{
title: 'View Status Message',
buttonStyleType: ButtonStyleType.NORMAL,
icon: IconProp.Error,
onClick: async (
item: JSONObject,
onCompleteAction: Function
) => {
setEmailText(item['statusMessage'] as string);
setEmailModalTitle('Status Message');
setShowViewEmailTextModal(true);
onCompleteAction();
},
},
]}
isViewable={false}
cardProps={{
icon: IconProp.Logs,
title: 'Email Logs',
description:
'Logs of all the emails sent by this project in the last 30 days.',
}}
noItemsMessage={
'Looks like no email is sent by this project in the last 30 days.'
}
showRefreshButton={true}
showFilterButton={true}
columns={modelTableColumns}
/>
{showViewEmailTextModal && (
<ConfirmModal
title={EmailModelTitle}
description={
<div className="text-gray-500 mt-5 text-sm h-96 overflow-y-auto overflow-x-hidden p-5 border-gray-50 border border-2 bg-gray-100 rounded">
{EmailText}
</div>
}
onSubmit={() => {
setShowViewEmailTextModal(false);
}}
submitButtonText="Close"
submitButtonType={ButtonStyleType.NORMAL}
/>
)}
</>
</Page>
);
};
export default EmailLogs;

View File

@@ -47,7 +47,7 @@ const DashboardSideMenu: FunctionComponent = (): ReactElement => {
title: 'Custom Fields',
to: RouteUtil.populateRouteParams(
RouteMap[
PageMap.SETTINGS_MONITOR_CUSTOM_FIELDS
PageMap.SETTINGS_MONITOR_CUSTOM_FIELDS
] as Route
),
}}
@@ -60,7 +60,7 @@ const DashboardSideMenu: FunctionComponent = (): ReactElement => {
title: 'Custom Fields',
to: RouteUtil.populateRouteParams(
RouteMap[
PageMap.SETTINGS_STATUS_PAGE_CUSTOM_FIELDS
PageMap.SETTINGS_STATUS_PAGE_CUSTOM_FIELDS
] as Route
),
}}
@@ -73,8 +73,8 @@ const DashboardSideMenu: FunctionComponent = (): ReactElement => {
title: 'Custom Fields',
to: RouteUtil.populateRouteParams(
RouteMap[
PageMap
.SETTINGS_ON_CALL_DUTY_POLICY_CUSTOM_FIELDS
PageMap
.SETTINGS_ON_CALL_DUTY_POLICY_CUSTOM_FIELDS
] as Route
),
}}
@@ -96,7 +96,7 @@ const DashboardSideMenu: FunctionComponent = (): ReactElement => {
title: 'Incident Severity',
to: RouteUtil.populateRouteParams(
RouteMap[
PageMap.SETTINGS_INCIDENTS_SEVERITY
PageMap.SETTINGS_INCIDENTS_SEVERITY
] as Route
),
}}
@@ -107,7 +107,7 @@ const DashboardSideMenu: FunctionComponent = (): ReactElement => {
title: 'Custom Fields',
to: RouteUtil.populateRouteParams(
RouteMap[
PageMap.SETTINGS_INCIDENT_CUSTOM_FIELDS
PageMap.SETTINGS_INCIDENT_CUSTOM_FIELDS
] as Route
),
}}
@@ -127,7 +127,7 @@ const DashboardSideMenu: FunctionComponent = (): ReactElement => {
title: 'Event State',
to: RouteUtil.populateRouteParams(
RouteMap[
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE
] as Route
),
}}
@@ -138,8 +138,8 @@ const DashboardSideMenu: FunctionComponent = (): ReactElement => {
title: 'Custom Fields',
to: RouteUtil.populateRouteParams(
RouteMap[
PageMap
.SETTINGS_SCHEDULED_MAINTENANCE_CUSTOM_FIELDS
PageMap
.SETTINGS_SCHEDULED_MAINTENANCE_CUSTOM_FIELDS
] as Route
),
}}
@@ -194,6 +194,15 @@ const DashboardSideMenu: FunctionComponent = (): ReactElement => {
}}
icon={IconProp.Call}
/>
<SideMenuItem
link={{
title: 'Email Logs',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_EMAIL_LOGS] as Route
),
}}
icon={IconProp.Call}
/>
</SideMenuSection>
<SideMenuSection title="Advanced">
<SideMenuItem
@@ -248,7 +257,7 @@ const DashboardSideMenu: FunctionComponent = (): ReactElement => {
title: 'Invoices',
to: RouteUtil.populateRouteParams(
RouteMap[
PageMap.SETTINGS_BILLING_INVOICES
PageMap.SETTINGS_BILLING_INVOICES
] as Route
),
}}

View File

@@ -168,6 +168,7 @@ enum PageMap {
// SMS and Call
SETTINGS_CALL_SMS = 'SETTINGS_CALL_SMS',
SETTINGS_SMS_LOGS = 'SETTINGS_SMS_LOGS',
SETTINGS_EMAIL_LOGS = 'SETTINGS_EMAIL_LOGS',
SETTINGS_CALL_LOGS = 'SETTINGS_CALL_LOGS',
}

View File

@@ -356,6 +356,10 @@ const RouteMap: Dictionary<Route> = {
`/dashboard/${RouteParams.ProjectID}/settings/sms-logs`
),
[PageMap.SETTINGS_EMAIL_LOGS]: new Route(
`/dashboard/${RouteParams.ProjectID}/settings/email-logs`
),
[PageMap.SETTINGS_CALL_LOGS]: new Route(
`/dashboard/${RouteParams.ProjectID}/settings/call-logs`
),

View File

@@ -85,6 +85,11 @@ import SmsLogService, {
Service as SmsLogServiceType,
} from 'CommonServer/Services/SmsLogService';
import EmailLog from 'Model/Models/EmailLog';
import EmailLogService, {
Service as EmailLogServiceType,
} from 'CommonServer/Services/EmailLogService';
import CallLog from 'Model/Models/CallLog';
import CallLogService, {
Service as CallLogServiceType,
@@ -295,6 +300,8 @@ import IncidentCustomFieldService, {
Service as IncidentCustomFieldServiceType,
} from 'CommonServer/Services/IncidentCustomFieldService';
import OnCallDutyPolicyExecutionLogTimeline from 'Model/Models/OnCallDutyPolicyExecutionLogTimeline';
import OnCallDutyPolicyExecutionLogTimelineService, {
Service as OnCallDutyPolicyExecutionLogTimelineServiceType,
@@ -719,6 +726,11 @@ app.use(
new BaseAPI<SmsLog, SmsLogServiceType>(SmsLog, SmsLogService).getRouter()
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<EmailLog, EmailLogServiceType>(EmailLog, EmailLogService).getRouter()
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<CallLog, CallLogServiceType>(

View File

@@ -1,46 +1,235 @@
import { Column, Entity } from 'typeorm';
import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm';
import BaseModel from 'Common/Models/BaseModel';
import User from './User';
import Project from './Project';
import CrudApiEndpoint from 'Common/Types/Database/CrudApiEndpoint';
import MailStatus from 'Common/Types/Mail/MailStatus';
import Route from 'Common/Types/API/Route';
import TableColumnType from 'Common/Types/Database/TableColumnType';
import TableColumn from 'Common/Types/Database/TableColumn';
import ColumnType from 'Common/Types/Database/ColumnType';
import ObjectID from 'Common/Types/ObjectID';
import ColumnLength from 'Common/Types/Database/ColumnLength';
import TableAccessControl from 'Common/Types/Database/AccessControl/TableAccessControl';
import Permission from 'Common/Types/Permission';
import ColumnAccessControl from 'Common/Types/Database/AccessControl/ColumnAccessControl';
import TenantColumn from 'Common/Types/Database/TenantColumn';
import TableMetadata from 'Common/Types/Database/TableMetadata';
import EnableWorkflow from 'Common/Types/Model/EnableWorkflow';
import IconProp from 'Common/Types/Icon/IconProp';
import EnableDocumentation from 'Common/Types/Model/EnableDocumentation';
import Email from 'Common/Types/Email';
import EmailTemplateType from 'Common/Types/Email/EmailTemplateType';
import OperationResult from 'Common/Types/Operation/OperationResult';
import Hostname from 'Common/Types/API/Hostname';
@EnableDocumentation()
@TenantColumn('projectId')
@TableAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CanReadEmailLog,
],
delete: [],
update: [],
})
@CrudApiEndpoint(new Route('/email-log'))
@Entity({
name: 'EmailLog',
})
@EnableWorkflow({
create: true,
delete: false,
update: false,
read: true,
})
@TableMetadata({
tableName: 'EmailLog',
singularName: 'Email Log',
pluralName: 'Email Logs',
icon: IconProp.Email,
tableDescription:
'Logs of all the Email sent out to all users and subscribers for this project.',
})
export default class EmailLog extends BaseModel {
@Column()
public fromEmail?: Email = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CanReadEmailLog,
],
update: [],
})
@TableColumn({
manyToOneRelationColumn: 'projectId',
type: TableColumnType.Entity,
modelType: Project,
title: 'Project',
description:
'Relation to Project Resource in which this object belongs',
})
@ManyToOne(
(_type: string) => {
return Project;
},
{
eager: false,
nullable: true,
onDelete: 'CASCADE',
orphanedRowAction: 'nullify',
}
)
@JoinColumn({ name: 'projectId' })
public project?: Project = undefined;
@Column()
public fromName?: string = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CanReadEmailLog,
],
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;
@Column()
public project?: Project;
@Column()
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CanReadEmailLog,
],
update: [],
})
@Index()
@TableColumn({
required: true,
type: TableColumnType.Email,
title: 'To Email',
description: 'Email address where the mail was sent',
canReadOnRelationQuery: false,
})
@Column({
nullable: false,
type: ColumnType.Email,
length: ColumnLength.Email,
transformer: Email.getDatabaseTransformer(),
})
public toEmail?: Email = undefined;
@Column()
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CanReadEmailLog,
],
update: [],
})
@Index()
@TableColumn({
required: true,
type: TableColumnType.Email,
title: 'From Email',
description: 'Email address where the mail was sent from',
canReadOnRelationQuery: false,
})
@Column({
nullable: false,
type: ColumnType.Email,
length: ColumnLength.Email,
transformer: Email.getDatabaseTransformer(),
})
public fromEmail?: Email = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CanReadEmailLog,
],
update: [],
})
@TableColumn({
required: true,
type: TableColumnType.LongText,
title: 'Email Subject',
description: 'Subject of the email sent',
canReadOnRelationQuery: false,
})
@Column({
nullable: false,
type: ColumnType.LongText,
length: ColumnLength.LongText,
})
public subject?: string = undefined;
@Column()
public body?: string = undefined;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CanReadEmailLog,
],
update: [],
})
@TableColumn({
required: false,
type: TableColumnType.LongText,
title: 'Status Message',
description: 'Status Message (if any)',
canReadOnRelationQuery: false,
})
@Column({
nullable: true,
type: ColumnType.LongText,
length: ColumnLength.LongText,
})
public statusMessage?: string = undefined;
@Column()
public templateType?: EmailTemplateType;
@Column()
public status?: OperationResult;
@Column()
public errorDescription?: string = undefined;
@Column()
public smtpHost?: Hostname;
@Column()
public deletedByUser?: User;
@ColumnAccessControl({
create: [],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CanReadEmailLog,
],
update: [],
})
@TableColumn({
required: true,
type: TableColumnType.ShortText,
title: 'Status of the SMS',
description: 'Status of the SMS sent',
canReadOnRelationQuery: false,
})
@Column({
nullable: false,
type: ColumnType.ShortText,
length: ColumnLength.ShortText,
})
public status?: MailStatus = undefined;
}

View File

@@ -111,6 +111,7 @@ import DataMigration from './DataMigration';
// Short link.
import ShortLink from './ShortLink';
import EmailLog from './EmailLog';
export default [
User,
@@ -194,6 +195,7 @@ export default [
SmsLog,
CallLog,
EmailLog,
UserEmail,
UserSms,
@@ -207,4 +209,6 @@ export default [
DataMigration,
ShortLink,
];