Auto-commit local changes before build (2026-01-09 13:34:03) #82

Merged
ivooskamp merged 1 commits from v20260109-08-ui-ellipsis-and-remove-objects-header into main 2026-01-13 11:35:16 +01:00
10 changed files with 146 additions and 55 deletions
Showing only changes of commit 7da364638a - Show all commits

View File

@ -1 +1 @@
v20260109-07-feedback-open-default-resolved-sort v20260109-08-ui-ellipsis-and-remove-objects-header

View File

@ -14,3 +14,23 @@ main.dashboard-container {
width: min(90vw, 1728px); width: min(90vw, 1728px);
max-width: 1728px; max-width: 1728px;
} }
/* Prevent long detail values (e.g., email addresses) from overlapping other fields */
.dl-compact dt {
white-space: nowrap;
}
.dl-compact .ellipsis-field {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
.dl-compact .ellipsis-field.is-expanded {
overflow: visible;
text-overflow: clip;
white-space: normal;
cursor: text;
}

View File

@ -185,5 +185,70 @@
</main> </main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
(function () {
function isOverflowing(el) {
try {
return el && el.scrollWidth > el.clientWidth;
} catch (e) {
return false;
}
}
function setEllipsisTitle(el) {
if (!el || el.classList.contains('is-expanded')) {
return;
}
var txt = (el.textContent || '').trim();
if (!txt) {
el.removeAttribute('title');
return;
}
if (isOverflowing(el)) {
el.setAttribute('title', txt);
} else {
el.removeAttribute('title');
}
}
document.addEventListener('click', function (e) {
var el = e.target;
if (!el) return;
if (!el.classList || !el.classList.contains('ellipsis-field')) return;
// Ignore clicks on interactive children
if (e.target.closest && e.target.closest('a, button, input, select, textarea, label')) return;
el.classList.toggle('is-expanded');
if (el.classList.contains('is-expanded')) {
el.removeAttribute('title');
} else {
setEllipsisTitle(el);
}
});
document.addEventListener('dblclick', function (e) {
var el = e.target;
if (!el || !el.classList || !el.classList.contains('ellipsis-field')) return;
// Expand on double click and select all text
el.classList.add('is-expanded');
el.removeAttribute('title');
try {
var range = document.createRange();
range.selectNodeContents(el);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} catch (err) {
// no-op
}
});
document.addEventListener('mouseover', function (e) {
var el = e.target;
if (!el || !el.classList || !el.classList.contains('ellipsis-field')) return;
setEllipsisTitle(el);
});
})();
</script>
</body> </body>
</html> </html>

View File

@ -168,30 +168,30 @@
<div class="modal-body"> <div class="modal-body">
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-3">
<dl class="row mb-0"> <dl class="row mb-0 dl-compact">
<dt class="col-4">From</dt> <dt class="col-4">From</dt>
<dd class="col-8" id="msg_from"></dd> <dd class="col-8 ellipsis-field" id="msg_from"></dd>
<dt class="col-4">Backup</dt> <dt class="col-4">Backup</dt>
<dd class="col-8" id="msg_backup"></dd> <dd class="col-8 ellipsis-field" id="msg_backup"></dd>
<dt class="col-4">Type</dt> <dt class="col-4">Type</dt>
<dd class="col-8" id="msg_type"></dd> <dd class="col-8 ellipsis-field" id="msg_type"></dd>
<dt class="col-4">Job</dt> <dt class="col-4">Job</dt>
<dd class="col-8" id="msg_job"></dd> <dd class="col-8 ellipsis-field" id="msg_job"></dd>
<dt class="col-4">Overall</dt> <dt class="col-4">Overall</dt>
<dd class="col-8" id="msg_overall"></dd> <dd class="col-8 ellipsis-field" id="msg_overall"></dd>
<dt class="col-4">Customer</dt> <dt class="col-4">Customer</dt>
<dd class="col-8" id="msg_customer"></dd> <dd class="col-8 ellipsis-field" id="msg_customer"></dd>
<dt class="col-4">Received</dt> <dt class="col-4">Received</dt>
<dd class="col-8" id="msg_received"></dd> <dd class="col-8 ellipsis-field" id="msg_received"></dd>
<dt class="col-4">Parsed</dt> <dt class="col-4">Parsed</dt>
<dd class="col-8" id="msg_parsed"></dd> <dd class="col-8 ellipsis-field" id="msg_parsed"></dd>
<dt class="col-4">Details</dt> <dt class="col-4">Details</dt>
<dd class="col-8" id="msg_overall_message" style="white-space: pre-wrap;"></dd> <dd class="col-8" id="msg_overall_message" style="white-space: pre-wrap;"></dd>
@ -204,7 +204,6 @@
</div> </div>
<div class="mt-3"> <div class="mt-3">
<h6>Objects</h6>
<div id="msg_objects_container"></div> <div id="msg_objects_container"></div>
</div> </div>
</div> </div>

View File

@ -172,18 +172,18 @@
<div id="dj_runs_list" class="list-group"></div> <div id="dj_runs_list" class="list-group"></div>
</div> </div>
<div class="col-md-9 dj-detail-col"> <div class="col-md-9 dj-detail-col">
<dl class="row mb-3"> <dl class="row mb-3 dl-compact">
<dt class="col-3">From</dt> <dt class="col-3">From</dt>
<dd class="col-9" id="dj_from"></dd> <dd class="col-9 ellipsis-field" id="dj_from"></dd>
<dt class="col-3">Subject</dt> <dt class="col-3">Subject</dt>
<dd class="col-9" id="dj_subject"></dd> <dd class="col-9 ellipsis-field" id="dj_subject"></dd>
<dt class="col-3">Received</dt> <dt class="col-3">Received</dt>
<dd class="col-9" id="dj_received"></dd> <dd class="col-9 ellipsis-field" id="dj_received"></dd>
<dt class="col-3">Status</dt> <dt class="col-3">Status</dt>
<dd class="col-9" id="dj_status"></dd> <dd class="col-9 ellipsis-field" id="dj_status"></dd>
<dt class="col-3">Remark</dt> <dt class="col-3">Remark</dt>
<dd class="col-9" id="dj_remark" style="white-space: pre-wrap;"></dd> <dd class="col-9" id="dj_remark" style="white-space: pre-wrap;"></dd>
@ -234,7 +234,6 @@
</div> </div>
<div class="dj-objects-panel"> <div class="dj-objects-panel">
<h6>Objects</h6>
<div class="table-responsive dj-objects-scroll"> <div class="table-responsive dj-objects-scroll">
<table class="table table-sm table-bordered" id="dj_objects_table"> <table class="table table-sm table-bordered" id="dj_objects_table">
<thead class="table-light" style="position: sticky; top: 0; z-index: 1;"> <thead class="table-light" style="position: sticky; top: 0; z-index: 1;">

View File

@ -135,21 +135,21 @@
<div class="modal-body"> <div class="modal-body">
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-3">
<dl class="row mb-0"> <dl class="row mb-0 dl-compact">
<dt class="col-4">From</dt> <dt class="col-4">From</dt>
<dd class="col-8" id="msg_from"></dd> <dd class="col-8 ellipsis-field" id="msg_from"></dd>
<dt class="col-4">Backup</dt> <dt class="col-4">Backup</dt>
<dd class="col-8" id="msg_backup"></dd> <dd class="col-8 ellipsis-field" id="msg_backup"></dd>
<dt class="col-4">Type</dt> <dt class="col-4">Type</dt>
<dd class="col-8" id="msg_type"></dd> <dd class="col-8 ellipsis-field" id="msg_type"></dd>
<dt class="col-4">Job</dt> <dt class="col-4">Job</dt>
<dd class="col-8" id="msg_job"></dd> <dd class="col-8 ellipsis-field" id="msg_job"></dd>
<dt class="col-4">Overall</dt> <dt class="col-4">Overall</dt>
<dd class="col-8" id="msg_overall"></dd> <dd class="col-8 ellipsis-field" id="msg_overall"></dd>
<dt class="col-4">Customer</dt> <dt class="col-4">Customer</dt>
<dd class="col-8"> <dd class="col-8">
@ -161,15 +161,15 @@
{% endfor %} {% endfor %}
</datalist> </datalist>
{% else %} {% else %}
<span id="msg_customer_display"></span> <span id="msg_customer_display" class="ellipsis-field"></span>
{% endif %} {% endif %}
</dd> </dd>
<dt class="col-4">Received</dt> <dt class="col-4">Received</dt>
<dd class="col-8" id="msg_received"></dd> <dd class="col-8 ellipsis-field" id="msg_received"></dd>
<dt class="col-4">Parsed</dt> <dt class="col-4">Parsed</dt>
<dd class="col-8" id="msg_parsed"></dd> <dd class="col-8 ellipsis-field" id="msg_parsed"></dd>
</dl> </dl>
</div> </div>
@ -183,7 +183,6 @@
</div> </div>
<div class="mt-3"> <div class="mt-3">
<h6>Objects</h6>
<div id="msg_objects_container"> <div id="msg_objects_container">
<!-- Parsed objects will be rendered here --> <!-- Parsed objects will be rendered here -->
</div> </div>

View File

@ -99,18 +99,18 @@
<div class="modal-body"> <div class="modal-body">
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-3">
<dl class="row mb-0"> <dl class="row mb-0 dl-compact">
<dt class="col-4">From</dt> <dt class="col-4">From</dt>
<dd class="col-8" id="dmsg_from"></dd> <dd class="col-8 ellipsis-field" id="dmsg_from"></dd>
<dt class="col-4">Received</dt> <dt class="col-4">Received</dt>
<dd class="col-8" id="dmsg_received"></dd> <dd class="col-8 ellipsis-field" id="dmsg_received"></dd>
<dt class="col-4">Deleted by</dt> <dt class="col-4">Deleted by</dt>
<dd class="col-8" id="dmsg_deleted_by"></dd> <dd class="col-8 ellipsis-field" id="dmsg_deleted_by"></dd>
<dt class="col-4">Deleted at</dt> <dt class="col-4">Deleted at</dt>
<dd class="col-8" id="dmsg_deleted_at"></dd> <dd class="col-8 ellipsis-field" id="dmsg_deleted_at"></dd>
</dl> </dl>
</div> </div>

View File

@ -4,18 +4,18 @@
<div class="card mb-3"> <div class="card mb-3">
<div class="card-body"> <div class="card-body">
<dl class="row mb-0"> <dl class="row mb-0 dl-compact">
<dt class="col-sm-3">Customer</dt> <dt class="col-sm-3">Customer</dt>
<dd class="col-sm-9">{{ job.customer.name if job.customer else "" }}</dd> <dd class="col-sm-9 ellipsis-field">{{ job.customer.name if job.customer else "" }}</dd>
<dt class="col-sm-3">Backup</dt> <dt class="col-sm-3">Backup</dt>
<dd class="col-sm-9">{{ job.backup_software }}</dd> <dd class="col-sm-9 ellipsis-field">{{ job.backup_software }}</dd>
<dt class="col-sm-3">Type</dt> <dt class="col-sm-3">Type</dt>
<dd class="col-sm-9">{{ job.backup_type }}</dd> <dd class="col-sm-9 ellipsis-field">{{ job.backup_type }}</dd>
<dt class="col-sm-3">Job name</dt> <dt class="col-sm-3">Job name</dt>
<dd class="col-sm-9">{{ job.job_name }}</dd> <dd class="col-sm-9 ellipsis-field">{{ job.job_name }}</dd>
<dt class="col-sm-3">Tickets</dt> <dt class="col-sm-3">Tickets</dt>
<dd class="col-sm-9">{{ ticket_open_count }} open / {{ ticket_total_count }} total</dd> <dd class="col-sm-9">{{ ticket_open_count }} open / {{ ticket_total_count }} total</dd>
@ -168,21 +168,21 @@
<div class="modal-body"> <div class="modal-body">
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-3">
<dl class="row mb-0"> <dl class="row mb-0 dl-compact">
<dt class="col-4">From</dt> <dt class="col-4">From</dt>
<dd class="col-8" id="run_msg_from"></dd> <dd class="col-8 ellipsis-field" id="run_msg_from"></dd>
<dt class="col-4">Backup</dt> <dt class="col-4">Backup</dt>
<dd class="col-8" id="run_msg_backup"></dd> <dd class="col-8 ellipsis-field" id="run_msg_backup"></dd>
<dt class="col-4">Type</dt> <dt class="col-4">Type</dt>
<dd class="col-8" id="run_msg_type"></dd> <dd class="col-8 ellipsis-field" id="run_msg_type"></dd>
<dt class="col-4">Ticket</dt> <dt class="col-4">Ticket</dt>
<dd class="col-8" id="run_msg_ticket"></dd> <dd class="col-8 ellipsis-field" id="run_msg_ticket"></dd>
<dt class="col-4">Remark</dt> <dt class="col-4">Remark</dt>
<dd class="col-8" id="run_msg_remark"></dd> <dd class="col-8 ellipsis-field" id="run_msg_remark"></dd>
<dt class="col-12 mt-2">Tickets &amp; remarks</dt> <dt class="col-12 mt-2">Tickets &amp; remarks</dt>
<dd class="col-12"> <dd class="col-12">
@ -208,19 +208,19 @@
</dd> </dd>
<dt class="col-4">Job</dt> <dt class="col-4">Job</dt>
<dd class="col-8" id="run_msg_job"></dd> <dd class="col-8 ellipsis-field" id="run_msg_job"></dd>
<dt class="col-4">Overall</dt> <dt class="col-4">Overall</dt>
<dd class="col-8" id="run_msg_overall"></dd> <dd class="col-8 ellipsis-field" id="run_msg_overall"></dd>
<dt class="col-4">Customer</dt> <dt class="col-4">Customer</dt>
<dd class="col-8" id="run_msg_customer"></dd> <dd class="col-8 ellipsis-field" id="run_msg_customer"></dd>
<dt class="col-4">Received</dt> <dt class="col-4">Received</dt>
<dd class="col-8" id="run_msg_received"></dd> <dd class="col-8 ellipsis-field" id="run_msg_received"></dd>
<dt class="col-4">Parsed</dt> <dt class="col-4">Parsed</dt>
<dd class="col-8" id="run_msg_parsed"></dd> <dd class="col-8 ellipsis-field" id="run_msg_parsed"></dd>
</dl> </dl>
</div> </div>
@ -235,7 +235,6 @@
</div> </div>
<div class="mt-3"> <div class="mt-3">
<h6>Objects</h6>
<div id="run_msg_objects_container"> <div id="run_msg_objects_container">
<!-- Parsed objects will be rendered here --> <!-- Parsed objects will be rendered here -->
</div> </div>

View File

@ -177,18 +177,18 @@
<div id="rcm_runs_list" class="list-group"></div> <div id="rcm_runs_list" class="list-group"></div>
</div> </div>
<div class="col-md-9 rcm-detail-col"> <div class="col-md-9 rcm-detail-col">
<dl class="row mb-3"> <dl class="row mb-3 dl-compact">
<dt class="col-3">From</dt> <dt class="col-3">From</dt>
<dd class="col-9" id="rcm_from"></dd> <dd class="col-9 ellipsis-field" id="rcm_from"></dd>
<dt class="col-3">Subject</dt> <dt class="col-3">Subject</dt>
<dd class="col-9" id="rcm_subject"></dd> <dd class="col-9 ellipsis-field" id="rcm_subject"></dd>
<dt class="col-3">Received</dt> <dt class="col-3">Received</dt>
<dd class="col-9" id="rcm_received"></dd> <dd class="col-9 ellipsis-field" id="rcm_received"></dd>
<dt class="col-3">Indicator</dt> <dt class="col-3">Indicator</dt>
<dd class="col-9" id="rcm_status"></dd> <dd class="col-9 ellipsis-field" id="rcm_status"></dd>
<dt class="col-3">Remark</dt> <dt class="col-3">Remark</dt>
<dd class="col-9" id="rcm_remark" style="white-space: pre-wrap;"></dd> <dd class="col-9" id="rcm_remark" style="white-space: pre-wrap;"></dd>
@ -239,7 +239,6 @@
</div> </div>
<div> <div>
<h6>Objects</h6>
<div class="table-responsive rcm-objects-scroll"> <div class="table-responsive rcm-objects-scroll">
<table class="table table-sm table-bordered" id="rcm_objects_table"> <table class="table table-sm table-bordered" id="rcm_objects_table">
<thead class="table-light" style="position: sticky; top: 0; z-index: 1;"> <thead class="table-light" style="position: sticky; top: 0; z-index: 1;">

View File

@ -53,6 +53,17 @@
- Updated feedback listing to show only Open items by default. - Updated feedback listing to show only Open items by default.
- Adjusted sorting logic so Resolved items are always placed at the bottom when viewing all items. - Adjusted sorting logic so Resolved items are always placed at the bottom when viewing all items.
- Preserved existing filtering, searching, and user-controlled sorting behavior. - Preserved existing filtering, searching, and user-controlled sorting behavior.
---
## v20260109-08-ui-ellipsis-and-remove-objects-header
- Added reusable ellipsis styling for detail fields to prevent long values (e.g., email addresses) from overlapping other UI elements.
- Implemented click-to-expand for ellipsized fields so the full text becomes visible and selectable; double-click expands and selects all text.
- Added automatic tooltip (title) showing the full value when the field is truncated.
- Removed the redundant "Objects" heading above the objects table (table column header remains as the single label).
- Applied the detail-field truncation behavior consistently across Inbox, Deleted Mail, Run Checks, Daily Jobs, Job Detail, and Admin All Mail popups/pages where long values can occur.
================================================================================================================================================ ================================================================================================================================================
## v0.1.19 ## 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. 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.