mirror of https://github.com/muety/wakapi.git
feat: ability to choose number of top entities to display (resolve #81)
This commit is contained in:
parent
39c4777fc8
commit
9766d8e903
|
@ -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()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
1.17.4
|
1.18.0
|
||||||
|
|
|
@ -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: </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: </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: </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: </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: </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">
|
||||||
|
|
Loading…
Reference in New Issue