Allow some badges to be awarded multiple times (#20876)
* Add migration, update badgeachievements model and admin view to set flag on badges * Show multiple badges on profile * update factory * badge model validation * safe navigation to badge? * add null: false to migratrion
This commit is contained in:
parent
c44a2dcdb0
commit
3ceb9a178a
12 changed files with 57 additions and 7 deletions
|
|
@ -179,3 +179,16 @@
|
|||
border-bottom: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-indicator {
|
||||
font-size: var(--fs-s);
|
||||
color: var(--base-0);
|
||||
width: var(--su-6);
|
||||
height: var(--su-6);
|
||||
line-height: var(--su-6);
|
||||
position: absolute;
|
||||
background-color: var(--accent-brand);
|
||||
right: var(--su-1);
|
||||
bottom: -5px;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ module Admin
|
|||
private
|
||||
|
||||
def badge_params
|
||||
params.require(:badge).permit(:title, :description, :badge_image, :credits_awarded)
|
||||
params.require(:badge).permit(:title, :description, :badge_image, :credits_awarded, :allow_multiple_awards)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ class Badge < ApplicationRecord
|
|||
validates :description, presence: true
|
||||
validates :slug, presence: true
|
||||
validates :title, presence: true, uniqueness: true
|
||||
validates :allow_multiple_awards, inclusion: { in: [true, false] }
|
||||
|
||||
before_validation :generate_slug
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class BadgeAchievement < ApplicationRecord
|
|||
|
||||
counter_culture :user, column_name: "badge_achievements_count"
|
||||
|
||||
validates :badge_id, uniqueness: { scope: :user_id }
|
||||
validates :badge_id, uniqueness: { scope: :user_id, if: :single_award_badge? }
|
||||
|
||||
before_validation :render_rewarding_context_message_html
|
||||
after_create :award_credits
|
||||
|
|
@ -53,4 +53,8 @@ class BadgeAchievement < ApplicationRecord
|
|||
|
||||
Credit.add_to(user, badge.credits_awarded)
|
||||
end
|
||||
|
||||
def single_award_badge?
|
||||
badge&.allow_multiple_awards == false
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -33,6 +33,14 @@
|
|||
<%= form.text_field :credits_awarded, class: "crayons-textfield" %>
|
||||
</div>
|
||||
|
||||
<div class="crayons-field crayons-field--checkbox ">
|
||||
<%= form.check_box :allow_multiple_awards, class: "crayons-checkbox" %>
|
||||
<%= form.label :allow_multiple_awards, class: "crayons-field__label" do %>
|
||||
Allow multiple awards
|
||||
<p class="crayons-field__description">Allows this badge to be awarded multiple times to the same user</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= submit_tag "Update badge", class: "c-btn c-btn--primary" %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,15 @@
|
|||
<%= form.text_field :credits_awarded, class: "crayons-textfield" %>
|
||||
</div>
|
||||
|
||||
<div class="crayons-field crayons-field--checkbox ">
|
||||
<%= form.check_box :allow_multiple_awards, class: "crayons-checkbox" %>
|
||||
<%= form.label :allow_multiple_awards, class: "crayons-field__label" do %>
|
||||
Allow multiple awards
|
||||
<p class="crayons-field__description">Allows this badge to be awarded multiple times to the same user</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<%= submit_tag "Create Badge", class: "c-btn c-btn--primary" %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,15 +5,17 @@
|
|||
|
||||
<div class="crayons-card__body">
|
||||
<div class="grid gap-4 grid-cols-3 s:grid-cols-4 m:grid-cols-2 align-center items-center js-profile-badges">
|
||||
<% achievements.each_with_index do |achievement, i| %>
|
||||
<% achievements.group_by(&:badge_id).each_with_index do |(badge_id, badge_achievements), i| %>
|
||||
<% achievement = badge_achievements.first %>
|
||||
<div role="button" onclick="window.Forem.showModal({size: 'medium', showHeader: false, contentSelector: '#badge-<%= achievement.badge_id %>', overlay: true})"
|
||||
title="<%= achievement.badge_title %>"
|
||||
class="js-profile-badge <% if i >= limit %>hidden<% end %>">
|
||||
class="js-profile-badge <% if i >= limit %>hidden<% end %> relative">
|
||||
<img src="<%= optimized_image_url(achievement.badge_image_url, width: 180) %>"
|
||||
alt="<%= achievement.badge_title %>"
|
||||
class="mx-auto max-w-75 h-auto align-middle"
|
||||
style="object-fit: contain; cursor: pointer; width: 100%; aspect-ratio: 1 / 1; transform: rotate(<%= rand(-10..10) %>deg);"
|
||||
style="object-fit: contain; cursor: pointer; width: 100%; aspect-ratio: 1 / 1;"
|
||||
loading="lazy" />
|
||||
<% if badge_achievements.length > 1 %><div class="badge-indicator" title="<%= t("views.badges.indicator", user: @user.name, number: badge_achievements.length) %>"><%= badge_achievements.length %></div><% end %>
|
||||
</div>
|
||||
|
||||
<div id="badge-<%= achievement.badge_id %>" class="hidden">
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ en:
|
|||
desc: Receive badges for being awesome! Click on a badge to see how you can earn it.
|
||||
icon_close: Close
|
||||
gotit: Got it
|
||||
indicator: "%{user} earned this badge %{number} times."
|
||||
campaign:
|
||||
subtitle: Stories (%{count})
|
||||
view: See all posts
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ fr:
|
|||
desc: Receive badges for being awesome! Click on a badge to see how you can earn it.
|
||||
icon_close: Close
|
||||
gotit: Got it
|
||||
indicator: "%{user} a obtenu ce badge %{number} fois."
|
||||
campaign:
|
||||
subtitle: Stories (%{count})
|
||||
view: See all posts
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
class AddAllowMultipleAwardsToBadges < ActiveRecord::Migration[7.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
add_column :badges, :allow_multiple_awards, :boolean, null: false, default: false
|
||||
|
||||
# remove unique index
|
||||
remove_index :badge_achievements, column: [:badge_id, :user_id], algorithm: :concurrently if index_exists?(:badge_achievements, [:badge_id, :user_id])
|
||||
end
|
||||
end
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.0].define(version: 2024_04_08_101038) do
|
||||
ActiveRecord::Schema[7.0].define(version: 2024_04_19_201108) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "citext"
|
||||
enable_extension "ltree"
|
||||
|
|
@ -207,11 +207,11 @@ ActiveRecord::Schema[7.0].define(version: 2024_04_08_101038) do
|
|||
t.text "rewarding_context_message_markdown"
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.bigint "user_id", null: false
|
||||
t.index ["badge_id", "user_id"], name: "index_badge_achievements_on_badge_id_and_user_id", unique: true
|
||||
t.index ["user_id", "badge_id"], name: "index_badge_achievements_on_user_id_and_badge_id"
|
||||
end
|
||||
|
||||
create_table "badges", force: :cascade do |t|
|
||||
t.boolean "allow_multiple_awards", default: false, null: false
|
||||
t.string "badge_image"
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.integer "credits_awarded", default: 0, null: false
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@ FactoryBot.define do
|
|||
sequence(:title) { |n| "#{Faker::Book.title}-#{n}" }
|
||||
description { Faker::Lorem.sentence }
|
||||
badge_image { Rack::Test::UploadedFile.new(image_path, "image/jpeg") }
|
||||
allow_multiple_awards { false }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue