(function (global) { var MODES = [ { id: 'neo-bars', label: 'Neo staafdiagram' }, { id: 'neo-rings', label: 'Neo ringen' }, { id: 'neo-equalizer', label: 'Neo equalizer' }, { id: 'neo-cards', label: 'Neo kaarten' }, { id: 'neo-table', label: 'Neo tabel' }, ]; var charts = {}; function destroy(key) { if (charts[key]) { charts[key].destroy(); charts[key] = null; } } function colors() { return { gold: 'rgba(252, 211, 77, 0.9)', cyan: 'rgba(56, 189, 248, 0.9)', green: 'rgba(74, 222, 128, 0.9)', red: 'rgba(251, 113, 133, 0.9)', purple: 'rgba(168, 85, 247, 0.9)', gray: 'rgba(159, 176, 196, 0.85)', grid: 'rgba(159, 176, 196, 0.15)', text: '#c8d4e0', }; } function eqBars(counts, cls) { var max = Math.max.apply(null, counts.concat([1])); return '
' + counts.map(function (v) { var h = Math.max(18, Math.round((v / max) * 92)); return ''; }).join('') + '
'; } function findPanel(canvas, alt) { var el = (canvas && canvas.closest('.page-viz-panel')) || (alt && alt.closest('.page-viz-panel')); return el || null; } function applyPanelLayout(canvas, alt, mode) { var panel = findPanel(canvas, alt); if (!panel) return; var isCanvas = mode === 'neo-bars' || mode === 'neo-rings'; panel.classList.toggle('viz-mode-chart', isCanvas); panel.classList.toggle('viz-mode-alt', !isCanvas); panel.classList.toggle('viz-mode-rings', mode === 'neo-rings'); } function useHorizontal(labels, opts) { if (opts && opts.horizontal !== undefined) return opts.horizontal; return (labels || []).length >= 6; } function renderBars(canvas, labels, values, opts) { if (!canvas || typeof Chart === 'undefined') return; opts = opts || { key: 'chart' }; var c = colors(); var horiz = useHorizontal(labels, opts); destroy(opts.key); charts[opts.key] = new Chart(canvas, { type: 'bar', data: { labels: labels, datasets: [{ data: values, backgroundColor: opts.color || c.cyan, borderRadius: 6, barThickness: horiz ? 'flex' : undefined, maxBarThickness: horiz ? 28 : 48 }], }, options: { indexAxis: horiz ? 'y' : 'x', responsive: true, maintainAspectRatio: false, layout: { padding: { top: 4, right: 8, bottom: 4, left: 4 } }, plugins: { legend: { display: false }, title: { display: !!opts.title, text: opts.title, color: c.text, padding: { bottom: 8 } } }, scales: { y: horiz ? { ticks: { color: c.text, autoSkip: false, font: { size: 11 } }, grid: { color: c.grid } } : { ticks: { color: c.text }, grid: { color: c.grid }, beginAtZero: true }, x: horiz ? { ticks: { color: c.text }, grid: { display: false }, beginAtZero: true } : { ticks: { color: c.text, maxRotation: 45, minRotation: 0, autoSkip: false, font: { size: 10 } }, grid: { display: false } }, }, }, }); requestAnimationFrame(function () { if (charts[opts.key]) charts[opts.key].resize(); }); } function renderRings(canvas, labels, values, key, title) { if (!canvas || typeof Chart === 'undefined') return; var c = colors(); destroy(key); charts[key] = new Chart(canvas, { type: 'doughnut', data: { labels: labels, datasets: [{ data: values, backgroundColor: [c.green, c.gray, c.red, c.gold, c.cyan, c.purple], borderWidth: 0 }], }, options: { responsive: true, maintainAspectRatio: false, cutout: '62%', layout: { padding: 4 }, plugins: { legend: { position: 'bottom', labels: { color: c.text, boxWidth: 10, padding: 8, font: { size: 10 } } }, title: { display: !!title, text: title, color: c.text, font: { size: 11 } }, }, }, }); requestAnimationFrame(function () { if (charts[key]) charts[key].resize(); }); } function renderCards(container, rows) { if (!container) return; container.innerHTML = '
' + rows.map(function (r) { return '
' + r.label + '' + r.value + '
'; }).join('') + '
'; } function renderTable(container, rows) { if (!container) return; container.innerHTML = '' + rows.map(function (r) { return ''; }).join('') + '
ItemWaarde
' + r.label + '' + r.value + '
'; } function renderEqualizer(container, rows, cls) { if (!container) return; container.innerHTML = rows.map(function (r) { return '
' + r.label + '' + r.value + '
'; }).join('') + eqBars(rows.map(function (r) { return Number(r.raw) || 0; }), cls); } function renderWidget(mode, spec) { var canvas = spec.canvas; var alt = spec.altContainer; applyPanelLayout(canvas, alt, mode); if (mode === 'neo-bars' && canvas) { if (alt) alt.innerHTML = ''; canvas.style.display = ''; renderBars(canvas, spec.labels, spec.values, spec.chartOpts || { key: spec.key }); return; } if (mode === 'neo-rings' && canvas) { if (alt) alt.innerHTML = ''; canvas.style.display = ''; renderRings(canvas, spec.labels, spec.values, spec.key, spec.title); return; } if (canvas) canvas.style.display = 'none'; if (!alt) return; if (mode === 'neo-equalizer') renderEqualizer(alt, spec.rows, spec.eqClass); else if (mode === 'neo-cards') renderCards(alt, spec.rows); else if (mode === 'neo-table') renderTable(alt, spec.rows); else { if (canvas) { canvas.style.display = ''; renderBars(canvas, spec.labels, spec.values, spec.chartOpts || { key: spec.key }); } } } global.VizEngine = { MODES: MODES, renderWidget: renderWidget, destroyAll: function () { Object.keys(charts).forEach(destroy); }, renderSentiment: function (mode, canvas, alt, stats, widgetMode) { var m = widgetMode || mode; var files = stats.nas_files || []; var counts = { positive: 0, neutral: 0, negative: 0 }; files.forEach(function (f) { var s = (f.sentiment_label || 'neutral').toLowerCase(); if (counts[s] !== undefined) counts[s]++; }); if (!files.length) counts.neutral = 1; renderWidget(m, { canvas: canvas, altContainer: alt, key: 'sentiment', labels: ['Positief', 'Neutraal', 'Negatief'], values: [counts.positive, counts.neutral, counts.negative], title: 'NAS sentiment', rows: [ { label: 'Positief', value: counts.positive, raw: counts.positive }, { label: 'Neutraal', value: counts.neutral, raw: counts.neutral }, { label: 'Negatief', value: counts.negative, raw: counts.negative }, ], eqClass: 'hm-eq-purple', }); }, renderAgents: function (mode, canvas, alt, stats, widgetMode) { var m = widgetMode || mode; var map = {}; (stats.recent_events || []).forEach(function (e) { var a = e.agent_name || 'other'; map[a] = (map[a] || 0) + 1; }); var labels = Object.keys(map); var values = labels.map(function (k) { return map[k]; }); if (!labels.length) { labels = ['geen']; values = [0]; } renderWidget(m, { canvas: canvas, altContainer: alt, key: 'agents', labels: labels, values: values, title: 'Agent activiteit', chartOpts: { key: 'agents', color: colors().gold }, rows: labels.map(function (l, i) { return { label: l, value: values[i], raw: values[i] }; }), eqClass: 'hm-eq-lime', }); }, renderFromRows: function (mode, canvas, alt, key, title, rows, eqClass, chartColor) { var labels = rows.map(function (r) { return r.label; }); var values = rows.map(function (r) { return Number(r.raw) || 0; }); renderWidget(mode, { canvas: canvas, altContainer: alt, key: key, labels: labels, values: values, title: title, chartOpts: { key: key, color: chartColor || colors().cyan }, rows: rows, eqClass: eqClass || 'hm-eq-cyan', }); }, }; })(window);