(function (app) {
'use strict';
const dom = app.dom;
const json = app.json;
const util = app.util;
/**
* Hydrates static HTML content with data from JSON.
* Called on page load to hide static placeholders and show dynamic content.
*/
function hydrate() {
// Hide static "Not Validated" warning (will be replaced by dynamic validation)
const staticWarning = dom.qs('#signature-status-static');
if (staticWarning) {
staticWarning.hidden = true;
}
// Digest will be populated by security.renderSignaturesList()
// which is called after signature verification
}
/**
* Populates static HTML before saving/publishing.
* This ensures the page displays content even without JavaScript.
*/
async function populateStatic() {
const data = json.parse();
const envelope = data.envelope || {};
const payload = data.payload || {};
const signatures = Array.isArray(envelope.signatures) ? envelope.signatures : [];
const files = Array.isArray(payload.files) ? payload.files : [];
// Populate all form fields with actual values
const fields = {
'#type': payload.type || 'Transmittal',
'#title': payload.title || '',
'#owner-name': payload.client || '',
'#project-name': payload.project || '',
'#project-number': payload.projectNumber || '',
'#tracking-number': payload.trackingNumber || '',
'#date': payload.date || '',
'#from': payload.from || '',
'#to': payload.to || '',
'#purpose': payload.purpose || '',
'#response-due': payload.responseDue || '',
'#subject': payload.subject || '',
'#remarks': payload.remarks || ''
};
Object.keys(fields).forEach(function(selector) {
const el = dom.qs(selector);
if (el) {
if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {
el.value = fields[selector];
el.setAttribute('value', fields[selector]);
} else {
el.textContent = fields[selector];
}
}
});
var typeDisp = dom.qs('#type-display');
if (typeDisp) { typeDisp.textContent = fields['#type']; }
// Render markdown for static display
if (app.modules.markdown && payload.remarks) {
const remarksRender = dom.qs('#remarks-render');
if (remarksRender) {
remarksRender.innerHTML = app.modules.markdown.render(payload.remarks);
}
}
// Populate table with file data
const SELF_HASH = app.constants.SELF_HASH;
const tbody = dom.qs('.table-wrapper tbody');
if (tbody) {
let html = '';
let rowNum = 0;
// Separate self-entry from regular files
var selfFile = null;
var regularFiles = [];
files.forEach(function(file) {
if (file.sha256 === SELF_HASH) {
selfFile = file;
} else {
regularFiles.push(file);
}
});
// If no explicit self-entry in JSON, synthesize one from payload header
if (!selfFile) {
selfFile = {
trackingNumber: payload.trackingNumber || '',
title: payload.subject || payload.title || '',
revision: payload.date || '',
status: payload.purpose || '',
extension: 'html',
fileSize: 0,
sha256: SELF_HASH
};
}
// Build self-link filename from payload fields
var selfFilename = '';
var dataModule = app.modules.data;
if (dataModule && dataModule.buildFileName) {
selfFilename = dataModule.buildFileName(payload, { extension: 'html' });
}
var selfHref = selfFilename ? encodeURI('./' + selfFilename) : '';
var selfTrackingHtml = selfHref
? '' + util.escapeHtml(selfFile.trackingNumber || '') + ''
: util.escapeHtml(selfFile.trackingNumber || '');
// Row 0: self-entry
html += '
' +
'| 0 | ' +
'' + selfTrackingHtml + ' | ' +
'' + util.escapeHtml(selfFile.title || '') + ' | ' +
'' + util.escapeHtml(selfFile.revision || '') + ' | ' +
'' + util.escapeHtml(selfFile.status || '') + ' | ' +
'html | ' +
'\u2014 | ' +
'see above | ' +
'
';
// Remaining files
regularFiles.forEach(function(file) {
rowNum++;
var isUnmatched = !file.sha256 && !file.fileSize;
var formattedSize = isUnmatched ? '\u2014' : (file.fileSize ? util.formatFileSize(file.fileSize) : '');
var sizeClass = isUnmatched ? 'px-2 py-1 text-right text-gray-400' : 'px-2 py-1 text-right';
var hashContent = isUnmatched ? 'pending' : (file.sha256 ? util.formatShortFileHash(file.sha256) : '');
html += '' +
'| ' + rowNum + ' | ' +
'' + (file.trackingNumber || '') + ' | ' +
'' + (file.title || '') + ' | ' +
'' + (file.revision || '') + ' | ' +
'' + (file.status || '') + ' | ' +
'' + (file.extension || '') + ' | ' +
'' + formattedSize + ' | ' +
'' + hashContent + ' | ' +
'
';
});
tbody.innerHTML = html || ' | | | | | | | |
';
}
// Populate digest card (static fallback using verify-card format)
const digestDisplay = dom.qs('#digest-display');
if (digestDisplay && envelope.digest) {
const digestedAt = envelope.digestedAt ? new Date(envelope.digestedAt).toLocaleString() : 'Unknown';
digestDisplay.innerHTML =
'' +
'
Digest (SHA-256)
' +
'
' + envelope.digest + '
' +
'
' + digestedAt + '
' +
'
';
}
// Populate digest in Advanced section
const digestEl = dom.qs('#digest-info');
if (digestEl && envelope.digest) {
const digestedAt = envelope.digestedAt ? new Date(envelope.digestedAt).toLocaleString() : 'Unknown';
digestEl.innerHTML = '' +
'
Digest (SHA-256):
' +
'
' + envelope.digest + '' +
'
Created: ' + digestedAt + '
' +
'
';
}
// Populate static signature cards
const sigList = dom.qs('#signatures-list');
if (sigList && signatures.length > 0) {
let html = '';
for (let i = 0; i < signatures.length; i++) {
const sig = signatures[i];
const fingerprint = await util.publicKeyFingerprint(sig.publicKeyJwk);
const fpDisplay = fingerprint === null ? 'unavailable' : (fingerprint || 'Unknown');
const signedAt = sig.signedAt ? new Date(sig.signedAt).toLocaleString() : 'Unknown';
html += '' +
'
Signature ' + (i + 1) + '
' +
'
Key: ' + fpDisplay + '
' +
'
' + signedAt + '
' +
'
';
}
sigList.innerHTML = html;
}
// Show static warning
const staticWarning = dom.qs('#signature-status-static');
if (staticWarning) {
staticWarning.hidden = !(envelope.digest || signatures.length > 0);
}
}
/**
* Populates form fields from current JSON data at runtime.
* Used by verification mode to hydrate the form with loaded data.
*/
function hydrateForm() {
const data = json.parse();
const payload = data.payload || {};
const files = Array.isArray(payload.files) ? payload.files : [];
var fields = {
'#type': payload.type || 'Transmittal',
'#title': payload.title || '',
'#owner-name': payload.client || '',
'#project-name': payload.project || '',
'#project-number': payload.projectNumber || '',
'#tracking-number': payload.trackingNumber || '',
'#date': payload.date || '',
'#from': payload.from || '',
'#to': payload.to || '',
'#purpose': payload.purpose || '',
'#response-due': payload.responseDue || '',
'#subject': payload.subject || '',
'#remarks': payload.remarks || ''
};
Object.keys(fields).forEach(function (selector) {
var el = dom.qs(selector);
if (el) {
if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {
el.value = fields[selector];
} else {
el.textContent = fields[selector];
}
}
});
var typeDisp2 = dom.qs('#type-display');
if (typeDisp2) { typeDisp2.textContent = fields['#type']; }
// Render markdown
if (app.modules.markdown && payload.remarks) {
var remarksRender = dom.qs('#remarks-render');
if (remarksRender) {
remarksRender.innerHTML = app.modules.markdown.render(payload.remarks);
}
}
// Render email fields
if (app.modules.emailTags) {
if (app.modules.emailTags.render) { app.modules.emailTags.render(); }
if (app.modules.emailTags.renderFrom) { app.modules.emailTags.renderFrom(); }
}
// Visibility
if (app.modules.visibility && app.modules.visibility.applyFieldVisibility) {
app.modules.visibility.applyFieldVisibility();
}
}
app.modules.hydrate = {
hydrate: hydrate,
hydrateForm: hydrateForm,
populateStatic: populateStatic
};
app.registerInit(function () {
hydrate();
});
})(window.transmittalApp);