Added ability to remove users from a competition
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 2 Oct 2019 21:27:47 +0000 (16:27 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 2 Oct 2019 21:27:47 +0000 (16:27 -0500)
codebox/app/app.moon
codebox/controllers/admin/competition/edit.moon
codebox/controllers/admin/competition/remove_user.moon [new file with mode: 0644]
codebox/views/admin/competition/edit.moon
docs/todo

index a4a6fbd3a39e1e82b685c5e765f205b2adf8cbd6..53328afbd0d6d031d2342c7414da71bae8b6d199 100644 (file)
@@ -81,6 +81,7 @@ class extends lapis.Application
        ['admin.competition.add_problem': "/admin/competitions/add_problem"]: controller "admin.competition.add_problem"
        ['admin.competition.delete_problem': "/admin/competitions/delete_problem"]: controller "admin.competition.delete_problem"
        ['admin.competition.activate': "/admin/competitions/activate/:competition_id"]: controller "admin.competition.activate"
+       ['admin.competition.remove_user': "/admin/competitions/remove_user"]: controller "admin.competition.remove_user"
 
     ['admin.utils.score': "/admin/score"]: controller "admin.utils.score"
 
index 2aacac8c3d934e1757708cd0e61002dac37a3eb5..519aa01f1eac9105444a52945e7be1108e71a95c 100644 (file)
@@ -1,7 +1,7 @@
 import make_controller from require "controllers.controller"
 import assert_valid from require "lapis.validate"
 import capture_errors, capture_errors_json, yield_error from require 'lapis.application'
-import Competitions, Problems from require 'models'
+import Competitions, Problems, Users from require 'models'
 
 make_controller
        layout: require 'views.partials.admin_layout'
@@ -21,6 +21,11 @@ make_controller
                        return
 
                @comp_problems = @comp\get_problems!
+               @comp_users = @comp\get_competition_users!
+               Users\include_in @comp_users, 'id',
+                       flip: true
+                       as: 'u'
+                       local_key: 'user_id'
                @all_problems = Problems\select!
 
                -- Postgres puts a space between the date and time, need a T
diff --git a/codebox/controllers/admin/competition/remove_user.moon b/codebox/controllers/admin/competition/remove_user.moon
new file mode 100644 (file)
index 0000000..be32f45
--- /dev/null
@@ -0,0 +1,29 @@
+import make_controller from require "controllers.controller"
+import capture_errors, capture_errors_json, yield_error from require 'lapis.application'
+import assert_valid from require 'lapis.validate'
+import CompetitionUsers from require 'models'
+
+make_controller
+       inject:
+               executer: 'executer'
+
+       middleware: { 'logged_in', 'admin_required' }
+
+       get: capture_errors_json =>
+               assert_valid @params, {
+                       { "competition_id", exists: true, is_integer: true }
+                       { "user_id", exists: true, is_integer: true }
+               }
+
+               comp_user = CompetitionUsers\find
+                       competition_id: @params.competition_id
+                       user_id: @params.user_id
+
+               if comp_user
+                       comp_user\delete!
+
+                       @executer\rescore!
+               return redirect_to: @url_for "admin.competition.edit", { competition_id: @params.competition_id }
+               else
+                       yield_error "Compeition user not found"
+
index af684a11985723a0099818faf12c438f0f42825f..ff2694a9c6dd1be10952e6dac6913c8e866dc77b 100644 (file)
@@ -6,42 +6,53 @@ class AdminCompetitionEdit extends html.Widget
 
                div class: 'content', ->
                        div class: 'split-2-1', ->
-                               form method: 'POST', ->
-                                       input type: 'hidden', name: 'id', value: "#{@comp.id}", ""
-
-                    div class: 'split-3-1', ->
-                        div class: 'mar-r-24', ->
-                            label for: 'name', 'Competition name'
-                            input type: 'text', name: 'name', value: "#{@comp.name}", ""
-                        div ->
-                            label for: 'time_offset', 'Time offset (in minutes)'
-                            input type: 'number', name: 'time_offset', value: "#{@comp.time_offset}", ""
-
-                    div class: 'split-2', ->
-                        div ->
-                            label for: 'start_time', 'Start time'
-                            input type: 'datetime-local', name: 'start_time', value: "#{@comp.start}", ""
-
-                        div ->
-                            label for: 'end_time', 'End time'
-                            input type: 'datetime-local', name: 'end_time', value: "#{@comp.end}", ""
-
-                    div class: 'mar-t-48', -> text ""
-
-                    div class: 'split-3', ->
-                        div class: 'mar-r-12', ->
-                            label for: 'programming_points', 'Programming points'
-                            input type: 'number', name: 'programming_points', value: "#{@comp.programming_points}", ""
-
-                        div class: 'mar-r-12 mar-l-12', ->
-                            label for: 'codegolf_points', 'Code golf points'
-                            input type: 'number', name: 'codegolf_points', value: "#{@comp.codegolf_points}", ""
-
-                        div class: 'mar-l-12', ->
-                            label for: 'word_points', 'Word points'
-                            input type: 'number', name: 'word_points', value: "#{@comp.word_points}", ""
-
-                                       input class: 'mar-t-24', type: 'submit', value: 'Save competition'
+                               div ->
+                                       form method: 'POST', ->
+                                               input type: 'hidden', name: 'id', value: "#{@comp.id}", ""
+
+                                               div class: 'split-3-1', ->
+                                                       div class: 'mar-r-24', ->
+                                                               label for: 'name', 'Competition name'
+                                                               input type: 'text', name: 'name', value: "#{@comp.name}", ""
+                                                       div ->
+                                                               label for: 'time_offset', 'Time offset (in minutes)'
+                                                               input type: 'number', name: 'time_offset', value: "#{@comp.time_offset}", ""
+
+                                               div class: 'split-2', ->
+                                                       div ->
+                                                               label for: 'start_time', 'Start time'
+                                                               input type: 'datetime-local', name: 'start_time', value: "#{@comp.start}", ""
+
+                                                       div ->
+                                                               label for: 'end_time', 'End time'
+                                                               input type: 'datetime-local', name: 'end_time', value: "#{@comp.end}", ""
+
+                                               div class: 'mar-t-48', -> text ""
+
+                                               div class: 'split-3', ->
+                                                       div class: 'mar-r-12', ->
+                                                               label for: 'programming_points', 'Programming points'
+                                                               input type: 'number', name: 'programming_points', value: "#{@comp.programming_points}", ""
+
+                                                       div class: 'mar-r-12 mar-l-12', ->
+                                                               label for: 'codegolf_points', 'Code golf points'
+                                                               input type: 'number', name: 'codegolf_points', value: "#{@comp.codegolf_points}", ""
+
+                                                       div class: 'mar-l-12', ->
+                                                               label for: 'word_points', 'Word points'
+                                                               input type: 'number', name: 'word_points', value: "#{@comp.word_points}", ""
+
+                                               input class: 'mar-t-24', type: 'submit', value: 'Save competition'
+
+                                       div class: 'header-line mar-t-48', ->
+                                               span "Joined users"
+
+                                       div class: 'box', ->
+                                               for user in *@comp_users
+                                                       div class: 'highlight pad-12 split-lr', ->
+                                                               div "#{user.u.username} - #{user.u.nickname}"
+                                                               div class: 'button-list', ->
+                                                                       a href: (@url_for "admin.competition.remove_user", {}, { competition_id: @comp.id, user_id: user.user_id }), 'Remove'
 
                                div class: 'mar-l-24', ->
                                        div class: 'header-line', ->
index 99d6c4c4217b095bae2dfafa7e0f33c81a2bd859..e05b89f1cf1a9b8174a154468129c2dbf2c5e0f2 100644 (file)
--- a/docs/todo
+++ b/docs/todo
@@ -2,7 +2,7 @@
 [X] Competition users table for enrolled users
 [X] Problem language blacklist
 [X] Leaderboard timer and just better looking
-[ ] Removing users from a competition
+[X] Removing users from a competition
 [X] Animations throughout the site
 [ ] Word problems
        * Use test case 1 for answer