diff --git a/app/assets/javascripts/discourse/app/components/modal/dismiss-new.gjs b/app/assets/javascripts/discourse/app/components/modal/dismiss-new.gjs new file mode 100644 index 00000000000..287c5e2d76a --- /dev/null +++ b/app/assets/javascripts/discourse/app/components/modal/dismiss-new.gjs @@ -0,0 +1,144 @@ +import Component from "@glimmer/component"; +import { action } from "@ember/object"; +import DModal from "discourse/components/d-modal"; +import DButton from "discourse/components/d-button"; +import PreferenceCheckbox from "discourse/components/preference-checkbox"; +import I18n from "I18n"; +import { tracked } from "@glimmer/tracking"; + +const REPLIES_SUBSET = "replies"; +const TOPICS_SUBSET = "topics"; + +export default class DismissNew extends Component { + + + <:body> + + {{#if this.showDismissNewTopics}} + + {{/if}} + {{#if this.showDismissNewReplies}} + + {{/if}} + + + + <:footer> + + + + + + @tracked untrack = false; + @tracked dismissTopics = true; + @tracked dismissPosts = true; + + constructor() { + super(...arguments); + + if (this.args.model.subset === "replies") { + this.dismissTopics = false; + } + if (this.args.model.subset === "topics") { + this.dismissPosts = false; + } + } + + get partialDismiss() { + return (this.selectedTopics?.length || 0) !== 0; + } + + get dismissNewTopicsLabel() { + return ( + "topics.bulk.dismiss_new_modal.topics" + + (this.partialDismiss ? "_with_count" : "") + ); + } + + get dismissNewRepliesLabel() { + return ( + "topics.bulk.dismiss_new_modal.replies" + + (this.partialDismiss ? "_with_count" : "") + ); + } + + get showDismissNewTopics() { + if (this.partialDismiss) { + return this.countNewTopics > 0; + } + + return this.subset === TOPICS_SUBSET || !this.subset; + } + + get showDismissNewReplies() { + if (this.partialDismiss) { + return this.countNewReplies > 0; + } + + return this.subset === REPLIES_SUBSET || !this.subset; + } + + get countNewTopics() { + const topics = this.selectedTopics; + if (!topics?.length) { + return 0; + } + + return topics.filter((topic) => !topic.unread_posts).length; + } + + get countNewReplies() { + const topics = this.selectedTopics; + if (!topics?.length) { + return 0; + } + return topics.filter((topic) => topic.unread_posts).length; + } + + get subset() { + return this.args.model.subset; + } + + get selectedTopics() { + return this.args.model.selectedTopics; + } + + get modalTitle() { + return I18n.t("topics.bulk.dismiss_new_modal.title"); + } + + @action + dismissed() { + this.args.model.dismissCallback({ + dismissTopics: this.dismissTopics, + dismissPosts: this.dismissPosts, + untrack: this.untrack, + }); + + this.args.closeModal(); + } +} diff --git a/app/assets/javascripts/discourse/app/components/modal/dismiss-new.hbs b/app/assets/javascripts/discourse/app/components/modal/dismiss-new.hbs deleted file mode 100644 index 9563e469f63..00000000000 --- a/app/assets/javascripts/discourse/app/components/modal/dismiss-new.hbs +++ /dev/null @@ -1,33 +0,0 @@ - - <:body> - - - - - - - <:footer> - - - \ No newline at end of file diff --git a/app/assets/javascripts/discourse/app/components/modal/dismiss-new.js b/app/assets/javascripts/discourse/app/components/modal/dismiss-new.js deleted file mode 100644 index b9a161f53b4..00000000000 --- a/app/assets/javascripts/discourse/app/components/modal/dismiss-new.js +++ /dev/null @@ -1,19 +0,0 @@ -import Component from "@glimmer/component"; -import { action } from "@ember/object"; - -export default class DismissNew extends Component { - dismissTopics = true; - dismissPosts = true; - untrack = false; - - @action - dismissed() { - this.args.model.dismissCallback({ - dismissTopics: this.dismissTopics, - dismissPosts: this.dismissPosts, - untrack: this.untrack, - }); - - this.args.closeModal(); - } -} diff --git a/app/assets/javascripts/discourse/app/components/preference-checkbox.js b/app/assets/javascripts/discourse/app/components/preference-checkbox.js index d138f58e19c..c89094deefc 100644 --- a/app/assets/javascripts/discourse/app/components/preference-checkbox.js +++ b/app/assets/javascripts/discourse/app/components/preference-checkbox.js @@ -5,9 +5,13 @@ import discourseComputed from "discourse-common/utils/decorators"; export default Component.extend({ classNames: ["controls"], - @discourseComputed("labelKey") - label(labelKey) { - return I18n.t(labelKey); + @discourseComputed("labelKey", "labelCount") + label(labelKey, labelCount) { + if (labelCount) { + return I18n.t(labelKey, { count: labelCount }); + } else { + return I18n.t(labelKey); + } }, change() { diff --git a/app/assets/javascripts/discourse/app/components/topic-dismiss-buttons.js b/app/assets/javascripts/discourse/app/components/topic-dismiss-buttons.js index 3b5e4603ea9..23e1c70aac4 100644 --- a/app/assets/javascripts/discourse/app/components/topic-dismiss-buttons.js +++ b/app/assets/javascripts/discourse/app/components/topic-dismiss-buttons.js @@ -37,7 +37,7 @@ export default Component.extend({ return true; } - return topicCount > 5; + return this.currentUser?.new_new_view_enabled || topicCount > 5; }, @discourseComputed("selectedTopics.length") @@ -52,7 +52,7 @@ export default Component.extend({ @discourseComputed("selectedTopics.length") dismissNewLabel(selectedTopicCount) { - if (this.currentUser.new_new_view_enabled) { + if (this.currentUser?.new_new_view_enabled) { return I18n.t("topics.bulk.dismiss_button"); } else if (selectedTopicCount === 0) { return I18n.t("topics.bulk.dismiss_new"); diff --git a/app/assets/javascripts/discourse/app/mixins/dismiss-topics.js b/app/assets/javascripts/discourse/app/mixins/dismiss-topics.js index 2d99c5c9d61..23d33e94e9a 100644 --- a/app/assets/javascripts/discourse/app/mixins/dismiss-topics.js +++ b/app/assets/javascripts/discourse/app/mixins/dismiss-topics.js @@ -1,7 +1,7 @@ import Mixin from "@ember/object/mixin"; import { inject as service } from "@ember/service"; import { action } from "@ember/object"; -import DismissNewModal from "discourse/components/modal/dismiss-new"; +import DismissNew from "discourse/components/modal/dismiss-new"; export default Mixin.create({ modal: service(), @@ -13,8 +13,10 @@ export default Mixin.create({ return this.callResetNew(); } - this.modal.show(DismissNewModal, { + this.modal.show(DismissNew, { model: { + selectedTopics: this.selected, + subset: this.model.listParams?.subset, dismissCallback: ({ dismissPosts, dismissTopics, untrack }) => { this.callResetNew(dismissPosts, dismissTopics, untrack); }, diff --git a/app/assets/javascripts/discourse/app/models/topic-tracking-state.js b/app/assets/javascripts/discourse/app/models/topic-tracking-state.js index b546c6d65f0..ad5798e365c 100644 --- a/app/assets/javascripts/discourse/app/models/topic-tracking-state.js +++ b/app/assets/javascripts/discourse/app/models/topic-tracking-state.js @@ -732,22 +732,23 @@ const TopicTrackingState = EmberObject.extend({ lookupCount({ type, category, tagId, noSubcategories, customFilterFn } = {}) { if (type === "latest") { - return ( - this.lookupCount({ - type: "new", - category, - tagId, - noSubcategories, - customFilterFn, - }) + - this.lookupCount({ + let count = this.lookupCount({ + type: "new", + category, + tagId, + noSubcategories, + customFilterFn, + }); + if (!this.currentUser?.new_new_view_enabled) { + count += this.lookupCount({ type: "unread", category, tagId, noSubcategories, customFilterFn, - }) - ); + }); + } + return count; } let categoryId = category ? get(category, "id") : null; diff --git a/app/assets/javascripts/discourse/tests/integration/components/dismiss-new-test.js b/app/assets/javascripts/discourse/tests/integration/components/dismiss-new-test.js new file mode 100644 index 00000000000..743a6084f5d --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/dismiss-new-test.js @@ -0,0 +1,120 @@ +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { click, render } from "@ember/test-helpers"; +import { hbs } from "ember-cli-htmlbars"; +import I18n from "I18n"; + +module("Integration | Component | modal/dismiss-new", function (hooks) { + setupRenderingTest(hooks); + + hooks.beforeEach(function () { + this.model = { selectedTopics: [] }; + }); + + test("modal title", async function (assert) { + await render( + hbs`` + ); + + assert + .dom("#discourse-modal-title") + .hasText(I18n.t("topics.bulk.dismiss_new_modal.title")); + }); + + test("default state", async function (assert) { + await render( + hbs`` + ); + + assert.dom(".dismiss-topics input").isChecked(); + assert.dom(".dismiss-posts input").isChecked(); + assert.dom(".untrack input").isNotChecked(); + }); + + test("one new selected topic", async function (assert) { + this.model.selectedTopics.push({ + id: 1, + title: "Topic 1", + unread_posts: false, + }); + + await render( + hbs`` + ); + + assert.dom(".dismiss-posts").doesNotExist(); + assert + .dom(".dismiss-topics") + .hasText( + I18n.t("topics.bulk.dismiss_new_modal.topics_with_count", { count: 1 }) + ); + }); + + test("one new unread in selected topic", async function (assert) { + this.model.selectedTopics.push({ + id: 1, + title: "Topic 1", + unread_posts: true, + }); + + await render( + hbs`` + ); + + assert.dom(".dismiss-topics").doesNotExist(); + assert + .dom(".dismiss-posts") + .hasText( + I18n.t("topics.bulk.dismiss_new_modal.replies_with_count", { count: 1 }) + ); + }); + + test("no selected topics with topics subset", async function (assert) { + this.model.subset = "topics"; + + await render( + hbs`` + ); + + assert.dom(".dismiss-posts").doesNotExist(); + assert + .dom(".dismiss-topics") + .hasText(I18n.t("topics.bulk.dismiss_new_modal.topics")); + }); + + test("no selected topics with replies subset", async function (assert) { + this.model.subset = "replies"; + + await render( + hbs`` + ); + + assert.dom(".dismiss-topics").doesNotExist(); + assert + .dom(".dismiss-posts") + .hasText(I18n.t("topics.bulk.dismiss_new_modal.replies")); + }); + + test("dismissed", async function (assert) { + let state; + + this.model.dismissCallback = (newState) => { + state = newState; + }; + + this.noop = () => {}; + + await render( + hbs`` + ); + + await click(".dismiss-topics [type='checkbox']"); + await click(".dismiss-posts [type='checkbox']"); + await click(".untrack [type='checkbox']"); + await click("#dismiss-read-confirm"); + + assert.strictEqual(state.dismissTopics, false); + assert.strictEqual(state.dismissPosts, false); + assert.strictEqual(state.untrack, true); + }); +}); diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index d03c4c2eb53..2a0716e392d 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -2848,7 +2848,14 @@ en: dismiss_new_modal: title: "Dismiss new" topics: "Dismiss new topics" - posts: "Dismiss new posts" + posts: "Dismiss new replies" + topics_with_count: + one: "Dismiss %{count} new topic" + other: "Dismiss %{count} new topics" + replies_with_count: + one: "Dismiss %{count} new reply" + other: "Dismiss %{count} new replies" + replies: "Dismiss new replies" untrack: "Stop tracking these topics so they stop appearing in my new list" dismiss_new_with_selected: one: "Dismiss New (%{count})"
+ {{#if this.showDismissNewTopics}} + + {{/if}} + {{#if this.showDismissNewReplies}} + + {{/if}} + +
- - - -