Skip to content

Commit

Permalink
[1.x] Chart Improvements (#206)
Browse files Browse the repository at this point in the history
* Extract chart components

* Update minimum Livewire version

* Fix scaling
  • Loading branch information
jessarcher authored Dec 11, 2023
1 parent 3e54049 commit 7ec3524
Show file tree
Hide file tree
Showing 5 changed files with 384 additions and 341 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"illuminate/routing": "^10.21",
"illuminate/support": "^10.21",
"illuminate/view": "^10.21",
"livewire/livewire": "^3.02",
"livewire/livewire": "^3.2",
"nesbot/carbon": "^2.67"
},
"require-dev": {
Expand Down
247 changes: 133 additions & 114 deletions resources/views/livewire/queues.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,120 +66,11 @@
<div
wire:ignore
class="h-14"
x-data="{
init() {
let chart = new Chart(
this.$refs.canvas,
{
type: 'line',
data: {
labels: @js($readings->first()->keys()),
datasets: [
{
label: 'Queued',
borderColor: 'rgba(107,114,128,0.5)',
data: @js($readings->get('queued')->values()->map(fn ($value) => $value * (1 / $config['sample_rate']))),
order: 4,
},
{
label: 'Processing',
borderColor: 'rgba(147,51,234,0.5)',
data: @js($readings->get('processing')->values()->map(fn ($value) => $value * (1 / $config['sample_rate']))),
order: 3,
},
{
label: 'Released',
borderColor: '#eab308',
data: @js($readings->get('released')->values()->map(fn ($value) => $value * (1 / $config['sample_rate']))),
order: 2,
},
{
label: 'Processed',
borderColor: '#9333ea',
data: @js($readings->get('processed')->values()->map(fn ($value) => $value * (1 / $config['sample_rate']))),
order: 1,
},
{
label: 'Failed',
borderColor: '#e11d48',
data: @js($readings->get('failed')->values()->map(fn ($value) => $value * (1 / $config['sample_rate']))),
order: 0,
},
],
},
options: {
maintainAspectRatio: false,
layout: {
autoPadding: false,
padding: {
top: 1,
},
},
datasets: {
line: {
borderWidth: 2,
borderCapStyle: 'round',
pointHitRadius: 10,
pointStyle: false,
tension: 0.2,
spanGaps: false,
segment: {
borderColor: (ctx) => ctx.p0.raw === 0 && ctx.p1.raw === 0 ? 'transparent' : undefined,
}
}
},
scales: {
x: {
display: false,
},
y: {
display: false,
min: 0,
max: @js($highest),
},
},
plugins: {
legend: {
display: false,
},
tooltip: {
mode: 'index',
position: 'nearest',
intersect: false,
callbacks: {
beforeBody: (context) => context
.map(item => `${item.dataset.label}: {{ $config['sample_rate'] < 1 ? '~' : ''}}${item.formattedValue}`)
.join(', '),
label: () => null,
},
},
},
},
}
)
Livewire.on('queues-chart-update', ({ queues }) => {
if (chart === undefined) {
return
}
if (queues['{{ $queue }}'] === undefined && chart) {
chart.destroy()
chart = undefined
return
}
chart.data.labels = Object.keys(Object.values(queues['{{ $queue }}'])[0])
chart.options.scales.y.max = Math.max(...Object.values(queues['{{ $queue }}']).map(readings => Math.max(...Object.values(readings))))
chart.data.datasets[0].data = Object.values(queues['{{ $queue }}']['queued']).map(value => value * (1 / {{ $config['sample_rate']}}))
chart.data.datasets[1].data = Object.values(queues['{{ $queue }}']['processing']).map(value => value * (1 / {{ $config['sample_rate']}}))
chart.data.datasets[2].data = Object.values(queues['{{ $queue }}']['released']).map(value => value * (1 / {{ $config['sample_rate']}}))
chart.data.datasets[3].data = Object.values(queues['{{ $queue }}']['processed']).map(value => value * (1 / {{ $config['sample_rate']}}))
chart.data.datasets[4].data = Object.values(queues['{{ $queue }}']['failed']).map(value => value * (1 / {{ $config['sample_rate']}}))
chart.update()
})
}
}"
x-data="queueChart({
queue: '{{ $queue }}',
readings: @js($readings),
sampleRate: {{ $config['sample_rate'] }},
})"
>
<canvas x-ref="canvas" class="ring-1 ring-gray-900/5 dark:ring-gray-100/10 bg-gray-50 dark:bg-gray-800 rounded-md shadow-sm"></canvas>
</div>
Expand All @@ -190,3 +81,131 @@ class="h-14"
@endif
</x-pulse::scroll>
</x-pulse::card>

@script
<script>
Alpine.data('queueChart', (config) => ({
init() {
let chart = new Chart(
this.$refs.canvas,
{
type: 'line',
data: {
labels: this.labels(config.readings),
datasets: [
{
label: 'Queued',
borderColor: 'rgba(107,114,128,0.5)',
data: this.scale(config.readings.queued),
order: 4,
},
{
label: 'Processing',
borderColor: 'rgba(147,51,234,0.5)',
data: this.scale(config.readings.processing),
order: 3,
},
{
label: 'Released',
borderColor: '#eab308',
data: this.scale(config.readings.released),
order: 2,
},
{
label: 'Processed',
borderColor: '#9333ea',
data: this.scale(config.readings.processed),
order: 1,
},
{
label: 'Failed',
borderColor: '#e11d48',
data: this.scale(config.readings.failed),
order: 0,
},
],
},
options: {
maintainAspectRatio: false,
layout: {
autoPadding: false,
padding: {
top: 1,
},
},
datasets: {
line: {
borderWidth: 2,
borderCapStyle: 'round',
pointHitRadius: 10,
pointStyle: false,
tension: 0.2,
spanGaps: false,
segment: {
borderColor: (ctx) => ctx.p0.raw === 0 && ctx.p1.raw === 0 ? 'transparent' : undefined,
}
}
},
scales: {
x: {
display: false,
},
y: {
display: false,
min: 0,
max: this.highest(config.readings),
},
},
plugins: {
legend: {
display: false,
},
tooltip: {
mode: 'index',
position: 'nearest',
intersect: false,
callbacks: {
beforeBody: (context) => context
.map(item => `${item.dataset.label}: ${config.sampleRate < 1 ? '~' : ''}${item.formattedValue}`)
.join(', '),
label: () => null,
},
},
},
},
}
)
Livewire.on('queues-chart-update', ({ queues }) => {
if (chart === undefined) {
return
}
if (queues[config.queue] === undefined && chart) {
chart.destroy()
chart = undefined
return
}
chart.data.labels = this.labels(queues[config.queue])
chart.options.scales.y.max = this.highest(queues[config.queue])
chart.data.datasets[0].data = this.scale(queues[config.queue].queued)
chart.data.datasets[1].data = this.scale(queues[config.queue].processing)
chart.data.datasets[2].data = this.scale(queues[config.queue].released)
chart.data.datasets[3].data = this.scale(queues[config.queue].processed)
chart.data.datasets[4].data = this.scale(queues[config.queue].failed)
chart.update()
})
},
labels(readings) {
return Object.keys(readings.queued)
},
scale(data) {
return Object.values(data).map(value => value * (1 / config.sampleRate ))
},
highest(readings) {
return Math.max(...Object.values(readings).map(dataset => Math.max(...Object.values(dataset)))) * (1 / config.sampleRate)
}
}))
</script>
@endscript
Loading

0 comments on commit 7ec3524

Please sign in to comment.