IO-1984 Email Audit Trail
This commit is contained in:
@@ -4,6 +4,8 @@ import { useQuery } from "@apollo/client";
|
||||
import { QUERY_AUDIT_TRAIL } from "../../graphql/audit_trail.queries";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import EmailAuditTrailListComponent from "./email-audit-trail-list.component";
|
||||
import { Card, Row } from "antd";
|
||||
|
||||
export default function AuditTrailListContainer({ recordId }) {
|
||||
const { loading, error, data } = useQuery(QUERY_AUDIT_TRAIL, {
|
||||
@@ -18,10 +20,20 @@ export default function AuditTrailListContainer({ recordId }) {
|
||||
{error ? (
|
||||
<AlertComponent type="error" message={error.message} />
|
||||
) : (
|
||||
<AuditTrailListComponent
|
||||
loading={loading}
|
||||
data={data ? data.audit_trail : null}
|
||||
/>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Card>
|
||||
<AuditTrailListComponent
|
||||
loading={loading}
|
||||
data={data ? data.audit_trail : []}
|
||||
/>
|
||||
</Card>
|
||||
<Card>
|
||||
<EmailAuditTrailListComponent
|
||||
loading={loading}
|
||||
data={data ? data.audit_trail : []}
|
||||
/>
|
||||
</Card>
|
||||
</Row>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import React, { useState } from "react";
|
||||
import { Table } from "antd";
|
||||
import { alphaSort } from "../../utils/sorters";
|
||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import AuditTrailValuesComponent from "../audit-trail-values/audit-trail-values.component";
|
||||
|
||||
export default function EmailAuditTrailListComponent({ loading, data }) {
|
||||
const [state, setState] = useState({
|
||||
sortedInfo: {},
|
||||
filteredInfo: {},
|
||||
});
|
||||
const { t } = useTranslation();
|
||||
const columns = [
|
||||
{
|
||||
title: t("audit.fields.created"),
|
||||
dataIndex: " created",
|
||||
key: " created",
|
||||
width: "10%",
|
||||
render: (text, record) => (
|
||||
<DateTimeFormatter>{record.created}</DateTimeFormatter>
|
||||
),
|
||||
sorter: (a, b) => a.created - b.created,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "created" && state.sortedInfo.order,
|
||||
},
|
||||
|
||||
{
|
||||
title: t("audit.fields.useremail"),
|
||||
dataIndex: "useremail",
|
||||
key: "useremail",
|
||||
width: "10%",
|
||||
sorter: (a, b) => alphaSort(a.useremail, b.useremail),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "useremail" && state.sortedInfo.order,
|
||||
},
|
||||
];
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
xs: { span: 12 },
|
||||
sm: { span: 5 },
|
||||
},
|
||||
wrapperCol: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 12 },
|
||||
},
|
||||
};
|
||||
const handleTableChange = (pagination, filters, sorter) => {
|
||||
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
|
||||
};
|
||||
|
||||
return (
|
||||
<Table
|
||||
{...formItemLayout}
|
||||
loading={loading}
|
||||
pagination={{ position: "top", defaultPageSize: 25 }}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
dataSource={data}
|
||||
onChange={handleTableChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -77,6 +77,9 @@ export function EmailOverlayContainer({
|
||||
setSending(true);
|
||||
try {
|
||||
await axios.post("/sendemail", {
|
||||
bodyshopid: bodyshop.id,
|
||||
jobid: emailConfig.jobid,
|
||||
|
||||
...defaultEmailFrom,
|
||||
ReplyTo: {
|
||||
Email: from,
|
||||
@@ -181,10 +184,11 @@ export function EmailOverlayContainer({
|
||||
loading: sending,
|
||||
disabled:
|
||||
selectedMedia &&
|
||||
( (selectedMedia
|
||||
(selectedMedia
|
||||
.filter((s) => s.isSelected)
|
||||
.reduce((acc, val) => (acc = acc + val.size), 0) >=
|
||||
10485760 - new Blob([form.getFieldValue("html")]).size) || selectedMedia.filter((s) => s.isSelected).length > 10),
|
||||
10485760 - new Blob([form.getFieldValue("html")]).size ||
|
||||
selectedMedia.filter((s) => s.isSelected).length > 10),
|
||||
}}
|
||||
>
|
||||
<Form layout="vertical" form={form} onFinish={handleFinish}>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useQuery } from "@apollo/client";
|
||||
import { Card, Table } from "antd";
|
||||
import { Button, Card, Col, Row, Table, Tag } from "antd";
|
||||
import { SyncOutlined } from "@ant-design/icons";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { QUERY_AUDIT_TRAIL } from "../../graphql/audit_trail.queries";
|
||||
@@ -7,7 +8,7 @@ import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||
|
||||
export default function JobAuditTrail({ jobId }) {
|
||||
const { t } = useTranslation();
|
||||
const { loading, data } = useQuery(QUERY_AUDIT_TRAIL, {
|
||||
const { loading, data, refetch } = useQuery(QUERY_AUDIT_TRAIL, {
|
||||
variables: { jobid: jobId },
|
||||
skip: !jobId,
|
||||
fetchPolicy: "network-only",
|
||||
@@ -34,15 +35,102 @@ export default function JobAuditTrail({ jobId }) {
|
||||
key: "operation",
|
||||
},
|
||||
];
|
||||
const emailColumns = [
|
||||
{
|
||||
title: t("audit.fields.created"),
|
||||
dataIndex: " created_at",
|
||||
key: " created_at",
|
||||
width: "10%",
|
||||
render: (text, record) => (
|
||||
<DateTimeFormatter>{record.created_at}</DateTimeFormatter>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
title: t("audit.fields.useremail"),
|
||||
dataIndex: "useremail",
|
||||
key: "useremail",
|
||||
width: "10%",
|
||||
},
|
||||
|
||||
{
|
||||
title: t("audit.fields.to"),
|
||||
dataIndex: "to",
|
||||
key: "to",
|
||||
width: "10%",
|
||||
render: (text, record) =>
|
||||
record.to &&
|
||||
record.to.map((email, idx) => <Tag key={idx}>{email}</Tag>),
|
||||
},
|
||||
{
|
||||
title: t("audit.fields.cc"),
|
||||
dataIndex: "cc",
|
||||
key: "cc",
|
||||
width: "10%",
|
||||
render: (text, record) =>
|
||||
record.cc &&
|
||||
record.cc.map((email, idx) => <Tag key={idx}>{email}</Tag>),
|
||||
},
|
||||
{
|
||||
title: t("audit.fields.subject"),
|
||||
dataIndex: "subject",
|
||||
key: "subject",
|
||||
width: "10%",
|
||||
},
|
||||
// {
|
||||
// title: t("audit.fields.contents"),
|
||||
// dataIndex: "contents",
|
||||
// key: "contents",
|
||||
// width: "10%",
|
||||
// render: (text, record) => (
|
||||
// <Button
|
||||
// onClick={() => {
|
||||
// var win = window.open(
|
||||
// "",
|
||||
// "Title",
|
||||
// "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=780,height=400,"
|
||||
// );
|
||||
// win.document.body.innerHTML = record.contents;
|
||||
// }}
|
||||
// >
|
||||
// Preview
|
||||
// </Button>
|
||||
// ),
|
||||
// },
|
||||
];
|
||||
return (
|
||||
<Card title={t("jobs.labels.audit")}>
|
||||
<Table
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
dataSource={data ? data.audit_trail : []}
|
||||
/>
|
||||
</Card>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<Card
|
||||
title={t("jobs.labels.audit")}
|
||||
extra={
|
||||
<Button
|
||||
onClick={() => {
|
||||
refetch();
|
||||
}}
|
||||
>
|
||||
<SyncOutlined />
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Table
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
dataSource={data ? data.audit_trail : []}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Card title={t("jobs.labels.emailaudit")}>
|
||||
<Table
|
||||
loading={loading}
|
||||
columns={emailColumns}
|
||||
rowKey="id"
|
||||
dataSource={data ? data.email_audit_trail : []}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user