mirror of
https://github.com/discourse/discourse.git
synced 2025-02-09 12:54:56 +00:00
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:
parent
c9ebc75a1d
commit
997c839626
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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>
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,9 +5,13 @@ import discourseComputed from "discourse-common/utils/decorators";
|
|||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
classNames: ["controls"],
|
classNames: ["controls"],
|
||||||
|
|
||||||
@discourseComputed("labelKey")
|
@discourseComputed("labelKey", "labelCount")
|
||||||
label(labelKey) {
|
label(labelKey, labelCount) {
|
||||||
return I18n.t(labelKey);
|
if (labelCount) {
|
||||||
|
return I18n.t(labelKey, { count: labelCount });
|
||||||
|
} else {
|
||||||
|
return I18n.t(labelKey);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
change() {
|
change() {
|
||||||
|
@ -37,7 +37,7 @@ export default Component.extend({
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return topicCount > 5;
|
return this.currentUser?.new_new_view_enabled || topicCount > 5;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("selectedTopics.length")
|
@discourseComputed("selectedTopics.length")
|
||||||
@ -52,7 +52,7 @@ export default Component.extend({
|
|||||||
|
|
||||||
@discourseComputed("selectedTopics.length")
|
@discourseComputed("selectedTopics.length")
|
||||||
dismissNewLabel(selectedTopicCount) {
|
dismissNewLabel(selectedTopicCount) {
|
||||||
if (this.currentUser.new_new_view_enabled) {
|
if (this.currentUser?.new_new_view_enabled) {
|
||||||
return I18n.t("topics.bulk.dismiss_button");
|
return I18n.t("topics.bulk.dismiss_button");
|
||||||
} else if (selectedTopicCount === 0) {
|
} else if (selectedTopicCount === 0) {
|
||||||
return I18n.t("topics.bulk.dismiss_new");
|
return I18n.t("topics.bulk.dismiss_new");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Mixin from "@ember/object/mixin";
|
import Mixin from "@ember/object/mixin";
|
||||||
import { inject as service } from "@ember/service";
|
import { inject as service } from "@ember/service";
|
||||||
import { action } from "@ember/object";
|
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({
|
export default Mixin.create({
|
||||||
modal: service(),
|
modal: service(),
|
||||||
@ -13,8 +13,10 @@ export default Mixin.create({
|
|||||||
return this.callResetNew();
|
return this.callResetNew();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.modal.show(DismissNewModal, {
|
this.modal.show(DismissNew, {
|
||||||
model: {
|
model: {
|
||||||
|
selectedTopics: this.selected,
|
||||||
|
subset: this.model.listParams?.subset,
|
||||||
dismissCallback: ({ dismissPosts, dismissTopics, untrack }) => {
|
dismissCallback: ({ dismissPosts, dismissTopics, untrack }) => {
|
||||||
this.callResetNew(dismissPosts, dismissTopics, untrack);
|
this.callResetNew(dismissPosts, dismissTopics, untrack);
|
||||||
},
|
},
|
||||||
|
@ -732,22 +732,23 @@ const TopicTrackingState = EmberObject.extend({
|
|||||||
|
|
||||||
lookupCount({ type, category, tagId, noSubcategories, customFilterFn } = {}) {
|
lookupCount({ type, category, tagId, noSubcategories, customFilterFn } = {}) {
|
||||||
if (type === "latest") {
|
if (type === "latest") {
|
||||||
return (
|
let count = this.lookupCount({
|
||||||
this.lookupCount({
|
type: "new",
|
||||||
type: "new",
|
category,
|
||||||
category,
|
tagId,
|
||||||
tagId,
|
noSubcategories,
|
||||||
noSubcategories,
|
customFilterFn,
|
||||||
customFilterFn,
|
});
|
||||||
}) +
|
if (!this.currentUser?.new_new_view_enabled) {
|
||||||
this.lookupCount({
|
count += this.lookupCount({
|
||||||
type: "unread",
|
type: "unread",
|
||||||
category,
|
category,
|
||||||
tagId,
|
tagId,
|
||||||
noSubcategories,
|
noSubcategories,
|
||||||
customFilterFn,
|
customFilterFn,
|
||||||
})
|
});
|
||||||
);
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
let categoryId = category ? get(category, "id") : null;
|
let categoryId = category ? get(category, "id") : null;
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
@ -2848,7 +2848,14 @@ en:
|
|||||||
dismiss_new_modal:
|
dismiss_new_modal:
|
||||||
title: "Dismiss new"
|
title: "Dismiss new"
|
||||||
topics: "Dismiss new topics"
|
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"
|
untrack: "Stop tracking these topics so they stop appearing in my new list"
|
||||||
dismiss_new_with_selected:
|
dismiss_new_with_selected:
|
||||||
one: "Dismiss New (%{count})"
|
one: "Dismiss New (%{count})"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user