summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/database/database.rs23
-rw-r--r--src/main.rs5
-rw-r--r--src/routes/submission.rs11
-rw-r--r--static/default.css4
-rw-r--r--static/main.js5
-rw-r--r--static/submission.html40
-rw-r--r--static/submission.js35
-rw-r--r--static/submit.html3
8 files changed, 121 insertions, 5 deletions
diff --git a/src/database/database.rs b/src/database/database.rs
index 961c39c..95c8bf6 100644
--- a/src/database/database.rs
+++ b/src/database/database.rs
@@ -244,6 +244,29 @@ impl Database {
.map_err(|e| DatabaseError::Query(e.to_string()))?
)
}
+
+ pub fn fetch_display_submission(&self, submission_id: i64) -> Result<Option<DisplaySubmission>, DatabaseError> {
+ static QUERY: &str = include_str!("sql/fetch_display_submissions.sql");
+ let conn = self.pool
+ .get()
+ .map_err(|e| DatabaseError::Connection(e.to_string()))?;
+ let mut statement = conn.prepare(QUERY)
+ .map_err(|e| DatabaseError::Query(e.to_string()))?;
+
+ Ok(statement
+ .query_one([submission_id], |row| {
+ Ok(DisplaySubmission {
+ id: row.get("id")?,
+ username: row.get("username")?,
+ language: row.get("language")?,
+ details: row.get("details")?,
+ code: row.get("code")?,
+ })
+ })
+ .optional()
+ .map_err(|e| DatabaseError::Query(e.to_string()))?
+ )
+ }
pub fn initialize(&self) -> Result<(), DatabaseError> {
static QUERY: &str = include_str!("sql/initialize.sql");
diff --git a/src/main.rs b/src/main.rs
index 9659af3..afa9821 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -14,7 +14,7 @@ use routes::user::{create_user, me};
use routes::auth::{login, logout};
use tower_http::services::ServeDir;
-use crate::{database::Database, routes::submission::{create_submission, get_display_submissions, get_submissions_by_problem_id}, utils::register_admin};
+use crate::{database::Database, routes::submission::{create_submission, get_display_submission, get_display_submissions, get_submissions_by_problem_id}, utils::register_admin};
#[derive(Clone)]
struct AppState {
@@ -62,10 +62,11 @@ async fn main() {
.route("/login", post(login))
.route("/logout", post(logout))
.route("/problem/{problem_id}", get(get_problem))
+ .route("/problem/{problem_id}/submission", get(get_display_submissions))
.route("/problem", get(get_problems))
.route("/problem", post(create_problem))
.route("/submission", post(create_submission))
- .route("/submission/{problem_id}", get(get_display_submissions))
+ .route("/submission/{submission_id}", get(get_display_submission))
.route("/user", post(create_user))
.route("/me", get(me))
.nest_service("/static", static_files)
diff --git a/src/routes/submission.rs b/src/routes/submission.rs
index 4cfad5c..b3cf2b9 100644
--- a/src/routes/submission.rs
+++ b/src/routes/submission.rs
@@ -48,3 +48,14 @@ pub async fn get_display_submissions(
Ok(Json(submissions))
}
+pub async fn get_display_submission(
+ State(state): State<AppState>,
+ Path(submission_id): Path<i64>
+) -> Result<impl IntoResponse, RouteError> {
+ match state.database.fetch_display_submission(submission_id) {
+ Ok(None) => Err(RouteError::NotFound("submission".into())),
+ Ok(Some(submission)) => Ok(Json(submission)),
+ Err(e) => Err(RouteError::Internal(format!("unable to fetch submission: {e:?}")))
+ }
+}
+
diff --git a/static/default.css b/static/default.css
index 8f24f39..b137fca 100644
--- a/static/default.css
+++ b/static/default.css
@@ -26,6 +26,10 @@ h3 {
margin-bottom: 2px;
}
+code {
+ border: 1px solid black;
+}
+
#container {
width: 640px;
margin: auto;
diff --git a/static/main.js b/static/main.js
index b070ccb..b3bf50f 100644
--- a/static/main.js
+++ b/static/main.js
@@ -88,7 +88,8 @@ function create_problem_element(problem, submissions) {
const sub_subm = document.createElement("td");
const sub_anch = document.createElement("a");
- sub_anch.href = "submission.html?id=5";
+
+ sub_anch.href = `submission.html?problem_id=${problem.id}&submission_id=${submission.id}`;
sub_anch.innerText = "view submission";
sub_subm.appendChild(sub_anch);
sub_row.appendChild(sub_subm);
@@ -99,7 +100,7 @@ function create_problem_element(problem, submissions) {
}
async function fetch_submissions(problem_id) {
- const response = await fetch(`/submission/${problem_id}`)
+ const response = await fetch(`/problem/${problem_id}/submission`)
const result = await response.json();
return result;
}
diff --git a/static/submission.html b/static/submission.html
new file mode 100644
index 0000000..0789c12
--- /dev/null
+++ b/static/submission.html
@@ -0,0 +1,40 @@
+<!doctype html>
+
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Code Golf Login</title>
+ <link rel="icon" href="favicon.ico">
+ <link rel="stylesheet" href="default.css">
+ <script type="text/javascript" src="submission.js"></script>
+
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/styles/default.min.css">
+ <script src="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/languages/c.min.js"></script>
+ </head>
+
+ <body onload="init()">
+ <div id="layout">
+ <div id="container">
+ <div id="content">
+ <a href="index.html">Home</a>
+ <h1>C&amp;! Code Golf Leaderboard</h1>
+ <div id="submission-problem"></div>
+ <div id="error" hidden>
+ <span id="error-message" style="color: red"></span>
+ <br><br>
+ </div>
+ <h2>Submission</h2>
+ <div id="submission-div">
+ <p id="submission-author"</p>
+ <p id="submission-size"</p>
+ <pre><code id="submission-code"></code></pre>
+ <h3>Additional Details</h3>
+ <p id="submission-details"></p>
+ </div>
+ <center>&copy; 2026 Daniel Hader</center>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/static/submission.js b/static/submission.js
new file mode 100644
index 0000000..bbe4075
--- /dev/null
+++ b/static/submission.js
@@ -0,0 +1,35 @@
+async function get_problem() {
+ const url_params = new URLSearchParams(window.location.search);
+ const problem_id = parseInt(url_params.get("problem_id"));
+ const response = await fetch(`/problem/${problem_id}`)
+ return await response.json();
+}
+
+async function get_submission() {
+ const url_params = new URLSearchParams(window.location.search);
+ const submission_id = parseInt(url_params.get("submission_id"));
+ const response = await fetch(`/submission/${submission_id}`)
+ return await response.json();
+}
+
+async function init() {
+ const problem = await get_problem();
+ const submission = await get_submission();
+
+ const problem_div = document.getElementById("submission-problem");
+
+ const title = document.createElement("h2");
+ title.innerHTML = `Problem: ${problem.title}`;
+ problem_div.appendChild(title);
+
+ const description = document.createElement("p");
+ description.innerHTML = problem.description;
+ problem_div.appendChild(description);
+
+ document.getElementById("submission-author").innerHTML = `by ${submission.username}`;
+ document.getElementById("submission-size").innerHTML = `${new Blob([submission.code]).size} bytes`;
+ document.getElementById("submission-details").innerHTML = submission.details;
+ document.getElementById("submission-code").innerHTML = submission.code;
+
+ hljs.highlightAll();
+}
diff --git a/static/submit.html b/static/submit.html
index 151fba5..43a1dbf 100644
--- a/static/submit.html
+++ b/static/submit.html
@@ -25,7 +25,8 @@
<label for="submission-language">Language</label><br>
<select id="submission-language">
<option value="c">C</option>
- <option value="c++">C++</option>
+ <option value="cpp">C++</option>
+ <option value="csharp">C♯</option>
<option value="go">Go</option>
<option value="haskell">Haskell</option>
<option value="java">Java</option>