dockerfile, fixing hardcoded url and cleanup

This commit is contained in:
Jan Dickmann 2024-06-30 12:40:39 +02:00
parent 11f051c7d9
commit 3e482d2e49
12 changed files with 246 additions and 255 deletions

View File

@ -657,5 +657,8 @@ def delete_all_entries():
# Close the session # Close the session
db.session.close() db.session.close()
def create_app():
return app
if __name__ == '__main__': if __name__ == '__main__':
app.run() app.run()

17
slaeforms/dockerfile Normal file
View File

@ -0,0 +1,17 @@
# Use the official Python image from the Docker Hub
FROM python:3.10-slim
# Set the working directory
WORKDIR /slaeforms
# Copy the rest of the application code to the working directory
COPY . .
# Install the dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Expose the port on which the app will run
EXPOSE 8000
# Define the command to run the application using Gunicorn
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:create_app()"]

View File

@ -0,0 +1,16 @@
blinker==1.8.2
click==8.1.7
colorama==0.4.6
Flask==3.0.3
Flask-SQLAlchemy==3.1.1
Flask-WTF==1.2.1
greenlet==3.0.3
gunicorn==22.0.0
itsdangerous==2.2.0
Jinja2==3.1.4
MarkupSafe==2.1.5
packaging==24.1
SQLAlchemy==2.0.30
typing_extensions==4.12.2
Werkzeug==3.0.3
WTForms==3.1.2

View File

@ -1,64 +1,64 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css')}}"" /> <!-- styles.css {{ url_for('static', filename='styles.css')}}--> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css')}}"" /> <!-- styles.css {{ url_for('static', filename='styles.css')}}-->
<title>Testform</title> <title>Testform</title>
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"> <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
</head> </head>
<body> <body>
<h2>Question: {{ current_question }}</h2> <h2>Question: {{ current_question }}</h2>
{% if (videotype == "single")%} <!-- first figure out what video type we have --> {% if (videotype == "single")%} <!-- first figure out what video type we have -->
<div class="center"> <div class="center">
<h3>Video 1</h3> <h3>Video 1</h3>
<iframe width="560" height="315" class="center" src="{{ video_url }}" title="YouTube video player" <iframe width="560" height="315" class="center" src="{{ video_url }}" title="YouTube video player"
frameborder="0" frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe> allowfullscreen></iframe>
</div> </div>
{% elif (videotype == "pairwise")%} {% elif (videotype == "pairwise")%}
<div class="columncontainer"> <div class="columncontainer">
<div class="columnleft center"> <div class="columnleft center">
<h3>Video 1</h3> <h3>Video 1</h3>
<iframe width="560" height="315" class="center" src="{{ video_url_left }}" title="YouTube video player" <iframe width="560" height="315" class="center" src="{{ video_url_left }}" title="YouTube video player"
frameborder="0" frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe> allowfullscreen></iframe>
</div> </div>
<div class="columnright"> <div class="columnright">
<h3>Video 2</h3> <h3>Video 2</h3>
<iframe width="560" height="315" src="{{ video_url_right }}" title="YouTube video player" frameborder="0" <iframe width="560" height="315" src="{{ video_url_right }}" title="YouTube video player" frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe> allowfullscreen></iframe>
</div> </div>
</div> </div>
{% else %} {% else %}
<p>Error: No Videotype could be matched or was given!</p> <p>Error: No Videotype could be matched or was given!</p>
{% endif %} {% endif %}
<form action="http://localhost:5000/send" method="post"> <form action="http://localhost:5000/send" method="post">
{% for block in config["question 1"]["blocks"] %} {% for block in config["question 1"]["blocks"] %}
{% if (config["question 1"]["blocks"][block]["type"] == "likert") %} {% if (config["question 1"]["blocks"][block]["type"] == "likert") %}
<div class="likercontainer"> <div class="likercontainer">
<div class="likert"> <div class="likert">
<label><input name="likertscale" type="radio" value="1" /><span>I dont like it at all</span></label> <label><input name="likertscale" type="radio" value="1" /><span>I dont like it at all</span></label>
<label><input name="likertscale" type="radio" value="2" /><span>I dont like it</span></label> <label><input name="likertscale" type="radio" value="2" /><span>I dont like it</span></label>
<label><input name="likertscale" type="radio" value="3" /><span>I am indifferent</span></label> <label><input name="likertscale" type="radio" value="3" /><span>I am indifferent</span></label>
<label><input name="likertscale" type="radio" value="4" /><span>I like it</span></label> <label><input name="likertscale" type="radio" value="4" /><span>I like it</span></label>
<label><input name="likertscale" type="radio" value="5" /><span>I like it a lot</span></label> <label><input name="likertscale" type="radio" value="5" /><span>I like it a lot</span></label>
</div> </div>
</div> </div>
{% elif (config["question 1"]["blocks"][block]["type"] == "textinput") %} {% elif (config["question 1"]["blocks"][block]["type"] == "textinput") %}
<label for="feedback">Additional Feedback: </label> <label for="feedback">Additional Feedback: </label>
<textarea id="feedback" name="feedback" rows="3" cols="30" maxlength="200"></textarea> <textarea id="feedback" name="feedback" rows="3" cols="30" maxlength="200"></textarea>
{% else %} {% else %}
<p>Error: A block could not be loaded!</p> <p>Error: A block could not be loaded!</p>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<p><input id="submitbutton" type = "submit" value = "submit";/></p> <p><input id="submitbutton" type = "submit" value = "submit";/></p>
</form> </form>
</body> </body>
</html> </html>

View File

@ -12,7 +12,7 @@
<div class="container"> <div class="container">
<div class="login-container" > <div class="login-container" >
<p>Some pages require you to be logged in.</p> <p>Some pages require you to be logged in.</p>
<form action="http://localhost:5000/login" method="post"> <form action="{{ url_for('login') }}" method="post">
<input class="login-elements" type="password" value="" name="password" placeholder="password"> <input class="login-elements" type="password" value="" name="password" placeholder="password">
<input class="login-elements" id="loginbutton" type="submit" value="submit";/> <input class="login-elements" id="loginbutton" type="submit" value="submit";/>
</form></div> </form></div>

View File

@ -1,142 +1,142 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css')}}" /> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css')}}" />
<!-- styles.css {{ url_for('static', filename='styles.css')}}--> <!-- styles.css {{ url_for('static', filename='styles.css')}}-->
<title>Testform</title> <title>Testform</title>
<link rel="shortcut icon" href="{{ url_for('static', filename='icons/favicon.ico') }}"> <link rel="shortcut icon" href="{{ url_for('static', filename='icons/favicon.ico') }}">
</head> </head>
<body> <body>
<div class="container"> <div class="container">
<h2>Gib Feedback als Video</h2> <h2>Gib Feedback als Video</h2>
<div class="centertext"> <div class="centertext">
<button type="button" class="videocontrols" id="buttonCamera" onclick="cameraButton()"> <button type="button" class="videocontrols" id="buttonCamera" onclick="cameraButton()">
<img id="buttonCameraIcon" src="{{ url_for('static', filename='icons/camera-icon.png')}}" alt="Camera Icon"> <img id="buttonCameraIcon" src="{{ url_for('static', filename='icons/camera-icon.png')}}" alt="Camera Icon">
</button> </button>
</div> </div>
<div class="spacer" aria-hidden="true" style="height:30px"></div> <div class="spacer" aria-hidden="true" style="height:30px"></div>
<div class="centertext"> <div class="centertext">
<button type="button" class="videocontrols" id="buttonRecord" style="display:none" onclick="recordButton()"> <button type="button" class="videocontrols" id="buttonRecord" style="display:none" onclick="recordButton()">
<img id="buttonRecordIcon" src="{{ url_for('static', filename='icons/record-icon.png')}}" alt="Camera Icon"> <img id="buttonRecordIcon" src="{{ url_for('static', filename='icons/record-icon.png')}}" alt="Camera Icon">
</button> </button>
<button type="button" class="videocontrols" id="buttonDelete" style="display:none" disabled <button type="button" class="videocontrols" id="buttonDelete" style="display:none" disabled
onclick="deleteButton()"> onclick="deleteButton()">
<img id="buttonDeleteIcon" src="{{ url_for('static', filename='icons/trash-icon.png')}}" alt="Delete Icon" <img id="buttonDeleteIcon" src="{{ url_for('static', filename='icons/trash-icon.png')}}" alt="Delete Icon"
class="buttondisable"> class="buttondisable">
</button> </button>
</div> </div>
<div class="spacer" aria-hidden="true" style="height:15px"></div> <div class="spacer" aria-hidden="true" style="height:15px"></div>
<div class="centertext"> <div class="centertext">
<video autoplay muted playsinline id="videoDisplay"></video> <video autoplay muted playsinline id="videoDisplay"></video>
</div> </div>
<script> <script>
const buttonCamera = document.getElementById('buttonCamera'); const buttonCamera = document.getElementById('buttonCamera');
const buttonRecord = document.getElementById('buttonRecord'); const buttonRecord = document.getElementById('buttonRecord');
const buttonDelete = document.getElementById('buttonDelete'); const buttonDelete = document.getElementById('buttonDelete');
const videoDisplay = document.getElementById('videoDisplay'); const videoDisplay = document.getElementById('videoDisplay');
const buttonCameraIcon = document.getElementById('buttonCameraIcon'); const buttonCameraIcon = document.getElementById('buttonCameraIcon');
const buttonRecordIcon = document.getElementById('buttonRecordIcon'); const buttonRecordIcon = document.getElementById('buttonRecordIcon');
//const buttonDeleteIcon = document.getElementById('buttonDeleteIcon'); //const buttonDeleteIcon = document.getElementById('buttonDeleteIcon');
var mediaRecorder = null; var mediaRecorder = null;
var stream = null; var stream = null;
let recordedVideoBlob = null; let recordedVideoBlob = null;
let isRecording = false; let isRecording = false;
let videoAccess = false; let videoAccess = false;
async function cameraButton() { async function cameraButton() {
if (!videoAccess) { //test what happens if user doesnt give the permission if (!videoAccess) { //test what happens if user doesnt give the permission
console.log("cameraButton case videoAccess = false"); console.log("cameraButton case videoAccess = false");
// maybe a try catch block? // maybe a try catch block?
try { try {
stream = await navigator.mediaDevices.getUserMedia({ stream = await navigator.mediaDevices.getUserMedia({
video: true, video: true,
}); });
} catch (error) { } catch (error) {
//TODO when this occurs the user should get a hint to reload the page or to allow it next to the url //TODO when this occurs the user should get a hint to reload the page or to allow it next to the url
newerror = error newerror = error
console.log("Error: ", error); console.log("Error: ", error);
return return
} }
console.log("stream is active"); console.log("stream is active");
videoAccess = true videoAccess = true
videoDisplay.srcObject = stream videoDisplay.srcObject = stream
buttonCameraIcon.src = "{{ url_for('static', filename='icons/camera-off-icon.png') }}"; //todo, not sure if this works buttonCameraIcon.src = "{{ url_for('static', filename='icons/camera-off-icon.png') }}"; //todo, not sure if this works
buttonCameraIcon.alt = "Camera-off Icon"; buttonCameraIcon.alt = "Camera-off Icon";
buttonRecord.style.display = 'inline-block'; buttonRecord.style.display = 'inline-block';
buttonDelete.style.display = 'inline-block'; buttonDelete.style.display = 'inline-block';
videoDisplay.style.display = 'inline-block'; videoDisplay.style.display = 'inline-block';
mediaRecorder = new MediaRecorder(stream, { mediaRecorder = new MediaRecorder(stream, {
mimeType: "video/webm", //could use other video format: https://www.iana.org/assignments/media-types/media-types.xhtml#video mimeType: "video/webm", //could use other video format: https://www.iana.org/assignments/media-types/media-types.xhtml#video
// I probably want to change the bitrate: https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/MediaRecorder // I probably want to change the bitrate: https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/MediaRecorder
}); });
} else { } else {
console.log("cameraButton case videoAccess = true"); console.log("cameraButton case videoAccess = true");
stream = null; stream = null;
videoAccess = false videoAccess = false
buttonCameraIcon.src = "{{ url_for('static', filename='icons/camera-icon.png') }}"; //todo, not sure if this works buttonCameraIcon.src = "{{ url_for('static', filename='icons/camera-icon.png') }}"; //todo, not sure if this works
buttonCameraIcon.alt = "Camera Icon"; buttonCameraIcon.alt = "Camera Icon";
buttonRecord.style.display = 'none'; buttonRecord.style.display = 'none';
buttonDelete.style.display = 'none'; buttonDelete.style.display = 'none';
videoDisplay.style.display = 'none'; videoDisplay.style.display = 'none';
} }
console.log("camera button function ends"); console.log("camera button function ends");
} }
mediaRecorder.addEventListener("dataavailable", (event) => { mediaRecorder.addEventListener("dataavailable", (event) => {
videoRecorded.src = URL.createObjectURL(event.data); videoRecorded.src = URL.createObjectURL(event.data);
recordedVideoBlob = event.data; recordedVideoBlob = event.data;
}); });
function recordButton() { function recordButton() {
console.log("recordButton pressed"); console.log("recordButton pressed");
if (!isRecording) { if (!isRecording) {
console.log("recordButton pressed case isRecording = false"); console.log("recordButton pressed case isRecording = false");
deleteButton(); deleteButton();
buttonDelete.setAttribute("disabled", ""); buttonDelete.setAttribute("disabled", "");
buttonDeleteIcon.classList.add("buttondisable"); buttonDeleteIcon.classList.add("buttondisable");
mediaRecorder.start(); mediaRecorder.start();
buttonRecordIcon.src = "{{ url_for('static', filename='icons/stop-icon.png') }}"; buttonRecordIcon.src = "{{ url_for('static', filename='icons/stop-icon.png') }}";
buttonRecordIcon.alt = 'record icon'; buttonRecordIcon.alt = 'record icon';
isRecording = true; isRecording = true;
console.log('Recording started'); console.log('Recording started');
} else { } else {
console.log("recordButton pressed case isRecording = true"); console.log("recordButton pressed case isRecording = true");
mediaRecorder.stop(); mediaRecorder.stop();
buttonRecordIcon.src = "{{ url_for('static', filename='icons/record-icon.png') }}"; buttonRecordIcon.src = "{{ url_for('static', filename='icons/record-icon.png') }}";
buttonRecordIcon.alt = 'Stop Icon'; buttonRecordIcon.alt = 'Stop Icon';
isRecording = false; isRecording = false;
console.log('Recording stopped'); console.log('Recording stopped');
buttonDelete.removeAttribute("disabled"); buttonDelete.removeAttribute("disabled");
buttonDeleteIcon.classList.remove("buttondisable"); buttonDeleteIcon.classList.remove("buttondisable");
} }
} }
function deleteButton() { function deleteButton() {
//todo delete data //todo delete data
buttonDelete.setAttribute("disabled", ""); buttonDelete.setAttribute("disabled", "");
buttonDeleteIcon.classList.add("buttondisable"); buttonDeleteIcon.classList.add("buttondisable");
} }
</script> </script>
</div> </div>
</body> </body>
</html> </html>

View File

@ -39,7 +39,7 @@
If you have further questions, please send an email to testemail@notarealemail.deee If you have further questions, please send an email to testemail@notarealemail.deee
</p> </p>
</div> </div>
<form class="dsgvoform" action="http://localhost:5000/start" method="post"> <form class="dsgvoform" action="{{ url_for('startpage') }}" method="post">
<label for="terms-and-conditions"> <label for="terms-and-conditions">
<input class="inline" id="terms-and-conditions" type="checkbox" required name="terms-and-conditions" /> I accept the +terms and conditions <input class="inline" id="terms-and-conditions" type="checkbox" required name="terms-and-conditions" /> I accept the +terms and conditions
</label> </label>

View File

@ -123,7 +123,7 @@ step={{question["step"]}}
<p>Error: Block {{ stimulus["type"] }} could not be loaded!</p> <p>Error: Block {{ stimulus["type"] }} could not be loaded!</p>
{% endif %} {% endif %}
<form class="formlayout" id="question_form" action="http://localhost:5000/send" method="post"> <form class="formlayout" id="question_form" action="{{ url_for('sendpage') }}" method="post">
{% for question in questions %} {% for question in questions %}
{% if (questions[question]["type"] == "likert") %} {% if (questions[question]["type"] == "likert") %}

