diff --git a/assets/javascripts/discourse/components/solved-unaccept-answer-button.gjs b/assets/javascripts/discourse/components/solved-unaccept-answer-button.gjs index 5407b29..8f690ae 100644 --- a/assets/javascripts/discourse/components/solved-unaccept-answer-button.gjs +++ b/assets/javascripts/discourse/components/solved-unaccept-answer-button.gjs @@ -4,8 +4,40 @@ import { service } from "@ember/service"; import DButton from "discourse/components/d-button"; import { ajax } from "discourse/lib/ajax"; import { popupAjaxError } from "discourse/lib/ajax-error"; -import dIcon from "discourse-common/helpers/d-icon"; -import i18n from "discourse-common/helpers/i18n"; +import icon from "discourse-common/helpers/d-icon"; +import { i18n } from "discourse-i18n"; + +export function unacceptAnswer(post, appEvents) { + // TODO (glimmer-post-menu): Remove this exported function and move the code into the button action after the widget code is removed + unacceptPost(post); + + appEvents.trigger("discourse-solved:solution-toggled", post); + + post.get("topic.postStream.posts").forEach((p) => { + p.set("topic_accepted_answer", false); + appEvents.trigger("post-stream:refresh", { id: p.id }); + }); +} + +function unacceptPost(post) { + if (!post.can_unaccept_answer) { + return; + } + const topic = post.topic; + + post.setProperties({ + can_accept_answer: true, + can_unaccept_answer: false, + accepted_answer: false, + }); + + topic.set("accepted_answer", undefined); + + ajax("/solution/unaccept", { + type: "POST", + data: { id: post.id }, + }).catch(popupAjaxError); +} export default class SolvedUnacceptAnswerButton extends Component { @service appEvents; @@ -31,7 +63,7 @@ export default class SolvedUnacceptAnswerButton extends Component { class="accepted-text" title={{i18n "solved.accepted_description"}} > - {{dIcon "check"}} + {{icon "check"}} {{i18n "solved.solution"}} @@ -40,35 +72,3 @@ export default class SolvedUnacceptAnswerButton extends Component { } - -export function unacceptAnswer(post, appEvents) { - // TODO (glimmer-post-menu): Remove this exported function and move the code into the button action after the widget code is removed - unacceptPost(post); - - appEvents.trigger("discourse-solved:solution-toggled", post); - - post.get("topic.postStream.posts").forEach((p) => { - p.set("topic_accepted_answer", false); - appEvents.trigger("post-stream:refresh", { id: p.id }); - }); -} - -function unacceptPost(post) { - if (!post.can_unaccept_answer) { - return; - } - const topic = post.topic; - - post.setProperties({ - can_accept_answer: true, - can_unaccept_answer: false, - accepted_answer: false, - }); - - topic.set("accepted_answer", undefined); - - ajax("/solution/unaccept", { - type: "POST", - data: { id: post.id }, - }).catch(popupAjaxError); -} diff --git a/assets/javascripts/discourse/connectors/bread-crumbs-right/solved-status-filter.js b/assets/javascripts/discourse/connectors/bread-crumbs-right/solved-status-filter.js index 01554ba..8cd8465 100644 --- a/assets/javascripts/discourse/connectors/bread-crumbs-right/solved-status-filter.js +++ b/assets/javascripts/discourse/connectors/bread-crumbs-right/solved-status-filter.js @@ -1,7 +1,7 @@ import Component from "@glimmer/component"; import { action } from "@ember/object"; import { service } from "@ember/service"; -import I18n from "I18n"; +import { i18n } from "discourse-i18n"; const QUERY_PARAM_VALUES = { solved: "yes", @@ -40,7 +40,7 @@ export default class SolvedStatusFilter extends Component { get statuses() { return ["all", "solved", "unsolved"].map((status) => { return { - name: I18n.t(`solved.topic_status_filter.${status}`), + name: i18n(`solved.topic_status_filter.${status}`), value: status, }; }); diff --git a/assets/javascripts/discourse/initializers/extend-for-solved-button.js b/assets/javascripts/discourse/initializers/extend-for-solved-button.js index 0a711d3..d245c87 100644 --- a/assets/javascripts/discourse/initializers/extend-for-solved-button.js +++ b/assets/javascripts/discourse/initializers/extend-for-solved-button.js @@ -8,7 +8,7 @@ import TopicStatus from "discourse/raw-views/topic-status"; import PostCooked from "discourse/widgets/post-cooked"; import { withSilencedDeprecations } from "discourse-common/lib/deprecated"; import { iconHTML, iconNode } from "discourse-common/lib/icon-library"; -import I18n from "I18n"; +import { i18n } from "discourse-i18n"; import SolvedAcceptAnswerButton, { acceptAnswer, } from "../components/solved-accept-answer-button"; @@ -161,11 +161,11 @@ function customizeWidgetPostMenu(api) { return h( "span.accepted-text", { - title: I18n.t("solved.accepted_description"), + title: i18n("solved.accepted_description"), }, [ h("span", iconNode("check")), - h("span.accepted-label", I18n.t("solved.solution")), + h("span.accepted-label", i18n("solved.solution")), ] ); }, @@ -194,7 +194,7 @@ export default { ? name : formatUsername(username); - return I18n.t("solved.accepted_html", { + return i18n("solved.accepted_html", { icon: iconHTML("check-square", { class: "accepted" }), username_lower: username.toLowerCase(), username: displayedUser, @@ -213,7 +213,7 @@ export default { results.push({ openTag: "span", closeTag: "span", - title: I18n.t("topic_statuses.solved.help"), + title: i18n("topic_statuses.solved.help"), icon: "far-check-square", key: "solved", }); @@ -225,7 +225,7 @@ export default { results.push({ openTag: "span", closeTag: "span", - title: I18n.t("solved.has_no_accepted_answer"), + title: i18n("solved.has_no_accepted_answer"), icon: "far-square", }); } @@ -246,11 +246,11 @@ export default { api.addAdvancedSearchOptions({ statusOptions: [ { - name: I18n.t("search.advanced.statuses.solved"), + name: i18n("search.advanced.statuses.solved"), value: "solved", }, { - name: I18n.t("search.advanced.statuses.unsolved"), + name: i18n("search.advanced.statuses.unsolved"), value: "unsolved", }, ], diff --git a/assets/javascripts/discourse/routes/user-activity-solved.js b/assets/javascripts/discourse/routes/user-activity-solved.js index fa4a674..ef41d18 100644 --- a/assets/javascripts/discourse/routes/user-activity-solved.js +++ b/assets/javascripts/discourse/routes/user-activity-solved.js @@ -1,5 +1,5 @@ import UserActivityStreamRoute from "discourse/routes/user-activity-stream"; -import I18n from "I18n"; +import { i18n } from "discourse-i18n"; export default class UserActivitySolved extends UserActivityStreamRoute { userActionType = 15; @@ -10,10 +10,10 @@ export default class UserActivitySolved extends UserActivityStreamRoute { let title, body; if (this.isCurrentUser(user)) { - title = I18n.t("solved.no_solved_topics_title"); - body = I18n.t("solved.no_solved_topics_body"); + title = i18n("solved.no_solved_topics_title"); + body = i18n("solved.no_solved_topics_body"); } else { - title = I18n.t("solved.no_solved_topics_title_others", { + title = i18n("solved.no_solved_topics_title_others", { username: user.username, }); body = ""; diff --git a/test/javascripts/acceptance/discourse-solved-post-menu-test.js b/test/javascripts/acceptance/discourse-solved-post-menu-test.js index 60df5ba..a8c7be9 100644 --- a/test/javascripts/acceptance/discourse-solved-post-menu-test.js +++ b/test/javascripts/acceptance/discourse-solved-post-menu-test.js @@ -1,15 +1,13 @@ import { click, visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -import I18n from "I18n"; +import { i18n } from "discourse-i18n"; import { postStreamWithAcceptedAnswerExcerpt } from "../helpers/discourse-solved-helpers"; acceptance( "Discourse Solved | Post Menu | Accept and Unaccept", function (needs) { - needs.user({ - admin: true, - }); + needs.user({ admin: true }); needs.settings({ glimmer_post_menu_mode: "enabled", @@ -23,9 +21,9 @@ acceptance( helper.response({ success: "OK" }) ); - server.get("/t/12.json", () => { - return helper.response(postStreamWithAcceptedAnswerExcerpt(null)); - }); + server.get("/t/12.json", () => + helper.response(postStreamWithAcceptedAnswerExcerpt(null)) + ); }); test("accepting and unaccepting a post works", async function (assert) { @@ -34,7 +32,7 @@ acceptance( assert .dom("#post_2 .post-action-menu__solved-accepted") .exists("Unaccept button is visible") - .hasText(I18n.t("solved.solution"), "Unaccept button has correct text"); + .hasText(i18n("solved.solution"), "Unaccept button has correct text"); await click("#post_2 .post-action-menu__solved-accepted"); @@ -46,7 +44,7 @@ acceptance( assert .dom("#post_2 .post-action-menu__solved-accepted") - .exists("Unccept button is visible again"); + .exists("Unaccept button is visible again"); }); } ); diff --git a/test/javascripts/acceptance/discourse-solved-test.js b/test/javascripts/acceptance/discourse-solved-test.js index 08620df..d18f7db 100644 --- a/test/javascripts/acceptance/discourse-solved-test.js +++ b/test/javascripts/acceptance/discourse-solved-test.js @@ -1,53 +1,45 @@ import { click, fillIn, visit } from "@ember/test-helpers"; import { test } from "qunit"; -import { fixturesByUrl } from "discourse/tests/helpers/create-pretender"; -import { acceptance, queryAll } from "discourse/tests/helpers/qunit-helpers"; +import pretender, { + fixturesByUrl, + response, +} from "discourse/tests/helpers/create-pretender"; +import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import { cloneJSON } from "discourse-common/lib/object"; import { postStreamWithAcceptedAnswerExcerpt } from "../helpers/discourse-solved-helpers"; acceptance("Discourse Solved Plugin", function (needs) { needs.user(); - needs.pretender((server, helper) => { - server.get("/t/11.json", () => { - return helper.response( - postStreamWithAcceptedAnswerExcerpt("this is an excerpt") - ); - }); - - server.get("/t/12.json", () => { - return helper.response(postStreamWithAcceptedAnswerExcerpt(null)); - }); - - server.get("/search", () => { - const fixtures = cloneJSON(fixturesByUrl["/search.json"]); - fixtures.topics[0].has_accepted_answer = true; - return helper.response(fixtures); - }); - }); - test("A topic with an accepted answer shows an excerpt of the answer, if provided", async function (assert) { - await visit("/t/with-excerpt/11"); + pretender.get("/t/11.json", () => + response(postStreamWithAcceptedAnswerExcerpt("this is an excerpt")) + ); - assert.strictEqual( - queryAll('.quote blockquote:contains("this is an excerpt")').length, - 1 + pretender.get("/t/12.json", () => + response(postStreamWithAcceptedAnswerExcerpt(null)) ); - await visit("/t/without-excerpt/12"); + await visit("/t/with-excerpt/11"); + assert.dom(".quote blockquote").hasText("this is an excerpt"); - assert.notStrictEqual(queryAll(".quote blockquote").length, 1); - assert.strictEqual(queryAll(".quote .title.title-only").length, 1); + await visit("/t/without-excerpt/12"); + assert.dom(".quote blockquote").doesNotExist(); + assert.dom(".quote .title.title-only").exists(); }); test("Full page search displays solved status", async function (assert) { - await visit("/search"); + pretender.get("/search", () => { + const fixtures = cloneJSON(fixturesByUrl["/search.json"]); + fixtures.topics[0].has_accepted_answer = true; + return response(fixtures); + }); + await visit("/search"); await fillIn(".search-query", "discourse"); await click(".search-cta"); - assert.strictEqual(queryAll(".fps-topic").length, 1, "has one post"); - - assert.ok(queryAll(".topic-status .solved").length, "shows the right icon"); + assert.dom(".fps-topic").exists({ count: 1 }, "has one post"); + assert.dom(".topic-status .solved").exists("shows the right icon"); }); }); diff --git a/test/javascripts/acceptance/discourse-solved-widget-post-menu-test.js b/test/javascripts/acceptance/discourse-solved-widget-post-menu-test.js index e390d2f..2733541 100644 --- a/test/javascripts/acceptance/discourse-solved-widget-post-menu-test.js +++ b/test/javascripts/acceptance/discourse-solved-widget-post-menu-test.js @@ -1,15 +1,13 @@ import { click, visit } from "@ember/test-helpers"; import { test } from "qunit"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; -import I18n from "I18n"; +import { i18n } from "discourse-i18n"; import { postStreamWithAcceptedAnswerExcerpt } from "../helpers/discourse-solved-helpers"; acceptance( "Discourse Solved | Widget Post Menu |Accept and Unaccept", function (needs) { - needs.user({ - admin: true, - }); + needs.user({ admin: true }); needs.settings({ glimmer_post_menu_mode: "disabled", @@ -23,9 +21,9 @@ acceptance( helper.response({ success: "OK" }) ); - server.get("/t/12.json", () => { - return helper.response(postStreamWithAcceptedAnswerExcerpt(null)); - }); + server.get("/t/12.json", () => + helper.response(postStreamWithAcceptedAnswerExcerpt(null)) + ); }); test("accepting and unaccepting a post works", async function (assert) { @@ -34,7 +32,7 @@ acceptance( assert .dom("#post_2 .accepted") .exists("Unaccept button is visible") - .hasText(I18n.t("solved.solution"), "Unaccept button has correct text"); + .hasText(i18n("solved.solution"), "Unaccept button has correct text"); await click("#post_2 .accepted"); @@ -42,7 +40,9 @@ acceptance( await click("#post_2 .unaccepted"); - assert.dom("#post_2 .accepted").exists("Unccept button is visible again"); + assert + .dom("#post_2 .accepted") + .exists("Unaccept button is visible again"); }); } ); diff --git a/test/javascripts/acceptance/user-activity-solved-test.js b/test/javascripts/acceptance/user-activity-solved-test.js index 99a8e46..ce55280 100644 --- a/test/javascripts/acceptance/user-activity-solved-test.js +++ b/test/javascripts/acceptance/user-activity-solved-test.js @@ -1,46 +1,39 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; -import { acceptance, query } from "discourse/tests/helpers/qunit-helpers"; -import I18n from "I18n"; +import { acceptance } from "discourse/tests/helpers/qunit-helpers"; +import { i18n } from "discourse-i18n"; acceptance( "Discourse Solved Plugin | activity/solved | empty state", function (needs) { - const currentUser = "eviltrout"; - const anotherUser = "charlie"; needs.user(); needs.pretender((server, helper) => { - const emptyResponse = { user_actions: [] }; - - server.get("/user_actions.json", () => { - return helper.response(emptyResponse); - }); + server.get("/user_actions.json", () => + helper.response({ user_actions: [] }) + ); }); test("When looking at own activity", async function (assert) { - await visit(`/u/${currentUser}/activity/solved`); + await visit(`/u/eviltrout/activity/solved`); - assert.equal( - query("div.empty-state span.empty-state-title").innerText, - I18n.t("solved.no_solved_topics_title") - ); - assert.equal( - query("div.empty-state div.empty-state-body").innerText, - I18n.t("solved.no_solved_topics_body") - ); + assert + .dom("div.empty-state span.empty-state-title") + .hasText(i18n("solved.no_solved_topics_title")); + assert + .dom("div.empty-state div.empty-state-body") + .hasText(i18n("solved.no_solved_topics_body")); }); test("When looking at another user's activity", async function (assert) { - await visit(`/u/${anotherUser}/activity/solved`); + await visit(`/u/charlie/activity/solved`); - assert.equal( - query("div.empty-state span.empty-state-title").innerText, - I18n.t("solved.no_solved_topics_title_others", { - username: anotherUser, + assert.dom("div.empty-state span.empty-state-title").hasText( + i18n("solved.no_solved_topics_title_others", { + username: "charlie", }) ); - assert.equal(query("div.empty-state div.empty-state-body").innerText, ""); + assert.dom("div.empty-state div.empty-state-body").hasNoText(); }); } );