mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 10:57:04 +08:00
UX: Add show more button to long post queued reviewables (#23075)
This commit is contained in:
parent
ac4e854a04
commit
61571bee43
|
@ -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 {
|
||||||
|
<template>
|
||||||
|
{{! template-lint-disable modifier-name-case }}
|
||||||
|
<div
|
||||||
|
...attributes
|
||||||
|
{{didUpdate this.buildOneboxes this.cooked}}
|
||||||
|
{{didUpdate this.resolveShortUrls this.cooked}}
|
||||||
|
{{didUpdate this.calculateOffsetHeight this.cooked}}
|
||||||
|
>
|
||||||
|
{{this.cooked}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
{{this.cooked}}
|
|
|
@ -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;
|
|
|
@ -1,11 +1,11 @@
|
||||||
<ReviewableTopicLink @reviewable={{this.reviewable}} @tagName="">
|
<ReviewableTopicLink @reviewable={{@reviewable}} @tagName="">
|
||||||
<div class="title-text">
|
<div class="title-text">
|
||||||
{{d-icon "plus-square" title="review.new_topic"}}
|
{{d-icon "plus-square" title="review.new_topic"}}
|
||||||
{{this.reviewable.payload.title}}
|
{{@reviewable.payload.title}}
|
||||||
</div>
|
</div>
|
||||||
{{category-badge this.reviewable.category}}
|
{{category-badge @reviewable.category}}
|
||||||
<ReviewableTags @tags={{this.reviewable.payload.tags}} @tagName="" />
|
<ReviewableTags @tags={{@reviewable.payload.tags}} @tagName="" />
|
||||||
{{#if this.reviewable.payload.via_email}}
|
{{#if @reviewable.payload.via_email}}
|
||||||
<a href {{on "click" this.showRawEmail}} class="show-raw-email">
|
<a href {{on "click" this.showRawEmail}} class="show-raw-email">
|
||||||
{{d-icon "envelope" title="post.via_email"}}
|
{{d-icon "envelope" title="post.via_email"}}
|
||||||
</a>
|
</a>
|
||||||
|
@ -13,27 +13,34 @@
|
||||||
</ReviewableTopicLink>
|
</ReviewableTopicLink>
|
||||||
|
|
||||||
<div class="post-contents-wrapper">
|
<div class="post-contents-wrapper">
|
||||||
<ReviewableCreatedBy
|
<ReviewableCreatedBy @user={{@reviewable.target_created_by}} @tagName="" />
|
||||||
@user={{this.reviewable.target_created_by}}
|
|
||||||
@tagName=""
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="post-contents">
|
<div class="post-contents">
|
||||||
<ReviewablePostHeader
|
<ReviewablePostHeader
|
||||||
@reviewable={{this.reviewable}}
|
@reviewable={{@reviewable}}
|
||||||
@createdBy={{this.reviewable.target_created_by}}
|
@createdBy={{@reviewable.target_created_by}}
|
||||||
@tagName=""
|
@tagName=""
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CookText
|
<CookText
|
||||||
@rawText={{this.reviewable.payload.raw}}
|
class="post-body {{if this.isCollapsed 'is-collapsed'}}"
|
||||||
@class="post-body"
|
@rawText={{@reviewable.payload.raw}}
|
||||||
@categoryId={{this.reviewable.category_id}}
|
@categoryId={{@reviewable.category_id}}
|
||||||
@topicId={{this.reviewable.topic_id}}
|
@topicId={{@reviewable.topic_id}}
|
||||||
@paintOneboxes={{true}}
|
@paintOneboxes={{true}}
|
||||||
@opts={{hash removeMissing=true}}
|
@opts={{hash removeMissing=true}}
|
||||||
|
@onOffsetHeightCalculated={{this.setPostBodyHeight}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{{#if this.isLongPost}}
|
||||||
|
<DButton
|
||||||
|
@class="btn-default btn-icon post-body__toggle-btn"
|
||||||
|
@action={{this.toggleContent}}
|
||||||
|
@label={{this.collapseButtonProps.label}}
|
||||||
|
@icon={{this.collapseButtonProps.icon}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{yield}}
|
{{yield}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -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 { action } from "@ember/object";
|
||||||
import showModal from "discourse/lib/show-modal";
|
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
|
@action
|
||||||
showRawEmail(event) {
|
showRawEmail(event) {
|
||||||
event?.preventDefault();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ module("Integration | Component | cook-text", function (hooks) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("renders markdown", async function (assert) {
|
test("renders markdown", async function (assert) {
|
||||||
await render(hbs`<CookText @rawText="_foo_" @class="post-body" />`);
|
await render(hbs`<CookText @rawText="_foo_" class="post-body" />`);
|
||||||
|
|
||||||
const html = query(".post-body").innerHTML.trim();
|
const html = query(".post-body").innerHTML.trim();
|
||||||
assert.strictEqual(html, "<p><em>foo</em></p>");
|
assert.strictEqual(html, "<p><em>foo</em></p>");
|
||||||
|
@ -32,7 +32,7 @@ module("Integration | Component | cook-text", function (hooks) {
|
||||||
);
|
);
|
||||||
|
|
||||||
await render(
|
await render(
|
||||||
hbs`<CookText @rawText="![an image](upload://a.png)" @class="post-body" />`
|
hbs`<CookText @rawText="![an image](upload://a.png)" class="post-body" />`
|
||||||
);
|
);
|
||||||
|
|
||||||
const html = query(".post-body").innerHTML.trim();
|
const html = query(".post-body").innerHTML.trim();
|
||||||
|
|
|
@ -52,7 +52,7 @@ module I18n
|
||||||
# load it
|
# load it
|
||||||
I18n.backend.load_translations(I18n.load_path.grep(/\.#{Regexp.escape locale}\.yml\z/))
|
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.backend.load_translations(
|
||||||
I18n.load_path.grep(%r{.*faker.*/#{Regexp.escape locale}\.yml\z}),
|
I18n.load_path.grep(%r{.*faker.*/#{Regexp.escape locale}\.yml\z}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "faker"
|
||||||
|
|
||||||
Fabricator(:reviewable) do
|
Fabricator(:reviewable) do
|
||||||
reviewable_by_moderator true
|
reviewable_by_moderator true
|
||||||
type "ReviewableUser"
|
type "ReviewableUser"
|
||||||
|
@ -59,6 +61,36 @@ Fabricator(:reviewable_queued_post) do
|
||||||
end
|
end
|
||||||
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
|
Fabricator(:reviewable_flagged_post) do
|
||||||
reviewable_by_moderator true
|
reviewable_by_moderator true
|
||||||
type "ReviewableFlaggedPost"
|
type "ReviewableFlaggedPost"
|
||||||
|
|
|
@ -8,7 +8,7 @@ describe "Reviewables", type: :system do
|
||||||
|
|
||||||
before { sign_in(admin) }
|
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) }
|
fab!(:long_reviewable) { Fabricate(:reviewable_flagged_post, target: long_post) }
|
||||||
|
|
||||||
it "should show a button to expand/collapse the post content" do
|
it "should show a button to expand/collapse the post content" do
|
||||||
|
@ -22,7 +22,7 @@ describe "Reviewables", type: :system do
|
||||||
end
|
end
|
||||||
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) }
|
fab!(:short_reviewable) { Fabricate(:reviewable_flagged_post) }
|
||||||
|
|
||||||
it "should not show a button to expand/collapse the post content" do
|
it "should not show a button to expand/collapse the post content" do
|
||||||
|
@ -32,6 +32,30 @@ describe "Reviewables", type: :system do
|
||||||
end
|
end
|
||||||
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 "when performing a review action from the show route" do
|
||||||
context "with a ReviewableQueuedPost" do
|
context "with a ReviewableQueuedPost" do
|
||||||
fab!(:queued_post_reviewable) { Fabricate(:reviewable_queued_post) }
|
fab!(:queued_post_reviewable) { Fabricate(:reviewable_queued_post) }
|
||||||
|
|
Loading…
Reference in New Issue
Block a user