Skip to content

Commit 75fd5b9

Browse files
committed
fix: Ensure chart always shows as line chart with filled areas
- Fix data extraction to use toArray() for reliable data structure - For single data point, create a second point to form a line segment - Ensure chart always renders as line chart (not just points) for all time periods - Maintain filled area styling for all datasets - Fix chart rendering for 'last hour' and 'last 6 hours' periods
1 parent 929c067 commit 75fd5b9

File tree

1 file changed

+78
-22
lines changed

1 file changed

+78
-22
lines changed

resources/vantage-views/dashboard.blade.php

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -677,13 +677,26 @@
677677
return;
678678
}
679679
680-
// Prepare data
681-
const hours = @json($jobsByHour->pluck('hour'));
682-
const totals = @json($jobsByHour->pluck('count'));
683-
const failures = @json($jobsByHour->pluck('failed_count'));
680+
// Prepare data - ensure we get proper arrays
681+
const jobsData = @json($jobsByHour->toArray());
684682
685-
// Ensure we have data
686-
if (!hours || hours.length === 0) {
683+
if (!jobsData || jobsData.length === 0) {
684+
if (ctx && ctx.parentElement) {
685+
ctx.parentElement.innerHTML = '<div class="p-4 text-gray-500 text-center">No data available for the selected time period.</div>';
686+
}
687+
return;
688+
}
689+
690+
// Extract arrays from data
691+
const hours = jobsData.map(item => item.hour);
692+
const totals = jobsData.map(item => parseInt(item.count) || 0);
693+
const failures = jobsData.map(item => parseInt(item.failed_count) || 0);
694+
695+
// Ensure arrays are valid and same length
696+
if (hours.length === 0 || totals.length === 0 || hours.length !== totals.length) {
697+
if (ctx && ctx.parentElement) {
698+
ctx.parentElement.innerHTML = '<div class="p-4 text-gray-500 text-center">No data available for the selected time period.</div>';
699+
}
687700
return;
688701
}
689702
@@ -721,73 +734,116 @@
721734
return;
722735
}
723736
737+
// For single data point, create a small time range to show as a line
738+
// This ensures the chart always shows as a line chart with filled area
739+
let chartLabels = labels;
740+
let chartSuccessRates = successRates;
741+
let chartTotals = totals;
742+
let chartFailures = failures;
743+
744+
if (labels.length === 1) {
745+
// Create a second point 1 hour later to form a line segment
746+
try {
747+
const singleDate = new Date(hours[0].replace(' ', 'T'));
748+
const nextHour = new Date(singleDate.getTime() + 60 * 60 * 1000);
749+
const nextLabel = nextHour.toLocaleDateString('en-US', { month: 'short', day: 'numeric', hour: '2-digit' });
750+
751+
chartLabels = [labels[0], nextLabel];
752+
chartSuccessRates = [successRates[0], successRates[0]];
753+
chartTotals = [totals[0], totals[0]];
754+
chartFailures = [failures[0], failures[0]];
755+
} catch (e) {
756+
// Fallback: just duplicate if date parsing fails
757+
chartLabels = [labels[0], labels[0]];
758+
chartSuccessRates = [successRates[0], successRates[0]];
759+
chartTotals = [totals[0], totals[0]];
760+
chartFailures = [failures[0], failures[0]];
761+
}
762+
}
763+
724764
try {
725-
// Ensure single data points are visible with larger point radius
726-
const pointRadius = labels.length === 1 ? 8 : 3;
727-
const pointHoverRadius = labels.length === 1 ? 10 : 5;
765+
// Point radius - smaller for single point (since we duplicate it)
766+
const pointRadius = 4;
767+
const pointHoverRadius = 6;
728768
729769
const chart = new Chart(ctx, {
730770
type: 'line',
731771
data: {
732-
labels: labels,
772+
labels: chartLabels,
733773
datasets: [
734774
{
735775
label: 'Success Rate (%)',
736-
data: successRates,
776+
data: chartSuccessRates,
737777
borderColor: 'rgb(34, 197, 94)',
738778
backgroundColor: 'rgba(34, 197, 94, 0.1)',
779+
borderWidth: 2,
739780
tension: 0.4,
740781
fill: true,
741782
yAxisID: 'y',
742783
pointRadius: pointRadius,
743784
pointHoverRadius: pointHoverRadius,
744-
pointBackgroundColor: function(context) {
745-
return context.dataset.borderColor;
746-
},
785+
pointBackgroundColor: 'rgb(34, 197, 94)',
747786
pointBorderColor: '#fff',
748787
pointBorderWidth: 2,
788+
// Ensure line is visible even with single point
789+
spanGaps: false,
790+
showLine: true,
749791
},
750792
{
751793
label: 'Total Jobs',
752-
data: totals,
794+
data: chartTotals,
753795
borderColor: 'rgb(99, 102, 241)',
754796
backgroundColor: 'rgba(99, 102, 241, 0.1)',
797+
borderWidth: 2,
755798
tension: 0.4,
756799
fill: true,
757800
yAxisID: 'y1',
758801
pointRadius: pointRadius,
759802
pointHoverRadius: pointHoverRadius,
760-
pointBackgroundColor: function(context) {
761-
return context.dataset.borderColor;
762-
},
803+
pointBackgroundColor: 'rgb(99, 102, 241)',
763804
pointBorderColor: '#fff',
764805
pointBorderWidth: 2,
806+
spanGaps: false,
807+
showLine: true,
765808
},
766809
{
767810
label: 'Failed Jobs',
768-
data: failures,
811+
data: chartFailures,
769812
borderColor: 'rgb(239, 68, 68)',
770813
backgroundColor: 'rgba(239, 68, 68, 0.1)',
814+
borderWidth: 2,
771815
tension: 0.4,
772816
fill: true,
773817
yAxisID: 'y1',
774818
pointRadius: pointRadius,
775819
pointHoverRadius: pointHoverRadius,
776-
pointBackgroundColor: function(context) {
777-
return context.dataset.borderColor;
778-
},
820+
pointBackgroundColor: 'rgb(239, 68, 68)',
779821
pointBorderColor: '#fff',
780822
pointBorderWidth: 2,
823+
spanGaps: false,
824+
showLine: true,
781825
}
782826
]
783827
},
784828
options: {
785829
responsive: true,
786830
maintainAspectRatio: false,
831+
animation: {
832+
duration: 750,
833+
},
787834
interaction: {
788835
mode: 'index',
789836
intersect: false,
790837
},
838+
elements: {
839+
line: {
840+
borderJoinStyle: 'round',
841+
borderCapStyle: 'round',
842+
},
843+
point: {
844+
hoverRadius: 8,
845+
}
846+
},
791847
plugins: {
792848
legend: {
793849
display: true,

0 commit comments

Comments
 (0)