aboutsummaryrefslogtreecommitdiffhomepage
path: root/backend/admin
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-09-17 00:45:46 +0900
committernsfisis <nsfisis@gmail.com>2025-09-17 00:45:46 +0900
commit611d93ea8a5dcc7dd92ec412e8fb28078438b31b (patch)
tree9b08446290e60af9bcda7547ece21e8dc6c40e76 /backend/admin
parenta49e0b2fc1a59b54043b9ca93828346c027973eb (diff)
downloadiosdc-japan-2025-albatross-611d93ea8a5dcc7dd92ec412e8fb28078438b31b.tar.gz
iosdc-japan-2025-albatross-611d93ea8a5dcc7dd92ec412e8fb28078438b31b.tar.zst
iosdc-japan-2025-albatross-611d93ea8a5dcc7dd92ec412e8fb28078438b31b.zip
feat(backend): add admin pages for submissions
Diffstat (limited to 'backend/admin')
-rw-r--r--backend/admin/handler.go83
-rw-r--r--backend/admin/templates/game_edit.html3
-rw-r--r--backend/admin/templates/games.html1
-rw-r--r--backend/admin/templates/submission_detail.html37
-rw-r--r--backend/admin/templates/submissions.html35
5 files changed, 159 insertions, 0 deletions
diff --git a/backend/admin/handler.go b/backend/admin/handler.go
index 2a50cb0..5316250 100644
--- a/backend/admin/handler.go
+++ b/backend/admin/handler.go
@@ -68,6 +68,8 @@ func (h *Handler) RegisterHandlers(g *echo.Group) {
g.GET("/games/:gameID", h.getGameEdit)
g.POST("/games/:gameID", h.postGameEdit)
g.POST("/games/:gameID/start", h.postGameStart)
+ g.GET("/games/:gameID/submissions", h.getSubmissions)
+ g.GET("/games/:gameID/submissions/:submissionID", h.getSubmissionDetail)
g.GET("/problems", h.getProblems)
g.GET("/problems/new", h.getProblemNew)
@@ -576,6 +578,87 @@ func (h *Handler) postGameStart(c echo.Context) error {
return c.Redirect(http.StatusSeeOther, h.conf.BasePath+"admin/games")
}
+func (h *Handler) getSubmissions(c echo.Context) error {
+ gameID, err := strconv.Atoi(c.Param("gameID"))
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, "Invalid game_id")
+ }
+
+ submissions, err := h.q.GetSubmissionsByGameID(c.Request().Context(), int32(gameID))
+ if err != nil {
+ return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
+ }
+
+ entries := make([]echo.Map, len(submissions))
+ for i, r := range submissions {
+ entries[i] = echo.Map{
+ "SubmissionID": r.SubmissionID,
+ "UserID": r.UserID,
+ "Status": r.Status,
+ "CodeSize": r.CodeSize,
+ "CreatedAt": r.CreatedAt.Time.In(jst).Format("2006-01-02T15:04"),
+ }
+ }
+
+ return c.Render(http.StatusOK, "submissions", echo.Map{
+ "BasePath": h.conf.BasePath,
+ "Title": "Submissions",
+ "GameID": gameID,
+ "Submissions": entries,
+ })
+}
+
+func (h *Handler) getSubmissionDetail(c echo.Context) error {
+ gameID, err := strconv.Atoi(c.Param("gameID"))
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, "Invalid game_id")
+ }
+
+ submissionID, err := strconv.Atoi(c.Param("submissionID"))
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, "Invalid submission_id")
+ }
+
+ submission, err := h.q.GetSubmissionByID(c.Request().Context(), int32(submissionID))
+ if err != nil {
+ if errors.Is(err, pgx.ErrNoRows) {
+ return echo.NewHTTPError(http.StatusNotFound)
+ }
+ return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
+ }
+
+ testcaseResultRows, err := h.q.GetTestcaseResultsBySubmissionID(c.Request().Context(), int32(submissionID))
+ if err != nil {
+ return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
+ }
+ testcaseResults := make([]echo.Map, len(testcaseResultRows))
+ for i, r := range testcaseResultRows {
+ testcaseResults[i] = echo.Map{
+ "TestcaseResultID": r.TestcaseResultID,
+ "TestcaseID": r.TestcaseID,
+ "Status": r.Status,
+ "CreatedAt": r.CreatedAt.Time.In(jst).Format("2006-01-02T15:04"),
+ "Stdout": r.Stdout,
+ "Stderr": r.Stderr,
+ }
+ }
+
+ return c.Render(http.StatusOK, "submission_detail", echo.Map{
+ "BasePath": h.conf.BasePath,
+ "Title": "Submission Detail",
+ "GameID": gameID,
+ "Submission": echo.Map{
+ "SubmissionID": submission.SubmissionID,
+ "UserID": submission.UserID,
+ "Status": submission.Status,
+ "CodeSize": submission.CodeSize,
+ "CreatedAt": submission.CreatedAt.Time.In(jst).Format("2006-01-02T15:04"),
+ "Code": submission.Code,
+ },
+ "TestcaseResults": testcaseResults,
+ })
+}
+
func (h *Handler) getProblems(c echo.Context) error {
rows, err := h.q.ListProblems(c.Request().Context())
if err != nil {
diff --git a/backend/admin/templates/game_edit.html b/backend/admin/templates/game_edit.html
index b171343..a6900e8 100644
--- a/backend/admin/templates/game_edit.html
+++ b/backend/admin/templates/game_edit.html
@@ -66,4 +66,7 @@
<button type="submit" formaction="{{ .BasePath }}admin/games/{{ .Game.GameID }}/start">Start</button>
</div>
</form>
+<div>
+ <a href="{{ .BasePath }}admin/games/{{ .Game.GameID }}/submissions">View Submissions</a>
+</div>
{{ end }}
diff --git a/backend/admin/templates/games.html b/backend/admin/templates/games.html
index d642f07..63f27b7 100644
--- a/backend/admin/templates/games.html
+++ b/backend/admin/templates/games.html
@@ -21,6 +21,7 @@
{{ if .IsPublic }}
<li><a href="{{ $.BasePath }}golf/{{ .GameID }}/watch">Watch</a></li>
{{ end }}
+ <li><a href="{{ $.BasePath }}admin/games/{{ .GameID }}/submissions">Submissions</a></li>
</ul>
</li>
{{ end }}
diff --git a/backend/admin/templates/submission_detail.html b/backend/admin/templates/submission_detail.html
new file mode 100644
index 0000000..406c0b4
--- /dev/null
+++ b/backend/admin/templates/submission_detail.html
@@ -0,0 +1,37 @@
+{{ template "base.html" . }}
+
+{{ define "breadcrumb" }}
+<a href="{{ .BasePath }}admin/dashboard">Dashboard</a> |
+<a href="{{ .BasePath }}admin/games">Games</a> |
+<a href="{{ .BasePath }}admin/games/{{ .GameID }}">Game {{ .GameID }}</a> |
+<a href="{{ .BasePath }}admin/games/{{ .GameID }}/submissions">Submissions</a>
+{{ end }}
+
+{{ define "content" }}
+<h2>Submission {{ .Submission.SubmissionID }}</h2>
+
+<h3>Basics</h3>
+<ul>
+ <li>User: {{ .Submission.UserID }}</li>
+ <li>Status: {{ .Submission.Status }}</li>
+ <li>Code Size: {{ .Submission.CodeSize }}</li>
+ <li>Created At: {{ .Submission.CreatedAt }}</li>
+</ul>
+
+<h3>Code</h3>
+<pre><code>{{ .Submission.Code }}</code></pre>
+
+<h3>Testcase Results</h3>
+{{ range .TestcaseResults }}
+ <h4>Testcase Result {{ .TestcaseResultID }}</h4>
+ <ul>
+ <li>Testcase ID: {{ .TestcaseID }}</li>
+ <li>Status: {{ .Status }}</li>
+ <li>Created At: {{ .CreatedAt }}</li>
+ </ul>
+ <h5>Stdout</h5>
+ <pre><code>{{ .Stdout }}</code></pre>
+ <h5>Stderr</h5>
+ <pre><code>{{ .Stderr }}</code></pre>
+{{ end }}
+{{ end }}
diff --git a/backend/admin/templates/submissions.html b/backend/admin/templates/submissions.html
new file mode 100644
index 0000000..6870c2a
--- /dev/null
+++ b/backend/admin/templates/submissions.html
@@ -0,0 +1,35 @@
+{{ template "base.html" . }}
+
+{{ define "breadcrumb" }}
+<a href="{{ .BasePath }}admin/dashboard">Dashboard</a> |
+<a href="{{ .BasePath }}admin/games">Games</a> |
+<a href="{{ .BasePath }}admin/games/{{ .GameID }}">Game {{ .GameID }}</a>
+{{ end }}
+
+{{ define "content" }}
+<h2>Submissions for Game {{ .GameID }}</h2>
+<table>
+ <thead>
+ <tr>
+ <th>ID</th>
+ <th>User</th>
+ <th>Status</th>
+ <th>Code Size</th>
+ <th>Created At</th>
+ <th>View</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{ range .Submissions }}
+ <tr>
+ <td>{{ .SubmissionID }}</td>
+ <td>{{ .UserID }}</td>
+ <td>{{ .Status }}</td>
+ <td>{{ .CodeSize }}</td>
+ <td>{{ .CreatedAt }}</td>
+ <td><a href="{{ $.BasePath }}admin/games/{{ $.GameID }}/submissions/{{ .SubmissionID }}">View</a></td>
+ </tr>
+ {{ end }}
+ </tbody>
+</table>
+{{ end }}