Skip to content

Commit

Permalink
Static pages using iframes
Browse files Browse the repository at this point in the history
  • Loading branch information
jdabtieu committed Jan 3, 2025
1 parent 4241a3c commit 480a22f
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 2 deletions.
11 changes: 11 additions & 0 deletions src/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,17 @@ def ranking():
is_ongoing_contest=is_ongoing_contest)


@app.route('/page/<path:path>')
def static_page(path):
path = path.strip().strip('/').lower()
page = db.execute("SELECT * FROM static_pages WHERE path=?", path)
if len(page) == 0:
return abort(404)

Check warning on line 891 in src/application.py

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

W293 blank line contains whitespace

Check warning on line 891 in src/application.py

View workflow job for this annotation

GitHub Actions / build (windows-latest)

W293 blank line contains whitespace
return render_template("staticpage.html", data=page[0])

Check warning on line 893 in src/application.py

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

W293 blank line contains whitespace

Check warning on line 893 in src/application.py

View workflow job for this annotation

GitHub Actions / build (windows-latest)

W293 blank line contains whitespace


# Error handling
def errorhandler(e):
if not isinstance(e, HTTPException):
Expand Down
6 changes: 6 additions & 0 deletions src/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,9 @@ CREATE TABLE 'contest_problems' (
'instanced' boolean NOT NULL DEFAULT(0),
UNIQUE(contest_id, problem_id) ON CONFLICT ABORT
);
CREATE TABLE 'static_pages' (
'id' integer PRIMARY KEY NOT NULL,
'title' varchar(256) NOT NULL,
'path' varchar(256) NOT NULL UNIQUE,
'content' text NOT NULL
);
6 changes: 4 additions & 2 deletions src/templates/admin/console.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,14 @@ <h5 class="card-title">Manage Problems</h5>
<div class="col-sm-6 admin-card">
<div class="card bg-ld-blue">
<div class="card-body">
<h5 class="card-title">Manage Homepage</h5>
<h5 class="card-title">Manage Static Pages</h5>
<p class="card-text">Edit and preview your homepage, if enabled in site settings.</p>
<a class="btn btn-primary" href="/admin/edithomepage" role="button">Edit Homepage</a>
&nbsp;&nbsp;&nbsp;&nbsp;
<a class="btn btn-primary" href="/admin/previewhomepage" role="button">Preview Homepage</a>
<br>
<br>
<a class="btn btn-primary" href="/admin/previewhomepage" role="button">Preview Homepage</a>
<a class="btn btn-primary" href="/admin/staticpages" role="button">Manage Static Pages</a>
</div>
</div>
</div>
Expand Down
41 changes: 41 additions & 0 deletions src/templates/admin/createstaticpage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{% extends "layout.html" %}

{% block title %}Create Static Page{% endblock %}
{% block active %}Admin Console{% endblock %}

{% block main %}
<h1>Create Static Page</h1>
<form autocomplete="off" method="post" id="create" name="create">
<div class="form-floating">
<input autofocus
class="form-control mb-3"
name="title"
id="title"
placeholder="Title"
required>
<label for="title">Title</label>
</div>
<div class="flex">
<p style="margin: auto 4px auto 0;">/page/</p>
<div class="form-floating" style="flex: 1;">
<input autofocus
class="form-control mb-3"
name="path"
id="path"
placeholder="Path"
required>
<label for="name">Path</label>
</div>
</div>
<div style="display: flex;">
<textarea class="form-control mb-3"
id="content"
name="content"
rows="20"
placeholder="HTML Content"
required></textarea>
</div>
<input class="btn btn-primary" type="submit" id="submit" name="submit" value="Create">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
</form>
{% endblock %}
43 changes: 43 additions & 0 deletions src/templates/admin/editstaticpage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{% extends "layout.html" %}

{% block title %}Edit Static Page{% endblock %}
{% block active %}Admin Console{% endblock %}

{% block main %}
<h1>Edit Static Page</h1>
<form autocomplete="off" method="post" id="edit" name="edit">
<div class="form-floating">
<input autofocus
class="form-control mb-3"
name="title"
id="title"
placeholder="Title"
value="{{ data['title'] }}"
required>
<label for="title">Title</label>
</div>
<div class="flex">
<p style="margin: auto 4px auto 0;">/page/</p>
<div class="form-floating" style="flex: 1;">
<input autofocus
class="form-control mb-3"
name="path"
id="path"
placeholder="Path"
value="{{ data['path'] }}"
required>
<label for="name">Path</label>
</div>
</div>
<div style="display: flex;">
<textarea class="form-control mb-3"
id="content"
name="content"
rows="20"
placeholder="HTML Content"
required>{{ data['content'] }}</textarea>
</div>
<input class="btn btn-primary" type="submit" id="submit" name="submit" value="Edit">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
</form>
{% endblock %}
70 changes: 70 additions & 0 deletions src/templates/admin/staticpages.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{% extends "layout.html" %}

{% block title %}Static Pages{% endblock %}
{% block active %}Admin Console{% endblock %}

