added download button to slides with pdfs

This commit is contained in:
2025-10-28 22:58:36 +01:00
parent b13314037f
commit bec3d5a0ea
4 changed files with 53 additions and 7 deletions

1
.gitignore vendored
View File

@@ -4,5 +4,6 @@ node_modules
.venv
config.py
slides
exports
log
nohup.out

View File

@@ -71,6 +71,7 @@ class Deck(db.Model):
deck : Mapped[str] = mapped_column(String(60), nullable=False)
description : Mapped[str] = mapped_column(String(60))
index_file: Mapped[str] = mapped_column(String(40), nullable=False)
export_file: Mapped[Optional[str]] = mapped_column(String(40), nullable=True)
passwords : Mapped[List[Password]] = relationship("Password", secondary=deck_password, back_populates='decks')
tokens : Mapped[List[Token]] = relationship("Token", secondary=deck_token, back_populates='decks')
@@ -78,12 +79,14 @@ class Deck(db.Model):
course: Mapped['Course'] = relationship("Course", back_populates='decks')
def __init__(self, name: str, deck: str, course: Course, description: str = "", index_file: str = "index.html") -> None:
def __init__(self, name: str, deck: str, course: Course, description: str = "", index_file: str = "index.html", export_file: str | None = None) -> None:
self.name = name
self.deck = deck
self.description = description
self.course = course
self.index_file = index_file
if export_file:
self.export_file = export_file
def __repr__(self) -> str:
return f"<Deck(name={self.name}, deck={self.deck}, course={self.course}, index={self.index_file})>"

View File

@@ -102,6 +102,9 @@ def index():
if not token:
return redirect(url_for("main.set_token"))
else:
for deck in get_unlocked_decks(token):
print(str(deck) + " | " + str(deck.export_file))
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())
def set_cookie(token):
@@ -308,6 +311,28 @@ def serve_deck(deck, course_folder, path='index.html'):
abort(404)
@main.route('/exports/<course_folder>/<deck>/<path>')
def serve_export(deck, course_folder, path):
course = db.session.execute(db.select(Course).where(Course.folder==course_folder)).scalar()
if not course:
abort(404)
assert isinstance(course, Course)
deck = db.session.execute(db.select(Deck).where(Deck.deck==deck and Deck.course_id == course.id)).scalar()
if not deck:
abort(404)
assert isinstance(deck, Deck)
if not is_deck_unlocked(deck.deck):
return redirect(url_for('main.index'))
exports_dir = os.path.join(current_app.config['EXPORTS_DIR'], course.folder)
deck_path = os.path.join(exports_dir, deck.deck)
requested_file = os.path.join(deck_path, path)
if os.path.isfile(requested_file):
return send_from_directory(deck_path, path)
abort(404)
@main.route('/admin', methods=['GET', 'POST'])
@flask_login.login_required
def admin():

View File

@@ -132,10 +132,27 @@
<section>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{% for deck in decks %}
<a href="/slides/{{deck.course.folder}}/{{ deck.deck }}/{{ deck.index_file}}" class="block bg-surface border border-border rounded-xl p-5 shadow-sm hover:border-primary hover:bg-background transition">
<div class="bg-surface border border-border rounded-xl shadow-sm transition hover:shadow-lg flex flex-col">
<div class="flex items-center p-5 gap-4">
<a href="/slides/{{deck.course.folder}}/{{ deck.deck }}/{{ deck.index_file}}"
class="flex-grow block border-r border-border pr-4 hover:border-primary transition rounded-xl">
<h3 class="text-lg font-semibold mb-1">{{ deck.name }}</h3>
<p class="text-muted text-sm">{{ deck.description }}</p>
</a>
{% if deck.export_file %}
<a href="/exports/{{deck.course.folder}}/{{ deck.deck }}/{{ deck.export_file}}"
class="inline-flex items-center justify-center flex-shrink-0 h-10 w-10 text-on-primary hover:bg-primary/90 transition"
download title="Download Presentation">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
</a>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</section>