1
0
mirror of https://github.com/ohwgiles/laminar.git synced 2026-10-12 22:20:47 +00:00

3 Commits

Author SHA1 Message Date
Oliver Giles
7ed63abd0d Better average line in Build time graph
The technique to display the average line in the old Chart.js
does not look so great in the new version. Take a different
approach using a plugin instead.
2022-10-26 20:14:21 +13:00
Guilherme Lima
9db4211091 Minor tweaks to charts appearance
Some charts had a more 'curvy' look to it. Adjusted this by using the
'tension' parameter.
Adjusted 'Utilization' pie chart aspect ratio so it is not so big.
2022-10-04 23:36:32 +02:00
Guilherme Lima
b38cbe5827 Update Chart.js to version 3.9
Fixes #175

Following 3.x Migration Guide, here is a list of the changes:

https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#specific-changes
- Chart.scaleService was replaced with Chart.registry. Scale defaults are now in Chart.defaults.scales[type].
- scales.[x/y]Axes arrays were removed. Scales are now configured directly to options.scales object with the object key being the scale Id.
- scales.[x/y]Axes.barPercentage was moved to dataset option barPercentages
- scales.[x/y]Axes.barThickness was moved to dataset option barThickness
- scales.[x/y]Axes.scaleLabel was renamed to scales[id].title
- scales.[x/y]Axes.scaleLabel.labelString was renamed to scales[id].title.text
- scales.[x/y]Axes.ticks.userCallback was renamed to scales[id].ticks.callback
- tooltips namespace was renamed to tooltip to match the plugin name
- legend, title and tooltip namespaces were moved from options to options.plugins

https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#defaults
- legend, title and tooltip namespaces were moved from Chart.defaults to Chart.defaults.plugins.
- elements.line.fill default changed from true to false

https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#chart-types
- horizontalBar chart type was removed. Horizontal bar charts can be configured using the new indexAxis option

https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#tooltip
- xLabel and yLabel were removed. Please use label and formattedValue
- The callbacks no longer are given a data parameter. The tooltip item parameter contains the chart and dataset instead
- The tooltip item's index parameter was renamed to dataIndex and value was renamed to formattedValue

https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#ticks
- options.gridLines was renamed to options.gridLines
2022-09-28 00:22:36 +02:00
2 changed files with 107 additions and 84 deletions

View File

@@ -87,8 +87,8 @@ file(DOWNLOAD https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.12/vue.min.js
js/vue.min.js EXPECTED_MD5 fb192338844efe86ec759a40152fcb8e)
file(DOWNLOAD https://raw.githubusercontent.com/drudru/ansi_up/v4.0.4/ansi_up.js
js/ansi_up.js EXPECTED_MD5 b31968e1a8fed0fa82305e978161f7f5)
file(DOWNLOAD https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js
js/Chart.min.js EXPECTED_MD5 f6c8efa65711e0cbbc99ba72997ecd0e)
file(DOWNLOAD https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js
js/Chart.min.js EXPECTED_MD5 7dd5ea7d2cf22a1c42b43c40093d2669)
# ...and compile them
generate_compressed_bins(${CMAKE_BINARY_DIR} js/vue.min.js
js/ansi_up.js js/Chart.min.js)

View File