{% block main %}
<h1>Static Pages <a class="btn btn-primary" href="/admin/staticpages/create" role="button">Create New</a></h1>
<div id="confirm" style="display: none;">
<form method="post" style="margin-bottom: 1rem;">
<input class="btn btn-danger" type="submit">
<input type="hidden" name="page_id">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
</form>
</div>
<div class="flex-desktop">
<div style="flex: 3; overflow-x: auto;">
<table class="table table-hover table-full-width">
<thead class="table-dark">
<tr>
<th scope="col" style="width: 45%;">Title</th>
<th scope="col" style="width: 45%;">Path</th>
<th scope="col" style="width: 10%;">Actions</th>
</tr>
</thead>
<tbody>
{% for row in data %}
<tr>
<td class="page-title">{{ row["title"] }}</td>
<td><a href="/page/{{ row['path'] }}">/page/{{ row["path"] }}</a></td>
<td data-id="{{ row['id'] }}">
<a href="/admin/staticpages/edit/{{ row['id'] }}">
<img src="/assets/images/pencil.svg"
onerror="this.src='/assets/images/pencil.png'"
class="icon"
alt="Edit page"
title="Edit page">
</a>
<a href="#">
<img src="/assets/images/trash.svg"
onerror="this.src='/assets/images/trash.png'"
class="icon pages-delete"
alt="Delete page"
title="Delete page">
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
{% block script %}
<script>
function createForm(msg, path, userId) {
document.getElementById("confirm").style.display = "";
document.querySelector("#confirm .btn").setAttribute("value", msg);
document.querySelector("#confirm form").setAttribute("action", path);
document.querySelector("#confirm input[name=page_id]").setAttribute("value", userId);
}

for (let node of document.getElementsByClassName("pages-delete")) {
node.parentElement.addEventListener("click", function() {
var title = this.parentElement.parentElement.querySelector(".page-title").textContent;
var msg = `Are you sure you want to delete ${title}? Click here to confirm.`;
createForm(msg, "/admin/staticpages/delete", this.parentElement.getAttribute("data-id"));
});
}
</script>
{% endblock %}
25 changes: 25 additions & 0 deletions src/templates/staticpage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#0d6efd">

<title>{{ data['title'] }} | {{ CLUB_NAME }}</title>
</head>
<body style="margin: 0; padding: 0; overflow: hidden;">
<template id="data">
{{ data['content'] }}
</template>
<iframe referrerpolicy="no-referrer"
sandbox="allow-downloads allow-forms allow-modals allow-pointer-lock allow-popups allow-presentation allow-scripts"
style="width: 100vw; height: 100vh; border: none;">
</iframe>
<script id="loader">
const data = document.getElementById('data').content.textContent;
document.querySelector('iframe').srcdoc = data;
document.getElementById('data').remove();
document.getElementById('loader').remove();
</script>
</body>
</html>
68 changes: 68 additions & 0 deletions src/views/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,3 +417,71 @@ def preview_homepage():
props["length"] = db.execute(
"SELECT COUNT(*) AS cnt FROM announcements")[0]["cnt"]
return render_template(f"home_fragment/home{template_type}.html", props=props)


@api.route("/staticpages")
@perm_required(["ADMIN", "SUPERADMIN", "CONTENT_MANAGER"])
def list_static_pages():
data = db.execute("SELECT * FROM static_pages")
return render_template("admin/staticpages.html", data=data)

@api.route("/staticpages/create", methods=["GET", "POST"])
@perm_required(["ADMIN", "SUPERADMIN", "CONTENT_MANAGER"])
def create_static_page():
if request.method == "GET":
return render_template("admin/createstaticpage.html")

# Reached via POST
title = request.form.get("title")
path = request.form.get("path")
content = request.form.get("content")

if not title or not path or not content:
flash('You have not entered all required fields', 'danger')
return render_template("admin/createstaticpage.html"), 400
path = path.strip().strip('/').lower()

db.execute("INSERT INTO static_pages (title, path, content) VALUES (?, ?, ?)",
title, path, content)
return redirect("/admin/staticpages")

@api.route("/staticpages/delete", methods=["POST"])
@perm_required(["ADMIN", "SUPERADMIN", "CONTENT_MANAGER"])
def delete_static_page():
page_id = request.form.get("page_id")
if not page_id:
return "Must provide page ID", 400

r = db.execute("DELETE FROM static_pages WHERE id=?", page_id)
if r == 0:
flash("That page doesn't exist", "warning")
return redirect("/admin/staticpages")

return redirect("/admin/staticpages")

@api.route("/staticpages/edit/<pid>", methods=["GET", "POST"])
@perm_required(["ADMIN", "SUPERADMIN", "CONTENT_MANAGER"])
def edit_static_page(pid):
data = db.execute("SELECT * FROM static_pages WHERE id=?", pid)
if len(data) == 0:
flash('That page does not exist', 'danger')
return redirect("/admin/staticpages")

data = data[0]
if request.method == "GET":
return render_template("admin/editstaticpage.html", data=data)

# Reached via POST
title = request.form.get("title")
path = request.form.get("path")
content = request.form.get("content")

if not title or not path or not content:
flash('You have not entered all required fields', 'danger')
return render_template("admin/editstaticpage.html"), 400
path = path.strip().strip('/').lower()

db.execute("UPDATE static_pages SET title=?, path=?, content=? WHERE id=?",
title, path, content, pid)
flash("Page successfully updated", "success")
return redirect("/admin/staticpages")

0 comments on commit 480a22f

Please sign in to comment.