Merge pull request #102 from ulsklyc/fix/100
feat: add edit button for ICS subscriptions
This commit is contained in:
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "خاص",
|
"private": "خاص",
|
||||||
"shared": "مشترك"
|
"shared": "مشترك"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "تم تحديث الاشتراك."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "رقم الهاتف (اختياري)",
|
"memberPhoneLabel": "رقم الهاتف (اختياري)",
|
||||||
"memberEmailLabel": "البريد الإلكتروني (اختياري)",
|
"memberEmailLabel": "البريد الإلكتروني (اختياري)",
|
||||||
|
|||||||
@@ -757,7 +757,8 @@
|
|||||||
"empty": "Noch keine Abonnements.",
|
"empty": "Noch keine Abonnements.",
|
||||||
"addedToast": "Abonnement hinzugefügt.",
|
"addedToast": "Abonnement hinzugefügt.",
|
||||||
"syncedToast": "Abonnement synchronisiert.",
|
"syncedToast": "Abonnement synchronisiert.",
|
||||||
"deletedToast": "Abonnement gelöscht."
|
"deletedToast": "Abonnement gelöscht.",
|
||||||
|
"updatedToast": "Abonnement aktualisiert."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Telefonnummer (optional)",
|
"memberPhoneLabel": "Telefonnummer (optional)",
|
||||||
"memberEmailLabel": "E-Mail (optional)",
|
"memberEmailLabel": "E-Mail (optional)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "Ιδιωτικό",
|
"private": "Ιδιωτικό",
|
||||||
"shared": "Κοινόχρηστο"
|
"shared": "Κοινόχρηστο"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "Η συνδρομή ενημερώθηκε."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Αριθμός τηλεφώνου (προαιρετικό)",
|
"memberPhoneLabel": "Αριθμός τηλεφώνου (προαιρετικό)",
|
||||||
"memberEmailLabel": "Email (προαιρετικό)",
|
"memberEmailLabel": "Email (προαιρετικό)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "Private",
|
"private": "Private",
|
||||||
"shared": "Shared"
|
"shared": "Shared"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "Subscription updated."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Phone number (optional)",
|
"memberPhoneLabel": "Phone number (optional)",
|
||||||
"memberEmailLabel": "Email (optional)",
|
"memberEmailLabel": "Email (optional)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "Privado",
|
"private": "Privado",
|
||||||
"shared": "Compartido"
|
"shared": "Compartido"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "Suscripción actualizada."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Número de teléfono (opcional)",
|
"memberPhoneLabel": "Número de teléfono (opcional)",
|
||||||
"memberEmailLabel": "Correo electrónico (opcional)",
|
"memberEmailLabel": "Correo electrónico (opcional)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "Privé",
|
"private": "Privé",
|
||||||
"shared": "Partagé"
|
"shared": "Partagé"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "Abonnement mis à jour."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Numéro de téléphone (facultatif)",
|
"memberPhoneLabel": "Numéro de téléphone (facultatif)",
|
||||||
"memberEmailLabel": "E-mail (facultatif)",
|
"memberEmailLabel": "E-mail (facultatif)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "निजी",
|
"private": "निजी",
|
||||||
"shared": "साझा"
|
"shared": "साझा"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "सदस्यता अपडेट की गई।"
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "फ़ोन नंबर (वैकल्पिक)",
|
"memberPhoneLabel": "फ़ोन नंबर (वैकल्पिक)",
|
||||||
"memberEmailLabel": "ईमेल (वैकल्पिक)",
|
"memberEmailLabel": "ईमेल (वैकल्पिक)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "Privato",
|
"private": "Privato",
|
||||||
"shared": "Condiviso"
|
"shared": "Condiviso"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "Abbonamento aggiornato."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Numero di telefono (opzionale)",
|
"memberPhoneLabel": "Numero di telefono (opzionale)",
|
||||||
"memberEmailLabel": "E-mail (opzionale)",
|
"memberEmailLabel": "E-mail (opzionale)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "プライベート",
|
"private": "プライベート",
|
||||||
"shared": "共有"
|
"shared": "共有"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "サブスクリプションが更新されました。"
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "電話番号(任意)",
|
"memberPhoneLabel": "電話番号(任意)",
|
||||||
"memberEmailLabel": "メールアドレス(任意)",
|
"memberEmailLabel": "メールアドレス(任意)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "Privado",
|
"private": "Privado",
|
||||||
"shared": "Partilhado"
|
"shared": "Partilhado"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "Subscrição atualizada."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Telefone (opcional)",
|
"memberPhoneLabel": "Telefone (opcional)",
|
||||||
"memberEmailLabel": "E-mail (opcional)",
|
"memberEmailLabel": "E-mail (opcional)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "Личное",
|
"private": "Личное",
|
||||||
"shared": "Общее"
|
"shared": "Общее"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "Подписка обновлена."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Номер телефона (необязательно)",
|
"memberPhoneLabel": "Номер телефона (необязательно)",
|
||||||
"memberEmailLabel": "Электронная почта (необязательно)",
|
"memberEmailLabel": "Электронная почта (необязательно)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "Privat",
|
"private": "Privat",
|
||||||
"shared": "Delad"
|
"shared": "Delad"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "Prenumeration uppdaterad."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Telefonnummer (valfritt)",
|
"memberPhoneLabel": "Telefonnummer (valfritt)",
|
||||||
"memberEmailLabel": "E-post (valfritt)",
|
"memberEmailLabel": "E-post (valfritt)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "Özel",
|
"private": "Özel",
|
||||||
"shared": "Paylaşımlı"
|
"shared": "Paylaşımlı"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "Abonelik güncellendi."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Telefon numarası (isteğe bağlı)",
|
"memberPhoneLabel": "Telefon numarası (isteğe bağlı)",
|
||||||
"memberEmailLabel": "E-posta (isteğe bağlı)",
|
"memberEmailLabel": "E-posta (isteğe bağlı)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "Приватне",
|
"private": "Приватне",
|
||||||
"shared": "Спільне"
|
"shared": "Спільне"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "Підписку оновлено."
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "Номер телефону (необов'язково)",
|
"memberPhoneLabel": "Номер телефону (необов'язково)",
|
||||||
"memberEmailLabel": "Електронна пошта (необов'язково)",
|
"memberEmailLabel": "Електронна пошта (необов'язково)",
|
||||||
|
|||||||
@@ -732,7 +732,8 @@
|
|||||||
"badges": {
|
"badges": {
|
||||||
"private": "私人",
|
"private": "私人",
|
||||||
"shared": "共享"
|
"shared": "共享"
|
||||||
}
|
},
|
||||||
|
"updatedToast": "订阅已更新。"
|
||||||
},
|
},
|
||||||
"memberPhoneLabel": "电话号码(可选)",
|
"memberPhoneLabel": "电话号码(可选)",
|
||||||
"memberEmailLabel": "电子邮件(可选)",
|
"memberEmailLabel": "电子邮件(可选)",
|
||||||
|
|||||||
@@ -1644,6 +1644,19 @@ function renderIcsList(container, subs, user) {
|
|||||||
syncBtn.appendChild(syncIcon);
|
syncBtn.appendChild(syncIcon);
|
||||||
actions.appendChild(syncBtn);
|
actions.appendChild(syncBtn);
|
||||||
|
|
||||||
|
const editBtn = document.createElement('button');
|
||||||
|
editBtn.className = 'btn btn--icon btn--ghost';
|
||||||
|
editBtn.title = t('settings.ics.actions.edit');
|
||||||
|
editBtn.setAttribute('aria-label', t('settings.ics.actions.edit'));
|
||||||
|
editBtn.dataset.action = 'ics-edit';
|
||||||
|
editBtn.dataset.id = sub.id;
|
||||||
|
const editIcon = document.createElement('i');
|
||||||
|
editIcon.setAttribute('data-lucide', 'pencil');
|
||||||
|
editIcon.style.cssText = 'width:14px;height:14px';
|
||||||
|
editIcon.setAttribute('aria-hidden', 'true');
|
||||||
|
editBtn.appendChild(editIcon);
|
||||||
|
actions.appendChild(editBtn);
|
||||||
|
|
||||||
const delBtn = document.createElement('button');
|
const delBtn = document.createElement('button');
|
||||||
delBtn.className = 'btn btn--icon btn--danger-outline';
|
delBtn.className = 'btn btn--icon btn--danger-outline';
|
||||||
delBtn.title = t('settings.ics.actions.delete');
|
delBtn.title = t('settings.ics.actions.delete');
|
||||||
@@ -1756,6 +1769,63 @@ function bindIcsEvents(container, user, initialSubs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action === 'ics-edit') {
|
||||||
|
const sub = subs.find((s) => s.id === id);
|
||||||
|
if (!sub) return;
|
||||||
|
openModal({
|
||||||
|
title: t('settings.ics.actions.edit'),
|
||||||
|
size: 'sm',
|
||||||
|
content: `
|
||||||
|
<form id="ics-edit-form" class="settings-form">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="ics-edit-name">${t('settings.ics.form.name')}</label>
|
||||||
|
<input class="form-input" type="text" id="ics-edit-name" value="${esc(sub.name)}" required maxlength="100" />
|
||||||
|
</div>
|
||||||
|
<div class="settings-name-color-row">
|
||||||
|
<div class="form-group settings-color-field">
|
||||||
|
<label class="form-label" for="ics-edit-color">${t('settings.ics.form.color')}</label>
|
||||||
|
<input class="settings-color-button" type="color" id="ics-edit-color" value="${esc(sub.color || '#3b82f6')}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="display:flex;align-items:center;gap:var(--space-2);padding-top:var(--space-5)">
|
||||||
|
<input type="checkbox" id="ics-edit-shared" ${sub.shared ? 'checked' : ''} />
|
||||||
|
<label class="form-label" for="ics-edit-shared" style="margin:0">${t('settings.ics.form.shared')}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="ics-edit-error" class="form-error" hidden></div>
|
||||||
|
<div class="settings-form-actions">
|
||||||
|
<button type="button" class="btn btn--secondary" id="ics-edit-cancel">${t('common.cancel')}</button>
|
||||||
|
<button type="submit" class="btn btn--primary">${t('settings.ics.actions.save')}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
`,
|
||||||
|
onSave(panel) {
|
||||||
|
panel.querySelector('#ics-edit-cancel')?.addEventListener('click', () => closeModal());
|
||||||
|
panel.querySelector('#ics-edit-form')?.addEventListener('submit', async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const submitBtn = panel.querySelector('[type=submit]');
|
||||||
|
const errEl = panel.querySelector('#ics-edit-error');
|
||||||
|
const name = panel.querySelector('#ics-edit-name').value.trim();
|
||||||
|
const color = panel.querySelector('#ics-edit-color').value;
|
||||||
|
const shared = panel.querySelector('#ics-edit-shared').checked ? 1 : 0;
|
||||||
|
errEl.hidden = true;
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
try {
|
||||||
|
const res = await api.patch(`/calendar/subscriptions/${id}`, { name, color, shared });
|
||||||
|
const idx = subs.findIndex((s) => s.id === id);
|
||||||
|
if (idx >= 0) subs[idx] = res.data;
|
||||||
|
renderIcsList(container, subs, user);
|
||||||
|
window.oikos?.showToast(t('settings.ics.updatedToast'), 'success');
|
||||||
|
closeModal({ force: true });
|
||||||
|
} catch (err) {
|
||||||
|
errEl.textContent = err.message ?? t('common.errorGeneric');
|
||||||
|
errEl.hidden = false;
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (action === 'ics-delete') {
|
if (action === 'ics-delete') {
|
||||||
const name = target.dataset.name;
|
const name = target.dataset.name;
|
||||||
if (!await confirmModal(t('settings.ics.confirm_delete'), { danger: true, confirmLabel: t('common.delete') })) return;
|
if (!await confirmModal(t('settings.ics.confirm_delete'), { danger: true, confirmLabel: t('common.delete') })) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user