fix(portal): extract inline JS to static file to resolve Qute {#raw} parse error
Deploy to Production / deploy (push) Successful in 3m5s
Deploy to Production / deploy (push) Successful in 3m5s
Quarkus 3.15 removed the {#raw} section helper. Moving the dashboard map/expires
JS to META-INF/resources/dashboard.js (served as static asset, bypasses Qute)
fixes the portal startup failure in CI.
Co-Authored-By: Mira <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
(function () {
|
||||
var data = window.__D || {};
|
||||
var visits = data.recentVisits || [];
|
||||
var hasRegistrar = typeof data.registrarLat === 'number' && typeof data.registrarLon === 'number';
|
||||
|
||||
// ── Expires display ──────────────────────────────────────────────────────
|
||||
var expiresEl = document.getElementById('expires-val');
|
||||
var expiresSub = document.getElementById('expires-sub');
|
||||
if (data.expiresAt && expiresEl) {
|
||||
var d = new Date(data.expiresAt);
|
||||
expiresEl.textContent = d.toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' });
|
||||
var days = Math.ceil((d - Date.now()) / 86400000);
|
||||
expiresSub.textContent = days > 0 ? days + ' days remaining' : 'expired';
|
||||
}
|
||||
|
||||
// ── Map ──────────────────────────────────────────────────────────────────
|
||||
var wrap = document.getElementById('map-wrap');
|
||||
var svg = d3.select('#world-map');
|
||||
var W = wrap.clientWidth || 800;
|
||||
var H = Math.round(W * 0.48);
|
||||
svg.attr('viewBox', '0 0 ' + W + ' ' + H)
|
||||
.attr('width', W)
|
||||
.attr('height', H);
|
||||
|
||||
var projection = d3.geoNaturalEarth1()
|
||||
.scale(W / 6.3)
|
||||
.translate([W / 2, H / 2]);
|
||||
var path = d3.geoPath(projection);
|
||||
|
||||
// Ocean
|
||||
svg.append('rect')
|
||||
.attr('width', W).attr('height', H)
|
||||
.attr('fill', '#060d18');
|
||||
|
||||
fetch('https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json')
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(world) {
|
||||
// Land
|
||||
svg.append('path')
|
||||
.datum(topojson.feature(world, world.objects.countries))
|
||||
.attr('d', path)
|
||||
.attr('fill', '#111820')
|
||||
.attr('stroke', '#1e2a38')
|
||||
.attr('stroke-width', 0.5);
|
||||
|
||||
// Graticule (faint grid)
|
||||
svg.append('path')
|
||||
.datum(d3.geoGraticule()())
|
||||
.attr('d', path)
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', '#0d1a28')
|
||||
.attr('stroke-width', 0.4);
|
||||
|
||||
// Agent blinks — resolve duplicates by approximate cell
|
||||
var cellSize = 1.5; // degrees
|
||||
var cells = {};
|
||||
visits.forEach(function(v) {
|
||||
var cell = Math.round(v.lat / cellSize) + ',' + Math.round(v.lon / cellSize);
|
||||
if (!cells[cell]) cells[cell] = { lat: v.lat, lon: v.lon, count: 0 };
|
||||
cells[cell].count++;
|
||||
});
|
||||
var points = Object.values(cells);
|
||||
points.forEach(function(pt, i) {
|
||||
var pos = projection([pt.lon, pt.lat]);
|
||||
if (!pos) return;
|
||||
var r = Math.min(2 + Math.log1p(pt.count) * 1.5, 8);
|
||||
svg.append('circle')
|
||||
.attr('class', 'agent-blink')
|
||||
.attr('cx', pos[0])
|
||||
.attr('cy', pos[1])
|
||||
.attr('r', r)
|
||||
.style('animation-delay', (i * 190 % 5000) + 'ms');
|
||||
});
|
||||
|
||||
// Registrar star — drawn last so it sits on top
|
||||
if (hasRegistrar) {
|
||||
var pos = projection([data.registrarLon, data.registrarLat]);
|
||||
if (pos) {
|
||||
svg.append('text')
|
||||
.attr('class', 'registrar-star')
|
||||
.attr('x', pos[0])
|
||||
.attr('y', pos[1])
|
||||
.text('★');
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function(e) {
|
||||
console.warn('Map load failed:', e);
|
||||
});
|
||||
|
||||
// ── Resize ────────────────────────────────────────────────────────────────
|
||||
window.addEventListener('resize', function() {
|
||||
W = wrap.clientWidth || 800;
|
||||
H = Math.round(W * 0.48);
|
||||
svg.attr('viewBox', '0 0 ' + W + ' ' + H)
|
||||
.attr('width', W).attr('height', H);
|
||||
projection.scale(W / 6.3).translate([W / 2, H / 2]);
|
||||
svg.selectAll('path').attr('d', path);
|
||||
});
|
||||
})();
|
||||
@@ -186,110 +186,7 @@ var __D = {dataJson.raw};
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/topojson-client@3/dist/topojson-client.min.js"></script>
|
||||
{#raw}
|
||||
<script>
|
||||
(function () {
|
||||
var data = window.__D || {};
|
||||
var visits = data.recentVisits || [];
|
||||
var hasRegistrar = typeof data.registrarLat === 'number' && typeof data.registrarLon === 'number';
|
||||
|
||||
// ── Expires display ──────────────────────────────────────────────────────
|
||||
var expiresEl = document.getElementById('expires-val');
|
||||
var expiresSub = document.getElementById('expires-sub');
|
||||
if (data.expiresAt && expiresEl) {
|
||||
var d = new Date(data.expiresAt);
|
||||
expiresEl.textContent = d.toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' });
|
||||
var days = Math.ceil((d - Date.now()) / 86400000);
|
||||
expiresSub.textContent = days > 0 ? days + ' days remaining' : 'expired';
|
||||
}
|
||||
|
||||
// ── Map ──────────────────────────────────────────────────────────────────
|
||||
var wrap = document.getElementById('map-wrap');
|
||||
var svg = d3.select('#world-map');
|
||||
var W = wrap.clientWidth || 800;
|
||||
var H = Math.round(W * 0.48);
|
||||
svg.attr('viewBox', '0 0 ' + W + ' ' + H)
|
||||
.attr('width', W)
|
||||
.attr('height', H);
|
||||
|
||||
var projection = d3.geoNaturalEarth1()
|
||||
.scale(W / 6.3)
|
||||
.translate([W / 2, H / 2]);
|
||||
var path = d3.geoPath(projection);
|
||||
|
||||
// Ocean
|
||||
svg.append('rect')
|
||||
.attr('width', W).attr('height', H)
|
||||
.attr('fill', '#060d18');
|
||||
|
||||
fetch('https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json')
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(world) {
|
||||
// Land
|
||||
svg.append('path')
|
||||
.datum(topojson.feature(world, world.objects.countries))
|
||||
.attr('d', path)
|
||||
.attr('fill', '#111820')
|
||||
.attr('stroke', '#1e2a38')
|
||||
.attr('stroke-width', 0.5);
|
||||
|
||||
// Graticule (faint grid)
|
||||
svg.append('path')
|
||||
.datum(d3.geoGraticule()())
|
||||
.attr('d', path)
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', '#0d1a28')
|
||||
.attr('stroke-width', 0.4);
|
||||
|
||||
// Agent blinks — resolve duplicates by approximate cell
|
||||
var cellSize = 1.5; // degrees
|
||||
var cells = {};
|
||||
visits.forEach(function(v) {
|
||||
var cell = Math.round(v.lat / cellSize) + ',' + Math.round(v.lon / cellSize);
|
||||
if (!cells[cell]) cells[cell] = { lat: v.lat, lon: v.lon, count: 0 };
|
||||
cells[cell].count++;
|
||||
});
|
||||
var points = Object.values(cells);
|
||||
points.forEach(function(pt, i) {
|
||||
var pos = projection([pt.lon, pt.lat]);
|
||||
if (!pos) return;
|
||||
var r = Math.min(2 + Math.log1p(pt.count) * 1.5, 8);
|
||||
svg.append('circle')
|
||||
.attr('class', 'agent-blink')
|
||||
.attr('cx', pos[0])
|
||||
.attr('cy', pos[1])
|
||||
.attr('r', r)
|
||||
.style('animation-delay', (i * 190 % 5000) + 'ms');
|
||||
});
|
||||
|
||||
// Registrar star — drawn last so it sits on top
|
||||
if (hasRegistrar) {
|
||||
var pos = projection([data.registrarLon, data.registrarLat]);
|
||||
if (pos) {
|
||||
svg.append('text')
|
||||
.attr('class', 'registrar-star')
|
||||
.attr('x', pos[0])
|
||||
.attr('y', pos[1])
|
||||
.text('★');
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function(e) {
|
||||
console.warn('Map load failed:', e);
|
||||
});
|
||||
|
||||
// ── Resize ────────────────────────────────────────────────────────────────
|
||||
window.addEventListener('resize', function() {
|
||||
W = wrap.clientWidth || 800;
|
||||
H = Math.round(W * 0.48);
|
||||
svg.attr('viewBox', '0 0 ' + W + ' ' + H)
|
||||
.attr('width', W).attr('height', H);
|
||||
projection.scale(W / 6.3).translate([W / 2, H / 2]);
|
||||
svg.selectAll('path').attr('d', path);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{/raw}
|
||||
<script src="/dashboard.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user