fix: modal onClose callback, calendar popup truncation, datetime validation

- modal.js: add onClose callback to openModal(), fix _initialFormTimeout
  cleanup, deduplicate escape/overlay-click handlers in confirmModal,
  promptModal, selectModal using the new callback
- calendar.js: replace popup.innerHTML with insertAdjacentHTML (constraint),
  add truncateDescription() to cap long event descriptions at 500 chars
- validate.js: extend DATETIME_RE to cover ISO 8601 with ms/timezone,
  normalise datetime values to YYYY-MM-DDTHH:MM on input
- index.js: include app version in startup log message
- docker-compose.yml / .env.example: switch from named volume to
  host-mounted DATA_DIR/BACKUP_DIR with sane defaults
- docs/installation.md: document host-mount data paths

Co-Authored-By: Rafael Foster <rafaelfoster@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ulas Kalayci
2026-05-06 07:00:07 +02:00
parent 56b2fd471d
commit b545d83f64
7 changed files with 101 additions and 172 deletions
+10 -3
View File
@@ -402,6 +402,13 @@ function attachmentHtml(event) {
</a>`;
}
function truncateDescription(description, maxLength = 500) {
const text = String(description || '').trim();
if (!text) return '';
if (text.length <= maxLength) return text;
return `${text.slice(0, maxLength)} (...)`;
}
function attachmentPreviewHtml(event) {
if (!event?.attachment_data) return '';
const name = esc(event.attachment_name || t('calendar.attachmentFallback'));
@@ -1067,14 +1074,14 @@ function showEventPopup(ev, anchor) {
+ (ev.end_datetime ? ` ${formatTime(ev.end_datetime)}${t('calendar.timeSuffix') ? ' ' + t('calendar.timeSuffix') : ''}`.trim() : '');
const displayColor = ev.cal_color || ev.color;
popup.innerHTML = `
popup.insertAdjacentHTML('beforeend', `
<div class="event-popup__color-bar" style="background-color:${esc(displayColor)};"></div>
<div class="event-popup__title">${eventIconHtml(ev.icon)}<span>${esc(ev.title)}</span></div>
<div class="event-popup__meta">
${ev.cal_name ? `<div><span class="event-cal-label" style="--cal-color:${esc(displayColor)}">${esc(ev.cal_name)}</span></div>` : ''}
<div>${timeStr}</div>
${ev.location ? `<div>📍 ${esc(fmtLocation(ev.location))}</div>` : ''}
${ev.description ? `<div>${esc(ev.description)}</div>` : ''}
${ev.description ? `<div>${esc(truncateDescription(ev.description, 500))}</div>` : ''}
${ev.attachment_data ? attachmentHtml(ev) : ''}
${ev.assigned_name ? `<div>👤 ${esc(ev.assigned_name)}</div>` : ''}
</div>
@@ -1084,7 +1091,7 @@ function showEventPopup(ev, anchor) {
<i data-lucide="trash-2" style="width:16px;height:16px;" aria-hidden="true"></i>
</button>
</div>
`;
`);
document.body.appendChild(popup);
if (window.lucide) lucide.createIcons();