From 61571bee43eae88755b5e258e96d03c146f9d2cb Mon Sep 17 00:00:00 2001 From: Keegan George Date: Mon, 14 Aug 2023 10:11:30 -0700 Subject: [PATCH] UX: Add show more button to long post queued reviewables (#23075) --- .../discourse/app/components/cook-text.gjs | 64 +++++++++++++++++++ .../discourse/app/components/cook-text.hbs | 1 - .../discourse/app/components/cook-text.js | 38 ----------- .../app/components/reviewable-queued-post.hbs | 37 ++++++----- .../app/components/reviewable-queued-post.js | 50 +++++++++++++-- .../integration/components/cook-text-test.js | 4 +- lib/freedom_patches/translate_accelerator.rb | 2 +- spec/fabricators/reviewable_fabricator.rb | 32 ++++++++++ spec/system/reviewables_spec.rb | 28 +++++++- 9 files changed, 192 insertions(+), 64 deletions(-) create mode 100644 app/assets/javascripts/discourse/app/components/cook-text.gjs delete mode 100644 app/assets/javascripts/discourse/app/components/cook-text.hbs delete mode 100644 app/assets/javascripts/discourse/app/components/cook-text.js diff --git a/app/assets/javascripts/discourse/app/components/cook-text.gjs b/app/assets/javascripts/discourse/app/components/cook-text.gjs new file mode 100644 index 00000000000..2c86d5b0ce7 --- /dev/null +++ b/app/assets/javascripts/discourse/app/components/cook-text.gjs @@ -0,0 +1,64 @@ +import Component from "@glimmer/component"; +import { inject as service } from "@ember/service"; +import didUpdate from "@ember/render-modifiers/modifiers/did-update"; +import { action } from "@ember/object"; +import { tracked } from "@glimmer/tracking"; +import { loadOneboxes } from "discourse/lib/load-oneboxes"; +import { cookAsync } from "discourse/lib/text"; +import { resolveAllShortUrls } from "pretty-text/upload-short-url"; +import { ajax } from "discourse/lib/ajax"; + +export default class CookText extends Component { + + + @service siteSettings; + @tracked cooked = null; + + constructor(owner, args) { + super(owner, args); + this.loadCookedText(); + } + + async loadCookedText() { + const cooked = await cookAsync(this.args.rawText); + this.cooked = cooked; + } + + @action + calculateOffsetHeight(element) { + if (!this.args.onOffsetHeightCalculated) { + return; + } + + return this.args.onOffsetHeightCalculated(element?.offsetHeight); + } + + @action + buildOneboxes(element) { + if (this.args.paintOneboxes && this.cooked !== null) { + loadOneboxes( + element, + ajax, + this.args.topicId, + this.args.categoryId, + this.siteSettings.max_oneboxes_per_post, + false // refresh + ); + } + } + + @action + resolveShortUrls(element) { + resolveAllShortUrls(ajax, this.siteSettings, element, this.args.opts); + } +} diff --git a/app/assets/javascripts/discourse/app/components/cook-text.hbs b/app/assets/javascripts/discourse/app/components/cook-text.hbs deleted file mode 100644 index 35fa3df7bb4..00000000000 --- a/app/assets/javascripts/discourse/app/components/cook-text.hbs +++ /dev/null @@ -1 +0,0 @@ -{{this.cooked}} \ No newline at end of file diff --git a/app/assets/javascripts/discourse/app/components/cook-text.js b/app/assets/javascripts/discourse/app/components/cook-text.js deleted file mode 100644 index a45339bd406..00000000000 --- a/app/assets/javascripts/discourse/app/components/cook-text.js +++ /dev/null @@ -1,38 +0,0 @@ -import Component from "@ember/component"; -import { ajax } from "discourse/lib/ajax"; -import { cookAsync } from "discourse/lib/text"; -import { loadOneboxes } from "discourse/lib/load-oneboxes"; -import { resolveAllShortUrls } from "pretty-text/upload-short-url"; - -const CookText = Component.extend({ - cooked: null, - - didReceiveAttrs() { - this._super(...arguments); - - cookAsync(this.rawText).then((cooked) => { - this.set("cooked", cooked); - }); - }, - - didRender() { - this._super(...arguments); - - if (this.paintOneboxes) { - loadOneboxes( - this.element, - ajax, - this.topicId, - this.categoryId, - this.siteSettings.max_oneboxes_per_post, - false // refresh - ); - } - - resolveAllShortUrls(ajax, this.siteSettings, this.element, this.opts); - }, -}); - -CookText.reopenClass({ positionalParams: ["rawText"] }); - -export default CookText; diff --git a/app/assets/javascripts/discourse/app/components/reviewable-queued-post.hbs b/app/assets/javascripts/discourse/app/components/reviewable-queued-post.hbs index cdb6d8e7a7f..f2a175541f1 100644 --- a/app/assets/javascripts/discourse/app/components/reviewable-queued-post.hbs +++ b/app/assets/javascripts/discourse/app/components/reviewable-queued-post.hbs @@ -1,11 +1,11 @@ - +
{{d-icon "plus-square" title="review.new_topic"}} - {{this.reviewable.payload.title}} + {{@reviewable.payload.title}}
- {{category-badge this.reviewable.category}} - - {{#if this.reviewable.payload.via_email}} + {{category-badge @reviewable.category}} + + {{#if @reviewable.payload.via_email}} {{d-icon "envelope" title="post.via_email"}} @@ -13,27 +13,34 @@
- +
+ {{#if this.isLongPost}} + + {{/if}} + {{yield}}
\ No newline at end of file diff --git a/app/assets/javascripts/discourse/app/components/reviewable-queued-post.js b/app/assets/javascripts/discourse/app/components/reviewable-queued-post.js index d06ddf3c1c5..6bd74bdbe73 100644 --- a/app/assets/javascripts/discourse/app/components/reviewable-queued-post.js +++ b/app/assets/javascripts/discourse/app/components/reviewable-queued-post.js @@ -1,11 +1,51 @@ -import Component from "@ember/component"; +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; import { action } from "@ember/object"; import showModal from "discourse/lib/show-modal"; -export default Component.extend({ +export default class ReviewableQueuedPost extends Component { + @tracked isCollapsed = false; + @tracked isLongPost = false; + @tracked postBodyHeight = 0; + maxPostHeight = 300; + @action showRawEmail(event) { event?.preventDefault(); - showModal("raw-email").set("rawEmail", this.reviewable.payload.raw_email); - }, -}); + showModal("raw-email").set( + "rawEmail", + this.args.reviewable.payload.raw_email + ); + } + + @action + toggleContent() { + this.isCollapsed = !this.isCollapsed; + } + + get collapseButtonProps() { + if (this.isCollapsed) { + return { + label: "review.show_more", + icon: "chevron-down", + }; + } + return { + label: "review.show_less", + icon: "chevron-up", + }; + } + + @action + setPostBodyHeight(offsetHeight) { + this.postBodyHeight = offsetHeight; + + if (this.postBodyHeight > this.maxPostHeight) { + this.isCollapsed = true; + this.isLongPost = true; + } else { + this.isCollapsed = false; + this.isLongPost = false; + } + } +} diff --git a/app/assets/javascripts/discourse/tests/integration/components/cook-text-test.js b/app/assets/javascripts/discourse/tests/integration/components/cook-text-test.js index 15d648f2cb7..001aad6e7a9 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/cook-text-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/cook-text-test.js @@ -14,7 +14,7 @@ module("Integration | Component | cook-text", function (hooks) { }); test("renders markdown", async function (assert) { - await render(hbs``); + await render(hbs``); const html = query(".post-body").innerHTML.trim(); assert.strictEqual(html, "

foo

"); @@ -32,7 +32,7 @@ module("Integration | Component | cook-text", function (hooks) { ); await render( - hbs`` + hbs`` ); const html = query(".post-body").innerHTML.trim(); diff --git a/lib/freedom_patches/translate_accelerator.rb b/lib/freedom_patches/translate_accelerator.rb index 047a4754506..4aa394d3dc4 100644 --- a/lib/freedom_patches/translate_accelerator.rb +++ b/lib/freedom_patches/translate_accelerator.rb @@ -52,7 +52,7 @@ module I18n # load it I18n.backend.load_translations(I18n.load_path.grep(/\.#{Regexp.escape locale}\.yml\z/)) - if Discourse.allow_dev_populate? + if Discourse.allow_dev_populate? || Rails.env.test? || Rails.env.development? I18n.backend.load_translations( I18n.load_path.grep(%r{.*faker.*/#{Regexp.escape locale}\.yml\z}), ) diff --git a/spec/fabricators/reviewable_fabricator.rb b/spec/fabricators/reviewable_fabricator.rb index c99634b7b9e..e9d4e288e2f 100644 --- a/spec/fabricators/reviewable_fabricator.rb +++ b/spec/fabricators/reviewable_fabricator.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "faker" + Fabricator(:reviewable) do reviewable_by_moderator true type "ReviewableUser" @@ -59,6 +61,36 @@ Fabricator(:reviewable_queued_post) do end end +Fabricator(:reviewable_queued_long_post, from: :reviewable_queued_post) do + reviewable_by_moderator true + type "ReviewableQueuedPost" + created_by { Fabricate(:user) } + target_created_by { Fabricate(:user) } + topic + payload do + { + raw: Faker::DiscourseMarkdown.sandwich(sentences: 6, repeat: 3), + reply_to_post_number: 1, + via_email: true, + raw_email: "store_me", + auto_track: true, + custom_fields: { + hello: "world", + }, + cooking_options: { + cat: "hat", + }, + cook_method: Post.cook_methods[:raw_html], + image_sizes: { + "http://foo.bar/image.png" => { + "width" => 0, + "height" => 222, + }, + }, + } + end +end + Fabricator(:reviewable_flagged_post) do reviewable_by_moderator true type "ReviewableFlaggedPost" diff --git a/spec/system/reviewables_spec.rb b/spec/system/reviewables_spec.rb index 9c40e4fc8a0..9bc9b665539 100644 --- a/spec/system/reviewables_spec.rb +++ b/spec/system/reviewables_spec.rb @@ -8,7 +8,7 @@ describe "Reviewables", type: :system do before { sign_in(admin) } - describe "when there is a reviewable with a long post" do + describe "when there is a flagged post reviewable with a long post" do fab!(:long_reviewable) { Fabricate(:reviewable_flagged_post, target: long_post) } it "should show a button to expand/collapse the post content" do @@ -22,7 +22,7 @@ describe "Reviewables", type: :system do end end - describe "when there is a reviewable with a short post" do + describe "when there is a flagged post reviewable with a short post" do fab!(:short_reviewable) { Fabricate(:reviewable_flagged_post) } it "should not show a button to expand/collapse the post content" do @@ -32,6 +32,30 @@ describe "Reviewables", type: :system do end end + describe "when there is a queued post reviewable with a short post" do + fab!(:short_queued_reviewable) { Fabricate(:reviewable_queued_post) } + + it "should not show a button to expand/collapse the post content" do + visit("/review") + expect(review_page).to have_no_post_body_collapsed + expect(review_page).to have_no_post_body_toggle + end + end + + describe "when there is a queued post reviewable with a long post" do + fab!(:long_queued_reviewable) { Fabricate(:reviewable_queued_long_post) } + + it "should show a button to expand/collapse the post content" do + visit("/review") + expect(review_page).to have_post_body_collapsed + expect(review_page).to have_post_body_toggle + review_page.click_post_body_toggle + expect(review_page).to have_no_post_body_collapsed + review_page.click_post_body_toggle + expect(review_page).to have_post_body_collapsed + end + end + context "when performing a review action from the show route" do context "with a ReviewableQueuedPost" do fab!(:queued_post_reviewable) { Fabricate(:reviewable_queued_post) }