Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
File size: 12,777 Bytes
40a04d4 789d3cf 40a04d4 46adba2 40a04d4 87200e9 40a04d4 cb49766 87200e9 40a04d4 46adba2 87200e9 40a04d4 bca6484 87200e9 40a04d4 2ce66e6 40a04d4 cdf264c 63424e9 cb49766 63424e9 cb49766 40a04d4 cdf264c 40a04d4 789d3cf 40a04d4 789d3cf 40a04d4 2ce66e6 40a04d4 cdf264c 40a04d4 2ce66e6 cdf264c 2ce66e6 40a04d4 cdf264c 40a04d4 87200e9 40a04d4 63424e9 cb49766 63424e9 cb49766 63424e9 cb49766 cdf264c cb49766 63424e9 87200e9 40a04d4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | {% extends 'base.html' %} {% block content %}
<div id="room-container">
<div id="welcome-modal" class="modal">
<div class="modal-content">
<h3>Welcome!</h3>
<p>
Your display name for this chat session will be:
<span id="displayNameText" style="font-weight:bold;"></span>.
</p>
<div class="modal-buttons">
<button class="modal-btn" id="welcomeOkBtn">OK</button>
</div>
</div>
</div>
<div id="timer-modal" class="modal">
<div class="modal-content">
<h3>Start a Timer</h3>
<p><strong>Please start a timer for 20 minutes</strong>. At the 20 minute mark, you may click the button "End Chat Session" to continue with the study.</p>
<div class="modal-buttons">
<button class="modal-btn" id="timerOkBtn">I have set a timer for 20 minutes.</button>
</div>
</div>
</div>
<h1 id="home-header">Chat Room</h1>
<div id="room-subsection">
<div class="topic-header-row">
<div class="topic-header-info">
<h2 id="room-code-display">Topic: <span class="topic-title">{{ topic_info.title }}</span></h2>
</div>
<div class="topic-header-buttons">
<button id="feedback-btn">Share Feedback and Report Bugs</button>
<button id="end-exp-btn">End Chat Session</button>
<button id="abort-exp-btn">Abort Experiment</button>
</div>
</div>
<div id="end-modal" class="modal">
<div class="modal-content">
<h3>Only Exit This Way After 20 Minutes of Participation in the Chatroom.</h3>
<p>This signals the end of the chat session of the experiment. You will be redirected to the post-survey.</p>
<p>This button is only to be used at the end of your 20 minutes of participation in the chatroom. <strong>If you wish to exit the chat before finishing your 20 minutes, use the "Abort Experiment" button instead.</strong></p>
<div class="modal-buttons">
<button class="modal-btn" id="endYesBtn">Continue</button>
<button class="modal-btn" id="endNoBtn">Cancel</button>
</div>
</div>
</div>
<div id="abort-modal" class="modal">
<div class="modal-content">
<h3>Are you sure you want to leave this experiment?</h3>
<p><strong>If you finished your 20 minutes in the chatroom, do NOT exit via this button. Use the "End Chat Session" button instead.</strong></p>
<p>By clicking yes, you will exit the experiment <strong>without</strong> completing the final survey.</p>
<div class="modal-buttons">
<button class="modal-btn" id="abortYesBtn">End early with code "C9V2XFDU"</button>
<button class="modal-btn" id="abortNoBtn">Cancel</button>
</div>
</div>
</div>
<div id="feedback-modal" class="modal">
<div class="modal-content">
<h3>Feedback</h3>
<form id="feedback-form">
<div class="feedback-col">
<label for="enter-feedback">Tell us if you noticed something confusing, unexpected, or not working.</label>
<textarea id="enter-feedback" name="feedback"></textarea>
</div>
<br>
<div class="modal-buttons">
<button class="modal-btn" id="submitFeedbackBtn" type="submit">Submit</button>
<button type="button" class="modal-btn" id="cancelFeedbackBtn">Cancel</button>
</div>
</form>
</div>
</div>
<div id="feedback-status-confirm" class="modal">
<div class="modal-content">
<p>Feedback submitted.</p>
<div class="modal-buttons">
<button class="modal-btn" id="cancelFeedbackStatusBtn">Ok</button>
</div>
</div>
</div>
<div id="feedback-status-fail" class="modal">
<div class="modal-content">
<p>Feedback failed to submit.</p>
<div class="modal-buttons">
<button class="modal-btn" id="cancelFeedbackStatusBtn2">Ok</button>
</div>
</div>
</div>
</div>
<div id="chat-room-widget">
<div id="msgs-container">
<ul id="messages"></ul>
</div>
<div id="message-box">
<textarea id="message-input" name="message" placeholder="Enter your message" rows="1"></textarea>
<button type="submit" id="send-btn" onclick="sendMessage()">Send</button>
</div>
</div>
<script type="text/javascript">
// Push a state when entering the page
history.pushState(null, "", location.href);
window.addEventListener("popstate", function () {
// Immediately push another state to prevent backward navigation
history.pushState(null, "", location.href);
});
var socketio = io();
const chatEnded = {{ ended | tojson }};
const textarea = document.getElementById("message-input");
if (chatEnded) {
textarea.disabled = true;
textarea.placeholder = "The chat has ended.";
document.getElementById("send-btn").disabled = true;
document.getElementById("end-exp-btn").disabled = true;
document.getElementById("abort-exp-btn").disabled = true;
document.getElementById("feedback-btn").disabled = true; //since without socket io, it won't submit
if (socketio) {
socketio.close();
}
}
// Handler for the welcome modal
let welcomeModal = document.getElementById("welcome-modal");
let timerModal = document.getElementById("timer-modal");
const displayNameText = document.getElementById("displayNameText");
displayNameText.textContent = "{{ user }}";
// Show the modal instantly when the page loads
window.onload = function() {
timerModal.style.display = "block";
};
//timer pop-up
document.getElementById("timerOkBtn").onclick = function () {
timerModal.style.display = "none";
welcomeModal.style.display = "block";
};
// Close the modal on OK
document.getElementById("welcomeOkBtn").onclick = function () {
welcomeModal.style.display = "none";
};
// Creates the post-survey link (based on the bot names)
const endpoint = "{{ url_for('post_survey') }}";
const endpointQuitEarly = "https://app.prolific.com/submissions/complete?cc=C9V2XFDU";
socketio.on("message", function (message) { createChatItem(message.message, message.sender) });
function createChatItem(message, sender) {
//autoscroll capabilities
const container = document.getElementById("msgs-container");
const shouldAutoScroll = isNearBottom(container);
var messages = document.getElementById("messages");
var content;
if (sender === "") {
content = `<p class="member-activity">${message}</p>`;
} else {
var senderIsUser = "{{user}}" === sender;
content = `
<li class="message-item ${senderIsUser ? "self-message-item" : "peer-message-item"}">
<p>${message}</p>
<small class="${senderIsUser ? "chat-user-sender" : "chat-sender"}">${sender}</small>
</li>
`;}
messages.insertAdjacentHTML("beforeend", content);
//autoscroll capabilities
if (shouldAutoScroll) {
smoothScrollToBottom(container);
}
}
function sendMessage() {
var msgInput = document.getElementById("message-input");
if (msgInput.value === "") return;
var msg = msgInput.value;
socketio.emit("message", { message: msg });
msgInput.value = "";
msgInput.style.height = "auto"; // reset height
}
document.getElementById("message-input").addEventListener("keydown", function (event) {
if (event.key === "Enter") {
return
// disabling send message so user can type a newline without sending
//event.preventDefault(); // prevent a newline or form submit
//sendMessage(); // call the same function as the Send button
}
});
textarea.addEventListener("input", () => {
textarea.style.height = "auto"; // reset height
textarea.style.overflowY = "hidden"; // start by hiding the scrollbar
textarea.style.height = (textarea.scrollHeight + 8) + "px"; // set to fit content (+8 for bottom padding)
// If we've hit the max height, allow scrolling
if (textarea.scrollHeight > parseInt(getComputedStyle(textarea).maxHeight)) {
textarea.style.overflowY = "auto";
}
});
// Handler for the Experiment Ends confirmation pop-up
const endModal = document.getElementById("end-modal");
document.getElementById("end-exp-btn").onclick = function () {
endModal.style.display = "block";
};
document.getElementById("endNoBtn").onclick = function () {
endModal.style.display = "none";
};
document.getElementById("endYesBtn").onclick = function (e) {
//block browser confirmation popup
e.stopPropagation();
// Redirect to ending survey
window.open(endpoint, "_blank");
endModal.style.display = "none";
textarea.disabled = true;
textarea.placeholder = "The chat has ended.";
document.getElementById("send-btn").disabled = true;
document.getElementById("end-exp-btn").disabled = true;
document.getElementById("abort-exp-btn").disabled = true;
document.getElementById("feedback-btn").disabled = true; //since without socket io, it won't submit
if (socketio) {
socketio.close();
}
};
// Handler for the Abort Experiment confirmation pop-up
let modal = document.getElementById("abort-modal");
document.getElementById("abort-exp-btn").onclick = function () {
modal.style.display = "block";
};
document.getElementById("abortNoBtn").onclick = function () {
modal.style.display = "none";
};
document.getElementById("abortYesBtn").onclick = function (e) {
//block browser confirmation popup
e.stopPropagation();
// Mark that user aborted and redirect to ending survey
fetch("/abort", { method: "POST" })
.then(() => {
window.open(endpointQuitEarly, "_blank");
});
modal.style.display = "none";
textarea.disabled = true;
textarea.placeholder = "The chat has ended.";
document.getElementById("send-btn").disabled = true;
document.getElementById("end-exp-btn").disabled = true;
document.getElementById("abort-exp-btn").disabled = true;
document.getElementById("feedback-btn").disabled = true; //since without socket io, it won't submit
if (socketio) {
socketio.close();
}
};
//handler for feedback modal popup
let feedbackModal = document.getElementById("feedback-modal");
let form = document.getElementById("feedback-form");
let feedbackConfirm = document.getElementById("feedback-status-confirm");
let feedbackFail = document.getElementById("feedback-status-fail");
document.getElementById("feedback-btn").onclick = function () {
feedbackModal.style.display = "block";
};
document.getElementById("cancelFeedbackBtn").onclick = function () {
feedbackModal.style.display = "none";
};
document.getElementById("cancelFeedbackStatusBtn").onclick = function () {
feedbackConfirm.style.display = "none";
feedbackFail.style.display = "none";
};
document.getElementById("cancelFeedbackStatusBtn2").onclick = function () {
feedbackConfirm.style.display = "none";
feedbackFail.style.display = "none";
};
//override form function to instead emit save feedback event
form.addEventListener("submit", function (e) {
e.preventDefault();
const data = new FormData(form);
const feedback = data.get("feedback")?.trim();
if (!feedback) return;
socketio.emit("feedback_given", { feedback }, (response) => {
if (response?.status === "True" || response?.status === true) {
feedbackConfirm.style.display = "block";
form.reset();
document.getElementById("feedback-modal").style.display = "none";
} else {
feedbackFail.style.display = "block";
}
});
});
// add auto scroll
function isNearBottom(container, threshold = 120) {
const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight);
return distanceFromBottom < threshold;
}
function smoothScrollToBottom(container) {
container.scrollTo({ top: container.scrollHeight, behavior: "smooth" });
}
</script>
<script type="text/javascript">
</script>
</div>
{% endblock %}
|