DEV: Add compatibility with the Glimmer Post Stream
This commit is contained in:
parent
ae01ad30c3
commit
200acada1b
|
@ -0,0 +1,96 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { service } from "@ember/service";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import concatClass from "discourse/helpers/concat-class";
|
||||
import { iconHTML } from "discourse/lib/icon-library";
|
||||
import { formatUsername } from "discourse/lib/utilities";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
export default class SolvedAcceptedAnswer extends Component {
|
||||
@service siteSettings;
|
||||
@service store;
|
||||
|
||||
get topic() {
|
||||
return this.args.post.topic;
|
||||
}
|
||||
|
||||
get hasExcerpt() {
|
||||
return !!this.topic.accepted_answer.excerpt;
|
||||
}
|
||||
|
||||
get htmlAccepter() {
|
||||
const username = this.topic.accepted_answer.accepter_username;
|
||||
const name = this.topic.accepted_answer.accepter_name;
|
||||
|
||||
if (!this.siteSettings.show_who_marked_solved) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formattedUsername =
|
||||
this.siteSettings.display_name_on_posts && name
|
||||
? name
|
||||
: formatUsername(username);
|
||||
|
||||
return htmlSafe(
|
||||
i18n("solved.marked_solved_by", {
|
||||
username: formattedUsername,
|
||||
username_lower: username.toLowerCase(),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
get htmlExcerpt() {
|
||||
return htmlSafe(this.topic.accepted_answer.excerpt);
|
||||
}
|
||||
|
||||
get htmlSolvedBy() {
|
||||
const username = this.topic.accepted_answer.username;
|
||||
const name = this.topic.accepted_answer.name;
|
||||
const postNumber = this.topic.accepted_answer.post_number;
|
||||
|
||||
if (!username || !postNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
const displayedUser =
|
||||
this.siteSettings.display_name_on_posts && name
|
||||
? name
|
||||
: formatUsername(username);
|
||||
|
||||
const data = {
|
||||
icon: iconHTML("square-check", { class: "accepted" }),
|
||||
username_lower: username.toLowerCase(),
|
||||
username: displayedUser,
|
||||
post_path: `${this.topic.url}/${postNumber}`,
|
||||
post_number: postNumber,
|
||||
user_path: this.store.createRecord("user", { username }).path,
|
||||
};
|
||||
|
||||
return htmlSafe(i18n("solved.accepted_html", data));
|
||||
}
|
||||
|
||||
<template>
|
||||
<aside
|
||||
class="quote accepted-answer"
|
||||
data-post={{this.topic.accepted_answer.post_number}}
|
||||
data-topic={{this.topic.id}}
|
||||
>
|
||||
<div class={{concatClass "title" (if this.hasExcerpt "title-only")}}>
|
||||
<div class="accepted-answer--solver-accepter">
|
||||
<div class="accepted-answer--solver">
|
||||
{{this.htmlSolvedBy}}
|
||||
</div>
|
||||
<div class="accepted-answer--accepter">
|
||||
{{this.htmlAccepter}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="quote-controls"></div>
|
||||
</div>
|
||||
{{#if this.hasExcerpt}}
|
||||
<blockquote>
|
||||
{{this.htmlExcerpt}}
|
||||
</blockquote>
|
||||
{{/if}}
|
||||
</aside>
|
||||
</template>
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { computed } from "@ember/object";
|
||||
import { withSilencedDeprecations } from "discourse/lib/deprecated";
|
||||
import { iconHTML } from "discourse/lib/icon-library";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import { formatUsername } from "discourse/lib/utilities";
|
||||
import Topic from "discourse/models/topic";
|
||||
import User from "discourse/models/user";
|
||||
import PostCooked from "discourse/widgets/post-cooked";
|
||||
import RenderGlimmer from "discourse/widgets/render-glimmer";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import SolvedAcceptAnswerButton from "../components/solved-accept-answer-button";
|
||||
import SolvedAcceptedAnswer from "../components/solved-accepted-answer";
|
||||
import SolvedUnacceptAnswerButton from "../components/solved-unaccept-answer-button";
|
||||
|
||||
function initializeWithApi(api) {
|
||||
customizePost(api);
|
||||
customizePostMenu(api);
|
||||
|
||||
if (api.addDiscoveryQueryParam) {
|
||||
api.addDiscoveryQueryParam("solved", { replace: true, refreshModel: true });
|
||||
}
|
||||
}
|
||||
|
||||
function customizePost(api) {
|
||||
api.addTrackedPostProperties(
|
||||
"can_accept_answer",
|
||||
"can_unaccept_answer",
|
||||
"accepted_answer",
|
||||
"topic_accepted_answer"
|
||||
);
|
||||
|
||||
api.renderAfterWrapperOutlet(
|
||||
"post-content-cooked-html",
|
||||
class extends Component {
|
||||
static shouldRender(args) {
|
||||
return args.post.post_number === 1 && args.post.topic.accepted_answer;
|
||||
}
|
||||
|
||||
<template><SolvedAcceptedAnswer @post={{@outletArgs.post}} /></template>
|
||||
}
|
||||
);
|
||||
|
||||
withSilencedDeprecations("discourse.post-stream-widget-overrides", () =>
|
||||
customizeWidgetPost(api)
|
||||
);
|
||||
}
|
||||
|
||||
function customizeWidgetPost(api) {
|
||||
api.decorateWidget("post-contents:after-cooked", (helper) => {
|
||||
let post = helper.getModel();
|
||||
|
||||
if (helper.attrs.post_number === 1 && post?.topic?.accepted_answer) {
|
||||
return new RenderGlimmer(
|
||||
helper.widget,
|
||||
"div",
|
||||
<template><SolvedAcceptedAnswer @post={{@data.post}} /></template>,
|
||||
{ post }
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function customizePostMenu(api) {
|
||||
api.registerValueTransformer(
|
||||
"post-menu-buttons",
|
||||
({
|
||||
value: dag,
|
||||
context: {
|
||||
post,
|
||||
firstButtonKey,
|
||||
secondLastHiddenButtonKey,
|
||||
lastHiddenButtonKey,
|
||||
},
|
||||
}) => {
|
||||
let solvedButton;
|
||||
|
||||
if (post.can_accept_answer) {
|
||||
solvedButton = SolvedAcceptAnswerButton;
|
||||
} else if (post.accepted_answer) {
|
||||
solvedButton = SolvedUnacceptAnswerButton;
|
||||
}
|
||||
|
||||
solvedButton &&
|
||||
dag.add(
|
||||
"solved",
|
||||
solvedButton,
|
||||
post.topic_accepted_answer && !post.accepted_answer
|
||||
? {
|
||||
before: lastHiddenButtonKey,
|
||||
after: secondLastHiddenButtonKey,
|
||||
}
|
||||
: {
|
||||
before: [
|
||||
"assign", // button added by the assign plugin
|
||||
firstButtonKey,
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "extend-for-solved-button",
|
||||
initialize() {
|
||||
withPluginApi("1.34.0", initializeWithApi);
|
||||
|
||||
withPluginApi("0.8.10", (api) => {
|
||||
api.replaceIcon(
|
||||
"notification.solved.accepted_notification",
|
||||
"square-check"
|
||||
);
|
||||
});
|
||||
|
||||
withPluginApi("0.11.0", (api) => {
|
||||
api.addAdvancedSearchOptions({
|
||||
statusOptions: [
|
||||
{
|
||||
name: i18n("search.advanced.statuses.solved"),
|
||||
value: "solved",
|
||||
},
|
||||
{
|
||||
name: i18n("search.advanced.statuses.unsolved"),
|
||||
value: "unsolved",
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
withPluginApi("0.11.7", (api) => {
|
||||
api.addSearchSuggestion("status:solved");
|
||||
api.addSearchSuggestion("status:unsolved");
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,186 +0,0 @@
|
|||
import { computed } from "@ember/object";
|
||||
import { iconHTML } from "discourse/lib/icon-library";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import { formatUsername } from "discourse/lib/utilities";
|
||||
import Topic from "discourse/models/topic";
|
||||
import User from "discourse/models/user";
|
||||
import PostCooked from "discourse/widgets/post-cooked";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import SolvedAcceptAnswerButton, {
|
||||
acceptAnswer,
|
||||
} from "../components/solved-accept-answer-button";
|
||||
import SolvedUnacceptAnswerButton, {
|
||||
unacceptAnswer,
|
||||
} from "../components/solved-unaccept-answer-button";
|
||||
|
||||
function initializeWithApi(api) {
|
||||
customizePostMenu(api);
|
||||
|
||||
api.includePostAttributes(
|
||||
"can_accept_answer",
|
||||
"can_unaccept_answer",
|
||||
"accepted_answer",
|
||||
"topic_accepted_answer"
|
||||
);
|
||||
|
||||
if (api.addDiscoveryQueryParam) {
|
||||
api.addDiscoveryQueryParam("solved", { replace: true, refreshModel: true });
|
||||
}
|
||||
|
||||
api.decorateWidget("post-contents:after-cooked", (dec) => {
|
||||
if (dec.attrs.post_number === 1) {
|
||||
const postModel = dec.getModel();
|
||||
if (postModel) {
|
||||
const topic = postModel.topic;
|
||||
if (topic.accepted_answer) {
|
||||
const hasExcerpt = !!topic.accepted_answer.excerpt;
|
||||
const excerpt = hasExcerpt
|
||||
? ` <blockquote> ${topic.accepted_answer.excerpt} </blockquote> `
|
||||
: "";
|
||||
const solvedQuote = `
|
||||
<aside class='quote accepted-answer' data-post="${topic.get("accepted_answer").post_number}" data-topic="${topic.id}">
|
||||
<div class='title ${hasExcerpt ? "" : "title-only"}'>
|
||||
<div class="accepted-answer--solver-accepter">
|
||||
<div class="accepted-answer--solver">
|
||||
${topic.solvedByHtml}
|
||||
<\/div>
|
||||
<div class="accepted-answer--accepter">
|
||||
${topic.accepterHtml}
|
||||
<\/div>
|
||||
</div>
|
||||
<div class="quote-controls"><\/div>
|
||||
</div>
|
||||
${excerpt}
|
||||
</aside>`;
|
||||
|
||||
const cooked = new PostCooked({ cooked: solvedQuote }, dec);
|
||||
return dec.rawHtml(cooked.init());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
api.attachWidgetAction("post", "acceptAnswer", function () {
|
||||
acceptAnswer(this.model, this.appEvents, this.currentUser);
|
||||
});
|
||||
|
||||
api.attachWidgetAction("post", "unacceptAnswer", function () {
|
||||
unacceptAnswer(this.model, this.appEvents);
|
||||
});
|
||||
}
|
||||
|
||||
function customizePostMenu(api) {
|
||||
api.registerValueTransformer(
|
||||
"post-menu-buttons",
|
||||
({
|
||||
value: dag,
|
||||
context: {
|
||||
post,
|
||||
firstButtonKey,
|
||||
secondLastHiddenButtonKey,
|
||||
lastHiddenButtonKey,
|
||||
},
|
||||
}) => {
|
||||
let solvedButton;
|
||||
|
||||
if (post.can_accept_answer) {
|
||||
solvedButton = SolvedAcceptAnswerButton;
|
||||
} else if (post.accepted_answer) {
|
||||
solvedButton = SolvedUnacceptAnswerButton;
|
||||
}
|
||||
|
||||
solvedButton &&
|
||||
dag.add(
|
||||
"solved",
|
||||
solvedButton,
|
||||
post.topic_accepted_answer && !post.accepted_answer
|
||||
? {
|
||||
before: lastHiddenButtonKey,
|
||||
after: secondLastHiddenButtonKey,
|
||||
}
|
||||
: {
|
||||
before: [
|
||||
"assign", // button added by the assign plugin
|
||||
firstButtonKey,
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "extend-for-solved-button",
|
||||
initialize() {
|
||||
Topic.reopen({
|
||||
// keeping this here cause there is complex localization
|
||||
solvedByHtml: computed("accepted_answer", "id", function () {
|
||||
const username = this.get("accepted_answer.username");
|
||||
const name = this.get("accepted_answer.name");
|
||||
const postNumber = this.get("accepted_answer.post_number");
|
||||
|
||||
if (!username || !postNumber) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const displayedUser =
|
||||
this.siteSettings.display_name_on_posts && name
|
||||
? name
|
||||
: formatUsername(username);
|
||||
|
||||
return i18n("solved.accepted_html", {
|
||||
icon: iconHTML("square-check", { class: "accepted" }),
|
||||
username_lower: username.toLowerCase(),
|
||||
username: displayedUser,
|
||||
post_path: `${this.url}/${postNumber}`,
|
||||
post_number: postNumber,
|
||||
user_path: User.create({ username }).path,
|
||||
});
|
||||
}),
|
||||
accepterHtml: computed("accepted_answer", function () {
|
||||
const username = this.get("accepted_answer.accepter_username");
|
||||
const name = this.get("accepted_answer.accepter_name");
|
||||
if (!this.siteSettings.show_who_marked_solved) {
|
||||
return "";
|
||||
}
|
||||
const formattedUsername =
|
||||
this.siteSettings.display_name_on_posts && name
|
||||
? name
|
||||
: formatUsername(username);
|
||||
return i18n("solved.marked_solved_by", {
|
||||
username: formattedUsername,
|
||||
username_lower: username.toLowerCase(),
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
||||
withPluginApi("1.34.0", initializeWithApi);
|
||||
|
||||
withPluginApi("0.8.10", (api) => {
|
||||
api.replaceIcon(
|
||||
"notification.solved.accepted_notification",
|
||||
"square-check"
|
||||
);
|
||||
});
|
||||
|
||||
withPluginApi("0.11.0", (api) => {
|
||||
api.addAdvancedSearchOptions({
|
||||
statusOptions: [
|
||||
{
|
||||
name: i18n("search.advanced.statuses.solved"),
|
||||
value: "solved",
|
||||
},
|
||||
{
|
||||
name: i18n("search.advanced.statuses.unsolved"),
|
||||
value: "unsolved",
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
withPluginApi("0.11.7", (api) => {
|
||||
api.addSearchSuggestion("status:solved");
|
||||
api.addSearchSuggestion("status:unsolved");
|
||||
});
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue