oTree Forum >

Data saved locally but not on Heroku when using live_method in oTree

#1 by Daniel

Hello everyone,

I’m running into an issue with live_method in oTree. When I run the .otreezip file locally, the data are stored correctly. However, after deploying the same .otreezip file to Heroku, the data sent via liveSend() are not being saved.

I’m wondering whether anyone else has encountered a similar issue, or if this might be something specific to my setup. Below is the code for the page where the issue occurs. Any insights or suggestions would be greatly appreciated.


[code follows]
#########################################################################################################
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Checkout Survey</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
        body {
            font-family: 'Inter', sans-serif;
            background-color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }
        .container {
            width: 100%;
            max-width: 1200px;
            padding: 3rem;
            border-radius: 1rem;
            
        }
        .slider-wrapper {
            position: relative;
            margin-top: 2rem;
            margin-bottom: 4rem;
            height: 10px; /* Set a height for the wrapper to position children */
        }
        .slider-track {
            position: absolute;
            top: 0;
            left: 0;
            height: 10px;
            width: 100%;
            background-color: #e5e7eb;
            border-radius: 5px;
            z-index: 1;
        }
        .slider-track-fill {
            position: absolute;
            top: 0;
            left: 0;
            height: 100%;
            background-color: #6b7280;
            border-radius: 5px;
            z-index: 2;
            transition: width 0.1s linear;
        }
        input[type="range"] {
            -webkit-appearance: none;
            appearance: none;
            width: 100%;
            height: 10px;
            background: transparent;
            outline: none;
            cursor: pointer;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 5;
            margin: 0;
            padding: 0;
        }
        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 20px;
            height: 20px;
            background: transparent;
            cursor: pointer;
        }
        input[type="range"]::-moz-range-thumb {
            width: 20px;
            height: 20px;
            background: transparent;
            border: none;
            cursor: pointer;
        }
        .slider-thumb-visual {
            position: absolute;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 15px;
            height: 15px;
            background-color: #6b7280;
            border: 2px solid #6b7280;
            box-shadow: 0 0 0 5px rgba(107, 114, 128, 0.2);
            border-radius: 50%;
            z-index: 4;
            pointer-events: none; /* Prevents the div from interfering with slider clicks */
            transition: left 0.1s linear;
        }
        .slider-thumb-visual::after {
            content: "";
            position: absolute;
            top: 50%;
            left: 50%;
            width: 7px;
            height: 7px;
            background-color: #e5e7eb;
            transform: translate(-50%, -50%);
            border-radius: 50%;
        }
        .tick-mark {
            width: 2px;
            height: 10px;
            background-color: #6b7280;
            position: absolute;
            bottom: -25px;
            transform: translateX(-50%);
            z-index: 4;
        }
        .tick-label {
            position: absolute;
            bottom: -45px;
            white-space: nowrap;
            font-size: 1.00rem;
            color: #6b7280;
            text-align: center;
            transform: translateX(-50%);
            z-index: 4;
        }
        .tick-label-small {
            position: absolute;
            bottom: -85px;
            white-space: nowrap;
            font-size: 1.00rem;
            color: #6b7280;
            line-height: 1.25;
            z-index: 4;
            text-align: center;
            transform: translateX(-50%);
            width: 150px; /* Provides space for the centered text */
            left: 0; /* Default position, to be overridden inline */
        }
    </style>
