From 51e512ec0844543b46f6a5d9ad15392168acd1de Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Thu, 19 Feb 2026 23:06:18 +0100 Subject: [PATCH] feat: make admin user edit page fields editable (username, email, name) The admin-user-edit page had display-only fields for username, email, first name, and last name. Convert to editable form inputs with: - Dirty detection (unsaved changes indicator) - Only sends changed fields in PUT payload - Validation error display per field - Save button disabled when no changes Co-Authored-By: Claude Opus 4.6 --- .../static/admin/js/admin-user-edit.js | 88 +++++++++++++++++ .../tenancy/admin/admin-user-edit.html | 99 +++++++++++++------ 2 files changed, 156 insertions(+), 31 deletions(-) diff --git a/app/modules/tenancy/static/admin/js/admin-user-edit.js b/app/modules/tenancy/static/admin/js/admin-user-edit.js index f61863bd..b72bac42 100644 --- a/app/modules/tenancy/static/admin/js/admin-user-edit.js +++ b/app/modules/tenancy/static/admin/js/admin-user-edit.js @@ -18,6 +18,14 @@ function adminUserEditPage() { userId: null, currentUserId: null, + // Editable profile form + editForm: { + username: '', + email: '', + first_name: '', + last_name: '' + }, + // Platform assignment state showPlatformModal: false, availablePlatforms: [], @@ -98,6 +106,14 @@ function adminUserEditPage() { full_name: [response.first_name, response.last_name].filter(Boolean).join(' ') || null }; + // Populate editable form + this.editForm = { + username: this.adminUser.username || '', + email: this.adminUser.email || '', + first_name: this.adminUser.first_name || '', + last_name: this.adminUser.last_name || '' + }; + adminUserEditLog.info(`Admin user loaded in ${duration}ms`, { id: this.adminUser.id, username: this.adminUser.username, @@ -141,6 +157,78 @@ function adminUserEditPage() { return Utils.formatDate(dateString); }, + // Check if profile form has unsaved changes + get profileDirty() { + if (!this.adminUser) return false; + return this.editForm.username !== (this.adminUser.username || '') || + this.editForm.email !== (this.adminUser.email || '') || + this.editForm.first_name !== (this.adminUser.first_name || '') || + this.editForm.last_name !== (this.adminUser.last_name || ''); + }, + + // Save profile changes + async saveProfile() { + adminUserEditLog.info('Saving profile changes...'); + this.errors = {}; + + // Build update payload with only changed fields + const payload = {}; + if (this.editForm.username !== (this.adminUser.username || '')) { + payload.username = this.editForm.username; + } + if (this.editForm.email !== (this.adminUser.email || '')) { + payload.email = this.editForm.email; + } + if (this.editForm.first_name !== (this.adminUser.first_name || '')) { + payload.first_name = this.editForm.first_name; + } + if (this.editForm.last_name !== (this.adminUser.last_name || '')) { + payload.last_name = this.editForm.last_name; + } + + if (Object.keys(payload).length === 0) return; + + this.saving = true; + try { + const url = `/admin/users/${this.userId}`; + window.LogConfig.logApiCall('PUT', url, payload, 'request'); + + const response = await apiClient.put(url, payload); + + window.LogConfig.logApiCall('PUT', url, response, 'response'); + + // Update local state + this.adminUser.username = response.username; + this.adminUser.email = response.email; + this.adminUser.first_name = response.first_name; + this.adminUser.last_name = response.last_name; + this.adminUser.full_name = [response.first_name, response.last_name].filter(Boolean).join(' ') || null; + + // Re-sync form + this.editForm = { + username: response.username || '', + email: response.email || '', + first_name: response.first_name || '', + last_name: response.last_name || '' + }; + + Utils.showToast('Profile updated successfully', 'success'); + adminUserEditLog.info('Profile updated successfully'); + + } catch (error) { + window.LogConfig.logError(error, 'Save Profile'); + if (error.details) { + for (const detail of error.details) { + const field = detail.loc?.[detail.loc.length - 1]; + if (field) this.errors[field] = detail.msg; + } + } + Utils.showToast(error.message || 'Failed to save profile', 'error'); + } finally { + this.saving = false; + } + }, + // Toggle super admin status async toggleSuperAdmin() { const isSuperAdmin = this.adminUser.role === 'super_admin'; diff --git a/app/modules/tenancy/templates/tenancy/admin/admin-user-edit.html b/app/modules/tenancy/templates/tenancy/admin/admin-user-edit.html index 35efca53..905bd446 100644 --- a/app/modules/tenancy/templates/tenancy/admin/admin-user-edit.html +++ b/app/modules/tenancy/templates/tenancy/admin/admin-user-edit.html @@ -71,39 +71,76 @@ - +
-

- Admin Information -

-
- -
-
- User ID -

-
-
- Username -

-
-
- Email -

-
-
- -
-
- First Name -

-
-
- Last Name -

-
-
+
+

+ Admin Information +

+
+
+
+ +
+
+ + +

+
+
+ + +

+
+
+ +
+
+ + +
+
+ + +
+
+
+
+ Unsaved changes + +
+