/** * image-pages.js - helpers shared by the GE Aerospace image tabs. * Loaded by templates/_image_header.html. Exposes window.PxeImage: * * PxeImage.postJSON(url, body) POST JSON with the CSRF header; * resolves {ok, status, data}. * PxeImage.renderDiff(el, files) draw [{name, changed, diff, reformat}] * (services/control_files.public) into el. * PxeImage.reviewAndSave(opts) preview -> diff modal -> save -> reload. * opts: previewUrl, saveUrl, body (object), title (optional), * onSaved(data) (optional; default reloads the page). */ (function () { 'use strict'; function csrfToken() { var m = document.querySelector('meta[name="csrf-token"]'); return m ? m.getAttribute('content') : ''; } function postJSON(url, body) { return fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken() }, body: JSON.stringify(body || {}), credentials: 'same-origin' }).then(function (resp) { return resp.json().catch(function () { return { error: 'HTTP ' + resp.status }; }) .then(function (data) { return { ok: resp.ok, status: resp.status, data: data }; }); }); } function el(tag, cls, text) { var e = document.createElement(tag); if (cls) e.className = cls; if (text !== undefined) e.textContent = text; return e; } function renderDiff(container, files) { container.innerHTML = ''; var changed = (files || []).filter(function (f) { return f.changed; }); if (!changed.length) { container.appendChild(el('div', 'alert alert-info mb-0', 'No changes: the files already hold exactly this.')); return 0; } changed.forEach(function (f) { var box = el('div', 'diff-file'); var head = el('div', 'diff-file-head'); head.appendChild(el('i', 'bi bi-file-earmark-diff')); head.appendChild(el('span', 'mono', f.name)); if (!f.existed) head.appendChild(el('span', 'badge badge-info', 'new file')); if (f.reformat) { var w = el('span', 'badge badge-warning', 'whitespace also changes'); w.title = 'The current file is not laid out the way it will be written; ' + 'unchanged lines may show as changed.'; head.appendChild(w); } box.appendChild(head); var pre = el('pre', 'diff-view'); String(f.diff || '').split('\n').forEach(function (line, i, all) { if (i === all.length - 1 && line === '') return; var c = ''; if (line.indexOf('+++') === 0 || line.indexOf('---') === 0) c = 'd-meta'; else if (line.indexOf('@@') === 0) c = 'd-hunk'; else if (line.charAt(0) === '+') c = 'd-add'; else if (line.charAt(0) === '-') c = 'd-del'; pre.appendChild(el('span', c, line || ' ')); }); box.appendChild(pre); container.appendChild(box); }); return changed.length; } function reviewAndSave(opts) { var modalEl = document.getElementById('imageReviewModal'); var body = document.getElementById('imageReviewBody'); var err = document.getElementById('imageReviewError'); var confirmBtn = document.getElementById('imageReviewConfirm'); var title = document.getElementById('imageReviewTitle'); if (!modalEl || !window.bootstrap) return; title.textContent = opts.title || 'Review changes'; body.innerHTML = '