diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9fd693f..d10746f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -30,8 +30,12 @@ class ApplicationController < ActionController::Base def user_not_authorized(exception) policy_name = exception.policy.class.to_s.underscore - flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default - redirect_back_or_to(root_path) + if current_user + flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default + redirect_back_or_to(root_path) + else + not_found + end end def not_found diff --git a/app/controllers/contests_controller.rb b/app/controllers/contests_controller.rb index 6c3e9c3..17ecc01 100644 --- a/app/controllers/contests_controller.rb +++ b/app/controllers/contests_controller.rb @@ -1,6 +1,7 @@ class ContestsController < ApplicationController before_action :set_contest, only: %i[ destroy edit show update ] - skip_before_action :require_authentication, only: %i[ scoreboard offline_new ] + before_action :offline_setup, only: %i[ offline_new offline_create ] + skip_before_action :require_authentication, only: %i[ scoreboard offline_new offline_create ] def index authorize :contest @@ -100,22 +101,30 @@ class ContestsController < ApplicationController end def offline_new - @contest = Contest.find_by(slug: params[:id]) - unless @contest && @contest.offline_form - skip_authorization - not_found and return - end - authorize :contest - - I18n.locale = @contest.lang - - @title = I18n.t("contests.scoreboard.title", name: @contest.name) - + authorize @contest @offline = Offline.new end + def offline_create + authorize @contest + @offline = Offline.new(offline_start_params) + @offline.contest = @contest + @offline.start_time = Time.now() + if @offline.save + redirect_to "/public/#{@contest.friendly_id}/offline/test" + else + render :offline_new, status: :unprocessable_entity + end + end + private + def offline_setup + @contest = Contest.find_by(slug: params[:id]) + I18n.locale = @contest.lang + @title = I18n.t("contests.scoreboard.title", name: @contest.name) + end + def set_badges @badges = [] @badges.push(t("helpers.badges.team")) if @contest.team @@ -139,4 +148,8 @@ class ContestsController < ApplicationController end end end + + def offline_start_params + params.expect(offline: [ :name, :start_image ]) + end end diff --git a/app/models/offline.rb b/app/models/offline.rb index f0ad1ad..f140626 100644 --- a/app/models/offline.rb +++ b/app/models/offline.rb @@ -4,6 +4,7 @@ # # id :integer not null, primary key # end_time :datetime +# name :string not null # start_time :datetime not null # created_at :datetime not null # updated_at :datetime not null @@ -23,5 +24,17 @@ class Offline < ApplicationRecord has_one_attached :start_image has_one_attached :end_image + validates :name, presence: true validates :start_time, presence: true + + validate :start_image_is_present + + def start_image_is_present + logger = Logger.new(STDOUT) + logger.info "TESTddfzefzef" + logger.info self.start_image.attached? + if !self.start_image.attached? + errors.add(:start_image, I18n.t("activerecord.errors.models.offline.attributes.start_image.blank")) + end + end end diff --git a/app/policies/contest_policy.rb b/app/policies/contest_policy.rb index 5e6a300..c435e3a 100644 --- a/app/policies/contest_policy.rb +++ b/app/policies/contest_policy.rb @@ -47,24 +47,28 @@ class ContestPolicy < ApplicationPolicy record.user.id == user.id || user.admin? end + def offline? + record.offline_form + end + def offline_new? - true + offline? end def offline_create? - true + offline? end def offline_edit? - true + offline? end def offline_update? - true + offline? end def scoreboard? - true + record.public end def upload_csv? diff --git a/app/views/contests/offline_new.html.slim b/app/views/contests/offline_new.html.slim index 5d85d2d..bcf422f 100644 --- a/app/views/contests/offline_new.html.slim +++ b/app/views/contests/offline_new.html.slim @@ -1,8 +1,13 @@ -= form_with model: @offline, url: "/public/#{@contest.id}/offline" do |form| += form_with model: @offline, url: "/public/#{@contest.friendly_id}/offline" do |form| + .row.mb-3 + .col + .form-floating + = form.text_field :name, autocomplete: "off", class: "form-control" + = form.label :name, class: "required" .row.mb-3 .col .form-text.mb-1 - = t("puzzles.image_select") + = t("offlines.start_image_select") = form.file_field :start_image, accept: "image/*", class: "form-control" .form-text.error-message style="display: none;" id="image-error-message" = t("puzzles.form.file_too_big") @@ -20,6 +25,6 @@ } setMaxUploadSize(); - .row.mt-3 + .row.mt-4 .col - = form.submit t("helpers.buttons.add"), class: "btn btn-primary" \ No newline at end of file + = form.submit t("helpers.buttons.start"), class: "btn btn-primary" \ No newline at end of file diff --git a/config/initializers/form_errors.rb b/config/initializers/form_errors.rb index a95e2c6..3c26046 100644 --- a/config/initializers/form_errors.rb +++ b/config/initializers/form_errors.rb @@ -1,5 +1,5 @@ ActionView::Base.field_error_proc = proc do |html_tag, instance| - if html_tag.include? "" diff --git a/config/locales/en.yml b/config/locales/en.yml index 04a90ba..aed4394 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -74,6 +74,8 @@ en: processed: Processed? text: Content time: Time + offline: + name: Your name puzzle: brand: Brand image: Image @@ -112,6 +114,12 @@ en: blank: "No file selected" empty: "This file is empty" not_a_csv_file: "it must be a CSV file" + offline: + attributes: + name: + blank: Please enter a name for your participation + start_image: + blank: Please upload an image puzzle: attributes: name: @@ -216,6 +224,7 @@ en: refresh: Refresh sign_in: Sign in save: Save + start: Click here to start your participation field: Field none: No field selected rank: Rank @@ -232,6 +241,8 @@ en: home: My contests settings: Settings log_out: Log out + offlines: + start_image_select: Enter your photo of the puzzle with the provided code written on a paper before starting it puzzles: destroy: notice: Puzzle deleted diff --git a/config/locales/fr.yml b/config/locales/fr.yml index f3ad669..d21a2b2 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -45,6 +45,8 @@ fr: processed: Traité ? text: Contenu time: Temps + offline: + name: Ton nom ou pseudo puzzle: brand: Marque image: Image @@ -83,6 +85,12 @@ fr: blank: "Aucun fichier sélectionné" empty: "Ce fichier est vide" not_a_csv_file: "Le fichier doit être au format CSV" + offline: + attributes: + name: + blank: Tu dois entrer un nom pour pouvoir participer + start_image: + blank: Tu dois inclure cette image pour pouvoir participer puzzle: attributes: name: @@ -187,6 +195,7 @@ fr: refresh: Rafraîchir sign_in: Se connecter save: Modifier + start: Clique ici pour démarrer ta participation field: Champ none: Aucun champ sélectionné rank: Rang @@ -203,6 +212,8 @@ fr: home: Mes concours settings: Paramètres log_out: Déconnexion + offlines: + start_image_select: Prends une photo du puzzle avant de le commencer, avec le code donné par l'organisateur.ice écrit sur du papier puzzles: destroy: notice: Puzzle supprimé diff --git a/db/migrate/20251030094151_add_name_to_offline.rb b/db/migrate/20251030094151_add_name_to_offline.rb new file mode 100644 index 0000000..9d47ea0 --- /dev/null +++ b/db/migrate/20251030094151_add_name_to_offline.rb @@ -0,0 +1,5 @@ +class AddNameToOffline < ActiveRecord::Migration[8.0] + def change + add_column :offlines, :name, :string, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 0f4b1a0..40d6dbb 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2025_10_30_092221) do +ActiveRecord::Schema[8.0].define(version: 2025_10_30_094151) do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -132,6 +132,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_10_30_092221) do t.integer "contest_id", null: false t.datetime "start_time", null: false t.datetime "end_time" + t.string "name", null: false t.index ["contest_id"], name: "index_offlines_on_contest_id" end diff --git a/spec/factories/offlines.rb b/spec/factories/offlines.rb index dc0c4b7..baabcfb 100644 --- a/spec/factories/offlines.rb +++ b/spec/factories/offlines.rb @@ -4,6 +4,7 @@ # # id :integer not null, primary key # end_time :datetime +# name :string not null # start_time :datetime not null # created_at :datetime not null # updated_at :datetime not null diff --git a/spec/models/offline_spec.rb b/spec/models/offline_spec.rb index 913ae79..853bb59 100644 --- a/spec/models/offline_spec.rb +++ b/spec/models/offline_spec.rb @@ -4,6 +4,7 @@ # # id :integer not null, primary key # end_time :datetime +# name :string not null # start_time :datetime not null # created_at :datetime not null # updated_at :datetime not null