113 lines
5 KiB
JavaScript
113 lines
5 KiB
JavaScript
(function (app) {
|
|
'use strict';
|
|
|
|
// Friendly empty-state shown when the form is opened standalone
|
|
// (file:// or otherwise without a server-injected #form-context
|
|
// payload). The form renderer is always driven by the host —
|
|
// zddc-server's form handler injects schema+ui+data; the tool has
|
|
// no client-side picker because there's nothing it could pick from
|
|
// outside that contract.
|
|
function renderStandaloneWelcome(root) {
|
|
if (!root) return;
|
|
root.innerHTML = '';
|
|
const wrap = document.createElement('div');
|
|
wrap.className = 'form-welcome';
|
|
wrap.innerHTML = [
|
|
'<h2>ZDDC Form Renderer</h2>',
|
|
'<p>This tool renders a form spec injected by <code>zddc-server</code>',
|
|
' at <code><name>.form.html</code> URLs. There is no schema',
|
|
' to render here — most likely you opened the standalone HTML directly.</p>',
|
|
'<h3>To use it</h3>',
|
|
'<ol>',
|
|
'<li>Run <code>zddc-server</code> against an archive that contains a',
|
|
' <code><name>.form.yaml</code> spec.</li>',
|
|
'<li>Visit <code><path>/<name>.form.html</code> in the browser.</li>',
|
|
'</ol>',
|
|
'<p>See <a href="https://zddc.varasys.io/reference.html" target="_blank" rel="noopener">',
|
|
'zddc.varasys.io/reference.html</a> for the full ZDDC reference.</p>'
|
|
].join('');
|
|
root.appendChild(wrap);
|
|
|
|
const submitBtn = document.getElementById('submit-btn');
|
|
if (submitBtn) submitBtn.hidden = true;
|
|
}
|
|
|
|
function boot() {
|
|
// When this bundle is hosted by the unified tables.html, the
|
|
// mode dispatcher decides which app paints. Skip when mode is
|
|
// not "form" — table-mode requests are handled by tablesApp.
|
|
// (Standalone form/dist/form.html has no zddcMode global; treat
|
|
// undefined as form-mode for back-compat.)
|
|
if (window.zddcMode && window.zddcMode !== 'form') {
|
|
return;
|
|
}
|
|
app.context = app.modules.context.load();
|
|
|
|
if (app.context.title) {
|
|
// Standalone form.html has #form-title in its header; unified
|
|
// tables.html bundle has #table-title (shared across modes).
|
|
// Whichever exists, write to it.
|
|
const t = document.getElementById('form-title') ||
|
|
document.getElementById('table-title');
|
|
if (t) {
|
|
t.textContent = app.context.title;
|
|
}
|
|
document.title = app.context.title + ' — ZDDC';
|
|
}
|
|
|
|
const root = document.getElementById('form-root');
|
|
if (root && app.context.schema) {
|
|
app.rootWidget = app.modules.render.mount(
|
|
root,
|
|
app.context.schema,
|
|
app.context.ui || {},
|
|
app.context.data
|
|
);
|
|
} else if (root) {
|
|
// No schema — server-injected context is empty. Most common
|
|
// when the standalone form.html is opened from file:// without
|
|
// a host. Show a friendly explanation instead of a blank page.
|
|
renderStandaloneWelcome(root);
|
|
return;
|
|
}
|
|
|
|
if (app.context.errors && app.context.errors.length) {
|
|
app.modules.errors.apply(app.context.errors);
|
|
app.modules.post.showStatus('Please correct the errors below.', 'error');
|
|
}
|
|
|
|
const submitBtn = document.getElementById('submit-btn');
|
|
if (submitBtn) {
|
|
submitBtn.addEventListener('click', app.modules.post.submit);
|
|
// Pre-flight gate: hide Submit when the cascade denies
|
|
// create at the submission directory. Server still
|
|
// enforces on POST — this just avoids dangling an
|
|
// affordance that would 403. Submission directory is the
|
|
// parent of submitUrl; fall back to the page URL when
|
|
// submitUrl is absent (file:// / no-context mode).
|
|
if (window.zddc && window.zddc.cap && app.context && app.context.submitUrl) {
|
|
const subUrl = app.context.submitUrl;
|
|
const dir = subUrl.replace(/\/[^\/]*$/, '/') || subUrl;
|
|
window.zddc.cap.at(dir).then(function (view) {
|
|
if (!view) return;
|
|
const verbs = view.path_verbs || '';
|
|
if (verbs.indexOf('c') === -1) {
|
|
submitBtn.hidden = true;
|
|
const status = document.getElementById('form-status');
|
|
if (status) {
|
|
status.textContent = "You don't have permission to submit here.";
|
|
status.hidden = false;
|
|
status.classList.add('is-error');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', boot, { once: true });
|
|
} else {
|
|
boot();
|
|
}
|
|
})(window.formApp);
|