</head>

    <div class="container">
        <!-- Main Question -->
        <h1 class="text-2xl font-semibold mb-8 leading-tight">
            Based on the checkout task you did, what percentage (0-100%) of other participants in this study do you believe were slower than you in completing the checkout task?
        </h1>

        <div class="slider-wrapper">
            <!-- Slider Track and Fill -->
            <div class="slider-track">
                <div class="slider-track-fill"></div>
            </div>
            
            <!-- Slider Input (Transparent) -->
            <input type="range" id="percentageSlider" min="0" max="100" value="0" class="w-full">
            
            <!-- Visual Thumb -->
            <div id="sliderThumbVisual" class="slider-thumb-visual"></div>

            <!-- Tick Marks and Labels -->
            <div class="absolute w-full top-0">
                <!-- 0% -->
                <div class="tick-mark" style="left: 0%;"></div>
                <span class="tick-label" style="left: 0%;">0%</span>
                <span class="tick-label-small" style="left: 0%;">(I am the slowest)<br>(Nobody is slower than me)</span>

                <!-- 10% -->
                <div class="tick-mark" style="left: 10%;"></div>
                <span class="tick-label" style="left: 10%;">10%</span>
                
                <!-- 20% -->
                <div class="tick-mark" style="left: 20%;"></div>
                <span class="tick-label" style="left: 20%;">20%</span>
                
                <!-- 30% -->
                <div class="tick-mark" style="left: 30%;"></div>
                <span class="tick-label" style="left: 30%;">30%</span>
                
                <!-- 40% -->
                <div class="tick-mark" style="left: 40%;"></div>
                <span class="tick-label" style="left: 40%;">40%</span>
                
                <!-- 50% -->
                <div class="tick-mark" style="left: 50%;"></div>
                <span class="tick-label" style="left: 50%;">50%</span>
                <span class="tick-label-small" style="left: 50%;">(I am average)<br>(Half of the people is slower than me)</span>
                
                <!-- 60% -->
                <div class="tick-mark" style="left: 60%;"></div>
                <span class="tick-label" style="left: 60%;">60%</span>
                
                <!-- 70% -->
                <div class="tick-mark" style="left: 70%;"></div>
                <span class="tick-label" style="left: 70%;">70%</span>
                
                <!-- 80% -->
                <div class="tick-mark" style="left: 80%;"></div>
                <span class="tick-label" style="left: 80%;">80%</span>
                
                <!-- 90% -->
                <div class="tick-mark" style="left: 90%;"></div>
                <span class="tick-label" style="left: 90%;">90%</span>
                
                <!-- 100% -->
                <div class="tick-mark" style="left: 100%;"></div>
                <span class="tick-label" style="left: 100%;">100%</span>
                <span class="tick-label-small" style="left: 100%;">(I am the fastest)<br>(Everybody is slower than me)</span>
            </div>
            
            <!-- Percentage Display -->
            <div id="percentageDisplay" class="absolute right-0 top-1/2 transform -translate-y-1/2 -mr-28 px-4 py-2 border border-gray-400 rounded-md">
                82%
            </div>
        </div>

 
    </div>

<script>
    const slider = document.getElementById('percentageSlider');
    const percentageDisplay = document.getElementById('percentageDisplay');
    const sliderFill = document.querySelector('.slider-track-fill');
    const sliderThumbVisual = document.getElementById('sliderThumbVisual');
    
    // Declare userAnswer outside the function so it's accessible globally
    let userAnswer;

    function updateSliderVisuals() {
        const value = slider.value;
        percentageDisplay.textContent = `${value}%`;

        const progress = (value - slider.min) / (slider.max - slider.min);
        const thumbPosition = progress * 100;
        
        sliderFill.style.width = `${thumbPosition}%`;
        sliderThumbVisual.style.left = `${thumbPosition}%`;

        // Update the userAnswer variable here
        userAnswer = Number(value);
    }
    
    slider.addEventListener('input', updateSliderVisuals);
    
    // Initial update
    updateSliderVisuals();

    // Update visuals on window resize
    window.addEventListener('resize', updateSliderVisuals);
    
    // This function will now send the current value of userAnswer
    function valuesend() {
        liveSend({'userAnswer_var': userAnswer});
    };
</script>


       <!-- Next Button -->
<div class="flex justify-end w-full mt-4">
    <button onclick="valuesend()" class="text-3xl bg-gray-200 text-gray-800 border-2 border-black px-5 py-2 rounded-md cursor-pointer">Continue</button>
</div>
</html>

Write a reply

Set forum username