From 3e071f92816b7904b95f961d3a8db391d66becf6 Mon Sep 17 00:00:00 2001 From: sto Date: Thu, 20 Nov 2025 10:24:26 +0100 Subject: [PATCH] Add public form to add completions --- app/controllers/completions_controller.rb | 2 +- app/controllers/contestants_controller.rb | 55 ++++++++++++++++++- app/models/contestant.rb | 2 + app/views/completions/_form.html.slim | 19 ++++--- .../public_completion_updated.html.slim | 2 + config/locales/en.yml | 2 + config/locales/fr.yml | 2 + config/routes.rb | 3 + 8 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 app/views/contestants/public_completion_updated.html.slim diff --git a/app/controllers/completions_controller.rb b/app/controllers/completions_controller.rb index f28c744..cee64bd 100644 --- a/app/controllers/completions_controller.rb +++ b/app/controllers/completions_controller.rb @@ -24,7 +24,7 @@ class CompletionsController < ApplicationController authorize @contest @completion = Completion.new(completion_params) - @completion.contest_id = @contest.id + @completion.contest = @contet if @completion.save extend_completions!(@completion.contestant) if @contestant && !params[:completion].key?(:message_id) diff --git a/app/controllers/contestants_controller.rb b/app/controllers/contestants_controller.rb index 9030025..6038743 100644 --- a/app/controllers/contestants_controller.rb +++ b/app/controllers/contestants_controller.rb @@ -1,9 +1,11 @@ class ContestantsController < ApplicationController + include CompletionsConcern include ContestantsConcern - before_action :set_contest + before_action :set_contest, only: %i[ index edit new create update destroy import upload_csv convert_csv finalize_import export ] before_action :set_contestant, only: %i[ destroy edit update] before_action :set_completions, only: %i[edit update ] + skip_before_action :require_authentication, only: %i[ get_public_completion post_public_completion public_completion_updated ] def index authorize @contest @@ -118,6 +120,53 @@ class ContestantsController < ApplicationController end end + def get_public_completion + skip_authorization + + @contestant = Contestant.find_by_token_for(:token, params[:token]) + if !@contestant + not_found and return + end + @contest = @contestant.contest + @puzzles = @contest.puzzles + @completion = Completion.new + @completion.completed = true + @public = true + + render "completions/_form", locals: { completion: @completion, submit_text: t("helpers.buttons.create"), method: :post, url: "/public/p/#{params[:token]}" } + end + + def post_public_completion + skip_authorization + + @contestant = Contestant.find_by_token_for(:token, params[:token]) + if !@contestant + not_found and return + end + @contest = @contestant.contest + + @completion = Completion.new(completion_params) + @completion.contest = @contest + @completion.contestant = @contestant + if @completion.save + extend_completions!(@completion.contestant) + redirect_to "/public/p/#{params[:token]}/updated" + else + @puzzles = @contest.puzzles + @public = true + render "completions/_form", locals: { completion: @completion, submit_text: t("helpers.buttons.create"), method: :post, url: "/public/p/#{params[:token]}" }, status: :unprocessable_entity + end + end + + def public_completion_updated + skip_authorization + + @contestant = Contestant.find_by_token_for(:token, params[:token]) + if !@contestant + not_found and return + end + end + private def set_contest @@ -156,4 +205,8 @@ class ContestantsController < ApplicationController end end end + + def completion_params + params.expect(completion: [ :display_time_from_start, :completed, :missing_pieces, :remaining_pieces, :puzzle_id ]) + end end diff --git a/app/models/contestant.rb b/app/models/contestant.rb index 4e42d8d..adf9889 100644 --- a/app/models/contestant.rb +++ b/app/models/contestant.rb @@ -31,6 +31,8 @@ class Contestant < ApplicationRecord validates :name, presence: true validates :time_seconds, presence: true + generates_token_for :token + def form_name if email.present? "#{name} - #{email}" diff --git a/app/views/completions/_form.html.slim b/app/views/completions/_form.html.slim index 3c61c48..f03da20 100644 --- a/app/views/completions/_form.html.slim +++ b/app/views/completions/_form.html.slim @@ -9,14 +9,19 @@ = @message.author br = @message.text - .row + .row.mb-2 .col - h4 = t("completions.singular").capitalize - .row.mb-3 - .col - .form-floating - = form.select :contestant_id, @contestants.map { |contestant| [contestant.form_name, contestant.id] }, {}, class: "form-select" - = form.label :contestant_id + h4 + - if @public + = t("completions.form.validate_name", name: @contestant.name) + - else + = t("completions.singular").capitalize + - if @contestants.present? + .row.mb-3 + .col + .form-floating + = form.select :contestant_id, @contestants.map { |contestant| [contestant.form_name, contestant.id] }, {}, class: "form-select" + = form.label :contestant_id - if @closest_contestant javascript: el = document.querySelector('select[name="completion[contestant_id]"]'); diff --git a/app/views/contestants/public_completion_updated.html.slim b/app/views/contestants/public_completion_updated.html.slim new file mode 100644 index 0000000..9f3aece --- /dev/null +++ b/app/views/contestants/public_completion_updated.html.slim @@ -0,0 +1,2 @@ +h4 + = "Puzzle validated for #{@contestant.name}!" \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 0195588..312f1ea 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -170,6 +170,8 @@ en: edit: notice: Completion updated title: Edit completion + form: + validate_name: "Validate a puzzle for %{name}" new: notice: Completion added title: New completion diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 47ea94e..2588d83 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -141,6 +141,8 @@ fr: edit: notice: Complétion modifiée title: Modifier la complétion + form: + validate_name: "Valider un puzzle pour %{name}" new: notice: Complétion ajoutée title: Ajout d'une complétion diff --git a/config/routes.rb b/config/routes.rb index 2be6864..64d1023 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -44,4 +44,7 @@ Rails.application.routes.draw do get "public/:id/offline/:token", to: "contests#offline_edit" patch "public/:id/offline/:token", to: "contests#offline_update" get "public/:id/offline/:token/completed", to: "contests#offline_completed" + get "public/p/:token", to: "contestants#get_public_completion" + post "public/p/:token", to: "contestants#post_public_completion" + get "public/p/:token/updated", to: "contestants#public_completion_updated" end