fix: add missing submit button to CalDAV and CardDAV add account modals (#130)

The onSave callback was being executed immediately on modal open (its
purpose is to wire up event listeners), causing the required-fields
error to appear instantly and leaving the form with no way to submit.

Both forms now include modal-actions buttons in the content HTML, and
onSave correctly attaches a submit event listener instead of running
validation directly.

Fixes #128

Co-authored-by: Ulas Kalayci <ulas.kalayci@googlemail.com>
This commit is contained in:
ulsklyc
2026-05-06 10:37:35 +02:00
committed by GitHub
parent 8dfd8e4fbf
commit 1629356a6d
+67 -46
View File
@@ -1545,36 +1545,46 @@ function bindEvents(container, user, users, categories, icsSubscriptions, apiTok
<small class="form-hint">${t('settings.caldavPasswordHint')}</small> <small class="form-hint">${t('settings.caldavPasswordHint')}</small>
</div> </div>
<div id="caldav-add-error" class="form-error" hidden></div> <div id="caldav-add-error" class="form-error" hidden></div>
<div class="modal-actions">
<button type="button" class="btn btn--ghost" id="caldav-add-cancel">${t('common.cancel')}</button>
<button type="submit" class="btn btn--primary">${t('common.save')}</button>
</div>
</form> </form>
`, `,
onSave: async (panel) => { onSave: (panel) => {
const form = panel.querySelector('#caldav-add-form'); const form = panel.querySelector('#caldav-add-form');
const errorEl = panel.querySelector('#caldav-add-error'); const errorEl = panel.querySelector('#caldav-add-error');
errorEl.hidden = true;
const name = panel.querySelector('#caldav-name').value.trim(); panel.querySelector('#caldav-add-cancel')?.addEventListener('click', () => closeModal({ force: true }));
const caldavUrl = panel.querySelector('#caldav-url').value.trim();
const username = panel.querySelector('#caldav-username').value.trim();
const password = panel.querySelector('#caldav-password').value;
if (!name || !caldavUrl || !username || !password) { form.addEventListener('submit', async (e) => {
showError(errorEl, t('common.requiredFields')); e.preventDefault();
return; errorEl.hidden = true;
}
try { const name = panel.querySelector('#caldav-name').value.trim();
await api.post('/calendar/caldav/accounts', { const caldavUrl = panel.querySelector('#caldav-url').value.trim();
name, const username = panel.querySelector('#caldav-username').value.trim();
caldavUrl, const password = panel.querySelector('#caldav-password').value;
username,
password, if (!name || !caldavUrl || !username || !password) {
}); showError(errorEl, t('common.requiredFields'));
closeModal({ force: true }); return;
window.oikos?.showToast(t('settings.caldavAccountAdded'), 'success'); }
await loadCalDAVAccounts(container, user);
} catch (err) { try {
showError(errorEl, err.message); await api.post('/calendar/caldav/accounts', {
} name,
caldavUrl,
username,
password,
});
closeModal({ force: true });
window.oikos?.showToast(t('settings.caldavAccountAdded'), 'success');
await loadCalDAVAccounts(container, user);
} catch (err) {
showError(errorEl, err.message);
}
});
}, },
}); });
}); });
@@ -1610,35 +1620,46 @@ function bindEvents(container, user, users, categories, icsSubscriptions, apiTok
<small class="form-hint">${t('settings.cardavPasswordHint')}</small> <small class="form-hint">${t('settings.cardavPasswordHint')}</small>
</div> </div>
<div id="cardav-add-error" class="form-error" hidden></div> <div id="cardav-add-error" class="form-error" hidden></div>
<div class="modal-actions">
<button type="button" class="btn btn--ghost" id="cardav-add-cancel">${t('common.cancel')}</button>
<button type="submit" class="btn btn--primary">${t('common.save')}</button>
</div>
</form> </form>
`, `,
onSave: async (panel) => { onSave: (panel) => {
const form = panel.querySelector('#cardav-add-form');
const errorEl = panel.querySelector('#cardav-add-error'); const errorEl = panel.querySelector('#cardav-add-error');
errorEl.hidden = true;
const name = panel.querySelector('#cardav-name').value.trim(); panel.querySelector('#cardav-add-cancel')?.addEventListener('click', () => closeModal({ force: true }));
const cardavUrl = panel.querySelector('#cardav-url').value.trim();
const username = panel.querySelector('#cardav-username').value.trim();
const password = panel.querySelector('#cardav-password').value;
if (!name || !cardavUrl || !username || !password) { form.addEventListener('submit', async (e) => {
showError(errorEl, t('common.allFieldsRequired')); e.preventDefault();
return; errorEl.hidden = true;
}
try { const name = panel.querySelector('#cardav-name').value.trim();
await api.post('/contacts/cardav/accounts', { const cardavUrl = panel.querySelector('#cardav-url').value.trim();
name, const username = panel.querySelector('#cardav-username').value.trim();
cardavUrl, const password = panel.querySelector('#cardav-password').value;
username,
password, if (!name || !cardavUrl || !username || !password) {
}); showError(errorEl, t('common.allFieldsRequired'));
closeModal({ force: true }); return;
window.oikos?.showToast(t('settings.cardavAccountAdded'), 'success'); }
await loadCardDAVAccounts(container, user);
} catch (err) { try {
showError(errorEl, err.message); await api.post('/contacts/cardav/accounts', {
} name,
cardavUrl,
username,
password,
});
closeModal({ force: true });
window.oikos?.showToast(t('settings.cardavAccountAdded'), 'success');
await loadCardDAVAccounts(container, user);
} catch (err) {
showError(errorEl, err.message);
}
});
}, },
}); });
}); });