9.4 KiB
Survey Charts Fix - Complete Summary
Problem Identified
The survey response list page had empty charts showing no data, even though survey data existed in the database.
Root Causes
-
ApexCharts Series Structure Error
- Bar charts (Engagement Funnel, Completion Time, Score Distribution) had incorrect series structure
- They used simple arrays:
series: [18, 2, 7, 6, 29] - ApexCharts bar charts require:
series: [{name: 'Surveys', data: [18, 2, 7, 6, 29]}] - This triggered the error: "It is a possibility that you may have not included 'data' property in series"
-
Messy Django Template Loops in JavaScript
- All chart data was generated using
{% for %}loops inside JavaScript code - This made the code hard to maintain and debug
- Example of old code:
series: [{% for item in engagement_funnel %}{{ item.count }}{% if not forloop.last %},{% endif %}{% endfor %}] - All chart data was generated using
-
No Safety Checks for Empty Data
- Charts would try to render even with no data
- This caused errors when viewing as users with limited access
Solution Implemented
1. Refactored View to Serialize Data to JSON
File: apps/surveys/ui_views.py
Changed from passing multiple arrays to passing JSON-serialized data:
# Old way (removed)
context = {
'engagement_funnel': engagement_funnel,
'completion_time_distribution': completion_time_distribution,
'device_distribution': device_distribution,
'score_distribution': score_distribution,
'survey_type_labels': survey_type_labels,
'survey_type_counts': survey_type_counts,
'trend_labels': trend_labels,
'trend_sent': trend_sent,
'trend_completed': trend_completed,
}
# New way
import json
context = {
'engagement_funnel_json': json.dumps(engagement_funnel),
'completion_time_distribution_json': json.dumps(completion_time_distribution),
'device_distribution_json': json.dumps(device_distribution),
'score_distribution_json': json.dumps(score_distribution),
'survey_types_json': json.dumps(survey_types),
'trend_labels_json': json.dumps(trend_labels),
'trend_sent_json': json.dumps(trend_sent),
'trend_completed_json': json.dumps(trend_completed),
}
Benefits:
- Clean separation of concerns
- Data is computed once in Python, not multiple times in template
- JSON is validated before reaching the browser
- Easier to debug (can log JSON in browser console)
2. Fixed Bar Chart Series Structure
File: templates/surveys/instance_list.html
Fixed all three bar charts to use correct {name, data} format:
// Old (BROKEN)
const engagementFunnelOptions = {
series: [{% for item in engagement_funnel %}{{ item.count }}{% if not forloop.last %},{% endif %}{% endfor %}],
// ...
};
// New (FIXED)
const engagementFunnelOptions = {
series: [{
name: 'Surveys',
data: engagementFunnelData.map(item => item.count)
}],
// ...
};
This was applied to:
- Engagement Funnel Chart (horizontal bar)
- Completion Time Distribution Chart (vertical bar)
- Score Distribution Chart (vertical bar)
3. Removed All Django Template Loops from JavaScript
Before (messy):
series: [{% for item in engagement_funnel %}{{ item.count }}{% if not forloop.last %},{% endif %}{% endfor %}],
categories: [{% for item in engagement_funnel %}'{{ item.stage }}'{% if not forloop.last %},{% endif %}{% endfor %}],
After (clean):
// Parse JSON data from server
const engagementFunnelData = {{ engagement_funnel_json|safe }};
series: [{
name: 'Surveys',
data: engagementFunnelData.map(item => item.count)
}],
categories: engagementFunnelData.map(item => item.stage),
Benefits:
- Pure JavaScript, no Django template syntax
- Modern JavaScript array methods (map, filter, etc.)
- Much easier to read and maintain
- Better IDE support and IntelliSense
- Can easily debug in browser console
4. Added Safety Checks for Empty Data
// Helper function to check if data is valid
function hasData(data) {
return data && data.length > 0 && data.some(item => item.count > 0);
}
// Only render chart if data exists
if (hasData(engagementFunnelData)) {
const engagementFunnelOptions = { /* ... */ };
const engagementFunnelChart = new ApexCharts(...);
engagementFunnelChart.render();
}
Benefits:
- Prevents errors when viewing as limited users
- Charts won't render empty when no data is available
- Clean user experience - chart containers simply remain empty
5. Fixed Tooltip Formatters
Updated all tooltip formatters to use the new JSON data structure:
// Old
tooltip: {
y: {
formatter: function (value, { series, seriesIndex, dataPointIndex, w }) {
var percentages = [{% for item in engagement_funnel %}{{ item.percentage }}{% if not forloop.last %},{% endif %}{% endfor %}];
return value + " surveys (" + percentages[seriesIndex] + "%)";
}
}
}
// New
tooltip: {
y: {
formatter: function (value, { seriesIndex, dataPointIndex }) {
return value + " surveys (" + engagementFunnelData[dataPointIndex].percentage + "%)";
}
}
}
Charts Fixed
-
✅ Engagement Funnel Chart (Horizontal Bar)
- Shows survey progression from sent to completed
- Fixed series structure
- Clean JSON data
-
✅ Completion Time Distribution Chart (Vertical Bar)
- Shows how long users take to complete surveys
- Fixed series structure
- Clean JSON data
-
✅ Device Type Distribution Chart (Donut)
- Shows which devices users use to complete surveys
- Already had correct structure
- Clean JSON data
-
✅ Score Distribution Chart (Vertical Bar)
- Shows distribution of survey scores
- Fixed series structure
- Clean JSON data
-
✅ Survey Types Chart (Donut)
- Shows breakdown by survey type
- Already had correct structure
- Clean JSON data
-
✅ 30-Day Trend Chart (Line)
- Shows sent vs completed surveys over time
- Already had correct structure
- Clean JSON data
Testing Instructions
1. Access the Survey List Page
Navigate to: http://localhost:8000/surveys/instances/
2. Verify Charts Display
All six charts should display with actual data:
- Engagement Funnel (top left)
- Completion Time (top center)
- Device Types (top right)
- Score Distribution (bottom left)
- Survey Types (bottom center)
- 30-Day Trend (bottom right)
3. Check Browser Console
Open browser DevTools (F12) and check console for:
- No ApexCharts errors
- No JavaScript errors
- JSON data objects logged (if you add console.log)
4. Test with Different User Roles
Test as:
- PX Admin (should see all surveys)
- Hospital Admin (should see hospital's surveys only)
- Hospital User (should see hospital's surveys only)
5. Test with Filters
Apply different filters to ensure charts update correctly:
- Status filter
- Survey type filter
- Hospital filter
- Date range filter
Files Modified
-
apps/surveys/ui_views.py
- Refactored to serialize all chart data to JSON
- Removed separate arrays for labels and counts
- Added JSON serialization using
json.dumps()
-
templates/surveys/instance_list.html
- Removed all
{% for %}loops from JavaScript - Fixed bar chart series structure to
{name, data}format - Added
hasData()helper function for safety checks - Updated all chart configurations to use JSON data
- Fixed tooltip formatters to use data from JSON objects
- Removed all
Technical Details
JSON Data Structure
Each chart receives clean JSON arrays of objects:
[
{
"range": "1-2",
"count": 15,
"percentage": 25.5
},
{
"range": "2-3",
"count": 20,
"percentage": 34.0
}
]
ApexCharts Requirements
Bar Charts (vertical/horizontal):
{
series: [{
name: 'Series Name',
data: [value1, value2, value3, ...]
}],
xaxis: {
categories: ['label1', 'label2', 'label3', ...]
}
}
Donut/Pie Charts:
{
series: [value1, value2, value3, ...],
labels: ['label1', 'label2', 'label3', ...]
}
Line Charts:
{
series: [
{
name: 'Series 1',
data: [value1, value2, value3, ...]
},
{
name: 'Series 2',
data: [value1, value2, value3, ...]
}
],
xaxis: {
categories: ['label1', 'label2', 'label3', ...]
}
}
Benefits of This Fix
- No More Empty Charts - Charts display correctly with actual data
- Cleaner Code - No Django template syntax in JavaScript
- Better Maintainability - Easy to understand and modify
- Better Performance - Data computed once, not multiple times
- Better Debugging - Can inspect JSON in browser console
- Safer - Charts won't crash with empty data
- Modern Practices - Uses modern JavaScript array methods
- IDE Friendly - Better IntelliSense and error detection
Next Steps
- Test the survey list page at
http://localhost:8000/surveys/instances/ - Verify all six charts display correctly
- Check browser console for any errors
- Test with different user roles and filters
- Review the code changes if desired
Rollback Plan (if needed)
If issues arise, the fix can be easily rolled back by reverting the two modified files:
git checkout HEAD -- apps/surveys/ui_views.py templates/surveys/instance_list.html
However, the old code had the charts not working at all, so rolling back would break the charts again.