From 94ac8611f40a7a1c886b3e5a7e120d15d0682834 Mon Sep 17 00:00:00 2001 From: Andrei Prigorshnev Date: Mon, 8 Aug 2022 17:35:26 +0400 Subject: [PATCH] FEATURE: show status on post streams (#17813) --- .../discourse/app/lib/transform-post.js | 4 +++ .../discourse/app/widgets/post-user-status.js | 18 ++++++++++ .../discourse/app/widgets/poster-name.js | 14 ++++++-- .../components/widgets/post-test.js | 22 ++++++++++++ .../stylesheets/common/base/topic-post.scss | 4 +++ app/serializers/post_serializer.rb | 11 +++++- lib/topic_view.rb | 2 ++ spec/serializers/post_serializer_spec.rb | 34 +++++++++++++++++++ 8 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/discourse/app/widgets/post-user-status.js diff --git a/app/assets/javascripts/discourse/app/lib/transform-post.js b/app/assets/javascripts/discourse/app/lib/transform-post.js index 827b901f4a7..49ffd0e37f3 100644 --- a/app/assets/javascripts/discourse/app/lib/transform-post.js +++ b/app/assets/javascripts/discourse/app/lib/transform-post.js @@ -289,6 +289,10 @@ export default function transformPost( postAtts.isDeleted && post.can_permanently_delete; } + if (post.user_status) { + postAtts.userStatus = post.user_status; + } + _additionalAttributes.forEach((a) => (postAtts[a] = post[a])); return postAtts; diff --git a/app/assets/javascripts/discourse/app/widgets/post-user-status.js b/app/assets/javascripts/discourse/app/widgets/post-user-status.js new file mode 100644 index 00000000000..0e048575374 --- /dev/null +++ b/app/assets/javascripts/discourse/app/widgets/post-user-status.js @@ -0,0 +1,18 @@ +import { createWidget } from "discourse/widgets/widget"; +import RenderGlimmer from "discourse/widgets/render-glimmer"; +import { hbs } from "ember-cli-htmlbars"; + +createWidget("post-user-status", { + html(attrs) { + return [ + new RenderGlimmer( + this, + "div", + hbs``, + { + attrs, + } + ), + ]; + }, +}); diff --git a/app/assets/javascripts/discourse/app/widgets/poster-name.js b/app/assets/javascripts/discourse/app/widgets/poster-name.js index 2308b77155a..50c1f392030 100644 --- a/app/assets/javascripts/discourse/app/widgets/poster-name.js +++ b/app/assets/javascripts/discourse/app/widgets/poster-name.js @@ -95,9 +95,6 @@ export default createWidget("poster-name", { classNames.push("new-user"); } - let afterNameContents = - applyDecorators(this, "after-name", attrs, this.state) || []; - const primaryGroupName = attrs.primary_group_name; if (primaryGroupName && primaryGroupName.length) { classNames.push(primaryGroupName); @@ -110,6 +107,8 @@ export default createWidget("poster-name", { nameContents.push(glyph); } } + + const afterNameContents = this.afterNameContents(attrs); nameContents = nameContents.concat(afterNameContents); const contents = [ @@ -149,4 +148,13 @@ export default createWidget("poster-name", { return contents; }, + + afterNameContents(attrs) { + const contents = []; + if (this.siteSettings.enable_user_status && attrs.userStatus) { + contents.push(this.attach("post-user-status", attrs.userStatus)); + } + contents.push(...applyDecorators(this, "after-name", attrs, this.state)); + return contents; + }, }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/post-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-test.js index b6ee555991c..08c1a81ab6c 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/widgets/post-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/post-test.js @@ -917,4 +917,26 @@ module("Integration | Component | Widget | post", function (hooks) { "/g/testGroup/requests?filter=foo" ); }); + + test("shows user status if enabled in site settings", async function (assert) { + this.siteSettings.enable_user_status = true; + this.set("args", { + userStatus: { emoji: "tooth", description: "off to dentist" }, + }); + + await render(hbs``); + + assert.ok(exists(".user-status-message")); + }); + + test("doesn't show user status if disabled in site settings", async function (assert) { + this.siteSettings.enable_user_status = false; + this.set("args", { + userStatus: { emoji: "tooth", description: "off to dentist" }, + }); + + await render(hbs``); + + assert.notOk(exists(".user-status-message")); + }); }); diff --git a/app/assets/stylesheets/common/base/topic-post.scss b/app/assets/stylesheets/common/base/topic-post.scss index 4f0ea8faebd..5b664853090 100644 --- a/app/assets/stylesheets/common/base/topic-post.scss +++ b/app/assets/stylesheets/common/base/topic-post.scss @@ -74,6 +74,10 @@ $quote-share-maxwidth: 150px; .user-title a { color: var(--primary-med-or-secondary-med); } + + .user-status-message { + margin-left: 0.3em; + } } // global styles for the cooked HTML content in posts (and preview) diff --git a/app/serializers/post_serializer.rb b/app/serializers/post_serializer.rb index 472e3e87bb0..8f0bebf4c59 100644 --- a/app/serializers/post_serializer.rb +++ b/app/serializers/post_serializer.rb @@ -87,7 +87,8 @@ class PostSerializer < BasicPostSerializer :reviewable_id, :reviewable_score_count, :reviewable_score_pending_count, - :user_suspended + :user_suspended, + :user_status def initialize(object, opts) super(object, opts) @@ -551,6 +552,14 @@ class PostSerializer < BasicPostSerializer object.user&.suspended? end + def include_user_status? + SiteSetting.enable_user_status && object.user&.has_status? + end + + def user_status + UserStatusSerializer.new(object.user&.user_status, root: false) + end + private def can_review_topic? diff --git a/lib/topic_view.rb b/lib/topic_view.rb index c3363715d60..1c2ed0e7b05 100644 --- a/lib/topic_view.rb +++ b/lib/topic_view.rb @@ -760,6 +760,8 @@ class TopicView :image_upload ) + @posts = @posts.includes({ user: :user_status }) if SiteSetting.enable_user_status + @posts = apply_default_scope(@posts) @posts = filter_post_types(@posts) @posts = @posts.with_deleted if @guardian.can_see_deleted_posts?(@topic.category) diff --git a/spec/serializers/post_serializer_spec.rb b/spec/serializers/post_serializer_spec.rb index e47a83c104f..23c3123ad7a 100644 --- a/spec/serializers/post_serializer_spec.rb +++ b/spec/serializers/post_serializer_spec.rb @@ -299,6 +299,40 @@ RSpec.describe PostSerializer do end end + describe "#user_status" do + fab!(:user_status) { Fabricate(:user_status) } + fab!(:user) { Fabricate(:user, user_status: user_status) } + fab!(:post) { Fabricate(:post, user: user) } + let(:serializer) { described_class.new(post, scope: Guardian.new(user), root: false) } + + it "adds user status when enabled" do + SiteSetting.enable_user_status = true + + json = serializer.as_json + + expect(json[:user_status]).to_not be_nil do |status| + expect(status.description).to eq(user_status.description) + expect(status.emoji).to eq(user_status.emoji) + end + end + + it "doesn't add user status when disabled" do + SiteSetting.enable_user_status = false + json = serializer.as_json + expect(json.keys).not_to include :user_status + end + + it "doesn't add status if user doesn't have it" do + SiteSetting.enable_user_status = true + + user.clear_status! + user.reload + json = serializer.as_json + + expect(json.keys).not_to include :user_status + end + end + def serialized_post(u) s = PostSerializer.new(post, scope: Guardian.new(u), root: false) s.add_raw = true