made deployment finally prod ready
This commit is contained in:
@@ -102,7 +102,7 @@ def index():
|
|||||||
if not token:
|
if not token:
|
||||||
return redirect(url_for("main.set_token"))
|
return redirect(url_for("main.set_token"))
|
||||||
else:
|
else:
|
||||||
return render_template('index.html', active_banner=get_active_banner(), decks=get_unlocked_decks(token), user_name=token.name, active_course=token.active_course, courses=get_all_courses())
|
return render_template('index.html', active_banner=get_active_banner(), decks=get_unlocked_decks(token), user_name=token.name, active_course_name=token.active_course.name, courses=get_all_courses())
|
||||||
|
|
||||||
@main.route('/set_token', methods=['POST', 'GET'])
|
@main.route('/set_token', methods=['POST', 'GET'])
|
||||||
def set_token():
|
def set_token():
|
||||||
@@ -291,8 +291,7 @@ def serve_deck(deck, course_folder, path='index.html'):
|
|||||||
@main.route('/admin', methods=['GET', 'POST'])
|
@main.route('/admin', methods=['GET', 'POST'])
|
||||||
@flask_login.login_required
|
@flask_login.login_required
|
||||||
def admin():
|
def admin():
|
||||||
active_course_id = flask_login.current_user.active_course_id
|
active_course = get_course(flask_login.current_user.active_course_id)
|
||||||
active_course = get_course(active_course_id)
|
|
||||||
if active_course is None:
|
if active_course is None:
|
||||||
raise Exception
|
raise Exception
|
||||||
deck_form = DeckForm()
|
deck_form = DeckForm()
|
||||||
@@ -338,7 +337,7 @@ def admin():
|
|||||||
print(f"Error in {getattr(password_form, field).label.text}: {error}", flush=True)
|
print(f"Error in {getattr(password_form, field).label.text}: {error}", flush=True)
|
||||||
return redirect(url_for('main.admin'))
|
return redirect(url_for('main.admin'))
|
||||||
|
|
||||||
return render_template("admin.html", deck_form=deck_form, password_form=password_form, decks=decks, passwords=get_passwords(active_course), courses=get_all_courses(), active_course_id=active_course_id)
|
return render_template("admin.html", deck_form=deck_form, password_form=password_form, decks=decks, passwords=get_passwords(active_course), courses=get_all_courses(), active_course_name=active_course.name)
|
||||||
|
|
||||||
@main.route('/admin/switch_course/<new_course>', methods=['POST'])
|
@main.route('/admin/switch_course/<new_course>', methods=['POST'])
|
||||||
@flask_login.login_required
|
@flask_login.login_required
|
||||||
|
|||||||
1
app/static/css/.gitignore
vendored
Normal file
1
app/static/css/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
output.css
|
||||||
3
app/static/css/input.css
Normal file
3
app/static/css/input.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
BIN
app/static/favicon.ico
Normal file
BIN
app/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -6,31 +6,10 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Deck Admin</title>
|
<title>Deck Admin</title>
|
||||||
|
|
||||||
<!-- Tailwind CSS v4.1.4 CDN -->
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/output.css') }}">
|
||||||
<script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"></script>
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
|
|
||||||
<!-- Tailwind Config (Dark Mode + Theme Colors) -->
|
|
||||||
<script>
|
|
||||||
tailwind.config = {
|
|
||||||
darkMode: 'class',
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
background: '#121418', // dark slate with blue/gray tone
|
|
||||||
surface: '#1e2127', // a bit lighter for containers/cards
|
|
||||||
border: '#2a2d34', // visible but subtle borders
|
|
||||||
primary: '#4f8cff', // soft blue that pops but is not neon
|
|
||||||
text: '#e4e4e7', // light gray for high contrast
|
|
||||||
muted: '#a0a0ad', // for subdued text
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Flowbite -->
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/flowbite@3.1.2/dist/flowbite.min.css" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-background text-text min-h-screen font-sans">
|
<body class="bg-background text-text min-h-screen font-sans">
|
||||||
<nav class="bg-white border-gray-200 dark:bg-gray-900">
|
<nav class="bg-white border-gray-200 dark:bg-gray-900">
|
||||||
@@ -42,11 +21,7 @@
|
|||||||
|
|
||||||
<div class="relative group">
|
<div class="relative group">
|
||||||
<button class="flex items-center text-gray-900 dark:text-white hover:text-blue-700 dark:hover:text-blue-500 font-medium py-2 px-3 rounded-lg bg-transparent">
|
<button class="flex items-center text-gray-900 dark:text-white hover:text-blue-700 dark:hover:text-blue-500 font-medium py-2 px-3 rounded-lg bg-transparent">
|
||||||
{% for course in courses %}
|
{{active_course_name}}
|
||||||
{% if course.id == active_course_id %}
|
|
||||||
{{ course.name }}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
<svg class="w-2.5 h-2.5 ms-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
<svg class="w-2.5 h-2.5 ms-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@@ -4,15 +4,8 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Login</title>
|
<title>Login</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<!-- Tailwind CSS -->
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/output.css') }}">
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
<!-- Flowbite -->
|
|
||||||
<script src="https://unpkg.com/flowbite@2.3.0/dist/flowbite.min.js"></script>
|
|
||||||
<script>
|
|
||||||
tailwind.config = {
|
|
||||||
darkMode: 'class',
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-gray-900 text-gray-100 min-h-screen flex items-center justify-center">
|
<body class="bg-gray-900 text-gray-100 min-h-screen flex items-center justify-center">
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="dark">
|
<html lang="en" class="dark">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Banner</title>
|
<title>Banner</title>
|
||||||
|
|
||||||
<!-- Tailwind CSS v4.1.4 CDN -->
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/output.css') }}">
|
||||||
<script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"></script>
|
|
||||||
|
|
||||||
<!-- Tailwind Config (Dark Mode + Theme Colors) -->
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
<script>
|
|
||||||
tailwind.config = {
|
|
||||||
darkMode: 'class',
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
background: '#121418', // dark slate with blue/gray tone
|
|
||||||
surface: '#1e2127', // a bit lighter for containers/cards
|
|
||||||
border: '#2a2d34', // visible but subtle borders
|
|
||||||
primary: '#4f8cff', // soft blue that pops but is not neon
|
|
||||||
text: '#e4e4e7', // light gray for high contrast
|
|
||||||
muted: '#a0a0ad', // for subdued text
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Flowbite -->
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/flowbite@3.1.2/dist/flowbite.min.css" rel="stylesheet" />
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="bg-background text-text min-h-screen font-sans">
|
<body class="bg-background text-text min-h-screen font-sans">
|
||||||
|
|||||||
@@ -3,30 +3,8 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Live Confusion Alerts</title>
|
<title>Live Confusion Alerts</title>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/output.css') }}">
|
||||||
<!-- Tailwind DEV CDN (for production, use your compiled CSS) -->
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.1/socket.io.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Tailwind Config (Dark Mode + Theme Colors) -->
|
|
||||||
<script>
|
|
||||||
tailwind.config = {
|
|
||||||
darkMode: 'class',
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
background: '#121418', // dark slate with blue/gray tone
|
|
||||||
surface: '#1e2127', // a bit lighter for containers/cards
|
|
||||||
border: '#2a2d34', // visible but subtle borders
|
|
||||||
primary: '#4f8cff', // soft blue that pops but is not neon
|
|
||||||
text: '#e4e4e7', // light gray for high contrast
|
|
||||||
muted: '#a0a0ad', // for subdued text
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-background min-h-screen">
|
<body class="bg-background min-h-screen">
|
||||||
<nav class="bg-white border-gray-200 dark:bg-gray-900">
|
<nav class="bg-white border-gray-200 dark:bg-gray-900">
|
||||||
|
|||||||
@@ -5,37 +5,14 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Tutorial Materials</title>
|
<title>Tutorial Materials</title>
|
||||||
|
|
||||||
<!-- Tailwind CSS v4.1.4 CDN -->
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/output.css') }}">
|
||||||
<script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"></script>
|
|
||||||
|
|
||||||
<!-- Tailwind Config (Dark Mode + Theme Colors) -->
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
<script>
|
|
||||||
tailwind.config = {
|
|
||||||
darkMode: 'class',
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
background: '#121418', // dark slate with blue/gray tone
|
|
||||||
surface: '#1e2127', // a bit lighter for containers/cards
|
|
||||||
border: '#2a2d34', // visible but subtle borders
|
|
||||||
primary: '#4f8cff', // soft blue that pops but is not neon
|
|
||||||
text: '#e4e4e7', // light gray for high contrast
|
|
||||||
muted: '#a0a0ad', // for subdued text
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Flowbite -->
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/flowbite@3.1.2/dist/flowbite.min.css" rel="stylesheet" />
|
|
||||||
|
|
||||||
<!-- in base.html, in <head> or just before </body> -->
|
<!-- in base.html, in <head> or just before </body> -->
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.1/socket.io.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.1/socket.io.min.js"></script>
|
||||||
|
|
||||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
||||||
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
||||||
@@ -83,11 +60,7 @@
|
|||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<div class="relative group">
|
<div class="relative group">
|
||||||
<button class="flex items-center text-gray-900 dark:text-white hover:text-blue-700 dark:hover:text-blue-500 font-medium py-1 px-3 rounded-lg bg-transparent text-2xl">
|
<button class="flex items-center text-gray-900 dark:text-white hover:text-blue-700 dark:hover:text-blue-500 font-medium py-1 px-3 rounded-lg bg-transparent text-2xl">
|
||||||
{% for course in courses %}
|
{{active_course_name}}
|
||||||
{% if course.id == active_course.id %}
|
|
||||||
{{ course.name }}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
<svg class="w-2.5 h-2.5 ms-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
<svg class="w-2.5 h-2.5 ms-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
||||||
</svg>
|
</svg>
|
||||||
@@ -167,19 +140,5 @@
|
|||||||
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/flowbite@3.1.2/dist/flowbite.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/flowbite@3.1.2/dist/flowbite.min.js"></script>
|
||||||
<script>
|
|
||||||
function enableUsernameEdit() {
|
|
||||||
const input = document.getElementById('usernameInput');
|
|
||||||
const editBtn = document.getElementById('editBtn');
|
|
||||||
const saveBtn = document.getElementById('saveBtn');
|
|
||||||
|
|
||||||
input.removeAttribute('disabled');
|
|
||||||
input.classList.add('border-border');
|
|
||||||
input.focus();
|
|
||||||
|
|
||||||
editBtn.classList.add('hidden');
|
|
||||||
saveBtn.classList.remove('hidden');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -4,16 +4,10 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Register for Tutortool</title>
|
<title>Register for Tutortool</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/output.css') }}">
|
||||||
<style>
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
body {
|
|
||||||
@apply bg-background text-text font-sans;
|
|
||||||
background-color: #1a202c;
|
|
||||||
color: #a0aec0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="flex items-center justify-center min-h-screen">
|
<body class="flex items-center justify-center min-h-screen bg-background">
|
||||||
<div class="bg-gray-800 p-8 rounded-lg shadow-lg max-w-md w-full border border-gray-700">
|
<div class="bg-gray-800 p-8 rounded-lg shadow-lg max-w-md w-full border border-gray-700">
|
||||||
<div class="text-center mb-6">
|
<div class="text-center mb-6">
|
||||||
<h1 class="text-3xl font-bold text-white mb-2">Create an Account</h1>
|
<h1 class="text-3xl font-bold text-white mb-2">Create an Account</h1>
|
||||||
@@ -58,7 +52,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p class="text-center mt-4 text-sm">
|
<p class="text-center mt-4 text-sm text-text">
|
||||||
Already have an account? <a href="/set_token" class="text-blue-400 hover:underline">Log In</a>
|
Already have an account? <a href="/set_token" class="text-blue-400 hover:underline">Log In</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,16 +4,10 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Register for Tutortool</title>
|
<title>Register for Tutortool</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/output.css') }}">
|
||||||
<style>
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
body {
|
|
||||||
@apply bg-background text-text font-sans;
|
|
||||||
background-color: #1a202c;
|
|
||||||
color: #a0aec0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="flex items-center justify-center min-h-screen">
|
<body class="flex items-center justify-center min-h-screen bg-background">
|
||||||
<div class="bg-gray-800 p-8 rounded-lg shadow-lg max-w-md w-full border border-gray-700">
|
<div class="bg-gray-800 p-8 rounded-lg shadow-lg max-w-md w-full border border-gray-700">
|
||||||
<div class="text-center mb-6">
|
<div class="text-center mb-6">
|
||||||
<h1 class="text-3xl font-bold text-white mb-2">Login</h1>
|
<h1 class="text-3xl font-bold text-white mb-2">Login</h1>
|
||||||
@@ -44,7 +38,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p class="text-center mt-4 text-sm">
|
<p class="text-center mt-4 text-sm text-text">
|
||||||
Do not have an Account? <a href="/register" class="text-blue-400 hover:underline">Create one</a>
|
Do not have an Account? <a href="/register" class="text-blue-400 hover:underline">Create one</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
1856
package-lock.json
generated
Normal file
1856
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
package.json
Normal file
23
package.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "tutor",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build:css": "npx tailwindcss -i app/static/css/input.css -o app/static/css/output.css --minify"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "ssh://git@gitea.cato447.de:222/cato447/tutor-tool.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"type": "commonjs",
|
||||||
|
"devDependencies": {
|
||||||
|
"autoprefixer": "^10.4.21",
|
||||||
|
"flowbite": "^3.1.2",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
|
"tailwindcss": "^3.4.17"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#/bin/bash
|
#/bin/bash
|
||||||
|
|
||||||
|
npm run build:css
|
||||||
|
|
||||||
nohup .venv/bin/gunicorn \
|
nohup .venv/bin/gunicorn \
|
||||||
--bind 127.0.0.1:5000 \
|
--bind 127.0.0.1:5000 \
|
||||||
--worker-class eventlet \
|
--worker-class eventlet \
|
||||||
|
|||||||
20
tailwind.config.js
Normal file
20
tailwind.config.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ["./app/templates/**/*.html"], // <-- MUST BE CORRECT
|
||||||
|
darkMode: 'class',
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
background: '#121418',
|
||||||
|
surface: '#1e2127',
|
||||||
|
border: '#2a2d34',
|
||||||
|
primary: '#4f8cff',
|
||||||
|
text: '#e4e4e7',
|
||||||
|
muted: '#a0a0ad',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
require('flowbite/plugin')
|
||||||
|
],
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user