feat(dashboard): add client editing with PUT endpoint and edit modal
Some checks failed
CI / Check (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Formatting (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Release Build (push) Has been cancelled

Add PUT /api/clients/{id} with dynamic UPDATE for name, description,
is_active, and rate_limit_per_minute. Expose description and
rate_limit_per_minute in client list/detail responses. Replace the
frontend editClient stub with a modal that fetches, edits, and saves
client data.
This commit is contained in:
2026-03-02 14:56:19 -05:00
parent db5824f0fb
commit 4e53b05126
3 changed files with 188 additions and 4 deletions

View File

@@ -189,8 +189,82 @@ class ClientsPage {
}
}
editClient(id) {
window.authManager.showToast('Edit client not implemented yet', 'info');
async editClient(id) {
try {
const client = await window.api.get(`/clients/${id}`);
this.showEditClientModal(client);
} catch (error) {
window.authManager.showToast(`Failed to load client: ${error.message}`, 'error');
}
}
showEditClientModal(client) {
const modal = document.createElement('div');
modal.className = 'modal active';
modal.innerHTML = `
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Edit Client: ${client.id}</h3>
<button class="modal-close" onclick="this.closest('.modal').remove()">
<i class="fas fa-times"></i>
</button>
</div>
<div class="modal-body">
<div class="form-control">
<label for="edit-client-name">Display Name</label>
<input type="text" id="edit-client-name" value="${client.name || ''}" placeholder="e.g. My Coding Assistant">
</div>
<div class="form-control">
<label for="edit-client-description">Description</label>
<textarea id="edit-client-description" rows="3" placeholder="Optional description">${client.description || ''}</textarea>
</div>
<div class="form-control">
<label for="edit-client-rate-limit">Rate Limit (requests/minute)</label>
<input type="number" id="edit-client-rate-limit" min="0" value="${client.rate_limit_per_minute || ''}" placeholder="Leave empty for unlimited">
</div>
<div class="form-control">
<label class="toggle-label">
<input type="checkbox" id="edit-client-active" ${client.is_active ? 'checked' : ''}>
<span>Active</span>
</label>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" onclick="this.closest('.modal').remove()">Cancel</button>
<button class="btn btn-primary" id="confirm-edit-client">Save Changes</button>
</div>
</div>
`;
document.body.appendChild(modal);
modal.querySelector('#confirm-edit-client').onclick = async () => {
const name = modal.querySelector('#edit-client-name').value.trim();
const description = modal.querySelector('#edit-client-description').value.trim();
const rateLimitVal = modal.querySelector('#edit-client-rate-limit').value;
const isActive = modal.querySelector('#edit-client-active').checked;
if (!name) {
window.authManager.showToast('Name is required', 'error');
return;
}
const payload = {
name,
description: description || null,
is_active: isActive,
rate_limit_per_minute: rateLimitVal ? parseInt(rateLimitVal, 10) : null,
};
try {
await window.api.put(`/clients/${client.id}`, payload);
window.authManager.showToast(`Client "${name}" updated`, 'success');
modal.remove();
this.loadClients();
} catch (error) {
window.authManager.showToast(error.message, 'error');
}
};
}
}