@digitaldefiance/express-suite-react-components 4.26.20 → 4.26.21
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digitaldefiance/express-suite-react-components",
|
|
3
|
-
"version": "4.26.
|
|
3
|
+
"version": "4.26.21",
|
|
4
4
|
"homepage": "https://github.com/Digital-Defiance/react-components",
|
|
5
5
|
"description": "React MUI components for Digital Defiance Express Suite",
|
|
6
6
|
"repository": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FakeEmailAdminPanel.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/components/FakeEmailAdminPanel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FakeEmailAdminPanel.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/components/FakeEmailAdminPanel.tsx"],"names":[],"mappings":"AAkCA,OAAO,EAAE,EAAE,EAA4C,MAAM,OAAO,CAAC;AAQrE,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAiRD,eAAO,MAAM,mBAAmB,EAAE,EAIjC,CAAC;AAEF,eAAe,mBAAmB,CAAC;AAGnC,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,0BAA0B,CA8BhE,CAAC"}
|
|
@@ -23,12 +23,64 @@ const react_1 = require("react");
|
|
|
23
23
|
const contexts_1 = require("../contexts");
|
|
24
24
|
const ConfirmationDialog_1 = require("./ConfirmationDialog");
|
|
25
25
|
const useAuthenticatedApi_1 = require("../hooks/useAuthenticatedApi");
|
|
26
|
+
/**
|
|
27
|
+
* Renders email HTML content in a sandboxed iframe so that links are
|
|
28
|
+
* clickable and open in a new tab. Falls back to plain text when no
|
|
29
|
+
* HTML body is available.
|
|
30
|
+
*/
|
|
31
|
+
const EmailBodyIframe = ({ html, text, }) => {
|
|
32
|
+
const iframeRef = (0, react_1.useRef)(null);
|
|
33
|
+
(0, react_1.useEffect)(() => {
|
|
34
|
+
const iframe = iframeRef.current;
|
|
35
|
+
if (!iframe)
|
|
36
|
+
return;
|
|
37
|
+
const doc = iframe.contentDocument ?? iframe.contentWindow?.document;
|
|
38
|
+
if (!doc)
|
|
39
|
+
return;
|
|
40
|
+
if (html) {
|
|
41
|
+
// Inject a <base target="_blank"> so every link opens in a new tab,
|
|
42
|
+
// then write the original HTML body.
|
|
43
|
+
doc.open();
|
|
44
|
+
doc.write(`<!DOCTYPE html><html><head><base target="_blank"><style>body{font-family:sans-serif;font-size:14px;margin:8px;}</style></head><body>${html}</body></html>`);
|
|
45
|
+
doc.close();
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
doc.open();
|
|
49
|
+
doc.write(`<!DOCTYPE html><html><head><style>body{font-family:sans-serif;font-size:14px;margin:8px;white-space:pre-wrap;}</style></head><body>${text.replace(/</g, '<').replace(/>/g, '>')}</body></html>`);
|
|
50
|
+
doc.close();
|
|
51
|
+
}
|
|
52
|
+
// Auto-resize iframe height to fit content
|
|
53
|
+
const resize = () => {
|
|
54
|
+
if (doc.body) {
|
|
55
|
+
iframe.style.height = `${doc.body.scrollHeight + 16}px`;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
// Resize after content loads (images, etc.)
|
|
59
|
+
iframe.addEventListener('load', resize);
|
|
60
|
+
resize();
|
|
61
|
+
// Small delay to catch late-rendering content
|
|
62
|
+
const timer = setTimeout(resize, 200);
|
|
63
|
+
return () => {
|
|
64
|
+
iframe.removeEventListener('load', resize);
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
};
|
|
67
|
+
}, [html, text]);
|
|
68
|
+
return ((0, jsx_runtime_1.jsx)("iframe", { ref: iframeRef, sandbox: "allow-popups allow-popups-to-escape-sandbox allow-same-origin", style: {
|
|
69
|
+
width: '100%',
|
|
70
|
+
minHeight: 80,
|
|
71
|
+
border: '1px solid #e0e0e0',
|
|
72
|
+
borderRadius: 4,
|
|
73
|
+
background: '#fff',
|
|
74
|
+
}, title: "Email body" }));
|
|
75
|
+
};
|
|
26
76
|
const FakeEmailAdminPanelContent = () => {
|
|
27
77
|
const api = (0, useAuthenticatedApi_1.useAuthenticatedApi)();
|
|
28
78
|
const { tComponent } = (0, contexts_1.useI18n)();
|
|
29
79
|
const t = (key) => tComponent(suite_core_lib_1.SuiteCoreComponentId, key);
|
|
30
80
|
const [recipients, setRecipients] = (0, react_1.useState)([]);
|
|
31
81
|
const [expanded, setExpanded] = (0, react_1.useState)(null);
|
|
82
|
+
/** Tracks which individual email is expanded to show its body (address:idx) */
|
|
83
|
+
const [expandedEmail, setExpandedEmail] = (0, react_1.useState)(null);
|
|
32
84
|
const [emailsByAddress, setEmailsByAddress] = (0, react_1.useState)({});
|
|
33
85
|
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
34
86
|
const [error, setError] = (0, react_1.useState)(null);
|
|
@@ -78,7 +130,11 @@ const FakeEmailAdminPanelContent = () => {
|
|
|
78
130
|
setError(err instanceof Error ? err.message : String(err));
|
|
79
131
|
}
|
|
80
132
|
}, [api]);
|
|
81
|
-
return ((0, jsx_runtime_1.jsxs)(material_1.Paper, { variant: "outlined", sx: { p: 2 }, children: [(0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, mb: 1 }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle1", fontWeight: "bold", sx: { flexGrow: 1 }, children: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_Title) }), (0, jsx_runtime_1.jsx)(material_1.Chip, { label: "DEV", size: "small", color: "warning" }), (0, jsx_runtime_1.jsx)(material_1.IconButton, { size: "small", onClick: () => void loadRecipients(), title: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_Refresh), children: (0, jsx_runtime_1.jsx)(Refresh_1.default, { fontSize: "small" }) }), (0, jsx_runtime_1.jsx)(material_1.IconButton, { size: "small", color: "error", onClick: () => setClearDialogOpen(true), title: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_ClearAll), disabled: recipients.length === 0, children: (0, jsx_runtime_1.jsx)(Delete_1.default, { fontSize: "small" }) })] }), (0, jsx_runtime_1.jsx)(material_1.Divider, { sx: { mb: 1 } }), error && ((0, jsx_runtime_1.jsx)(material_1.Alert, { severity: "error", sx: { mb: 1 }, onClose: () => setError(null), children: error })), loading && ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: { display: 'flex', justifyContent: 'center', py: 2 }, children: (0, jsx_runtime_1.jsx)(material_1.CircularProgress, { size: 24 }) })), !loading && recipients.length === 0 && ((0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", children: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_NoRecipients) })), !loading && recipients.length > 0 && ((0, jsx_runtime_1.jsx)(material_1.List, { dense: true, disablePadding: true, children: recipients.map((r) => ((0, jsx_runtime_1.jsxs)(material_1.Box, { children: [(0, jsx_runtime_1.jsxs)(material_1.ListItemButton, { onClick: () => void toggleExpand(r.address), sx: { px: 0, py: 0.5 }, children: [(0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: r.address, secondary: `${r.count} ${t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_Recipients)}` }), expanded === r.address ? ((0, jsx_runtime_1.jsx)(ExpandLess_1.default, { fontSize: "small" })) : ((0, jsx_runtime_1.jsx)(ExpandMore_1.default, { fontSize: "small" }))] }), (0, jsx_runtime_1.jsx)(material_1.Collapse, { in: expanded === r.address, unmountOnExit: true, children: emailsByAddress[r.address]?.length === 0 ? ((0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", sx: { pl: 2, py: 0.5 }, children: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_NoEmails) })) : ((0, jsx_runtime_1.jsx)(material_1.List, { dense: true, disablePadding: true, sx: { pl: 2 }, children: (emailsByAddress[r.address] ?? []).map((email, idx) =>
|
|
133
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Paper, { variant: "outlined", sx: { p: 2 }, children: [(0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: 'flex', alignItems: 'center', gap: 1, mb: 1 }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle1", fontWeight: "bold", sx: { flexGrow: 1 }, children: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_Title) }), (0, jsx_runtime_1.jsx)(material_1.Chip, { label: "DEV", size: "small", color: "warning" }), (0, jsx_runtime_1.jsx)(material_1.IconButton, { size: "small", onClick: () => void loadRecipients(), title: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_Refresh), children: (0, jsx_runtime_1.jsx)(Refresh_1.default, { fontSize: "small" }) }), (0, jsx_runtime_1.jsx)(material_1.IconButton, { size: "small", color: "error", onClick: () => setClearDialogOpen(true), title: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_ClearAll), disabled: recipients.length === 0, children: (0, jsx_runtime_1.jsx)(Delete_1.default, { fontSize: "small" }) })] }), (0, jsx_runtime_1.jsx)(material_1.Divider, { sx: { mb: 1 } }), error && ((0, jsx_runtime_1.jsx)(material_1.Alert, { severity: "error", sx: { mb: 1 }, onClose: () => setError(null), children: error })), loading && ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: { display: 'flex', justifyContent: 'center', py: 2 }, children: (0, jsx_runtime_1.jsx)(material_1.CircularProgress, { size: 24 }) })), !loading && recipients.length === 0 && ((0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", children: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_NoRecipients) })), !loading && recipients.length > 0 && ((0, jsx_runtime_1.jsx)(material_1.List, { dense: true, disablePadding: true, children: recipients.map((r) => ((0, jsx_runtime_1.jsxs)(material_1.Box, { children: [(0, jsx_runtime_1.jsxs)(material_1.ListItemButton, { onClick: () => void toggleExpand(r.address), sx: { px: 0, py: 0.5 }, children: [(0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: r.address, secondary: `${r.count} ${t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_Recipients)}` }), expanded === r.address ? ((0, jsx_runtime_1.jsx)(ExpandLess_1.default, { fontSize: "small" })) : ((0, jsx_runtime_1.jsx)(ExpandMore_1.default, { fontSize: "small" }))] }), (0, jsx_runtime_1.jsx)(material_1.Collapse, { in: expanded === r.address, unmountOnExit: true, children: emailsByAddress[r.address]?.length === 0 ? ((0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", sx: { pl: 2, py: 0.5 }, children: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_NoEmails) })) : ((0, jsx_runtime_1.jsx)(material_1.List, { dense: true, disablePadding: true, sx: { pl: 2 }, children: (emailsByAddress[r.address] ?? []).map((email, idx) => {
|
|
134
|
+
const emailKey = `${r.address}:${idx}`;
|
|
135
|
+
const isEmailExpanded = expandedEmail === emailKey;
|
|
136
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { py: 0.25 }, children: [(0, jsx_runtime_1.jsxs)(material_1.ListItemButton, { disableGutters: true, onClick: () => setExpandedEmail(isEmailExpanded ? null : emailKey), sx: { py: 0.25, px: 0.5, borderRadius: 1 }, children: [(0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: email.subject || '(no subject)', secondary: `${t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_Timestamp)}: ${new Date(email.timestamp).toLocaleString()}`, primaryTypographyProps: { variant: 'body2' }, secondaryTypographyProps: { variant: 'caption' } }), isEmailExpanded ? ((0, jsx_runtime_1.jsx)(ExpandLess_1.default, { fontSize: "small" })) : ((0, jsx_runtime_1.jsx)(ExpandMore_1.default, { fontSize: "small" }))] }), (0, jsx_runtime_1.jsx)(material_1.Collapse, { in: isEmailExpanded, unmountOnExit: true, children: (0, jsx_runtime_1.jsx)(material_1.Box, { sx: { pl: 1, pr: 1, pb: 1 }, children: (0, jsx_runtime_1.jsx)(EmailBodyIframe, { html: email.html, text: email.text }) }) })] }, idx));
|
|
137
|
+
}) })) }), (0, jsx_runtime_1.jsx)(material_1.Divider, {})] }, r.address))) })), (0, jsx_runtime_1.jsx)(ConfirmationDialog_1.ConfirmationDialog, { open: clearDialogOpen, title: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_ClearAll), message: t(suite_core_lib_1.SuiteCoreStringKey.FakeEmail_Admin_ClearConfirm), onConfirm: () => void handleClearAll(), onCancel: () => setClearDialogOpen(false) })] }));
|
|
82
138
|
};
|
|
83
139
|
const FakeEmailAdminPanel = () => ((0, jsx_runtime_1.jsx)(useAuthenticatedApi_1.AuthenticatedApiProvider, { children: (0, jsx_runtime_1.jsx)(FakeEmailAdminPanelContent, {}) }));
|
|
84
140
|
exports.FakeEmailAdminPanel = FakeEmailAdminPanel;
|