Auto-commit local changes before build (2026-01-13 10:43:31) #107
@ -1 +1 @@
|
||||
v20260113-01-changelog-markdown-render
|
||||
v20260113-02-edge-mail-lightmode
|
||||
|
||||
@ -290,10 +290,33 @@
|
||||
container.innerHTML = tableHtml;
|
||||
}
|
||||
|
||||
function setIframeHtml(html) {
|
||||
function wrapMailHtml(html) {
|
||||
html = html || "";
|
||||
var trimmed = (typeof html === "string") ? html.trim() : "";
|
||||
var injection = '<meta charset="utf-8"><meta name="color-scheme" content="light"><meta name="supported-color-schemes" content="light"><meta name="viewport" content="width=device-width, initial-scale=1"><base target="_blank"><style>:root{color-scheme:light;}html{color-scheme:light;}body{margin:0;padding:8px;background:#fff;forced-color-adjust:none;-ms-high-contrast-adjust:none;}</style>';
|
||||
|
||||
function injectIntoFullDoc(doc) {
|
||||
var d = doc || "";
|
||||
if (/<head[^>]*>/i.test(d)) {
|
||||
return d.replace(/<head[^>]*>/i, function (m) { return m + injection; });
|
||||
}
|
||||
if (/<html[^>]*>/i.test(d)) {
|
||||
return d.replace(/<html[^>]*>/i, function (m) { return m + "<head>" + injection + "</head>"; });
|
||||
}
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + d + "</body></html>";
|
||||
}
|
||||
|
||||
if (trimmed.toLowerCase().indexOf("<!doctype") === 0 || trimmed.toLowerCase().indexOf("<html") === 0) {
|
||||
return injectIntoFullDoc(trimmed);
|
||||
}
|
||||
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + html + "</body></html>";
|
||||
}
|
||||
|
||||
function setIframeHtml(html) {
|
||||
var iframe = document.getElementById('msg_body_container_iframe');
|
||||
if (!iframe) return;
|
||||
iframe.srcdoc = html || '<p>No message content stored.</p>';
|
||||
iframe.srcdoc = wrapMailHtml(html || '<p>No message content stored.</p>');
|
||||
}
|
||||
|
||||
async function openMessage(messageId) {
|
||||
@ -314,7 +337,7 @@
|
||||
setText('msg_parsed', meta.parsed_at);
|
||||
setText('msg_overall_message', meta.overall_message);
|
||||
|
||||
setIframeHtml(data.body_html);
|
||||
setIframeHtml(data.body_html || "");
|
||||
renderObjects(data.objects);
|
||||
|
||||
modal.show();
|
||||
|
||||
@ -323,20 +323,28 @@
|
||||
|
||||
function wrapMailHtml(html) {
|
||||
html = html || "";
|
||||
// Ensure we render the mail HTML with its own CSS, isolated from the site styling.
|
||||
return (
|
||||
"<!doctype html><html><head><meta charset=\"utf-8\">" +
|
||||
"<base target=\"_blank\">" +
|
||||
"</head><body style=\"margin:0; padding:8px;\">" +
|
||||
html +
|
||||
"</body></html>"
|
||||
);
|
||||
var trimmed = (typeof html === "string") ? html.trim() : "";
|
||||
var injection = '<meta charset="utf-8"><meta name="color-scheme" content="light"><meta name="supported-color-schemes" content="light"><meta name="viewport" content="width=device-width, initial-scale=1"><base target="_blank"><style>:root{color-scheme:light;}html{color-scheme:light;}body{margin:0;padding:8px;background:#fff;forced-color-adjust:none;-ms-high-contrast-adjust:none;}</style>';
|
||||
|
||||
function injectIntoFullDoc(doc) {
|
||||
var d = doc || "";
|
||||
if (/<head[^>]*>/i.test(d)) {
|
||||
return d.replace(/<head[^>]*>/i, function (m) { return m + injection; });
|
||||
}
|
||||
if (/<html[^>]*>/i.test(d)) {
|
||||
return d.replace(/<html[^>]*>/i, function (m) { return m + "<head>" + injection + "</head>"; });
|
||||
}
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + d + "</body></html>";
|
||||
}
|
||||
|
||||
var currentJobId = null;
|
||||
var currentRunId = null;
|
||||
if (trimmed.toLowerCase().indexOf("<!doctype") === 0 || trimmed.toLowerCase().indexOf("<html") === 0) {
|
||||
return injectIntoFullDoc(trimmed);
|
||||
}
|
||||
|
||||
function escapeHtml(s) {
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + html + "</body></html>";
|
||||
}
|
||||
|
||||
function escapeHtml(s) {
|
||||
return (s || "").toString()
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
|
||||
@ -380,22 +380,26 @@
|
||||
function wrapMailHtml(html) {
|
||||
html = html || "";
|
||||
var trimmed = (typeof html === "string") ? html.trim() : "";
|
||||
var injection = '<meta charset="utf-8"><meta name="color-scheme" content="light"><meta name="supported-color-schemes" content="light"><meta name="viewport" content="width=device-width, initial-scale=1"><base target="_blank"><style>:root{color-scheme:light;}html{color-scheme:light;}body{margin:0;padding:8px;background:#fff;forced-color-adjust:none;-ms-high-contrast-adjust:none;}</style>';
|
||||
|
||||
function injectIntoFullDoc(doc) {
|
||||
var d = doc || "";
|
||||
if (/<head[^>]*>/i.test(d)) {
|
||||
return d.replace(/<head[^>]*>/i, function (m) { return m + injection; });
|
||||
}
|
||||
if (/<html[^>]*>/i.test(d)) {
|
||||
return d.replace(/<html[^>]*>/i, function (m) { return m + "<head>" + injection + "</head>"; });
|
||||
}
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + d + "</body></html>";
|
||||
}
|
||||
|
||||
// If the content already looks like a full HTML document (common for report attachments),
|
||||
// do not wrap it again.
|
||||
if (trimmed.toLowerCase().indexOf("<!doctype") === 0 || trimmed.toLowerCase().indexOf("<html") === 0) {
|
||||
return trimmed;
|
||||
return injectIntoFullDoc(trimmed);
|
||||
}
|
||||
|
||||
// Ensure we render the mail HTML with its own CSS, isolated from the site styling.
|
||||
return (
|
||||
"<!doctype html><html><head><meta charset=\"utf-8\">" +
|
||||
"<base target=\"_blank\">" +
|
||||
"</head><body style=\"margin:0; padding:8px;\">" +
|
||||
html +
|
||||
"</body></html>"
|
||||
);
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + html + "</body></html>";
|
||||
}
|
||||
|
||||
function findCustomerIdByName(name) {
|
||||
if (!name) return null;
|
||||
for (var i = 0; i < customers.length; i++) {
|
||||
|
||||
@ -132,16 +132,28 @@
|
||||
(function () {
|
||||
function wrapMailHtml(html) {
|
||||
html = html || "";
|
||||
return (
|
||||
"<!doctype html><html><head><meta charset=\"utf-8\">" +
|
||||
"<base target=\"_blank\">" +
|
||||
"</head><body style=\"margin:0; padding:8px;\">" +
|
||||
html +
|
||||
"</body></html>"
|
||||
);
|
||||
var trimmed = (typeof html === "string") ? html.trim() : "";
|
||||
var injection = '<meta charset="utf-8"><meta name="color-scheme" content="light"><meta name="supported-color-schemes" content="light"><meta name="viewport" content="width=device-width, initial-scale=1"><base target="_blank"><style>:root{color-scheme:light;}html{color-scheme:light;}body{margin:0;padding:8px;background:#fff;forced-color-adjust:none;-ms-high-contrast-adjust:none;}</style>';
|
||||
|
||||
function injectIntoFullDoc(doc) {
|
||||
var d = doc || "";
|
||||
if (/<head[^>]*>/i.test(d)) {
|
||||
return d.replace(/<head[^>]*>/i, function (m) { return m + injection; });
|
||||
}
|
||||
if (/<html[^>]*>/i.test(d)) {
|
||||
return d.replace(/<html[^>]*>/i, function (m) { return m + "<head>" + injection + "</head>"; });
|
||||
}
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + d + "</body></html>";
|
||||
}
|
||||
|
||||
function attachHandlers() {
|
||||
if (trimmed.toLowerCase().indexOf("<!doctype") === 0 || trimmed.toLowerCase().indexOf("<html") === 0) {
|
||||
return injectIntoFullDoc(trimmed);
|
||||
}
|
||||
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + html + "</body></html>";
|
||||
}
|
||||
|
||||
function attachHandlers() {
|
||||
var emlLinks = document.querySelectorAll("a.eml-download");
|
||||
emlLinks.forEach(function (a) {
|
||||
a.addEventListener("click", function (ev) {
|
||||
|
||||
@ -478,16 +478,28 @@
|
||||
|
||||
function wrapMailHtml(html) {
|
||||
html = html || "";
|
||||
// Ensure we render the mail HTML with its own CSS, isolated from the site styling.
|
||||
return (
|
||||
"<!doctype html><html><head><meta charset=\"utf-8\">" +
|
||||
"<base target=\"_blank\">" +
|
||||
"</head><body style=\"margin:0; padding:8px;\">" +
|
||||
html +
|
||||
"</body></html>"
|
||||
);
|
||||
var trimmed = (typeof html === "string") ? html.trim() : "";
|
||||
var injection = '<meta charset="utf-8"><meta name="color-scheme" content="light"><meta name="supported-color-schemes" content="light"><meta name="viewport" content="width=device-width, initial-scale=1"><base target="_blank"><style>:root{color-scheme:light;}html{color-scheme:light;}body{margin:0;padding:8px;background:#fff;forced-color-adjust:none;-ms-high-contrast-adjust:none;}</style>';
|
||||
|
||||
function injectIntoFullDoc(doc) {
|
||||
var d = doc || "";
|
||||
if (/<head[^>]*>/i.test(d)) {
|
||||
return d.replace(/<head[^>]*>/i, function (m) { return m + injection; });
|
||||
}
|
||||
function renderObjects(objects) {
|
||||
if (/<html[^>]*>/i.test(d)) {
|
||||
return d.replace(/<html[^>]*>/i, function (m) { return m + "<head>" + injection + "</head>"; });
|
||||
}
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + d + "</body></html>";
|
||||
}
|
||||
|
||||
if (trimmed.toLowerCase().indexOf("<!doctype") === 0 || trimmed.toLowerCase().indexOf("<html") === 0) {
|
||||
return injectIntoFullDoc(trimmed);
|
||||
}
|
||||
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + html + "</body></html>";
|
||||
}
|
||||
|
||||
function renderObjects(objects) {
|
||||
var container = document.getElementById("run_msg_objects_container");
|
||||
if (!container) return;
|
||||
|
||||
|
||||
@ -364,16 +364,28 @@ function statusClass(status) {
|
||||
|
||||
function wrapMailHtml(html) {
|
||||
html = html || "";
|
||||
return (
|
||||
"<!doctype html><html><head><meta charset=\"utf-8\">" +
|
||||
"<base target=\"_blank\">" +
|
||||
"</head><body style=\"margin:0; padding:8px;\">" +
|
||||
html +
|
||||
"</body></html>"
|
||||
);
|
||||
var trimmed = (typeof html === "string") ? html.trim() : "";
|
||||
var injection = '<meta charset="utf-8"><meta name="color-scheme" content="light"><meta name="supported-color-schemes" content="light"><meta name="viewport" content="width=device-width, initial-scale=1"><base target="_blank"><style>:root{color-scheme:light;}html{color-scheme:light;}body{margin:0;padding:8px;background:#fff;forced-color-adjust:none;-ms-high-contrast-adjust:none;}</style>';
|
||||
|
||||
function injectIntoFullDoc(doc) {
|
||||
var d = doc || "";
|
||||
if (/<head[^>]*>/i.test(d)) {
|
||||
return d.replace(/<head[^>]*>/i, function (m) { return m + injection; });
|
||||
}
|
||||
if (/<html[^>]*>/i.test(d)) {
|
||||
return d.replace(/<html[^>]*>/i, function (m) { return m + "<head>" + injection + "</head>"; });
|
||||
}
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + d + "</body></html>";
|
||||
}
|
||||
|
||||
function escapeHtml(s) {
|
||||
if (trimmed.toLowerCase().indexOf("<!doctype") === 0 || trimmed.toLowerCase().indexOf("<html") === 0) {
|
||||
return injectIntoFullDoc(trimmed);
|
||||
}
|
||||
|
||||
return "<!doctype html><html><head>" + injection + "</head><body>" + html + "</body></html>";
|
||||
}
|
||||
|
||||
function escapeHtml(s) {
|
||||
return (s || "").toString()
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
|
||||
@ -5,6 +5,14 @@
|
||||
- Ensured the changelog always fetches the latest version from the source repository at request time.
|
||||
- Removed plain-text rendering to prevent loss of Markdown structure.
|
||||
|
||||
---
|
||||
|
||||
## v20260113-02-edge-mail-lightmode
|
||||
|
||||
- Forced light color-scheme for embedded mail content to prevent Edge auto dark mode rendering.
|
||||
- Added explicit color-scheme and forced-color-adjust rules so original mail CSS is respected.
|
||||
- Ensured consistent mail readability across Edge and Firefox in Inbox, Deleted Inbox, Job Detail, Run Checks, Daily Jobs, and Admin All Mail views.
|
||||
|
||||
================================================================================================================================================
|
||||
## v0.1.20
|
||||
|
||||
@ -97,13 +105,13 @@ This release delivers a comprehensive set of improvements focused on parser corr
|
||||
## v0.1.19
|
||||
This release delivers a broad set of improvements focused on reliability, transparency, and operational control across mail processing, administrative auditing, and Run Checks workflows. The changes aim to make message handling more robust, provide better insight for administrators, and give operators clearer and more flexible control when reviewing backup runs.
|
||||
|
||||
Mail Import Reliability and Data Integrity
|
||||
### Mail Import Reliability and Data Integrity
|
||||
- Updated the mail import flow so messages are only moved to the processed folder after a successful database store and commit.
|
||||
- Prevented Graph emails from being moved when parsing, storing, or committing data fails, ensuring no messages are lost due to partial failures.
|
||||
- Added explicit commit and rollback handling to guarantee database consistency before any mail state changes occur.
|
||||
- Improved logging around import, commit, and rollback failures to make skipped or retried mails easier to trace and troubleshoot.
|
||||
|
||||
Administrative Mail Auditing and Visibility
|
||||
### Administrative Mail Auditing and Visibility
|
||||
- Introduced an admin-only “All Mail” audit page that provides a complete overview of all received mail messages.
|
||||
- Implemented pagination with a fixed page size of 50 items to ensure consistent performance and predictable navigation.
|
||||
- Added always-visible search filters that can be combined using AND logic, including From, Subject, Backup, Type, Job name, and a received date/time range.
|
||||
@ -112,14 +120,14 @@ Administrative Mail Auditing and Visibility
|
||||
- Added a dedicated navigation entry so administrators can easily access the All Mail audit view.
|
||||
- Fixed modal opening behavior in the All Mail page to fully align click handling and popups with the Inbox implementation.
|
||||
|
||||
Inbox and Mail Body Rendering Improvements
|
||||
### Inbox and Mail Body Rendering Improvements
|
||||
- Treated whitespace-only email bodies as empty during import so HTML report attachments can be extracted and displayed correctly.
|
||||
- Added legacy fallback logic in the Inbox message detail API to extract the first HTML attachment from stored EML files when bodies are empty or invalid.
|
||||
- Improved iframe rendering in the Inbox so full HTML documents (commonly used for report attachments) are rendered directly instead of being wrapped.
|
||||
- Added detection for “effectively empty” HTML bodies, such as empty Graph-generated HTML skeletons.
|
||||
- Ensured that both newly imported and already-stored messages can dynamically fall back to EML attachment extraction without requiring a reset.
|
||||
|
||||
Run Checks Usability and Control
|
||||
### Run Checks Usability and Control
|
||||
- Added a copy-to-clipboard icon next to ticket numbers in the Run Checks popup to quickly copy only the ticket code.
|
||||
- Prevented accidental selection of appended status text when copying ticket numbers.
|
||||
- Introduced a manual “Success (override)” action that allows Operators and Admins to mark a run as successful even if it originally failed or produced warnings.
|
||||
@ -130,13 +138,13 @@ Run Checks Usability and Control
|
||||
- Added support for extracting HTML content from stored EML files when both HTML and text bodies are unavailable.
|
||||
- Ensured plain-text emails are safely rendered using preformatted HTML to preserve readability.
|
||||
|
||||
Customer, Ticket, and Scope Cleanup
|
||||
### Customer, Ticket, and Scope Cleanup
|
||||
- Updated customer deletion logic to allow removal of customers even when tickets or remarks are linked.
|
||||
- Added explicit cleanup of related TicketScope and RemarkScope records prior to customer deletion.
|
||||
- Ensured jobs linked to a deleted customer are safely unassigned to prevent foreign key constraint errors.
|
||||
- Eliminated deletion failures caused by lingering ticket or remark relationships.
|
||||
|
||||
Parser Enhancements and Informational Messages
|
||||
### Parser Enhancements and Informational Messages
|
||||
- Added parser support for 3CX SSL Certificate notification emails.
|
||||
- Classified these messages as Backup: 3CX with Type: SSL Certificate.
|
||||
- Parsed and displayed certificate information in the Run Checks popup.
|
||||
@ -145,7 +153,7 @@ Parser Enhancements and Informational Messages
|
||||
- Classified Synology Updates messages as informational and set their overall status to Warning.
|
||||
- Excluded Synology Updates informational messages from scheduling logic and reporting output.
|
||||
|
||||
UI Layout and Status Accuracy Improvements
|
||||
### UI Layout and Status Accuracy Improvements
|
||||
- Moved the Details section above the email body in both Inbox and Job Details popups to improve readability.
|
||||
- Avoided long detail texts being constrained to narrow side columns.
|
||||
- Adjusted missed run detection to include a ±1 hour grace window around scheduled run times.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user