feat: ability to choose number of top entities to display (resolve #81)

This commit is contained in:
Ferdinand Mütsch 2021-01-05 12:41:01 +01:00
parent 39c4777fc8
commit 9766d8e903
3 changed files with 79 additions and 39 deletions

View File

@ -1,4 +1,3 @@
const SHOW_TOP_N = 10
const CHART_TARGET_SIZE = 200 const CHART_TARGET_SIZE = 200
const projectsCanvas = document.getElementById('chart-projects') const projectsCanvas = document.getElementById('chart-projects')
@ -17,7 +16,16 @@ const containers = [projectContainer, osContainer, editorContainer, languageCont
const canvases = [projectsCanvas, osCanvas, editorsCanvas, languagesCanvas, machinesCanvas] const canvases = [projectsCanvas, osCanvas, editorsCanvas, languagesCanvas, machinesCanvas]
const data = [wakapiData.projects, wakapiData.operatingSystems, wakapiData.editors, wakapiData.languages, wakapiData.machines] const data = [wakapiData.projects, wakapiData.operatingSystems, wakapiData.editors, wakapiData.languages, wakapiData.machines]
let topNPickers = [...document.getElementsByClassName('top-picker')]
topNPickers.sort(((a, b) => parseInt(a.attributes['data-entity'].value) - parseInt(b.attributes['data-entity'].value)))
topNPickers.forEach(e => {
const idx = parseInt(e.attributes['data-entity'].value)
e.max = Math.min(data[idx].length, 10)
e.value = e.max
})
let charts = [] let charts = []
let showTopN = []
let resizeCount = 0 let resizeCount = 0
String.prototype.toHHMMSS = function () { String.prototype.toHHMMSS = function () {
@ -38,7 +46,7 @@ String.prototype.toHHMMSS = function () {
return hours + ':' + minutes + ':' + seconds return hours + ':' + minutes + ':' + seconds
} }
function draw() { function draw(subselection) {
function getTooltipOptions(key, type) { function getTooltipOptions(key, type) {
return { return {
mode: 'single', mode: 'single',
@ -53,14 +61,20 @@ function draw() {
} }
} }
charts.forEach(c => c.destroy()) function shouldUpdate(index) {
return !subselection || (subselection.includes(index) && data[index].length >= showTopN[index])
}
let projectChart = !projectsCanvas.classList.contains('hidden') charts
.filter((c, i) => shouldUpdate(i))
.forEach(c => c.destroy())
let projectChart = !projectsCanvas.classList.contains('hidden') && shouldUpdate(0)
? new Chart(projectsCanvas.getContext('2d'), { ? new Chart(projectsCanvas.getContext('2d'), {
type: 'horizontalBar', type: 'horizontalBar',
data: { data: {
datasets: wakapiData.projects datasets: wakapiData.projects
.slice(0, Math.min(SHOW_TOP_N, wakapiData.projects.length)) .slice(0, Math.min(showTopN[0], wakapiData.projects.length))
.map(p => { .map(p => {
return { return {
label: p.key, label: p.key,
@ -88,18 +102,18 @@ function draw() {
}) })
: null : null
let osChart = !osCanvas.classList.contains('hidden') let osChart = !osCanvas.classList.contains('hidden') && shouldUpdate(1)
? new Chart(osCanvas.getContext('2d'), { ? new Chart(osCanvas.getContext('2d'), {
type: 'pie', type: 'pie',
data: { data: {
datasets: [{ datasets: [{
data: wakapiData.operatingSystems data: wakapiData.operatingSystems
.slice(0, Math.min(SHOW_TOP_N, wakapiData.operatingSystems.length)) .slice(0, Math.min(showTopN[1], wakapiData.operatingSystems.length))
.map(p => parseInt(p.total)), .map(p => parseInt(p.total)),
backgroundColor: wakapiData.operatingSystems.map(p => getRandomColor(p.key)) backgroundColor: wakapiData.operatingSystems.map(p => getRandomColor(p.key))
}], }],
labels: wakapiData.operatingSystems labels: wakapiData.operatingSystems
.slice(0, Math.min(SHOW_TOP_N, wakapiData.operatingSystems.length)) .slice(0, Math.min(showTopN[1], wakapiData.operatingSystems.length))
.map(p => p.key) .map(p => p.key)
}, },
options: { options: {
@ -110,18 +124,18 @@ function draw() {
}) })
: null : null
let editorChart = !editorsCanvas.classList.contains('hidden') let editorChart = !editorsCanvas.classList.contains('hidden') && shouldUpdate(2)
? new Chart(editorsCanvas.getContext('2d'), { ? new Chart(editorsCanvas.getContext('2d'), {
type: 'pie', type: 'pie',
data: { data: {
datasets: [{ datasets: [{
data: wakapiData.editors data: wakapiData.editors
.slice(0, Math.min(SHOW_TOP_N, wakapiData.editors.length)) .slice(0, Math.min(showTopN[2], wakapiData.editors.length))
.map(p => parseInt(p.total)), .map(p => parseInt(p.total)),
backgroundColor: wakapiData.editors.map(p => getRandomColor(p.key)) backgroundColor: wakapiData.editors.map(p => getRandomColor(p.key))
}], }],
labels: wakapiData.editors labels: wakapiData.editors
.slice(0, Math.min(SHOW_TOP_N, wakapiData.editors.length)) .slice(0, Math.min(showTopN[2], wakapiData.editors.length))
.map(p => p.key) .map(p => p.key)
}, },
options: { options: {
@ -132,18 +146,18 @@ function draw() {
}) })
: null : null
let languageChart = !languagesCanvas.classList.contains('hidden') let languageChart = !languagesCanvas.classList.contains('hidden') && shouldUpdate(3)
? new Chart(languagesCanvas.getContext('2d'), { ? new Chart(languagesCanvas.getContext('2d'), {
type: 'pie', type: 'pie',
data: { data: {
datasets: [{ datasets: [{
data: wakapiData.languages data: wakapiData.languages
.slice(0, Math.min(SHOW_TOP_N, wakapiData.languages.length)) .slice(0, Math.min(showTopN[3], wakapiData.languages.length))
.map(p => parseInt(p.total)), .map(p => parseInt(p.total)),
backgroundColor: wakapiData.languages.map(p => languageColors[p.key.toLowerCase()] || getRandomColor(p.key)) backgroundColor: wakapiData.languages.map(p => languageColors[p.key.toLowerCase()] || getRandomColor(p.key))
}], }],
labels: wakapiData.languages labels: wakapiData.languages
.slice(0, Math.min(SHOW_TOP_N, wakapiData.languages.length)) .slice(0, Math.min(showTopN[3], wakapiData.languages.length))
.map(p => p.key) .map(p => p.key)
}, },
options: { options: {
@ -154,18 +168,18 @@ function draw() {
}) })
: null : null
let machineChart = !machinesCanvas.classList.contains('hidden') let machineChart = !machinesCanvas.classList.contains('hidden') && shouldUpdate(4)
? new Chart(machinesCanvas.getContext('2d'), { ? new Chart(machinesCanvas.getContext('2d'), {
type: 'pie', type: 'pie',
data: { data: {
datasets: [{ datasets: [{
data: wakapiData.machines data: wakapiData.machines
.slice(0, Math.min(SHOW_TOP_N, wakapiData.machines.length)) .slice(0, Math.min(showTopN[4], wakapiData.machines.length))
.map(p => parseInt(p.total)), .map(p => parseInt(p.total)),
backgroundColor: wakapiData.machines.map(p => getRandomColor(p.key)) backgroundColor: wakapiData.machines.map(p => getRandomColor(p.key))
}], }],
labels: wakapiData.machines labels: wakapiData.machines
.slice(0, Math.min(SHOW_TOP_N, wakapiData.machines.length)) .slice(0, Math.min(showTopN[4], wakapiData.machines.length))
.map(p => p.key) .map(p => p.key)
}, },
options: { options: {
@ -180,13 +194,14 @@ function draw() {
charts = [projectChart, osChart, editorChart, languageChart, machineChart].filter(c => !!c) charts = [projectChart, osChart, editorChart, languageChart, machineChart].filter(c => !!c)
charts.forEach(c => c.options.onResize(c.chart)) if (!subselection) {
equalizeHeights() charts.forEach(c => c.options.onResize(c.chart))
equalizeHeights()
}
} }
function setTopLabels() { function parseTopN() {
[...document.getElementsByClassName('top-label')] showTopN = topNPickers.map(e => parseInt(e.value))
.forEach(e => e.innerText = `(top ${SHOW_TOP_N})`)
} }
function togglePlaceholders(mask) { function togglePlaceholders(mask) {
@ -301,7 +316,12 @@ window.addEventListener('click', function (event) {
}) })
window.addEventListener('load', function () { window.addEventListener('load', function () {
setTopLabels() topNPickers.forEach(e => e.addEventListener('change', () => {
parseTopN()
draw([parseInt(e.attributes['data-entity'].value)])
}))
parseTopN()
togglePlaceholders(getPresentDataMask()) togglePlaceholders(getPresentDataMask())
draw() draw()
}) })

View File

@ -1 +1 @@
1.17.4 1.18.0

View File

@ -66,9 +66,13 @@
<div class="flex flex-wrap justify-center"> <div class="flex flex-wrap justify-center">
<div class="w-full lg:w-1/2 p-1"> <div class="w-full lg:w-1/2 p-1">
<div class="p-4 pb-10 bg-white rounded shadow m-2 flex flex-col" id="project-container" style="height: 300px"> <div class="p-4 pb-10 bg-white rounded shadow m-2 flex flex-col" id="project-container" style="height: 300px">
<div class="self-center flex"> <div class="flex justify-between">
<span class="font-semibold mr-1">Projects</span> <div class="w-1/4 flex-1"></div>
<span id="project-top-label" class="top-label"></span> <span class="font-semibold w-1/2 text-center flex-1">Projects</span>
<div class="flex justify-end flex-1 text-xs items-center">
<label for="project-top-picker" class="mr-1">Show:&nbsp;</label>
<input type="number" min="1" id="project-top-picker" data-entity="0" class="w-1/4 top-picker bg-gray-200 rounded-md text-center" value="10">
</div>
</div> </div>
<canvas id="chart-projects"></canvas> <canvas id="chart-projects"></canvas>
<div class="hidden placeholder-container flex items-center justify-center h-full flex-col"> <div class="hidden placeholder-container flex items-center justify-center h-full flex-col">
@ -79,9 +83,13 @@
</div> </div>
<div class="w-full lg:w-1/2 p-1"> <div class="w-full lg:w-1/2 p-1">
<div class="p-4 pb-10 bg-white rounded shadow m-2 flex flex-col" id="os-container" style="height: 300px"> <div class="p-4 pb-10 bg-white rounded shadow m-2 flex flex-col" id="os-container" style="height: 300px">
<div class="self-center flex"> <div class="flex justify-between">
<span class="font-semibold mr-1">Operating Systems</span> <div class="w-1/4 flex-1"></div>
<span id="os-top-label" class="top-label"></span> <span class="font-semibold w-1/2 text-center flex-1">Operating Systems</span>
<div class="flex justify-end flex-1 text-xs items-center">
<label for="os-top-picker" class="mr-1">Show:&nbsp;</label>
<input type="number" min="1" id="os-top-picker" data-entity="1" class="w-1/4 top-picker bg-gray-200 rounded-md text-center" value="10">
</div>
</div> </div>
<canvas id="chart-os"></canvas> <canvas id="chart-os"></canvas>
<div class="hidden placeholder-container flex items-center justify-center h-full flex-col"> <div class="hidden placeholder-container flex items-center justify-center h-full flex-col">
@ -92,9 +100,13 @@
</div> </div>
<div class="w-full lg:w-1/2 p-1"> <div class="w-full lg:w-1/2 p-1">
<div class="p-4 pb-10 bg-white rounded shadow m-2 flex flex-col relative" id="language-container" style="height: 300px"> <div class="p-4 pb-10 bg-white rounded shadow m-2 flex flex-col relative" id="language-container" style="height: 300px">
<div class="self-center flex"> <div class="flex justify-between">
<span class="font-semibold mr-1">Languages</span> <div class="w-1/4 flex-1"></div>
<span id="language-top-label" class="top-label"></span> <span class="font-semibold w-1/2 text-center flex-1">Languages</span>
<div class="flex justify-end flex-1 text-xs items-center">
<label for="language-top-picker" class="mr-1">Show:&nbsp;</label>
<input type="number" min="1" id="language-top-picker" data-entity="3" class="w-1/4 top-picker bg-gray-200 rounded-md text-center" value="10">
</div>
</div> </div>
<canvas id="chart-language"></canvas> <canvas id="chart-language"></canvas>
<div class="hidden placeholder-container flex items-center justify-center h-full flex-col"> <div class="hidden placeholder-container flex items-center justify-center h-full flex-col">
@ -105,9 +117,13 @@
</div> </div>
<div class="w-full lg:w-1/2 p-1"> <div class="w-full lg:w-1/2 p-1">
<div class="p-4 pb-10 bg-white rounded shadow m-2 flex flex-col" id="editor-container" style="height: 300px"> <div class="p-4 pb-10 bg-white rounded shadow m-2 flex flex-col" id="editor-container" style="height: 300px">
<div class="self-center flex"> <div class="flex justify-between">
<span class="font-semibold mr-1">Editors</span> <div class="w-1/4 flex-1"></div>
<span id="editor-top-label" class="top-label"></span> <span class="font-semibold w-1/2 text-center flex-1">Editors</span>
<div class="flex justify-end flex-1 text-xs items-center">
<label for="editor-top-picker" class="mr-1">Show:&nbsp;</label>
<input type="number" min="1" id="editor-top-picker" data-entity="2" class="w-1/4 top-picker bg-gray-200 rounded-md text-center" value="10">
</div>
</div> </div>
<canvas id="chart-editor"></canvas> <canvas id="chart-editor"></canvas>
<div class="hidden placeholder-container flex items-center justify-center h-full flex-col"> <div class="hidden placeholder-container flex items-center justify-center h-full flex-col">
@ -118,9 +134,13 @@
</div> </div>
<div class="w-full lg:w-1/2 p-1"> <div class="w-full lg:w-1/2 p-1">
<div class="p-4 pb-10 bg-white rounded shadow m-2 flex flex-col" id="machine-container" style="height: 300px"> <div class="p-4 pb-10 bg-white rounded shadow m-2 flex flex-col" id="machine-container" style="height: 300px">
<div class="self-center flex"> <div class="flex justify-between">
<span class="font-semibold mr-1">Machines</span> <div class="w-1/4 flex-1"></div>
<span id="machine-top-label" class="top-label"></span> <span class="font-semibold w-1/2 text-center flex-1">Machines</span>
<div class="flex justify-end flex-1 text-xs items-center">
<label for="machine-top-picker" class="mr-1">Show:&nbsp;</label>
<input type="number" min="1" id="machine-top-picker" data-entity="4" class="w-1/4 top-picker bg-gray-200 rounded-md text-center" value="10">
</div>
</div> </div>
<canvas id="chart-machine"></canvas> <canvas id="chart-machine"></canvas>
<div class="hidden placeholder-container flex items-center justify-center h-full flex-col"> <div class="hidden placeholder-container flex items-center justify-center h-full flex-col">