View File

@ -10,7 +10,7 @@
<body> <body>
<div class="container"> <div class="container">
<h2>Hello! Thank you for participating in our study!</h2> <h2>Hello! Thank you for participating in our study!</h2>
<form action="http://localhost:5000/start" method="post"> <form action="{{ url_for('startpage') }}" method="post">
<label for="terms-and-conditions"> <label for="terms-and-conditions">
<input class="inline" id="terms-and-conditions" type="checkbox" required name="terms-and-conditions" /> I accept the +terms and conditions</a> <input class="inline" id="terms-and-conditions" type="checkbox" required name="terms-and-conditions" /> I accept the +terms and conditions</a>
</label> </label>

View File

@ -1,20 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css')}}"" /> <!-- styles.css {{ url_for('static', filename='styles.css')}}-->
<title>Test Page 0 - Nothing</title>
<link rel="shortcut icon" href="{{ url_for('static', filename='icons/favicon.ico') }}">
</head>
<body>
<div class="container">
<p>This is just a test page for the single page option of the json configuration, but without something to submit</p>
<form action="http://localhost:5000/send_json" method="post">
<input type="hidden" name="submittedString" value="Hello, backend!">
<input id="submitbutton" type = "submit" value = "submit";/>
</form>
</div>
</body>
</html>

View File

@ -1,25 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles.css')}}"" /> <!-- styles.css {{ url_for('static', filename='styles.css')}}-->
<title>Test Page 1 - Datenschutzerklaerung</title>
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
</head>
<body>
<div class="container">
<p>This is just a test page for the single page option of the json configuration</p>
<form action="http://localhost:5000/send_json" method="post">
<input
type="checkbox"
id="accepted"
name="accepted"
value="checked" />
<label for="accepted">Akzeptieren sie die Datenschutzerklaerung</label>
<p><input id="submitbutton" type = "submit" value = "submit";/></p>
</form>
</div>
</body>
</html>

View File

@ -32,7 +32,7 @@
</p> </p>
</div> </div>
<form class="dsgvoform" action="http://localhost:5000/start" method="post"> <form class="dsgvoform" action="{{ url_for('startpage') }}" method="post">
<label for="terms-and-conditions"> <label for="terms-and-conditions">
<input class="inline" id="terms-and-conditions" type="checkbox" required name="terms-and-conditions" /> I accept the +terms and conditions <input class="inline" id="terms-and-conditions" type="checkbox" required name="terms-and-conditions" /> I accept the +terms and conditions
</label> </label>