// create-transmittal.js — folder-creation plumbing for outgoing // transmittals. // // Surfaced by events.js as a pane-menu item (right-click empty space) // when state.scopeCanonicalFolder == 'staging'. The modal prompts for // a ZDDC-conforming folder name (date_tracking (purpose) - subject) // with live validation via zddc.parseFolder, then POSTs X-ZDDC-Op: // mkdir. On success the client navigates to the new folder URL — the // staging/ cascade serves the transmittal tool there, where the user // builds the manifest, adds files, and publishes. // // No manifest assembly happens here. This is plumbing. (function () { 'use strict'; function status(msg, level) { var t = window.zddc && window.zddc.toast; if (t) t(msg, level || 'info'); } function escapeHtml(s) { return String(s).replace(/[&<>"']/g, function (c) { return ({ '&':'&','<':'<','>':'>','"':'"',"'":''' })[c]; }); } function isoDateToday() { var d = new Date(); return d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2); } function openForm() { return new Promise(function (resolve, reject) { var overlay = document.createElement('div'); overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.4);display:flex;align-items:center;justify-content:center;z-index:9000;'; var box = document.createElement('div'); box.style.cssText = 'background:var(--bg,#fff);color:var(--fg,#111);padding:1.25rem 1.5rem;border-radius:6px;min-width:28rem;max-width:36rem;box-shadow:0 4px 20px rgba(0,0,0,0.25);'; box.innerHTML = '

Create Transmittal folder

' + '

' + "After it's created, the transmittal tool opens here so you can build the manifest — " + 'add rows from the MDL, choose revisions, and associate files.' + '

' + '' + '' + '
' + '
' + '' + '' + '
'; overlay.appendChild(box); document.body.appendChild(overlay); var input = box.querySelector('#ct-name'); var submit = box.querySelector('#ct-submit'); var feedback = box.querySelector('#ct-feedback'); function revalidate() { var v = input.value.trim(); if (!v) { feedback.textContent = ''; submit.disabled = true; return; } var parsed = window.zddc.parseFolder(v); if (parsed && parsed.valid) { feedback.style.color = '#2a8'; feedback.textContent = '✓ tracking=' + parsed.trackingNumber + ', status=' + parsed.status + ', title=' + parsed.title; submit.disabled = false; } else { feedback.style.color = '#c33'; feedback.textContent = '✗ does not match YYYY-MM-DD_TRACKING (PURPOSE) - SUBJECT'; submit.disabled = true; } } input.addEventListener('input', revalidate); revalidate(); function close() { if (overlay.parentNode) overlay.parentNode.removeChild(overlay); } box.querySelector('#ct-cancel').addEventListener('click', function () { close(); reject(new Error('cancelled')); }); overlay.addEventListener('click', function (e) { if (e.target === overlay) { close(); reject(new Error('cancelled')); } }); document.addEventListener('keydown', function escHandler(e) { if (e.key === 'Escape') { document.removeEventListener('keydown', escHandler); close(); reject(new Error('cancelled')); } }); submit.addEventListener('click', function () { var v = input.value.trim(); var parsed = window.zddc.parseFolder(v); if (!parsed || !parsed.valid) { status('Folder name must conform to ZDDC convention.', 'error'); return; } close(); resolve({ folderName: v }); }); // Position cursor after the date prefix. setTimeout(function () { input.focus(); input.setSelectionRange(input.value.length, input.value.length); }, 0); }); } async function invoke() { if (window.app.state.scopeCanonicalFolder !== 'staging') { status('Create Transmittal folder is only available inside staging/.', 'error'); return; } var stagingUrl = window.app.state.currentPath || '/'; if (!stagingUrl.endsWith('/')) stagingUrl += '/'; var choice; try { choice = await openForm(); } catch (_e) { return; } var newUrl = stagingUrl + encodeURIComponent(choice.folderName) + '/'; var resp; try { resp = await fetch(newUrl, { method: 'POST', headers: { 'X-ZDDC-Op': 'mkdir' }, credentials: 'same-origin' }); } catch (e) { status('Create failed: ' + (e && e.message ? e.message : e), 'error'); return; } if (!resp.ok) { var text = ''; try { text = await resp.text(); } catch (_e) {} status('Create failed (' + resp.status + '): ' + text, 'error'); return; } status('Created ' + choice.folderName + ' — opening transmittal tool…', 'success'); // Navigate to the new folder (no-slash form → default_tool: transmittal). window.location.href = stagingUrl + encodeURIComponent(choice.folderName); } window.app.modules.createTransmittal = { invoke: invoke }; })();