diff options
| author | Daniel Hader <[email protected]> | 2026-06-04 18:29:34 -0500 |
|---|---|---|
| committer | Daniel Hader <[email protected]> | 2026-06-04 18:29:34 -0500 |
| commit | 3ac68b8b59f150e08731a62026ce3ac825655614 (patch) | |
| tree | b493b1668721caf705aaeb7f700b14e21933ae25 | |
| parent | 9122911ca8a8be68d30194a3765a2d4cddaff1a1 (diff) | |
viewing submissions logic
| -rw-r--r-- | src/database/database.rs | 23 | ||||
| -rw-r--r-- | src/main.rs | 5 | ||||
| -rw-r--r-- | src/routes/submission.rs | 11 | ||||
| -rw-r--r-- | static/default.css | 4 | ||||
| -rw-r--r-- | static/main.js | 5 | ||||
| -rw-r--r-- | static/submission.html | 40 | ||||
| -rw-r--r-- | static/submission.js | 35 | ||||
| -rw-r--r-- | static/submit.html | 3 |
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&! 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>© 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> |
