From a7d5efc76448631d34194b6fa1d4d3f2fa747b2e Mon Sep 17 00:00:00 2001
From: William Mantly
Date: Tue, 28 Jul 2026 20:07:48 -0400
Subject: [PATCH] Unify API-token UI: card grid, Edit modal, description field
(#24)
The self-service API-token UI was inconsistent across all 3 apps
(sso-manager-node/proxy used a card grid with Edit/Rotate/Revoke and a
description field; jump-host used a bare table with no Edit action, no
description field anywhere in the UI, and icon-only buttons -- even though
its model and PUT route already fully supported both). jump-host is first
since it needed the least backend work (none -- description and the PUT
handler already existed, just unexposed) and the most view work, proving
the pattern before porting it to proxy/sso-manager-node.
- Card grid (jq-repeat="apiTokenCard") replacing the table, matching
sso-manager-node's exact template: name + truncated token-id, optional
description, a
of Token ID/Created/Last used/Expires, and labeled
Edit/Rotate/Revoke buttons.
- New Edit modal (app.modal, footer shows "Created by X on Y" via the
token's existing created_by/created_on) -- net-new UI on top of the
already-existing PUT /:id route.
- Create modal gained a Description field and now uses
app.modal.footerButtons() for its Cancel/Create pair.
- Standardized status badges on Bootstrap 5's text-bg-* classes.
- Bumped @simpleworkjs/frontend to ^0.2.6 (footer/footerButtons support;
this app was still on ^0.2.5) and added the missing app.apiToken.update()
client wrapper (list/add/remove/rotate already existed).
Found and fixed a real bug along the way: the planned "flash a checkmark on
copy" touch (porting sso-manager-node's copyField pattern) silently does
nothing once FontAwesome replaces icons with inline
-
@@ -84,10 +84,36 @@
(e.g. GET /api/user/hosts) — not for SSH login. A token carries
no group claims, so it can't reach admin-only endpoints.
-
-
Name
Created
Last used
Expires
-
-
+
+
No API tokens.
+
+
+
+
{{name}}
+ {{id_short}}
+
+
+
+ {{#description}}
{{description}}
{{/description}}
+
+
Token ID
+
{{id_short}}
+
Created
+
{{{created_display}}}
+
Last used
+
{{{last_used_display}}}
+
Expires
+
{{{expires_display}}}
+
+
+
+
+
+
@@ -108,7 +134,7 @@
var portFlag = SSH_PORT === 22 ? '' : ' -p ' + SSH_PORT;
return 'ssh ' + uid + (target ? '_-_' + target : '') + '@' + location.hostname + portFlag;
}
- function copySshCommand(sel){
+ function copyFieldValue(sel){
var $el = $(sel);
var text = $el.val();
if(!text) return;
@@ -130,42 +156,49 @@
+ '
' + app.jump.esc(addr) + '
'
+ '
'
+ ''
- + ''
+ + ''
+ '
');
});
}
- function tokenRows(tokens){
- var $b = $('#api-tokens').empty();
- if(!tokens || !tokens.length){ $b.append('