@@ -129,7 +129,8 @@ const Charts = (() => {
}]
},
options: {
hover: { mode: null }
hover: { mode: null },
aspectRatio: 2
}
});
c.executorBusyChanged = busy => {
@@ -159,20 +160,28 @@ const Charts = (() => {
datasets: [{
label: 'Failed Builds',
backgroundColor: "#883d3d",
data: data.map(e => e.failed || 0)
data: data.map(e => e.failed || 0),
fill: true,
tension: 0.35,
},{
label: 'Successful Builds',
backgroundColor: "#74af77",
data: data.map(e => e.success || 0)
data: data.map(e => e.success || 0),
fill: true,
tension: 0.35,
}]
},
options:{
title: { display: true, text: 'Runs per day' },
tooltips:{callbacks:{title: (tip, data) => dayNames[tip[0].index].long}},
scales:{yAxes:[{
ticks:{userCallback: (label, index, labels) => Number.isInteger(label) ? label: null},
stacked: true
}]}
plugins: {
title: { display: true, text: 'Runs per day' },
tooltip:{callbacks:{title: (tip) => dayNames[tip[0].dataIndex].long}},
},
scales: {
y: {
ticks:{callback: (label, index, labels) => Number.isInteger(label) ? label: null},
stacked: true
},
},
}
});
c.jobCompleted = success => {
@@ -183,7 +192,7 @@ const Charts = (() => {
},
createRunsPerJobChart: (id, data) => {
const c = new Chart(document.getElementById("chartBpj"), {
type: 'horizontalBar',
type: 'bar',
data: {
labels: Object.keys(data),
datasets: [{
@@ -193,9 +202,16 @@ const Charts = (() => {
}]
},
options:{
title: { display: true, text: 'Runs per job' },
indexAxis: 'y',
plugins: {
title: { display: true, text: 'Runs per job' },
},
hover: { mode: null },
scales:{xAxes:[{ticks:{userCallback: (label, index, labels)=> Number.isInteger(label) ? label: null}}]}
scales: {
x: {
ticks:{callback: (label, index, labels)=> Number.isInteger(label) ? label: null}
}
}
}
});
c.jobCompleted = name => {
@@ -216,7 +232,7 @@ const Charts = (() => {
createTimePerJobChart: (id, data, completedCounts) => {
const scale = timeScale(Math.max(...Object.values(data)));
const c = new Chart(document.getElementById(id), {
type: 'horizontalBar',
type: 'bar',
data: {
labels: Object.keys(data),
datasets: [{
@@ -226,18 +242,23 @@ const Charts = (() => {
}]
},
options:{
title: { display: true, text: 'Mean run time this week' },
indexAxis: 'y',
plugins: {
title: { display: true, text: 'Mean run time this week' },
tooltip:{callbacks:{
label: (tip) => tip.dataset.label + ': ' + tip.raw.toFixed(2) + ' ' + scale.label.toLowerCase()
}}
},
hover: { mode: null },
scales:{xAxes:[{
ticks:{userCallback: scale.ticks},
scaleLabel: {
display: true,
labelString: scale.label
scales: {
x:{
ticks: {callback: scale.ticks},
title: {
display: true,
text: scale.label
}
}
}]},
tooltips:{callbacks:{
label: (tip, data) => data.datasets[tip.datasetIndex].label + ': ' + tip.xLabel.toFixed(2) + ' ' + scale.label.toLowerCase()
}}
},
}
});
c.jobCompleted = (name, time) => {
@@ -261,7 +282,8 @@ const Charts = (() => {
label: name,
data: durations.map(x => x * scale.factor),
borderColor: 'hsl('+(name.hashCode() % 360)+', 27%, 57%)',
backgroundColor: 'transparent'
backgroundColor: 'transparent',
tension: 0.35,
});
const c = new Chart(document.getElementById(id), {
type: 'line',
@@ -270,21 +292,21 @@ const Charts = (() => {
datasets: data.map(e => dataValue(e.name, e.durations))
},
options:{
title: { display: true, text: 'Run time changes' },
legend:{ display: true, position: 'bottom' },
scales:{
xAxes:[{ticks:{display: false}}],
yAxes:[{
ticks:{userCallback: scale.ticks},
scaleLabel: {
display: true,
labelString: scale.label
}
}]
plugins: {
legend: { display: true, position: 'bottom' },
title: { display: true, text: 'Run time changes' },
tooltip: { enabled: false },
},
scales:{
x: {ticks: {display: false}},
y: {
ticks: {callback: scale.ticks},
title: {
display: true,
text: scale.label
}
}
},
tooltips:{
enabled:false
}
}
});
c.jobCompleted = (name, time) => {
@@ -310,62 +332,65 @@ const Charts = (() => {
data: {
labels: jobs.map(e => '#' + e.number).reverse(),
datasets: [{
label: 'Average',
type: 'line',
data: [{x:0, y:avg * scale.factor}, {x:1, y:avg * scale.factor}],
borderColor: '#7483af',
backgroundColor: 'transparent',
xAxisID: 'avg',
pointRadius: 0,
pointHitRadius: 0,
pointHoverRadius: 0,
},{
label: 'Build time',
backgroundColor: jobs.map(e => e.result == 'success' ? '#74af77': '#883d3d').reverse(),
barPercentage: 1.0,
categoryPercentage: 0.95,
data: jobs.map(e => (e.completed - e.started) * scale.factor).reverse()
}]
},
options: {
title: { display: true, text: 'Build time' },
plugins: {
title: { display: true, text: 'Build time' },
tooltip: {
callbacks:{
label: (tip) => scale.ticks(tip.raw) + ' ' + scale.label.toLowerCase()
}
}
},
hover: { mode: null },
scales:{
xAxes:[{
categoryPercentage: 0.95,
barPercentage: 1.0
},{
id: 'avg',
type: 'linear',
ticks: {
display: false
},
gridLines: {
x: {
grid: {
display: false,
drawBorder: false
}
}],
yAxes:[{
ticks:{userCallback: scale.ticks},
scaleLabel:{display: true, labelString: scale.label}
}]
},
y: {
suggestedMax: avg * scale.factor,
ticks: {callback: scale.ticks },
title: {display: true, text: scale.label}
}
},
tooltips:{callbacks:{
label: (tip, data) => scale.ticks(tip.yLabel) + ' ' + scale.label.toLowerCase()
}}
}
},
plugins: [{
afterDraw: (chart, args, options) => {
const {ctx, avg, chartArea, scales:{y:yaxis}} = chart;
const y = chartArea.top + yaxis.height - avg * scale.factor * yaxis.height / yaxis.end;
ctx.save();
ctx.beginPath();
ctx.translate(chartArea.left, y);
ctx.moveTo(0,0);
ctx.lineTo(chartArea.width, 0);
ctx.lineWidth = 2;
ctx.strokeStyle = '#7483af';
ctx.stroke();
ctx.restore();
}
}]
});
c.avg = avg;
c.jobCompleted = (num, result, time) => {
let avg = c.data.datasets[0].data[0].y / scale.factor;
avg = ((avg * (num - 1)) + time) / num;
c.data.datasets[0].data[0].y = avg * scale.factor;
c.data.datasets[0].data[1].y = avg * scale.factor;
if(c.data.datasets[1].data.length == 20) {
c.avg = ((c.avg * (num - 1)) + time) / num;
c.options.scales.y.suggestedMax = avg * scale.factor;
if(c.data.datasets[0].data.length == 20) {
c.data.labels.shift();
c.data.datasets[1].data.shift();
c.data.datasets[1].backgroundColor.shift();
c.data.datasets[0].data.shift();
c.data.datasets[0].backgroundColor.shift();
}
c.data.labels.push('#' + num);
c.data.datasets[1].data.push(time * scale.factor);
c.data.datasets[1].backgroundColor.push(result == 'success' ? '#74af77': '#883d3d');
c.data.datasets[0].data.push(time * scale.factor);
c.data.datasets[0].backgroundColor.push(result == 'success' ? '#74af77': '#883d3d');
c.update();
};
return c;
@@ -374,13 +399,11 @@ const Charts = (() => {
})();
// For all charts, set miniumum Y to 0
Chart.scaleService.updateScaleDefaults('linear', {
ticks: { suggestedMin: 0 }
});
Chart.defaults.scales.linear.suggestedMin = 0;
// Don't display legend by default
Chart.defaults.global.legend.display = false;
Chart.defaults.plugins.legend.display = false;
// Disable tooltip hover animations
Chart.defaults.global.hover.animationDuration = 0;
Chart.defaults.plugins.tooltip.animation = false;
// Component for the / endpoint
const Home = templateId => {