- new section: Top OCA modules, module / area / 19.0 / 20.0 status, rows rendered from the n8n webhook at n8n.odoo4projects.com/webhook/oc-guy/modules, with the last fetched snapshot in the markup as a no-JS fallback - photography swapped from archival maps to Pixabay photos (archive aisle, cardboard boxes, old books, workshop tools, warehouse) - featured module is now a full-bleed dark spread with the warehouse shot - contact address is oliver@oc-guy.com throughout - credits point at Pixabay and its Content License
143 lines
5.0 KiB
JavaScript
143 lines
5.0 KiB
JavaScript
/* The OC Guy — page behaviour.
|
|
Everything degrades: without JS the page is a plain, readable
|
|
document with working links and a mail form. */
|
|
(function () {
|
|
'use strict';
|
|
|
|
var doc = document.documentElement;
|
|
doc.classList.add('js');
|
|
|
|
var reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
|
|
/* ---------- entrance for the blocks of each section ---------- */
|
|
var targets = document.querySelectorAll(
|
|
'.lead-caption, .box, .side-list, .section-head, .card, .feature, .news li, .ask-inner'
|
|
);
|
|
|
|
if (!reduce && 'IntersectionObserver' in window) {
|
|
var io = new IntersectionObserver(function (entries) {
|
|
entries.forEach(function (entry) {
|
|
if (!entry.isIntersecting) return;
|
|
entry.target.classList.add('rv-in');
|
|
io.unobserve(entry.target);
|
|
});
|
|
}, { rootMargin: '0px 0px -8% 0px', threshold: 0.08 });
|
|
|
|
Array.prototype.forEach.call(targets, function (el) {
|
|
el.setAttribute('data-rv', '1');
|
|
io.observe(el);
|
|
});
|
|
} else {
|
|
Array.prototype.forEach.call(targets, function (el) { el.classList.add('rv-in'); });
|
|
}
|
|
|
|
/* ---------- the ask form: one question, by mail ---------- */
|
|
var form = document.querySelector('.ask-form');
|
|
var mail = document.getElementById('ask-mail');
|
|
|
|
if (form && mail) {
|
|
form.addEventListener('submit', function (event) {
|
|
event.preventDefault();
|
|
var addr = (mail.value || '').trim();
|
|
if (!addr || addr.indexOf('@') === -1) {
|
|
mail.setAttribute('aria-invalid', 'true');
|
|
mail.focus();
|
|
return;
|
|
}
|
|
mail.removeAttribute('aria-invalid');
|
|
var body = 'My question about Odoo Community:\n\n\n— reply to: ' + addr + '\n';
|
|
window.location.href = 'mailto:oliver@oc-guy.com'
|
|
+ '?subject=' + encodeURIComponent('Odoo Community question')
|
|
+ '&body=' + encodeURIComponent(body);
|
|
});
|
|
}
|
|
|
|
/* ---------- OCA module status, live from the n8n feed ---------- */
|
|
var ocaBody = document.getElementById('oca-rows');
|
|
var ocaNote = document.getElementById('oca-note');
|
|
|
|
function statusCell(ok, version) {
|
|
var td = document.createElement('td');
|
|
td.className = 'oca-status';
|
|
var mark = document.createElement('span');
|
|
mark.className = ok ? 'mark is-on' : 'mark';
|
|
mark.setAttribute('aria-hidden', 'true');
|
|
mark.textContent = ok ? '\u2713' : '\u2014';
|
|
var sr = document.createElement('span');
|
|
sr.className = 'sr-only';
|
|
sr.textContent = ok ? ' has a ' + version + ' branch' : ' no ' + version + ' branch yet';
|
|
td.appendChild(mark);
|
|
td.appendChild(sr);
|
|
return td;
|
|
}
|
|
|
|
function renderOca(rows) {
|
|
ocaBody.textContent = '';
|
|
rows.forEach(function (m) {
|
|
var tr = document.createElement('tr');
|
|
|
|
var name = document.createElement('td');
|
|
name.className = 'oca-name';
|
|
var a = document.createElement('a');
|
|
a.href = m.URL || '#';
|
|
a.target = '_blank';
|
|
a.rel = 'noopener';
|
|
a.textContent = m.name || 'Module';
|
|
name.appendChild(a);
|
|
|
|
var area = document.createElement('td');
|
|
area.className = 'oca-area';
|
|
area.textContent = m.area || '';
|
|
|
|
tr.appendChild(name);
|
|
tr.appendChild(area);
|
|
tr.appendChild(statusCell(!!m.v19, '19.0'));
|
|
tr.appendChild(statusCell(!!m.v20, '20.0'));
|
|
ocaBody.appendChild(tr);
|
|
});
|
|
}
|
|
|
|
if (ocaBody) {
|
|
fetch('https://n8n.odoo4projects.com/webhook/oc-guy/modules')
|
|
.then(function (r) { if (!r.ok) throw new Error('http ' + r.status); return r.json(); })
|
|
.then(function (payload) {
|
|
var rows = payload && Array.isArray(payload.data) ? payload.data
|
|
: (Array.isArray(payload) ? payload : null);
|
|
if (!rows || !rows.length) throw new Error('empty');
|
|
renderOca(rows);
|
|
if (ocaNote) {
|
|
ocaNote.textContent = 'Status read from the OCA module feed at '
|
|
+ new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
|
+ '. A tick means the module carries a branch for that series; a dash means it does not yet.';
|
|
}
|
|
})
|
|
.catch(function () {
|
|
if (ocaNote) {
|
|
ocaNote.textContent = 'The live feed could not be reached just now; the rows above are the last snapshot.';
|
|
}
|
|
});
|
|
}
|
|
|
|
/* ---------- which section the reader is in ---------- */
|
|
var links = Array.prototype.slice.call(document.querySelectorAll('.nav a[href^="#"]'));
|
|
var sections = links
|
|
.map(function (a) { return document.querySelector(a.getAttribute('href')); })
|
|
.filter(Boolean);
|
|
|
|
if (sections.length && 'IntersectionObserver' in window) {
|
|
var seen = new IntersectionObserver(function (entries) {
|
|
entries.forEach(function (entry) {
|
|
if (!entry.isIntersecting) return;
|
|
links.forEach(function (a) {
|
|
if (a.getAttribute('href') === '#' + entry.target.id) {
|
|
a.setAttribute('aria-current', 'true');
|
|
} else {
|
|
a.removeAttribute('aria-current');
|
|
}
|
|
});
|
|
});
|
|
}, { rootMargin: '-45% 0px -50% 0px' });
|
|
sections.forEach(function (s) { seen.observe(s); });
|
|
}
|
|
})();
|