diff --git a/static/js/core/types.js b/static/js/core/types.js index ef006901..5092ff06 100644 --- a/static/js/core/types.js +++ b/static/js/core/types.js @@ -149,7 +149,7 @@ * * @typedef {Object} User * @property {string} id - * @property {string} username + * @property {string} [username] Optional handle (PR 16); claim-once via /api/auth/me/profile (PR 24). Omitted from JSON when null. * @property {string} email * @property {string} role * @property {number} storage_quota_bytes @@ -162,8 +162,9 @@ * @property {string|null} [image] Avatar URL or data URI * @property {boolean} can_edit_image False for OIDC-only users * @property {boolean} is_external True for magic-link / OIDC-only / OCM recipients - * @property {string} [given_name] OIDC `given_name` claim, when set - * @property {string} [family_name] OIDC `family_name` claim, when set + * @property {string} [given_name] First/given name; set at OIDC JIT or via PATCH /api/auth/me/profile (PR 24) + * @property {string} [family_name] Last/family name; set at OIDC JIT or via PATCH /api/auth/me/profile (PR 24) + * @property {string} [email_verified_at] ISO 8601 timestamp of the first proof-of-email-control (PR 23). Omitted when unverified. */ /** diff --git a/static/js/views/profile/profile.js b/static/js/views/profile/profile.js index 28fe3796..312dc51e 100644 --- a/static/js/views/profile/profile.js +++ b/static/js/views/profile/profile.js @@ -336,6 +336,8 @@ async function init() { document.getElementById('password-section').classList.add('hidden'); } + _renderProfileEdit(user); + loadAppPasswords(); try { @@ -597,6 +599,137 @@ async function revokeAppPassword(id, label) { } } +/** + * Render the Edit Profile card based on the current user. + * + * For OIDC users: the entire form is hidden and a single alert tells + * them their profile is managed at the IdP. For local users: the form + * is populated from the current values, and the username input is + * disabled when a handle is already claimed (PR 24's claim-once + * policy). + * + * @param {import('../../core/types.js').User} user + */ +function _renderProfileEdit(user) { + const oidcNote = document.getElementById('profile-edit-oidc-note'); + const form = document.getElementById('profile-edit-form'); + if (!oidcNote || !form) return; + + const isOidc = user.auth_provider && user.auth_provider !== 'local'; + if (isOidc) { + oidcNote.classList.remove('hidden'); + form.classList.add('hidden'); + return; + } + + oidcNote.classList.add('hidden'); + form.classList.remove('hidden'); + + const usernameInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-username')); + const usernameHint = document.getElementById('profile-edit-username-hint'); + const givenInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-given-name')); + const familyInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-family-name')); + + if (user.username) { + usernameInput.value = user.username; + usernameInput.disabled = true; + if (usernameHint) { + usernameHint.textContent = i18n.t('profile.username_already_claimed'); + } + } else { + usernameInput.value = ''; + usernameInput.disabled = false; + if (usernameHint) { + usernameHint.textContent = i18n.t('profile.username_claim_hint'); + } + } + givenInput.value = user.given_name || ''; + familyInput.value = user.family_name || ''; +} + +/** + * Submit the profile edit form. Only sends fields the user can change: + * - Username only if not already claimed (input wasn't disabled). + * - Given/family names only when their value differs from the + * current (avoids 400-rejecting an empty string the user never + * touched). + * + * @param {Event} e + */ +async function submitProfile(e) { + e.preventDefault(); + + const statusEl = document.getElementById('profile-edit-status'); + const btn = /** @type {HTMLButtonElement} */ (document.getElementById('profile-edit-submit')); + const usernameInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-username')); + const givenInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-given-name')); + const familyInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-family-name')); + + /** @type {{ username?: string, given_name?: string, family_name?: string }} */ + const body = {}; + if (!usernameInput.disabled && usernameInput.value.trim()) { + body.username = usernameInput.value.trim(); + } + const given = givenInput.value.trim(); + if (given) body.given_name = given; + const family = familyInput.value.trim(); + if (family) body.family_name = family; + + if (Object.keys(body).length === 0) { + statusEl.innerHTML = `
${escapeHtml(i18n.t('profile.profile_no_changes'))}
`; + return false; + } + + btn.disabled = true; + btn.innerHTML = ` ${escapeHtml(i18n.t('profile.updating'))}`; + + try { + const resp = await fetch(`${API}/auth/me/profile`, { + method: 'PATCH', + headers: headers(), + credentials: 'same-origin', + body: JSON.stringify(body) + }); + + if (resp.ok) { + /** @type {import('../../core/types.js').User} */ + const updated = await resp.json(); + _renderProfileEdit(updated); + // Also refresh the read-only "Account Details" username field. + const detailUsername = document.getElementById('p-detail-username'); + if (detailUsername) detailUsername.textContent = updated.username || '—'; + const topUsername = document.getElementById('p-username'); + if (topUsername && updated.username) topUsername.textContent = updated.username; + statusEl.innerHTML = `
${escapeHtml(i18n.t('profile.profile_saved'))}
`; + } else if (resp.status === 409) { + const err = await resp.json().catch(() => ({})); + // Distinguish "username taken" from "username immutable" using the + // human-readable message — both are 409. Server audit has the + // structured `reason` field; the JSON body just carries `message`. + const msg = (err.message || '').toLowerCase(); + const key = msg.includes('already claimed') ? 'profile.username_immutable_error' : 'profile.username_taken_error'; + statusEl.innerHTML = `
${escapeHtml(i18n.t(key))}
`; + } else if (resp.status === 403) { + statusEl.innerHTML = `
${escapeHtml(i18n.t('profile.edit_oidc_managed'))}
`; + } else { + const err = await resp.json().catch(() => ({})); + statusEl.innerHTML = + '
' + + escapeHtml(err.message || i18n.t('profile.profile_save_failed')) + + '
'; + } + } catch (err) { + statusEl.innerHTML = + '
' + + escapeHtml(i18n.t('profile.error_network', { message: /** @type {Error} */ (err).message })) + + '
'; + } + + btn.disabled = false; + btn.innerHTML = ` ${escapeHtml(i18n.t('profile.save_profile'))}`; + return false; +} + /** @param {string} str */ function escapeHtml(str) { var div = document.createElement('div'); @@ -608,6 +741,7 @@ init(); /* Wire up event handlers (replaces inline onclick/onsubmit) */ document.getElementById('password-form').addEventListener('submit', changePassword); +document.getElementById('profile-edit-form')?.addEventListener('submit', submitProfile); document.getElementById('app-pw-generate').addEventListener('click', createAppPassword); document.getElementById('app-pw-copy-btn').addEventListener('click', copyAppPassword); document.getElementById('app-pw-auto-toggle').addEventListener('click', toggleAutoPasswords); diff --git a/static/locales/ar.json b/static/locales/ar.json index c3b7dc09..b08f05b4 100644 --- a/static/locales/ar.json +++ b/static/locales/ar.json @@ -703,6 +703,18 @@ "minutes_ago": "منذ {{n}} دقيقة", "hours_ago": "منذ {{n}} ساعة", "days_ago": "منذ {{n}} يوم", + "edit_profile": "تعديل الملف الشخصي", + "edit_oidc_managed": "لتغيير معلوماتك (الاسم، الاسم الأول، صورة الملف الشخصي، …)، يرجى تحديثها لدى مزود الهوية. ستظهر تغييراتك عند تسجيل الدخول التالي.", + "username_claim_hint": "2-64 حرفًا، أحرف / أرقام / نقطة / شرطة / شرطة سفلية. بمجرد الاختيار، لا يمكن تغيير اسم المستخدم (عملاء DAV/NextCloud يعتمدون عليه).", + "username_already_claimed": "اسم المستخدم محدد ولا يمكن تغييره (عملاء DAV/NextCloud يعتمدون عليه).", + "given_name": "الاسم الأول", + "family_name": "اسم العائلة", + "save_profile": "حفظ التغييرات", + "profile_saved": "تم تحديث الملف الشخصي", + "profile_no_changes": "لا توجد تغييرات لحفظها.", + "profile_save_failed": "فشل الحفظ", + "username_taken_error": "اسم المستخدم هذا مستخدم بالفعل.", + "username_immutable_error": "اسم المستخدم الخاص بك محدد بالفعل ولا يمكن تغييره هنا. اتصل بالمسؤول إذا كنت بحاجة إلى إعادة التسمية.", "change_password": "تغيير كلمة المرور", "current_password": "كلمة المرور الحالية", "new_password": "كلمة المرور الجديدة", diff --git a/static/locales/de.json b/static/locales/de.json index f7c16a7a..8b438032 100644 --- a/static/locales/de.json +++ b/static/locales/de.json @@ -703,6 +703,18 @@ "minutes_ago": "vor {{n}} Min", "hours_ago": "vor {{n}} Std", "days_ago": "vor {{n}} Tagen", + "edit_profile": "Profil bearbeiten", + "edit_oidc_managed": "Um Ihre Informationen (Name, Vorname, Profilbild, …) zu ändern, aktualisieren Sie sie bitte bei Ihrem Identity-Provider. Ihre Änderungen erscheinen bei der nächsten Anmeldung.", + "username_claim_hint": "2–64 Zeichen, Buchstaben / Ziffern / Punkt / Bindestrich / Unterstrich. Nach der Wahl kann der Benutzername nicht mehr geändert werden (DAV/NextCloud-Clients hängen davon ab).", + "username_already_claimed": "Benutzername ist gesetzt und kann nicht geändert werden (DAV/NextCloud-Clients hängen davon ab).", + "given_name": "Vorname", + "family_name": "Nachname", + "save_profile": "Änderungen speichern", + "profile_saved": "Profil aktualisiert", + "profile_no_changes": "Keine Änderungen zu speichern.", + "profile_save_failed": "Speichern fehlgeschlagen", + "username_taken_error": "Dieser Benutzername ist bereits vergeben.", + "username_immutable_error": "Ihr Benutzername ist bereits gesetzt und kann hier nicht geändert werden. Wenden Sie sich an einen Administrator, wenn Sie umbenennen möchten.", "change_password": "Passwort ändern", "current_password": "Aktuelles Passwort", "new_password": "Neues Passwort", diff --git a/static/locales/en.json b/static/locales/en.json index 2754eb01..0010c459 100644 --- a/static/locales/en.json +++ b/static/locales/en.json @@ -720,6 +720,18 @@ "minutes_ago": "{{n}} min ago", "hours_ago": "{{n}}h ago", "days_ago": "{{n}} days ago", + "edit_profile": "Edit Profile", + "edit_oidc_managed": "To change your information (name, first name, profile picture, …), please update it at your identity provider. Your changes will appear on your next sign-in.", + "username_claim_hint": "2–64 characters, letters/digits/dot/dash/underscore. Once chosen, the username can't be changed (DAV/NextCloud clients depend on it).", + "username_already_claimed": "Username is set and can't be changed (DAV/NextCloud clients depend on it).", + "given_name": "First name", + "family_name": "Last name", + "save_profile": "Save changes", + "profile_saved": "Profile updated", + "profile_no_changes": "No changes to save.", + "profile_save_failed": "Save failed", + "username_taken_error": "That username is already taken.", + "username_immutable_error": "Your username is already set and can't be changed here. Contact an administrator if you need a rename.", "change_password": "Change Password", "current_password": "Current Password", "new_password": "New Password", diff --git a/static/locales/es.json b/static/locales/es.json index a9ea765a..df412c6e 100644 --- a/static/locales/es.json +++ b/static/locales/es.json @@ -703,6 +703,18 @@ "minutes_ago": "hace {{n}} min", "hours_ago": "hace {{n}}h", "days_ago": "hace {{n}} días", + "edit_profile": "Editar perfil", + "edit_oidc_managed": "Para cambiar tu información (nombre, apellidos, foto de perfil, …), actualízala en tu proveedor de identidad. Los cambios se aplicarán en tu próximo inicio de sesión.", + "username_claim_hint": "Entre 2 y 64 caracteres, letras / dígitos / punto / guion / subrayado. Una vez elegido, el nombre de usuario no se puede cambiar (los clientes DAV/NextCloud dependen de él).", + "username_already_claimed": "Nombre de usuario fijado y no modificable (los clientes DAV/NextCloud dependen de él).", + "given_name": "Nombre", + "family_name": "Apellidos", + "save_profile": "Guardar cambios", + "profile_saved": "Perfil actualizado", + "profile_no_changes": "Sin cambios que guardar.", + "profile_save_failed": "Error al guardar", + "username_taken_error": "Ese nombre de usuario ya está en uso.", + "username_immutable_error": "Tu nombre de usuario ya está fijado y no se puede cambiar aquí. Contacta con un administrador si necesitas renombrarlo.", "change_password": "Cambiar Contraseña", "current_password": "Contraseña Actual", "new_password": "Nueva Contraseña", diff --git a/static/locales/fa.json b/static/locales/fa.json index bb640cfb..3936e963 100644 --- a/static/locales/fa.json +++ b/static/locales/fa.json @@ -686,6 +686,18 @@ "minutes_ago": "{{n}} دقیقه پیش", "hours_ago": "{{n}} ساعت پیش", "days_ago": "{{n}} روز پیش", + "edit_profile": "ویرایش نمایه", + "edit_oidc_managed": "برای تغییر اطلاعات خود (نام، نام خانوادگی، عکس نمایه، …)، لطفاً آن‌ها را در ارائه‌دهنده هویت خود به‌روز کنید. تغییرات شما در ورود بعدی ظاهر خواهد شد.", + "username_claim_hint": "۲ تا ۶۴ کاراکتر، حروف / ارقام / نقطه / خط تیره / زیرخط. پس از انتخاب، نام کاربری قابل تغییر نیست (کلاینت‌های DAV/NextCloud به آن وابسته‌اند).", + "username_already_claimed": "نام کاربری تنظیم شده و قابل تغییر نیست (کلاینت‌های DAV/NextCloud به آن وابسته‌اند).", + "given_name": "نام", + "family_name": "نام خانوادگی", + "save_profile": "ذخیره تغییرات", + "profile_saved": "نمایه به‌روز شد", + "profile_no_changes": "تغییری برای ذخیره وجود ندارد.", + "profile_save_failed": "ذخیره ناموفق بود", + "username_taken_error": "این نام کاربری قبلاً گرفته شده است.", + "username_immutable_error": "نام کاربری شما قبلاً تنظیم شده و در اینجا قابل تغییر نیست. در صورت نیاز به تغییر نام، با مدیر تماس بگیرید.", "change_password": "تغییر رمز عبور", "current_password": "رمز فعلی", "new_password": "رمز جدید", diff --git a/static/locales/fr.json b/static/locales/fr.json index 23e552b6..010b5054 100644 --- a/static/locales/fr.json +++ b/static/locales/fr.json @@ -720,6 +720,18 @@ "minutes_ago": "il y a {{n}} min", "hours_ago": "il y a {{n}}h", "days_ago": "il y a {{n}} jours", + "edit_profile": "Modifier le profil", + "edit_oidc_managed": "Pour modifier vos informations (nom, prénom, photo de profil, …), veuillez les mettre à jour chez votre fournisseur d'identité. Vos changements apparaîtront à votre prochaine connexion.", + "username_claim_hint": "2 à 64 caractères, lettres / chiffres / point / tiret / souligné. Une fois choisi, le nom d'utilisateur ne peut plus être modifié (les clients DAV/NextCloud en dépendent).", + "username_already_claimed": "Nom d'utilisateur fixé et non modifiable (les clients DAV/NextCloud en dépendent).", + "given_name": "Prénom", + "family_name": "Nom", + "save_profile": "Enregistrer", + "profile_saved": "Profil mis à jour", + "profile_no_changes": "Aucun changement à enregistrer.", + "profile_save_failed": "Échec de l'enregistrement", + "username_taken_error": "Ce nom d'utilisateur est déjà pris.", + "username_immutable_error": "Votre nom d'utilisateur est déjà défini et ne peut plus être modifié ici. Contactez un administrateur si vous souhaitez le renommer.", "change_password": "Changer le mot de passe", "current_password": "Mot de passe actuel", "new_password": "Nouveau mot de passe", diff --git a/static/locales/hi.json b/static/locales/hi.json index 546e3666..9801d852 100644 --- a/static/locales/hi.json +++ b/static/locales/hi.json @@ -703,6 +703,18 @@ "minutes_ago": "{{n}} मिनट पहले", "hours_ago": "{{n}} घंटे पहले", "days_ago": "{{n}} दिन पहले", + "edit_profile": "प्रोफ़ाइल संपादित करें", + "edit_oidc_managed": "अपनी जानकारी (नाम, प्रथम नाम, प्रोफ़ाइल चित्र, …) बदलने के लिए, कृपया अपने पहचान प्रदाता पर इसे अद्यतन करें। आपके परिवर्तन अगले साइन-इन पर दिखाई देंगे।", + "username_claim_hint": "2–64 अक्षर, अक्षर / अंक / डॉट / डैश / अंडरस्कोर। एक बार चुनने के बाद, उपयोगकर्ता नाम नहीं बदला जा सकता (DAV/NextCloud क्लाइंट इस पर निर्भर करते हैं)।", + "username_already_claimed": "उपयोगकर्ता नाम सेट है और बदला नहीं जा सकता (DAV/NextCloud क्लाइंट इस पर निर्भर करते हैं)।", + "given_name": "प्रथम नाम", + "family_name": "अंतिम नाम", + "save_profile": "परिवर्तन सहेजें", + "profile_saved": "प्रोफ़ाइल अद्यतन की गई", + "profile_no_changes": "सहेजने के लिए कोई परिवर्तन नहीं।", + "profile_save_failed": "सहेजना विफल", + "username_taken_error": "यह उपयोगकर्ता नाम पहले से उपयोग में है।", + "username_immutable_error": "आपका उपयोगकर्ता नाम पहले से सेट है और यहाँ नहीं बदला जा सकता। यदि आपको नाम बदलने की आवश्यकता है तो किसी व्यवस्थापक से संपर्क करें।", "change_password": "पासवर्ड बदलें", "current_password": "वर्तमान पासवर्ड", "new_password": "नया पासवर्ड", diff --git a/static/locales/it.json b/static/locales/it.json index 7e06c09d..35e67951 100644 --- a/static/locales/it.json +++ b/static/locales/it.json @@ -703,6 +703,18 @@ "minutes_ago": "{{n}} min fa", "hours_ago": "{{n}}h fa", "days_ago": "{{n}} giorni fa", + "edit_profile": "Modifica profilo", + "edit_oidc_managed": "Per modificare le tue informazioni (nome, cognome, foto profilo, …), aggiornale presso il tuo identity provider. Le modifiche compariranno al prossimo accesso.", + "username_claim_hint": "Da 2 a 64 caratteri, lettere / cifre / punto / trattino / sottolineatura. Una volta scelto, il nome utente non può essere modificato (i client DAV/NextCloud dipendono da esso).", + "username_already_claimed": "Nome utente impostato e non modificabile (i client DAV/NextCloud dipendono da esso).", + "given_name": "Nome", + "family_name": "Cognome", + "save_profile": "Salva modifiche", + "profile_saved": "Profilo aggiornato", + "profile_no_changes": "Nessuna modifica da salvare.", + "profile_save_failed": "Salvataggio non riuscito", + "username_taken_error": "Questo nome utente è già in uso.", + "username_immutable_error": "Il tuo nome utente è già impostato e non può essere cambiato qui. Contatta un amministratore se desideri rinominarlo.", "change_password": "Cambia Password", "current_password": "Password Attuale", "new_password": "Nuova Password", diff --git a/static/locales/ja.json b/static/locales/ja.json index cec41168..dc04aa61 100644 --- a/static/locales/ja.json +++ b/static/locales/ja.json @@ -703,6 +703,18 @@ "minutes_ago": "{{n}}分前", "hours_ago": "{{n}}時間前", "days_ago": "{{n}}日前", + "edit_profile": "プロフィールを編集", + "edit_oidc_managed": "情報(姓、名、プロフィール写真など)を変更するには、IDプロバイダーで更新してください。次回サインイン時に反映されます。", + "username_claim_hint": "2〜64文字、英数字 / ドット / ハイフン / アンダースコア。一度選択すると、ユーザー名は変更できません(DAV/NextCloudクライアントが依存します)。", + "username_already_claimed": "ユーザー名は設定済みで変更できません(DAV/NextCloudクライアントが依存します)。", + "given_name": "名", + "family_name": "姓", + "save_profile": "変更を保存", + "profile_saved": "プロフィールを更新しました", + "profile_no_changes": "保存する変更はありません。", + "profile_save_failed": "保存に失敗しました", + "username_taken_error": "このユーザー名はすでに使用されています。", + "username_immutable_error": "ユーザー名はすでに設定されており、ここでは変更できません。名前を変更したい場合は管理者にお問い合わせください。", "change_password": "パスワード変更", "current_password": "現在のパスワード", "new_password": "新しいパスワード", diff --git a/static/locales/ko.json b/static/locales/ko.json index f6b5250a..9a316b6b 100644 --- a/static/locales/ko.json +++ b/static/locales/ko.json @@ -703,6 +703,18 @@ "minutes_ago": "{{n}}분 전", "hours_ago": "{{n}}시간 전", "days_ago": "{{n}}일 전", + "edit_profile": "프로필 편집", + "edit_oidc_managed": "정보(이름, 성, 프로필 사진 등)를 변경하려면 ID 공급자에서 업데이트하세요. 변경 사항은 다음 로그인 시 반영됩니다.", + "username_claim_hint": "2~64자, 영문자 / 숫자 / 점 / 하이픈 / 밑줄. 선택한 후에는 사용자 이름을 변경할 수 없습니다(DAV/NextCloud 클라이언트가 이에 의존합니다).", + "username_already_claimed": "사용자 이름이 설정되어 있어 변경할 수 없습니다(DAV/NextCloud 클라이언트가 이에 의존합니다).", + "given_name": "이름", + "family_name": "성", + "save_profile": "변경 사항 저장", + "profile_saved": "프로필이 업데이트되었습니다", + "profile_no_changes": "저장할 변경 사항이 없습니다.", + "profile_save_failed": "저장 실패", + "username_taken_error": "이미 사용 중인 사용자 이름입니다.", + "username_immutable_error": "사용자 이름이 이미 설정되어 있어 여기서 변경할 수 없습니다. 이름을 변경하려면 관리자에게 문의하세요.", "change_password": "비밀번호 변경", "current_password": "현재 비밀번호", "new_password": "새 비밀번호", diff --git a/static/locales/nl.json b/static/locales/nl.json index 1926d174..ea05f347 100644 --- a/static/locales/nl.json +++ b/static/locales/nl.json @@ -703,6 +703,18 @@ "minutes_ago": "{{n}} min geleden", "hours_ago": "{{n}}u geleden", "days_ago": "{{n}} dagen geleden", + "edit_profile": "Profiel bewerken", + "edit_oidc_managed": "Om uw gegevens (naam, voornaam, profielfoto, …) te wijzigen, werk ze bij bij uw identity provider. De wijzigingen verschijnen bij uw volgende aanmelding.", + "username_claim_hint": "2–64 tekens, letters / cijfers / punt / streepje / underscore. Eenmaal gekozen kan de gebruikersnaam niet meer worden gewijzigd (DAV/NextCloud-clients zijn ervan afhankelijk).", + "username_already_claimed": "Gebruikersnaam ingesteld en niet wijzigbaar (DAV/NextCloud-clients zijn ervan afhankelijk).", + "given_name": "Voornaam", + "family_name": "Achternaam", + "save_profile": "Wijzigingen opslaan", + "profile_saved": "Profiel bijgewerkt", + "profile_no_changes": "Geen wijzigingen om op te slaan.", + "profile_save_failed": "Opslaan mislukt", + "username_taken_error": "Die gebruikersnaam is al in gebruik.", + "username_immutable_error": "Uw gebruikersnaam is al ingesteld en kan hier niet worden gewijzigd. Neem contact op met een beheerder als u wilt hernoemen.", "change_password": "Wachtwoord wijzigen", "current_password": "Huidig wachtwoord", "new_password": "Nieuw wachtwoord", diff --git a/static/locales/pl.json b/static/locales/pl.json index e9164225..9306477b 100644 --- a/static/locales/pl.json +++ b/static/locales/pl.json @@ -703,6 +703,18 @@ "minutes_ago": "{{n}} min temu", "hours_ago": "{{n}} godz. temu", "days_ago": "{{n}} dni temu", + "edit_profile": "Edytuj profil", + "edit_oidc_managed": "Aby zmienić swoje dane (nazwisko, imię, zdjęcie profilowe, …), zaktualizuj je u swojego dostawcy tożsamości. Twoje zmiany pojawią się przy następnym logowaniu.", + "username_claim_hint": "2–64 znaki, litery / cyfry / kropka / myślnik / podkreślenie. Po wybraniu nazwy użytkownika nie można jej zmienić (klienty DAV/NextCloud są od niej zależne).", + "username_already_claimed": "Nazwa użytkownika jest ustawiona i nie może być zmieniona (klienty DAV/NextCloud są od niej zależne).", + "given_name": "Imię", + "family_name": "Nazwisko", + "save_profile": "Zapisz zmiany", + "profile_saved": "Profil zaktualizowany", + "profile_no_changes": "Brak zmian do zapisania.", + "profile_save_failed": "Zapis nie powiódł się", + "username_taken_error": "Ta nazwa użytkownika jest już zajęta.", + "username_immutable_error": "Twoja nazwa użytkownika jest już ustawiona i nie można jej tutaj zmienić. Skontaktuj się z administratorem, jeśli chcesz ją zmienić.", "change_password": "Zmień hasło", "current_password": "Bieżące hasło", "new_password": "Nowe hasło", diff --git a/static/locales/pt.json b/static/locales/pt.json index db3175bb..0fb50174 100644 --- a/static/locales/pt.json +++ b/static/locales/pt.json @@ -703,6 +703,18 @@ "minutes_ago": "{{n}} min atrás", "hours_ago": "{{n}}h atrás", "days_ago": "{{n}} dias atrás", + "edit_profile": "Editar perfil", + "edit_oidc_managed": "Para alterar suas informações (nome, sobrenome, foto de perfil, …), atualize-as no seu provedor de identidade. As mudanças aparecerão no próximo login.", + "username_claim_hint": "De 2 a 64 caracteres, letras / dígitos / ponto / hífen / sublinhado. Uma vez escolhido, o nome de usuário não pode ser alterado (clientes DAV/NextCloud dependem dele).", + "username_already_claimed": "Nome de usuário definido e não pode ser alterado (clientes DAV/NextCloud dependem dele).", + "given_name": "Nome", + "family_name": "Sobrenome", + "save_profile": "Salvar alterações", + "profile_saved": "Perfil atualizado", + "profile_no_changes": "Sem alterações para salvar.", + "profile_save_failed": "Falha ao salvar", + "username_taken_error": "Este nome de usuário já está em uso.", + "username_immutable_error": "Seu nome de usuário já está definido e não pode ser alterado aqui. Contate um administrador se desejar renomeá-lo.", "change_password": "Alterar Senha", "current_password": "Senha Atual", "new_password": "Nova Senha", diff --git a/static/locales/ru.json b/static/locales/ru.json index cabd5af2..7c45a5d4 100644 --- a/static/locales/ru.json +++ b/static/locales/ru.json @@ -703,6 +703,18 @@ "minutes_ago": "{{n}} мин назад", "hours_ago": "{{n}} ч назад", "days_ago": "{{n}} дн назад", + "edit_profile": "Редактировать профиль", + "edit_oidc_managed": "Чтобы изменить ваши данные (имя, фамилию, фотографию профиля, …), обновите их у вашего провайдера идентификации. Изменения появятся при следующем входе.", + "username_claim_hint": "2–64 символа, буквы / цифры / точка / дефис / подчёркивание. После выбора имя пользователя нельзя изменить (клиенты DAV/NextCloud зависят от него).", + "username_already_claimed": "Имя пользователя установлено и не может быть изменено (клиенты DAV/NextCloud зависят от него).", + "given_name": "Имя", + "family_name": "Фамилия", + "save_profile": "Сохранить изменения", + "profile_saved": "Профиль обновлён", + "profile_no_changes": "Нет изменений для сохранения.", + "profile_save_failed": "Не удалось сохранить", + "username_taken_error": "Это имя пользователя уже занято.", + "username_immutable_error": "Ваше имя пользователя уже установлено и не может быть изменено здесь. Свяжитесь с администратором, если нужно переименовать.", "change_password": "Изменить пароль", "current_password": "Текущий пароль", "new_password": "Новый пароль", diff --git a/static/locales/zh-TW.json b/static/locales/zh-TW.json index efe99260..997840ca 100644 --- a/static/locales/zh-TW.json +++ b/static/locales/zh-TW.json @@ -686,6 +686,18 @@ "minutes_ago": "{{n}}分鐘前", "hours_ago": "{{n}}小時前", "days_ago": "{{n}}天前", + "edit_profile": "編輯個人資料", + "edit_oidc_managed": "要更改您的資訊(姓名、名字、頭像等),請前往您的身分提供者更新。變更將在您下次登入時顯示。", + "username_claim_hint": "2-64 個字元,字母 / 數字 / 點 / 短橫線 / 底線。一旦選定,使用者名稱將無法更改(DAV/NextCloud 用戶端依賴它)。", + "username_already_claimed": "使用者名稱已設定,不可更改(DAV/NextCloud 用戶端依賴它)。", + "given_name": "名", + "family_name": "姓", + "save_profile": "儲存變更", + "profile_saved": "個人資料已更新", + "profile_no_changes": "沒有變更可儲存。", + "profile_save_failed": "儲存失敗", + "username_taken_error": "該使用者名稱已被使用。", + "username_immutable_error": "您的使用者名稱已設定,無法在此更改。如需重新命名,請聯絡管理員。", "change_password": "修改密碼", "current_password": "當前密碼", "new_password": "新密碼", diff --git a/static/locales/zh.json b/static/locales/zh.json index ce67e137..af277cd0 100644 --- a/static/locales/zh.json +++ b/static/locales/zh.json @@ -686,6 +686,18 @@ "minutes_ago": "{{n}}分钟前", "hours_ago": "{{n}}小时前", "days_ago": "{{n}}天前", + "edit_profile": "编辑个人资料", + "edit_oidc_managed": "要更改您的信息(姓名、名字、头像等),请前往您的身份提供商更新。变更将在您下次登录时显示。", + "username_claim_hint": "2-64 个字符,字母 / 数字 / 点 / 短横线 / 下划线。一旦选定,用户名将无法更改(DAV/NextCloud 客户端依赖它)。", + "username_already_claimed": "用户名已设置,不可更改(DAV/NextCloud 客户端依赖它)。", + "given_name": "名", + "family_name": "姓", + "save_profile": "保存更改", + "profile_saved": "个人资料已更新", + "profile_no_changes": "无更改可保存。", + "profile_save_failed": "保存失败", + "username_taken_error": "该用户名已被占用。", + "username_immutable_error": "您的用户名已设置,无法在此更改。如需重命名,请联系管理员。", "change_password": "修改密码", "current_password": "当前密码", "new_password": "新密码", diff --git a/static/profile.html b/static/profile.html index 7a984390..0c3ccdf6 100644 --- a/static/profile.html +++ b/static/profile.html @@ -116,6 +116,36 @@ +
+

Edit Profile

+ + + +
+
+ + + 2–64 characters, letters/digits/dot/dash/underscore. Once chosen, the username can't be changed (DAV/NextCloud clients depend on it). +
+
+ + +
+
+ + +
+ +
+
+
+

Storage

diff --git a/static/sw.js b/static/sw.js index 99840ea2..74befcaf 100644 --- a/static/sw.js +++ b/static/sw.js @@ -1,6 +1,6 @@ // OxiCloud Service Worker // FIXME: generate cache name according build ? -const CACHE_NAME = 'oxicloud-cache-v24'; +const CACHE_NAME = 'oxicloud-cache-v25'; // Only cache static assets — NOT HTML files. // HTML files are served network-first so browsers always get the latest