Standardize the host modal: tabs onto app.modal, footer, linkable URL (#189)
Migrates proxy's hostModal (the modal this session's app.modal tabs/footer/
url support was originally modeled on) off its old always-in-DOM static
element and onto the shared app.modal component (@simpleworkjs/frontend
0.2.6), continuing the entity-modal standardization started with
sso-manager-node's resource modal.
Unlike the resource modal, this one already had 6 tabs and Host's audit
trail (created_by/created_on/updated_by/updated_on) already existed and was
already populated correctly by routes/host.js -- no model or route changes
needed there. The tab markup itself is kept as one hand-built bodyHtml
string rather than going through app.modal's own `tabs` array option: that
option builds the tab-content div itself, and there'd be no way to wrap a
<form> around just that piece without extending app.modal again, whereas
this modal's tabs already are exactly the pattern app.modal's own tabs
option was modeled on.
Key correctness points, found and handled:
- The one JS binding that was unsafe under DOM rebuild -- a `keyup` handler
driving the Let's-Encrypt challenge-type/wildcard visibility, previously
bound once directly against a captured selector -- is now delegated via
app.modal.on(), the same bug class already found and fixed in the
resource modal.
- hostLoadAuthSuggestions() (fills the SSO allow-list autocomplete
datalists) now re-runs on every modal open, not just once at page load,
since the datalists are rebuilt fresh (empty) each time.
- .actionMessage moved from a sibling of the old modal's <form> into a
descendant of it: formAJAX's error/success target resolution
(app.messages.action's closest('div.card') then a find('.actionMessage')
fallback) only succeeds via the fallback path once app.modal owns the
DOM, since app.modal's .modal-content carries no 'card' class.
- The footer's audit dates needed the explicit 'x' (unix ms) format token
for moment() -- Host's created_on/updated_on come back as redis-hash
strings, and moment's bare fallback parser silently produces "Invalid
date" for a numeric string without it (this app's own hostParseRow
already does this correctly elsewhere; the new footer code needed the
same treatment).
Also adds GET /hosts/:host (mirroring sso-manager-node's /directory/:slug)
plus a client-side deep-link check, threaded through a new onLoaded
callback on hostPopulate().
Verified live against the running dev stack: all 6 tabs render and save
correctly; the footer shows real created/updated-by/on dates; the SSO
autocomplete has options on a second modal open (not just the first);
the challenge-type keyup logic fires correctly on a second-ever modal
open (confirmed via the actual GET /api/host/wildcard-parent/... network
request); the address bar updates to /hosts/{host} and reverts on close;
a direct load of /hosts/{host} auto-opens the right host's modal; and a
real save (PUT) closes the modal and live-updates the row via the existing
pubsub subscription, end to end.
This commit is contained in:
Generated
+6
-6
@@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"name": "proxy-api",
|
"name": "proxy-api",
|
||||||
"version": "1.4.0",
|
"version": "1.5.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "proxy-api",
|
"name": "proxy-api",
|
||||||
"version": "1.4.0",
|
"version": "1.5.3",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^7.3.0",
|
"@fortawesome/fontawesome-free": "^7.3.0",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@simpleworkjs/app-stack": "^1.0.0",
|
"@simpleworkjs/app-stack": "^1.0.0",
|
||||||
"@simpleworkjs/conf": "^1.2.0",
|
"@simpleworkjs/conf": "^1.2.0",
|
||||||
"@simpleworkjs/frontend": "^0.2.5",
|
"@simpleworkjs/frontend": "^0.2.6",
|
||||||
"@simpleworkjs/ldap": "^1.0.0",
|
"@simpleworkjs/ldap": "^1.0.0",
|
||||||
"@simpleworkjs/oidc-client": "^1.0.0",
|
"@simpleworkjs/oidc-client": "^1.0.0",
|
||||||
"acme-client": "^5.4.0",
|
"acme-client": "^5.4.0",
|
||||||
@@ -310,9 +310,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@simpleworkjs/frontend": {
|
"node_modules/@simpleworkjs/frontend": {
|
||||||
"version": "0.2.5",
|
"version": "0.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/@simpleworkjs/frontend/-/frontend-0.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/@simpleworkjs/frontend/-/frontend-0.2.6.tgz",
|
||||||
"integrity": "sha512-PxR7UVPv3gRpdF0WsuAZplF1vYvKsEJQevVPhz9d72U+69vP/OH3tlaAXjtO/apMHfhT1viOPw2gMVOrPSxYZw==",
|
"integrity": "sha512-2uqvEjxyZ2LE+sfhP6rJcEMmqdViazJ3ZkitWJXInPMWF6DiEZuP5MYqBqJvfDko63CCHEt1/ChFQd7Ry85Pzg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0"
|
"node": ">=18.0.0"
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@
|
|||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@simpleworkjs/app-stack": "^1.0.0",
|
"@simpleworkjs/app-stack": "^1.0.0",
|
||||||
"@simpleworkjs/conf": "^1.2.0",
|
"@simpleworkjs/conf": "^1.2.0",
|
||||||
"@simpleworkjs/frontend": "^0.2.5",
|
"@simpleworkjs/frontend": "^0.2.6",
|
||||||
"@simpleworkjs/ldap": "^1.0.0",
|
"@simpleworkjs/ldap": "^1.0.0",
|
||||||
"@simpleworkjs/oidc-client": "^1.0.0",
|
"@simpleworkjs/oidc-client": "^1.0.0",
|
||||||
"acme-client": "^5.4.0",
|
"acme-client": "^5.4.0",
|
||||||
|
|||||||
@@ -40,6 +40,15 @@ router.get('/hosts', async function(req, res, next) {
|
|||||||
res.render('hosts', {...values});
|
res.render('hosts', {...values});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Linkable deep-link to a single host's modal, e.g. from the host modal's
|
||||||
|
// app.modal `url` option. No server-side use of :host -- the client reads
|
||||||
|
// location.pathname itself and opens the matching host's modal once the
|
||||||
|
// page's own data has loaded (same idiom sso-manager-node uses for
|
||||||
|
// /directory/:slug).
|
||||||
|
router.get('/hosts/:host', async function(req, res, next) {
|
||||||
|
res.render('hosts', {...values});
|
||||||
|
});
|
||||||
|
|
||||||
router.get('/dns', async function(req, res, next) {
|
router.get('/dns', async function(req, res, next) {
|
||||||
res.render('dns', {...values});
|
res.render('dns', {...values});
|
||||||
});
|
});
|
||||||
|
|||||||
+487
-477
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user