FEATURE: Show when a badge has been granted for a post (#29696)
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com> Co-authored-by: Jarek Radosz <jradosz@gmail.com> Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
This commit is contained in:
parent
435fbb7408
commit
2513339955
|
@ -27,6 +27,7 @@ const FORM_FIELDS = [
|
|||
"badge_grouping_id",
|
||||
"trigger",
|
||||
"badge_type_id",
|
||||
"show_in_post_header",
|
||||
];
|
||||
|
||||
export default class AdminBadgesShowController extends Controller {
|
||||
|
@ -40,8 +41,6 @@ export default class AdminBadgesShowController extends Controller {
|
|||
@tracked model;
|
||||
@tracked previewLoading = false;
|
||||
@tracked selectedGraphicType = null;
|
||||
@tracked userBadges;
|
||||
@tracked userBadgesAll;
|
||||
|
||||
@cached
|
||||
get formData() {
|
||||
|
@ -80,6 +79,17 @@ export default class AdminBadgesShowController extends Controller {
|
|||
return this.model.system;
|
||||
}
|
||||
|
||||
@action
|
||||
postHeaderDescription(data) {
|
||||
return this.disableBadgeOnPosts(data) && !data.system;
|
||||
}
|
||||
|
||||
@action
|
||||
disableBadgeOnPosts(data) {
|
||||
const { listable, show_posts } = data;
|
||||
return !listable || !show_posts;
|
||||
}
|
||||
|
||||
setup() {
|
||||
// this is needed because the model doesnt have default values
|
||||
// Using `set` here isn't ideal, but we don't know that tracking is set up on the model yet.
|
||||
|
|
|
@ -245,7 +245,7 @@
|
|||
</field.Menu>
|
||||
</form.Field>
|
||||
|
||||
<form.CheckboxGroup as |group|>
|
||||
<form.CheckboxGroup @title={{i18n "admin.badges.usage_heading"}} as |group|>
|
||||
<group.Field
|
||||
@title={{i18n "admin.badges.allow_title"}}
|
||||
@showTitle={{false}}
|
||||
|
@ -264,7 +264,12 @@
|
|||
>
|
||||
<field.Checkbox />
|
||||
</group.Field>
|
||||
</form.CheckboxGroup>
|
||||
|
||||
<form.CheckboxGroup
|
||||
@title={{i18n "admin.badges.visibility_heading"}}
|
||||
as |group|
|
||||
>
|
||||
<group.Field
|
||||
@title={{i18n "admin.badges.listable"}}
|
||||
@showTitle={{false}}
|
||||
|
@ -284,6 +289,20 @@
|
|||
>
|
||||
<field.Checkbox />
|
||||
</group.Field>
|
||||
|
||||
<group.Field
|
||||
@title={{i18n "admin.badges.show_in_post_header"}}
|
||||
@showTitle={{false}}
|
||||
@name="show_in_post_header"
|
||||
@disabled={{this.disableBadgeOnPosts data}}
|
||||
as |field|
|
||||
>
|
||||
<field.Checkbox>
|
||||
{{#if (this.postHeaderDescription data)}}
|
||||
{{i18n "admin.badges.show_in_post_header_disabled"}}
|
||||
{{/if}}
|
||||
</field.Checkbox>
|
||||
</group.Field>
|
||||
</form.CheckboxGroup>
|
||||
</form.Section>
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ export default class BadgeButton extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
get showName() {
|
||||
return this.args.showName ?? true;
|
||||
}
|
||||
|
||||
<template>
|
||||
<span
|
||||
title={{this.title}}
|
||||
|
@ -20,7 +24,9 @@ export default class BadgeButton extends Component {
|
|||
...attributes
|
||||
>
|
||||
{{iconOrImage @badge}}
|
||||
<span class="badge-display-name">{{@badge.name}}</span>
|
||||
{{#if this.showName}}
|
||||
<span class="badge-display-name">{{@badge.name}}</span>
|
||||
{{/if}}
|
||||
{{yield}}
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
@ -15,7 +15,7 @@ export default class UserBadge extends Component {
|
|||
|
||||
<template>
|
||||
<a class="user-card-badge-link" href={{this.badgeUrl}}>
|
||||
<BadgeButton @badge={{@badge}}>
|
||||
<BadgeButton @badge={{@badge}} @showName={{@showName}}>
|
||||
{{#if this.showGrantCount}}
|
||||
<span class="count"> (×{{@count}})</span>
|
||||
{{/if}}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { isEmpty } from "@ember/utils";
|
||||
import { userPath } from "discourse/lib/url";
|
||||
import Badge from "discourse/models/badge";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
|
@ -37,6 +38,9 @@ export function transformBasicPost(post) {
|
|||
user_id: post.user_id,
|
||||
usernameUrl: userPath(post.username),
|
||||
username: post.username,
|
||||
badgesGranted: post.badges_granted?.map(
|
||||
(badge) => Badge.createFromJson(badge)[0]
|
||||
),
|
||||
avatar_template: post.avatar_template,
|
||||
bookmarked: post.bookmarked,
|
||||
bookmarkReminderAt: post.bookmark_reminder_at,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { hbs } from "ember-cli-htmlbars";
|
||||
import { h } from "virtual-dom";
|
||||
import { prioritizeNameInUx } from "discourse/lib/settings";
|
||||
import { formatUsername } from "discourse/lib/utilities";
|
||||
import RenderGlimmer from "discourse/widgets/render-glimmer";
|
||||
import { applyDecorators, createWidget } from "discourse/widgets/widget";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import { iconNode } from "discourse-common/lib/icon-library";
|
||||
|
@ -139,6 +141,29 @@ export default createWidget("poster-name", {
|
|||
}
|
||||
}
|
||||
|
||||
if (attrs.badgesGranted) {
|
||||
const badges = [];
|
||||
attrs.badgesGranted.forEach((badge) => {
|
||||
// Alter the badge description to show that the badge was granted for this post.
|
||||
badge.description = i18n("post.badge_granted_tooltip", {
|
||||
username: attrs.username,
|
||||
badge_name: badge.name,
|
||||
});
|
||||
|
||||
const badgeIcon = new RenderGlimmer(
|
||||
this,
|
||||
`span.user-badge-button-${badge.slug}`,
|
||||
hbs`<UserBadge @badge={{@data.badge}} @user={{@data.user}} @showName={{false}} />`,
|
||||
{
|
||||
badge,
|
||||
user: attrs.user,
|
||||
}
|
||||
);
|
||||
badges.push(badgeIcon);
|
||||
});
|
||||
nameContents.push(h("span.user-badge-buttons", badges));
|
||||
}
|
||||
|
||||
const afterNameContents =
|
||||
applyDecorators(this, "after-name", attrs, this.state) || [];
|
||||
|
||||
|
|
|
@ -77,4 +77,22 @@ module("Integration | Component | badge-button", function (hooks) {
|
|||
|
||||
assert.dom(".user-badge.foo").exists();
|
||||
});
|
||||
|
||||
test("setting showName to false hides the name", async function (assert) {
|
||||
this.set("badge", { name: "foo" });
|
||||
|
||||
await render(
|
||||
hbs`<BadgeButton @badge={{this.badge}} @showName={{false}} />`
|
||||
);
|
||||
|
||||
assert.dom(".badge-display-name").doesNotExist();
|
||||
});
|
||||
|
||||
test("showName defaults to true", async function (assert) {
|
||||
this.set("badge", { name: "foo" });
|
||||
|
||||
await render(hbs`<BadgeButton @badge={{this.badge}} />`);
|
||||
|
||||
assert.dom(".badge-display-name").exists();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { render } from "@ember/test-helpers";
|
||||
import { hbs } from "ember-cli-htmlbars";
|
||||
import { module, test } from "qunit";
|
||||
import Badge from "discourse/models/badge";
|
||||
import User from "discourse/models/user";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
|
||||
module("Integration | Component | Widget | poster-name", function (hooks) {
|
||||
|
@ -70,4 +72,38 @@ module("Integration | Component | Widget | poster-name", function (hooks) {
|
|||
|
||||
assert.dom(".second").doesNotExist();
|
||||
});
|
||||
|
||||
test("renders badges that are passed in", async function (assert) {
|
||||
this.set("args", {
|
||||
username: "eviltrout",
|
||||
usernameUrl: "/u/eviltrout",
|
||||
user: User.create({
|
||||
username: "eviltrout",
|
||||
}),
|
||||
badgesGranted: [
|
||||
{ id: 1, icon: "heart", slug: "badge1", name: "Badge One" },
|
||||
{ id: 2, icon: "target", slug: "badge2", name: "Badge Two" },
|
||||
].map((badge) => Badge.createFromJson({ badges: [badge] })[0]),
|
||||
});
|
||||
|
||||
await render(
|
||||
hbs`<MountWidget @widget="poster-name" @args={{this.args}} />`
|
||||
);
|
||||
|
||||
// Check that the custom CSS classes are set
|
||||
assert.dom("span.user-badge-button-badge1").exists();
|
||||
assert.dom("span.user-badge-button-badge2").exists();
|
||||
|
||||
// Check that the custom titles are set
|
||||
assert.dom("span.user-badge[title*='Badge One']").exists();
|
||||
assert.dom("span.user-badge[title*='Badge Two']").exists();
|
||||
|
||||
// Check that the badges link to the correct badge page
|
||||
assert
|
||||
.dom("a.user-card-badge-link[href='/badges/1/badge1?username=eviltrout']")
|
||||
.exists();
|
||||
assert
|
||||
.dom("a.user-card-badge-link[href='/badges/2/badge2?username=eviltrout']")
|
||||
.exists();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -259,6 +259,19 @@
|
|||
margin-right: auto;
|
||||
}
|
||||
|
||||
.user-badge-buttons {
|
||||
margin-left: 15px;
|
||||
|
||||
a {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.user-badge {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.post-infos {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
|
|
|
@ -344,27 +344,28 @@ end
|
|||
#
|
||||
# Table name: badges
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string not null
|
||||
# description :text
|
||||
# badge_type_id :integer not null
|
||||
# grant_count :integer default(0), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# allow_title :boolean default(FALSE), not null
|
||||
# multiple_grant :boolean default(FALSE), not null
|
||||
# icon :string default("fa-certificate")
|
||||
# listable :boolean default(TRUE)
|
||||
# target_posts :boolean default(FALSE)
|
||||
# query :text
|
||||
# enabled :boolean default(TRUE), not null
|
||||
# auto_revoke :boolean default(TRUE), not null
|
||||
# badge_grouping_id :integer default(5), not null
|
||||
# trigger :integer
|
||||
# show_posts :boolean default(FALSE), not null
|
||||
# system :boolean default(FALSE), not null
|
||||
# long_description :text
|
||||
# image_upload_id :integer
|
||||
# id :integer not null, primary key
|
||||
# name :string not null
|
||||
# description :text
|
||||
# badge_type_id :integer not null
|
||||
# grant_count :integer default(0), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# allow_title :boolean default(FALSE), not null
|
||||
# multiple_grant :boolean default(FALSE), not null
|
||||
# icon :string default("fa-certificate")
|
||||
# listable :boolean default(TRUE)
|
||||
# target_posts :boolean default(FALSE)
|
||||
# query :text
|
||||
# enabled :boolean default(TRUE), not null
|
||||
# auto_revoke :boolean default(TRUE), not null
|
||||
# badge_grouping_id :integer default(5), not null
|
||||
# trigger :integer
|
||||
# show_posts :boolean default(FALSE), not null
|
||||
# system :boolean default(FALSE), not null
|
||||
# show_in_post_header :boolean default(FALSE), not null
|
||||
# long_description :text
|
||||
# image_upload_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
@ -35,6 +35,19 @@ class UserBadge < ActiveRecord::Base
|
|||
scope :for_enabled_badges,
|
||||
-> { where("user_badges.badge_id IN (SELECT id FROM badges WHERE enabled)") }
|
||||
|
||||
scope :by_post_and_user,
|
||||
->(posts) do
|
||||
posts.reduce(UserBadge.none) do |scope, post|
|
||||
scope.or(UserBadge.where(user_id: post.user_id, post_id: post.id))
|
||||
end
|
||||
end
|
||||
scope :for_post_header_badges,
|
||||
->(posts) do
|
||||
by_post_and_user(posts).where(
|
||||
"user_badges.badge_id IN (SELECT id FROM badges WHERE show_posts AND enabled AND listable AND show_in_post_header)",
|
||||
)
|
||||
end
|
||||
|
||||
validates :badge_id, presence: true, uniqueness: { scope: :user_id }, if: :single_grant_badge?
|
||||
|
||||
validates :user_id, presence: true
|
||||
|
|
|
@ -16,7 +16,8 @@ class BadgeSerializer < ApplicationSerializer
|
|||
:long_description,
|
||||
:slug,
|
||||
:has_badge,
|
||||
:manually_grantable?
|
||||
:manually_grantable?,
|
||||
:show_in_post_header
|
||||
|
||||
has_one :badge_type
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ class PostSerializer < BasicPostSerializer
|
|||
:flair_bg_color,
|
||||
:flair_color,
|
||||
:flair_group_id,
|
||||
:badges_granted,
|
||||
:version,
|
||||
:can_edit,
|
||||
:can_delete,
|
||||
|
@ -223,6 +224,18 @@ class PostSerializer < BasicPostSerializer
|
|||
object.user&.flair_group_id
|
||||
end
|
||||
|
||||
def badges_granted
|
||||
return [] unless SiteSetting.enable_badges && SiteSetting.show_badges_in_post_header
|
||||
|
||||
if @topic_view
|
||||
user_badges = @topic_view.post_user_badges[object.id] || []
|
||||
else
|
||||
user_badges = UserBadge.for_post_header_badges([object])
|
||||
end
|
||||
|
||||
user_badges.map { |user_badge| BasicUserBadgeSerializer.new(user_badge, scope: scope).as_json }
|
||||
end
|
||||
|
||||
def link_counts
|
||||
return @single_post_link_counts if @single_post_link_counts.present?
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ class WebHookPostSerializer < PostSerializer
|
|||
flair_color
|
||||
notice
|
||||
mentioned_users
|
||||
badges_granted
|
||||
].each { |attr| define_method("include_#{attr}?") { false } }
|
||||
|
||||
def topic_posts
|
||||
|
|
|
@ -3816,6 +3816,8 @@ en:
|
|||
in_reply_to: "Load parent post"
|
||||
view_all_posts: "View all posts"
|
||||
|
||||
badge_granted_tooltip: "%{username} earned the '%{badge_name}' badge for this post!"
|
||||
|
||||
errors:
|
||||
create: "Sorry, there was an error creating your post. Please try again."
|
||||
edit: "Sorry, there was an error editing your post. Please try again."
|
||||
|
@ -7195,9 +7197,13 @@ en:
|
|||
no_user_badges: "%{name} has not been granted any badges."
|
||||
no_badges: There are no badges that can be granted.
|
||||
none_selected: "Select a badge to get started"
|
||||
usage_heading: Usage
|
||||
allow_title: Allow badge to be used as a title
|
||||
multiple_grant: Can be granted multiple times
|
||||
visibility_heading: Visibility
|
||||
listable: Show badge on the public badges page
|
||||
show_in_post_header: Show badge on the post it was granted for
|
||||
show_in_post_header_disabled: Requires both 'Show badge on the public badges page' and 'Show post granting badge on badge page' to be enabled.
|
||||
enabled: enabled
|
||||
disabled: disabled
|
||||
icon: Icon
|
||||
|
|
|
@ -1942,6 +1942,7 @@ en:
|
|||
email_token_valid_hours: "Forgot password / activate account tokens are valid for (n) hours."
|
||||
|
||||
enable_badges: "Enable the badge system, which is a form of gamification to reinforce positive user actions. See <a href='https://meta.discourse.org/t/what-are-badges/32540' _target='blank'>What are Badges?</a> on Discourse Meta for more information."
|
||||
show_badges_in_post_header: "When a user earns a badge for a particular post, display the badge in the post header."
|
||||
max_favorite_badges: "Maximum number of badges that user can select"
|
||||
whispers_allowed_groups: "Allow private communication within topics for members of specified groups."
|
||||
hidden_post_visible_groups: "Allow members of these groups to view hidden posts. Staff users can always view hidden posts."
|
||||
|
|
|
@ -342,6 +342,9 @@ basic:
|
|||
enable_badges:
|
||||
client: true
|
||||
default: true
|
||||
show_badges_in_post_header:
|
||||
client: true
|
||||
default: true
|
||||
enable_badge_sql:
|
||||
client: true
|
||||
default: false
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
class AddPostHeaderToBadge < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
add_column :badges, :show_in_post_header, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
|
@ -205,6 +205,25 @@ class TopicView
|
|||
{ users: user_badge_mapping, badges: indexed_badges }
|
||||
end
|
||||
|
||||
def post_user_badges
|
||||
return [] unless SiteSetting.enable_badges && SiteSetting.show_badges_in_post_header
|
||||
|
||||
@post_user_badges ||=
|
||||
begin
|
||||
UserBadge
|
||||
.for_post_header_badges(@posts)
|
||||
.reduce({}) do |hash, user_badge|
|
||||
hash[user_badge.post_id] ||= []
|
||||
hash[user_badge.post_id] << user_badge
|
||||
hash
|
||||
end
|
||||
end
|
||||
|
||||
return [] unless @post_user_badges
|
||||
|
||||
@post_user_badges
|
||||
end
|
||||
|
||||
def show_read_indicator?
|
||||
return false if !@user || !topic.private_message?
|
||||
|
||||
|
|
|
@ -106,6 +106,9 @@
|
|||
},
|
||||
"badge_type_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"show_in_post_header": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -130,7 +133,8 @@
|
|||
"auto_revoke",
|
||||
"show_posts",
|
||||
"badge_type_id",
|
||||
"image_upload_id"
|
||||
"image_upload_id",
|
||||
"show_in_post_header"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
@ -91,6 +91,9 @@
|
|||
},
|
||||
"badge_type_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"show_in_post_header": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -115,7 +118,8 @@
|
|||
"auto_revoke",
|
||||
"show_posts",
|
||||
"badge_type_id",
|
||||
"image_upload_id"
|
||||
"image_upload_id",
|
||||
"show_in_post_header"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
@ -106,6 +106,9 @@
|
|||
},
|
||||
"badge_type_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"show_in_post_header": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -130,7 +133,8 @@
|
|||
"auto_revoke",
|
||||
"show_posts",
|
||||
"badge_type_id",
|
||||
"image_upload_id"
|
||||
"image_upload_id",
|
||||
"show_in_post_header"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
@ -98,6 +98,10 @@
|
|||
"null"
|
||||
]
|
||||
},
|
||||
"badges_granted": {
|
||||
"type": "array",
|
||||
"items": {}
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
},
|
||||
|
|
|
@ -109,6 +109,10 @@
|
|||
"null"
|
||||
]
|
||||
},
|
||||
"badges_granted": {
|
||||
"type": "array",
|
||||
"items": {}
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
},
|
||||
|
|
|
@ -438,6 +438,201 @@ RSpec.describe PostSerializer do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#badges_granted" do
|
||||
fab!(:user)
|
||||
fab!(:user2) { Fabricate(:user) }
|
||||
fab!(:post) { Fabricate(:post, user: user) }
|
||||
fab!(:post2) { Fabricate(:post, user: user) }
|
||||
|
||||
# Create twp badges that have all required flags set to true
|
||||
fab!(:badge1) do
|
||||
Badge.create!(
|
||||
name: "SomeBadge",
|
||||
badge_type_id: BadgeType::Bronze,
|
||||
listable: true,
|
||||
show_posts: true,
|
||||
show_in_post_header: true,
|
||||
multiple_grant: true,
|
||||
)
|
||||
end
|
||||
fab!(:ub1) do
|
||||
UserBadge.create!(
|
||||
badge_id: badge1.id,
|
||||
user: user,
|
||||
granted_by: Discourse.system_user,
|
||||
granted_at: Time.now,
|
||||
post_id: post.id,
|
||||
)
|
||||
end
|
||||
|
||||
fab!(:badge2) do
|
||||
Badge.create!(
|
||||
name: "SomeOtherBadge",
|
||||
badge_type_id: BadgeType::Bronze,
|
||||
listable: true,
|
||||
show_posts: true,
|
||||
show_in_post_header: true,
|
||||
multiple_grant: true,
|
||||
)
|
||||
end
|
||||
fab!(:ub2) do
|
||||
UserBadge.create!(
|
||||
badge_id: badge2.id,
|
||||
user: user,
|
||||
granted_by: Discourse.system_user,
|
||||
granted_at: Time.now,
|
||||
post_id: post.id,
|
||||
)
|
||||
end
|
||||
|
||||
# Create a badge that has the show_posts flag set to false
|
||||
fab!(:badge3) do
|
||||
Badge.create!(
|
||||
name: "YetAnotherBadge",
|
||||
badge_type_id: BadgeType::Bronze,
|
||||
listable: true,
|
||||
show_posts: false,
|
||||
show_in_post_header: true,
|
||||
)
|
||||
end
|
||||
fab!(:ub3) do
|
||||
UserBadge.create!(
|
||||
badge_id: badge3.id,
|
||||
user: user,
|
||||
granted_by: Discourse.system_user,
|
||||
granted_at: Time.now,
|
||||
post_id: post.id,
|
||||
)
|
||||
end
|
||||
|
||||
# Re-use our first badge, but on a different post
|
||||
fab!(:ub4) do
|
||||
UserBadge.create!(
|
||||
badge_id: badge1.id,
|
||||
user: user,
|
||||
granted_by: Discourse.system_user,
|
||||
granted_at: Time.now,
|
||||
post_id: post2.id,
|
||||
)
|
||||
end
|
||||
|
||||
# Now re-use our first badge, but on a different user
|
||||
fab!(:ub5) do
|
||||
UserBadge.create!(
|
||||
badge_id: badge1.id,
|
||||
user: user2,
|
||||
granted_by: Discourse.system_user,
|
||||
granted_at: Time.now,
|
||||
post_id: post.id,
|
||||
)
|
||||
end
|
||||
|
||||
# Create a badge that has the listable flag set to false
|
||||
fab!(:badge4) do
|
||||
Badge.create!(
|
||||
name: "WeirdBadge",
|
||||
badge_type_id: BadgeType::Bronze,
|
||||
listable: false,
|
||||
show_posts: true,
|
||||
show_in_post_header: true,
|
||||
)
|
||||
end
|
||||
fab!(:ub6) do
|
||||
UserBadge.create!(
|
||||
badge_id: badge4.id,
|
||||
user: user,
|
||||
granted_by: Discourse.system_user,
|
||||
granted_at: Time.now,
|
||||
post_id: post.id,
|
||||
)
|
||||
end
|
||||
|
||||
# Create a badge that has the show_in_post_header flag set to false
|
||||
fab!(:badge5) do
|
||||
Badge.create!(
|
||||
name: "StrangeBadge",
|
||||
badge_type_id: BadgeType::Bronze,
|
||||
listable: true,
|
||||
show_posts: true,
|
||||
show_in_post_header: false,
|
||||
)
|
||||
end
|
||||
fab!(:ub7) do
|
||||
UserBadge.create!(
|
||||
badge_id: badge5.id,
|
||||
user: user,
|
||||
granted_by: Discourse.system_user,
|
||||
granted_at: Time.now,
|
||||
post_id: post.id,
|
||||
)
|
||||
end
|
||||
|
||||
let(:serializer) { described_class.new(post, scope: Guardian.new(user), root: false) }
|
||||
|
||||
it "doesn't include badges when `enable_badges` site setting is disabled" do
|
||||
SiteSetting.enable_badges = false
|
||||
expect(serializer.as_json[:badges_granted]).to eq([])
|
||||
end
|
||||
|
||||
it "doesn't include badges when `show_badges_in_post_header` site setting is disabled" do
|
||||
SiteSetting.enable_badges = true
|
||||
SiteSetting.show_badges_in_post_header = false
|
||||
expect(serializer.as_json[:badges_granted]).to eq([])
|
||||
end
|
||||
|
||||
context "when `enable_badges` and `show_badges_in_post_header` site settings are enabled" do
|
||||
before do
|
||||
SiteSetting.enable_badges = true
|
||||
SiteSetting.show_badges_in_post_header = true
|
||||
end
|
||||
|
||||
it "includes badges that were granted for this user on this post" do
|
||||
json = serializer.as_json
|
||||
|
||||
expect(json[:badges_granted].length).to eq(2)
|
||||
expect(json[:badges_granted].map { |b| b[:badges][0][:id] }).to contain_exactly(
|
||||
ub1.badge_id,
|
||||
ub2.badge_id,
|
||||
)
|
||||
|
||||
expect(json[:badges_granted].map { |b| b[:basic_user_badge][:id] }).to contain_exactly(
|
||||
ub1.id,
|
||||
ub2.id,
|
||||
)
|
||||
end
|
||||
|
||||
it "does not return a user badge that has the show_posts flag set to false" do
|
||||
json = serializer.as_json
|
||||
|
||||
expect(json[:badges_granted].map { |b| b[:basic_user_badge][:id] }).not_to include(ub3.id)
|
||||
end
|
||||
|
||||
it "does not return a user badge that was not granted for this post" do
|
||||
json = serializer.as_json
|
||||
|
||||
expect(json[:badges_granted].map { |b| b[:basic_user_badge][:id] }).not_to include(ub4.id)
|
||||
end
|
||||
|
||||
it "does not return a user badge that was granted for a different user" do
|
||||
json = serializer.as_json
|
||||
|
||||
expect(json[:badges_granted].map { |b| b[:basic_user_badge][:id] }).not_to include(ub5.id)
|
||||
end
|
||||
|
||||
it "does not return a user badge that has the listable flag set to false" do
|
||||
json = serializer.as_json
|
||||
|
||||
expect(json[:badges_granted].map { |b| b[:basic_user_badge][:id] }).not_to include(ub6.id)
|
||||
end
|
||||
|
||||
it "does not return a user badge that has the show_in_post_header flag set to false" do
|
||||
json = serializer.as_json
|
||||
|
||||
expect(json[:badges_granted].map { |b| b[:basic_user_badge][:id] }).not_to include(ub7.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def serialized_post(u)
|
||||
s = PostSerializer.new(post, scope: Guardian.new(u), root: false)
|
||||
s.add_raw = true
|
||||
|
|
|
@ -33,4 +33,43 @@ describe "Granting Badges", type: :system do
|
|||
expect(granted_badge.post_id).to eq post.id
|
||||
end
|
||||
end
|
||||
|
||||
context "when granting a badge that shows in the post header" do
|
||||
fab!(:user)
|
||||
fab!(:post) { Fabricate(:post, user: user) }
|
||||
|
||||
let(:topic_page) { PageObjects::Pages::Topic.new }
|
||||
|
||||
fab!(:badge) do
|
||||
Fabricate(
|
||||
:manually_grantable_badge,
|
||||
name: "SomeBadge",
|
||||
listable: true,
|
||||
show_posts: true,
|
||||
show_in_post_header: true,
|
||||
)
|
||||
end
|
||||
fab!(:user_badge) do
|
||||
UserBadge.create!(
|
||||
badge_id: badge.id,
|
||||
user: user,
|
||||
granted_by: Discourse.system_user,
|
||||
granted_at: Time.now,
|
||||
post_id: post.id,
|
||||
)
|
||||
end
|
||||
|
||||
it "shows badge in post header" do
|
||||
topic_page.visit_topic(post.topic)
|
||||
expect(topic_page.post_by_number(post).find(".user-badge-buttons")).to have_css(
|
||||
".user-badge-button-somebadge",
|
||||
)
|
||||
end
|
||||
|
||||
it "doesn't show badge in post header when `show_badges_in_post_header` site setting is disabled" do
|
||||
SiteSetting.show_badges_in_post_header = false
|
||||
topic_page.visit_topic(post.topic)
|
||||
expect(topic_page.post_by_number(post)).to_not have_css(".user-badge-buttons")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue