fix(web): settings modal — table crash, tab restore, checkbox layout
Three separate settings bugs (all pre-existing, exposed once the modal actually opened): 1. renderCalendarTable() referenced a bare `owned` variable (undefined in that scope; should be cal.owned) → ReferenceError on the first owned local calendar → renderAllAccounts threw → the calendar table never rendered. This was the ROOT cause of "settings won't open" (it threw out of openSettingsModal); the earlier try/catch only masked it. Fixed to cal.owned. 2. On reload, writeUrlState() (via fetchAndRender) ran before openSettingsModal activated the saved tab and wrote the HTML-default (Profile) tab into the URL, so every reload landed on Profile. Now the stab is only rewritten once the modal is actually shown; otherwise the saved one is preserved. 3. The directory-hidden checkbox label inherited the global ".form-group label" uppercase/spaced/12px styling, stretching the text into a broken column. A higher-specificity .checkbox-row rule restores normal inline layout. v77. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2015,8 +2015,16 @@ a { color: var(--primary); text-decoration: none; }
|
|||||||
padding-top: 14px; font-size: 12px; font-weight: 600;
|
padding-top: 14px; font-size: 12px; font-weight: 600;
|
||||||
color: var(--text-3); text-transform: uppercase; letter-spacing: .04em;
|
color: var(--text-3); text-transform: uppercase; letter-spacing: .04em;
|
||||||
}
|
}
|
||||||
.checkbox-row { display: flex; align-items: center; gap: 8px; cursor: pointer; }
|
/* Higher specificity than the global ".form-group label" (uppercase / spaced /
|
||||||
.checkbox-row input[type=checkbox] { flex-shrink: 0; }
|
12px) so a checkbox label reads as normal inline text next to its box, not a
|
||||||
|
stretched uppercase column. */
|
||||||
|
.form-group label.checkbox-row,
|
||||||
|
.checkbox-row {
|
||||||
|
display: flex; align-items: center; justify-content: flex-start; gap: 8px;
|
||||||
|
cursor: pointer; text-transform: none; letter-spacing: normal;
|
||||||
|
font-size: 14px; font-weight: 400; color: var(--text-1);
|
||||||
|
}
|
||||||
|
.checkbox-row input[type=checkbox] { flex-shrink: 0; margin: 0; }
|
||||||
/* .popup-creator styling moved into the .popup-row / #popup-creator rules above. */
|
/* .popup-creator styling moved into the .popup-row / #popup-creator rules above. */
|
||||||
|
|
||||||
/* ── Groups ─────────────────────────────────────────────────── */
|
/* ── Groups ─────────────────────────────────────────────────── */
|
||||||
|
|||||||
@@ -91,8 +91,19 @@ function writeUrlState() {
|
|||||||
let newHash = `date=${dateStr}&view=${state.currentView}`;
|
let newHash = `date=${dateStr}&view=${state.currentView}`;
|
||||||
if (uiSettingsOpen) {
|
if (uiSettingsOpen) {
|
||||||
newHash += '&settings=1';
|
newHash += '&settings=1';
|
||||||
const activeTab = document.querySelector('.settings-nav-btn.active');
|
// Only read the active tab once the modal is actually shown. On an initial
|
||||||
if (activeTab) newHash += `&stab=${activeTab.dataset.panel}`;
|
// reload, writeUrlState() runs (via fetchAndRender) BEFORE openSettingsModal
|
||||||
|
// has activated the saved tab, and the HTML-default (Profile) tab is still
|
||||||
|
// marked active — writing it would clobber the saved stab and always send
|
||||||
|
// the user to Profile. In that window, keep the stab already in the URL.
|
||||||
|
const modalShown = !document.getElementById('modal-settings')?.classList.contains('hidden');
|
||||||
|
const activeTab = modalShown ? document.querySelector('.settings-nav-btn.active') : null;
|
||||||
|
if (activeTab) {
|
||||||
|
newHash += `&stab=${activeTab.dataset.panel}`;
|
||||||
|
} else {
|
||||||
|
const prev = new URLSearchParams(window.location.hash.replace(/^#/, '')).get('stab');
|
||||||
|
if (prev) newHash += `&stab=${prev}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (window.location.hash.replace(/^#/,'') !== newHash) {
|
if (window.location.hash.replace(/^#/,'') !== newHash) {
|
||||||
// replaceState statt pushState: prev/next-Klicks sollen nicht jeden
|
// replaceState statt pushState: prev/next-Klicks sollen nicht jeden
|
||||||
@@ -3516,7 +3527,7 @@ function renderCalendarTable() {
|
|||||||
<td><button class="icon-btn mini-btn" data-ct-del="local" data-ct-id="${cal.id}">${TRASH}</button></td>
|
<td><button class="icon-btn mini-btn" data-ct-del="local" data-ct-id="${cal.id}">${TRASH}</button></td>
|
||||||
</tr>`;
|
</tr>`;
|
||||||
rowCount++;
|
rowCount++;
|
||||||
if (owned && pub) {
|
if (cal.owned !== false && pub) {
|
||||||
rows += `<tr class="ct-dav-row"><td colspan="7">
|
rows += `<tr class="ct-dav-row"><td colspan="7">
|
||||||
<div class="ct-dav-box">
|
<div class="ct-dav-box">
|
||||||
<span class="ct-dav-label">${t('caldav_published_url')}</span>
|
<span class="ct-dav-label">${t('caldav_published_url')}</span>
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
// Increment APP_VERSION with every code change
|
// Increment APP_VERSION with every code change
|
||||||
export const APP_VERSION = 'v76';
|
export const APP_VERSION = 'v77';
|
||||||
|
|||||||
Reference in New Issue
Block a user