FEATURE: display count of topics being dismissed in dialog (#23288)

Previous to this change it was unclear if all new would be dismissed or just
some of them

Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
This commit is contained in:
Sam 2023-08-28 19:46:38 +10:00 committed by GitHub
parent c9ebc75a1d
commit 997c839626
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 297 additions and 71 deletions

View File

@ -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 {
<template>
<DModal
@closeModal={{@closeModal}}
@title={{this.modalTitle}}
@inline={{@inline}}
>
<:body>
<p>
{{#if this.showDismissNewTopics}}
<PreferenceCheckbox
@labelKey={{this.dismissNewTopicsLabel}}
@labelCount={{this.countNewTopics}}
@checked={{this.dismissTopics}}
@class="dismiss-topics"
/>
{{/if}}
{{#if this.showDismissNewReplies}}
<PreferenceCheckbox
@labelKey={{this.dismissNewRepliesLabel}}
@labelCount={{this.countNewReplies}}
@checked={{this.dismissPosts}}
@class="dismiss-posts"
/>
{{/if}}
<PreferenceCheckbox
@labelKey="topics.bulk.dismiss_new_modal.untrack"
@checked={{this.untrack}}
@class="untrack"
/>
</p>
</:body>
<:footer>
<DButton
id="dismiss-read-confirm"
@action={{this.dismissed}}
@icon="check"
@label="topics.bulk.dismiss"
class="btn-primary"
/>
</:footer>
</DModal>
</template>
@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();
}
}

View File

@ -1,33 +0,0 @@
<DModal
@closeModal={{@closeModal}}
@title={{i18n "topics.bulk.dismiss_new_modal.title"}}
>
<:body>
<p>
<PreferenceCheckbox
@labelKey="topics.bulk.dismiss_new_modal.topics"
@checked={{this.dismissTopics}}
@class="dismiss-topics"
/>
<PreferenceCheckbox
@labelKey="topics.bulk.dismiss_new_modal.posts"
@checked={{this.dismissPosts}}
@class="dismiss-posts"
/>
<PreferenceCheckbox
@labelKey="topics.bulk.dismiss_new_modal.untrack"
@checked={{this.untrack}}
@class="untrack"
/>
</p>
</:body>
<:footer>
<DButton
id="dismiss-read-confirm"
@action={{this.dismissed}}
@icon="check"
@label="topics.bulk.dismiss"
class="btn-primary"
/>
</:footer>
</DModal>

View File

@ -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();
}
}

View File

@ -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() {

View File

@ -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");

View File

@ -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);
},

View File

@ -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;

View File

@ -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`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
);
assert
.dom("#discourse-modal-title")
.hasText(I18n.t("topics.bulk.dismiss_new_modal.title"));
});
test("default state", async function (assert) {
await render(
hbs`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
);
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`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
);
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`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
);
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`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
);
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`<Modal::DismissNew @inline={{true}} @model={{this.model}} />`
);
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`<Modal::DismissNew @closeModal={{this.noop}} @inline={{true}} @model={{this.model}} />`
);
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);
});
});

View File

@ -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})"