parent
f6d63b7299
commit
41a8789ec3
|
@ -4,42 +4,8 @@ import { service } from "@ember/service";
|
||||||
import DButton from "discourse/components/d-button";
|
import DButton from "discourse/components/d-button";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
import dIcon from "discourse-common/helpers/d-icon";
|
import icon from "discourse-common/helpers/d-icon";
|
||||||
import i18n from "discourse-common/helpers/i18n";
|
import { i18n } from "discourse-i18n";
|
||||||
|
|
||||||
export default class SolvedUnacceptAnswerButton extends Component {
|
|
||||||
@service appEvents;
|
|
||||||
|
|
||||||
@action
|
|
||||||
unacceptAnswer() {
|
|
||||||
unacceptAnswer(this.args.post, this.appEvents);
|
|
||||||
}
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<span class="extra-buttons">
|
|
||||||
{{#if @post.can_unaccept_answer}}
|
|
||||||
<DButton
|
|
||||||
class="post-action-menu__solved-accepted accepted fade-out"
|
|
||||||
...attributes
|
|
||||||
@action={{this.unacceptAnswer}}
|
|
||||||
@icon="check-square"
|
|
||||||
@label="solved.solution"
|
|
||||||
@title="solved.unaccept_answer"
|
|
||||||
/>
|
|
||||||
{{else}}
|
|
||||||
<span
|
|
||||||
class="accepted-text"
|
|
||||||
title={{i18n "solved.accepted_description"}}
|
|
||||||
>
|
|
||||||
<span>{{dIcon "check"}}</span>
|
|
||||||
<span class="accepted-label">
|
|
||||||
{{i18n "solved.solution"}}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
{{/if}}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
}
|
|
||||||
|
|
||||||
export function unacceptAnswer(post, appEvents) {
|
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
|
// TODO (glimmer-post-menu): Remove this exported function and move the code into the button action after the widget code is removed
|
||||||
|
@ -72,3 +38,37 @@ function unacceptPost(post) {
|
||||||
data: { id: post.id },
|
data: { id: post.id },
|
||||||
}).catch(popupAjaxError);
|
}).catch(popupAjaxError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default class SolvedUnacceptAnswerButton extends Component {
|
||||||
|
@service appEvents;
|
||||||
|
|
||||||
|
@action
|
||||||
|
unacceptAnswer() {
|
||||||
|
unacceptAnswer(this.args.post, this.appEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<span class="extra-buttons">
|
||||||
|
{{#if @post.can_unaccept_answer}}
|
||||||
|
<DButton
|
||||||
|
class="post-action-menu__solved-accepted accepted fade-out"
|
||||||
|
...attributes
|
||||||
|
@action={{this.unacceptAnswer}}
|
||||||
|
@icon="check-square"
|
||||||
|
@label="solved.solution"
|
||||||
|
@title="solved.unaccept_answer"
|
||||||
|
/>
|
||||||
|
{{else}}
|
||||||
|
<span
|
||||||
|
class="accepted-text"
|
||||||
|
title={{i18n "solved.accepted_description"}}
|
||||||
|
>
|
||||||
|
<span>{{icon "check"}}</span>
|
||||||
|
<span class="accepted-label">
|
||||||
|
{{i18n "solved.solution"}}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Component from "@glimmer/component";
|
import Component from "@glimmer/component";
|
||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
import { service } from "@ember/service";
|
import { service } from "@ember/service";
|
||||||
import I18n from "I18n";
|
import { i18n } from "discourse-i18n";
|
||||||
|
|
||||||
const QUERY_PARAM_VALUES = {
|
const QUERY_PARAM_VALUES = {
|
||||||
solved: "yes",
|
solved: "yes",
|
||||||
|
@ -40,7 +40,7 @@ export default class SolvedStatusFilter extends Component {
|
||||||
get statuses() {
|
get statuses() {
|
||||||
return ["all", "solved", "unsolved"].map((status) => {
|
return ["all", "solved", "unsolved"].map((status) => {
|
||||||
return {
|
return {
|
||||||
name: I18n.t(`solved.topic_status_filter.${status}`),
|
name: i18n(`solved.topic_status_filter.${status}`),
|
||||||
value: status,
|
value: status,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ import TopicStatus from "discourse/raw-views/topic-status";
|
||||||
import PostCooked from "discourse/widgets/post-cooked";
|
import PostCooked from "discourse/widgets/post-cooked";
|
||||||
import { withSilencedDeprecations } from "discourse-common/lib/deprecated";
|
import { withSilencedDeprecations } from "discourse-common/lib/deprecated";
|
||||||
import { iconHTML, iconNode } from "discourse-common/lib/icon-library";
|
import { iconHTML, iconNode } from "discourse-common/lib/icon-library";
|
||||||
import I18n from "I18n";
|
import { i18n } from "discourse-i18n";
|
||||||
import SolvedAcceptAnswerButton, {
|
import SolvedAcceptAnswerButton, {
|
||||||
acceptAnswer,
|
acceptAnswer,
|
||||||
} from "../components/solved-accept-answer-button";
|
} from "../components/solved-accept-answer-button";
|
||||||
|
@ -161,11 +161,11 @@ function customizeWidgetPostMenu(api) {
|
||||||
return h(
|
return h(
|
||||||
"span.accepted-text",
|
"span.accepted-text",
|
||||||
{
|
{
|
||||||
title: I18n.t("solved.accepted_description"),
|
title: i18n("solved.accepted_description"),
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
h("span", iconNode("check")),
|
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
|
? name
|
||||||
: formatUsername(username);
|
: formatUsername(username);
|
||||||
|
|
||||||
return I18n.t("solved.accepted_html", {
|
return i18n("solved.accepted_html", {
|
||||||
icon: iconHTML("check-square", { class: "accepted" }),
|
icon: iconHTML("check-square", { class: "accepted" }),
|
||||||
username_lower: username.toLowerCase(),
|
username_lower: username.toLowerCase(),
|
||||||
username: displayedUser,
|
username: displayedUser,
|
||||||
|
@ -213,7 +213,7 @@ export default {
|
||||||
results.push({
|
results.push({
|
||||||
openTag: "span",
|
openTag: "span",
|
||||||
closeTag: "span",
|
closeTag: "span",
|
||||||
title: I18n.t("topic_statuses.solved.help"),
|
title: i18n("topic_statuses.solved.help"),
|
||||||
icon: "far-check-square",
|
icon: "far-check-square",
|
||||||
key: "solved",
|
key: "solved",
|
||||||
});
|
});
|
||||||
|
@ -225,7 +225,7 @@ export default {
|
||||||
results.push({
|
results.push({
|
||||||
openTag: "span",
|
openTag: "span",
|
||||||
closeTag: "span",
|
closeTag: "span",
|
||||||
title: I18n.t("solved.has_no_accepted_answer"),
|
title: i18n("solved.has_no_accepted_answer"),
|
||||||
icon: "far-square",
|
icon: "far-square",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -246,11 +246,11 @@ export default {
|
||||||
api.addAdvancedSearchOptions({
|
api.addAdvancedSearchOptions({
|
||||||
statusOptions: [
|
statusOptions: [
|
||||||
{
|
{
|
||||||
name: I18n.t("search.advanced.statuses.solved"),
|
name: i18n("search.advanced.statuses.solved"),
|
||||||
value: "solved",
|
value: "solved",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: I18n.t("search.advanced.statuses.unsolved"),
|
name: i18n("search.advanced.statuses.unsolved"),
|
||||||
value: "unsolved",
|
value: "unsolved",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import UserActivityStreamRoute from "discourse/routes/user-activity-stream";
|
import UserActivityStreamRoute from "discourse/routes/user-activity-stream";
|
||||||
import I18n from "I18n";
|
import { i18n } from "discourse-i18n";
|
||||||
|
|
||||||
export default class UserActivitySolved extends UserActivityStreamRoute {
|
export default class UserActivitySolved extends UserActivityStreamRoute {
|
||||||
userActionType = 15;
|
userActionType = 15;
|
||||||
|
@ -10,10 +10,10 @@ export default class UserActivitySolved extends UserActivityStreamRoute {
|
||||||
|
|
||||||
let title, body;
|
let title, body;
|
||||||
if (this.isCurrentUser(user)) {
|
if (this.isCurrentUser(user)) {
|
||||||
title = I18n.t("solved.no_solved_topics_title");
|
title = i18n("solved.no_solved_topics_title");
|
||||||
body = I18n.t("solved.no_solved_topics_body");
|
body = i18n("solved.no_solved_topics_body");
|
||||||
} else {
|
} else {
|
||||||
title = I18n.t("solved.no_solved_topics_title_others", {
|
title = i18n("solved.no_solved_topics_title_others", {
|
||||||
username: user.username,
|
username: user.username,
|
||||||
});
|
});
|
||||||
body = "";
|
body = "";
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
import { click, visit } from "@ember/test-helpers";
|
import { click, visit } from "@ember/test-helpers";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import I18n from "I18n";
|
import { i18n } from "discourse-i18n";
|
||||||
import { postStreamWithAcceptedAnswerExcerpt } from "../helpers/discourse-solved-helpers";
|
import { postStreamWithAcceptedAnswerExcerpt } from "../helpers/discourse-solved-helpers";
|
||||||
|
|
||||||
acceptance(
|
acceptance(
|
||||||
"Discourse Solved | Post Menu | Accept and Unaccept",
|
"Discourse Solved | Post Menu | Accept and Unaccept",
|
||||||
function (needs) {
|
function (needs) {
|
||||||
needs.user({
|
needs.user({ admin: true });
|
||||||
admin: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
needs.settings({
|
needs.settings({
|
||||||
glimmer_post_menu_mode: "enabled",
|
glimmer_post_menu_mode: "enabled",
|
||||||
|
@ -23,9 +21,9 @@ acceptance(
|
||||||
helper.response({ success: "OK" })
|
helper.response({ success: "OK" })
|
||||||
);
|
);
|
||||||
|
|
||||||
server.get("/t/12.json", () => {
|
server.get("/t/12.json", () =>
|
||||||
return helper.response(postStreamWithAcceptedAnswerExcerpt(null));
|
helper.response(postStreamWithAcceptedAnswerExcerpt(null))
|
||||||
});
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("accepting and unaccepting a post works", async function (assert) {
|
test("accepting and unaccepting a post works", async function (assert) {
|
||||||
|
@ -34,7 +32,7 @@ acceptance(
|
||||||
assert
|
assert
|
||||||
.dom("#post_2 .post-action-menu__solved-accepted")
|
.dom("#post_2 .post-action-menu__solved-accepted")
|
||||||
.exists("Unaccept button is visible")
|
.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");
|
await click("#post_2 .post-action-menu__solved-accepted");
|
||||||
|
|
||||||
|
@ -46,7 +44,7 @@ acceptance(
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom("#post_2 .post-action-menu__solved-accepted")
|
.dom("#post_2 .post-action-menu__solved-accepted")
|
||||||
.exists("Unccept button is visible again");
|
.exists("Unaccept button is visible again");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,53 +1,45 @@
|
||||||
import { click, fillIn, visit } from "@ember/test-helpers";
|
import { click, fillIn, visit } from "@ember/test-helpers";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import { fixturesByUrl } from "discourse/tests/helpers/create-pretender";
|
import pretender, {
|
||||||
import { acceptance, queryAll } from "discourse/tests/helpers/qunit-helpers";
|
fixturesByUrl,
|
||||||
|
response,
|
||||||
|
} from "discourse/tests/helpers/create-pretender";
|
||||||
|
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import { cloneJSON } from "discourse-common/lib/object";
|
import { cloneJSON } from "discourse-common/lib/object";
|
||||||
import { postStreamWithAcceptedAnswerExcerpt } from "../helpers/discourse-solved-helpers";
|
import { postStreamWithAcceptedAnswerExcerpt } from "../helpers/discourse-solved-helpers";
|
||||||
|
|
||||||
acceptance("Discourse Solved Plugin", function (needs) {
|
acceptance("Discourse Solved Plugin", function (needs) {
|
||||||
needs.user();
|
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) {
|
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
|
|
||||||
);
|
);
|
||||||
|
|
||||||
await visit("/t/without-excerpt/12");
|
pretender.get("/t/12.json", () =>
|
||||||
|
response(postStreamWithAcceptedAnswerExcerpt(null))
|
||||||
|
);
|
||||||
|
|
||||||
assert.notStrictEqual(queryAll(".quote blockquote").length, 1);
|
await visit("/t/with-excerpt/11");
|
||||||
assert.strictEqual(queryAll(".quote .title.title-only").length, 1);
|
assert.dom(".quote blockquote").hasText("this is an excerpt");
|
||||||
|
|
||||||
|
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) {
|
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 fillIn(".search-query", "discourse");
|
||||||
await click(".search-cta");
|
await click(".search-cta");
|
||||||
|
|
||||||
assert.strictEqual(queryAll(".fps-topic").length, 1, "has one post");
|
assert.dom(".fps-topic").exists({ count: 1 }, "has one post");
|
||||||
|
assert.dom(".topic-status .solved").exists("shows the right icon");
|
||||||
assert.ok(queryAll(".topic-status .solved").length, "shows the right icon");
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
import { click, visit } from "@ember/test-helpers";
|
import { click, visit } from "@ember/test-helpers";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import I18n from "I18n";
|
import { i18n } from "discourse-i18n";
|
||||||
import { postStreamWithAcceptedAnswerExcerpt } from "../helpers/discourse-solved-helpers";
|
import { postStreamWithAcceptedAnswerExcerpt } from "../helpers/discourse-solved-helpers";
|
||||||
|
|
||||||
acceptance(
|
acceptance(
|
||||||
"Discourse Solved | Widget Post Menu |Accept and Unaccept",
|
"Discourse Solved | Widget Post Menu |Accept and Unaccept",
|
||||||
function (needs) {
|
function (needs) {
|
||||||
needs.user({
|
needs.user({ admin: true });
|
||||||
admin: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
needs.settings({
|
needs.settings({
|
||||||
glimmer_post_menu_mode: "disabled",
|
glimmer_post_menu_mode: "disabled",
|
||||||
|
@ -23,9 +21,9 @@ acceptance(
|
||||||
helper.response({ success: "OK" })
|
helper.response({ success: "OK" })
|
||||||
);
|
);
|
||||||
|
|
||||||
server.get("/t/12.json", () => {
|
server.get("/t/12.json", () =>
|
||||||
return helper.response(postStreamWithAcceptedAnswerExcerpt(null));
|
helper.response(postStreamWithAcceptedAnswerExcerpt(null))
|
||||||
});
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("accepting and unaccepting a post works", async function (assert) {
|
test("accepting and unaccepting a post works", async function (assert) {
|
||||||
|
@ -34,7 +32,7 @@ acceptance(
|
||||||
assert
|
assert
|
||||||
.dom("#post_2 .accepted")
|
.dom("#post_2 .accepted")
|
||||||
.exists("Unaccept button is visible")
|
.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");
|
await click("#post_2 .accepted");
|
||||||
|
|
||||||
|
@ -42,7 +40,9 @@ acceptance(
|
||||||
|
|
||||||
await click("#post_2 .unaccepted");
|
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");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,46 +1,39 @@
|
||||||
import { visit } from "@ember/test-helpers";
|
import { visit } from "@ember/test-helpers";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import { acceptance, query } from "discourse/tests/helpers/qunit-helpers";
|
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||||
import I18n from "I18n";
|
import { i18n } from "discourse-i18n";
|
||||||
|
|
||||||
acceptance(
|
acceptance(
|
||||||
"Discourse Solved Plugin | activity/solved | empty state",
|
"Discourse Solved Plugin | activity/solved | empty state",
|
||||||
function (needs) {
|
function (needs) {
|
||||||
const currentUser = "eviltrout";
|
|
||||||
const anotherUser = "charlie";
|
|
||||||
needs.user();
|
needs.user();
|
||||||
|
|
||||||
needs.pretender((server, helper) => {
|
needs.pretender((server, helper) => {
|
||||||
const emptyResponse = { user_actions: [] };
|
server.get("/user_actions.json", () =>
|
||||||
|
helper.response({ user_actions: [] })
|
||||||
server.get("/user_actions.json", () => {
|
);
|
||||||
return helper.response(emptyResponse);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("When looking at own activity", async function (assert) {
|
test("When looking at own activity", async function (assert) {
|
||||||
await visit(`/u/${currentUser}/activity/solved`);
|
await visit(`/u/eviltrout/activity/solved`);
|
||||||
|
|
||||||
assert.equal(
|
assert
|
||||||
query("div.empty-state span.empty-state-title").innerText,
|
.dom("div.empty-state span.empty-state-title")
|
||||||
I18n.t("solved.no_solved_topics_title")
|
.hasText(i18n("solved.no_solved_topics_title"));
|
||||||
);
|
assert
|
||||||
assert.equal(
|
.dom("div.empty-state div.empty-state-body")
|
||||||
query("div.empty-state div.empty-state-body").innerText,
|
.hasText(i18n("solved.no_solved_topics_body"));
|
||||||
I18n.t("solved.no_solved_topics_body")
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("When looking at another user's activity", async function (assert) {
|
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(
|
assert.dom("div.empty-state span.empty-state-title").hasText(
|
||||||
query("div.empty-state span.empty-state-title").innerText,
|
i18n("solved.no_solved_topics_title_others", {
|
||||||
I18n.t("solved.no_solved_topics_title_others", {
|
username: "charlie",
|
||||||
username: anotherUser,
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert.equal(query("div.empty-state div.empty-state-body").innerText, "");
|
assert.dom("div.empty-state div.empty-state-body").hasNoText();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue