FEATURE: Add newly loaded topics to bulk-select automatically if Select All is on (#12026)

Currently it's very tedious to bulk select hundreds of topics in a topic list -- each time a new batch of topics is loaded you have to scroll all the way to the top to click the `Select All` button and scroll back down to load the next batch, or you have to tick each topic individually.

This commit should make that process a lot easier because we will now remember if the `Select All` button was clicked and so whenever a new batch of topics is loaded, they'll automatically be selected.

Meta topic: https://meta.discourse.org/t/add-select-all-controls-at-the-bottom-of-the-list/178020/2?u=osama.
This commit is contained in:
Osama Sayegh 2021-03-05 17:16:03 +03:00 committed by GitHub
parent ce34a46669
commit 5d95b68727
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 155 additions and 5 deletions

View File

@ -38,9 +38,17 @@ const DiscoveryTopicsListComponent = Component.extend(UrlRefresh, LoadMore, {
actions: {
loadMore() {
this.documentTitle.updateContextCount(0);
this.model.loadMore().then((hasMoreResults) => {
this.model.loadMore().then(({ moreTopicsUrl, newTopics } = {}) => {
if (
newTopics &&
newTopics.length &&
this.autoAddTopicsToBulkSelect &&
this.bulkSelectEnabled
) {
this.addTopicsToBulkSelect(newTopics);
}
schedule("afterRender", () => this.saveScrollPosition());
if (hasMoreResults && $(window).height() >= $(document).height()) {
if (moreTopicsUrl && $(window).height() >= $(document).height()) {
this.send("loadMore");
}
});

View File

@ -54,6 +54,11 @@ export default Component.extend({
"topicListItemContents",
template(this, RUNTIME_OPTIONS).htmlSafe()
);
schedule("afterRender", () => {
if (this.selected && this.selected.includes(this.topic)) {
this.element.querySelector("input.bulk-select").checked = true;
}
});
}
},

View File

@ -178,10 +178,12 @@ export default Component.extend(LoadMore, {
});
onClick("button.bulk-select-all", function () {
this.updateAutoAddTopicsToBulkSelect(true);
$("input.bulk-select:not(:checked)").click();
});
onClick("button.bulk-clear-all", function () {
this.updateAutoAddTopicsToBulkSelect(false);
$("input.bulk-select:checked").click();
});

View File

@ -9,6 +9,7 @@ export default Mixin.create({
router: service(),
bulkSelectEnabled: false,
autoAddTopicsToBulkSelect: false,
selected: null,
canBulkSelect: alias("currentUser.staff"),
@ -55,5 +56,13 @@ export default Mixin.create({
);
});
},
updateAutoAddTopicsToBulkSelect(newVal) {
this.set("autoAddTopicsToBulkSelect", newVal);
},
addTopicsToBulkSelect(topics) {
this.selected.pushObjects(topics);
},
},
});

View File

@ -108,7 +108,7 @@ const TopicList = RestModel.extend({
});
Session.currentProp("topicList", this);
return this.more_topics_url;
return { moreTopicsUrl: this.more_topics_url, newTopics };
}
});
} else {

View File

@ -36,7 +36,14 @@
{{bulk-select-button selected=selected action=(action "refresh") category=category}}
{{#discovery-topics-list model=model refresh=(action "refresh") incomingCount=topicTrackingState.incomingCount as |discoveryTopicList|}}
{{#discovery-topics-list
model=model
refresh=(action "refresh")
incomingCount=topicTrackingState.incomingCount
autoAddTopicsToBulkSelect=autoAddTopicsToBulkSelect
bulkSelectEnabled=bulkSelectEnabled
addTopicsToBulkSelect=(action "addTopicsToBulkSelect")
as |discoveryTopicList|}}
{{#if top}}
<div class="top-lists">
{{period-chooser period=period action=(action "changePeriod") fullDay=false}}
@ -61,6 +68,7 @@
canBulkSelect=canBulkSelect
changeSort=(route-action "changeSort")
toggleBulkSelect=(action "toggleBulkSelect")
updateAutoAddTopicsToBulkSelect=(action "updateAutoAddTopicsToBulkSelect")
hideCategory=model.hideCategory
order=order
ascending=ascending

View File

@ -38,13 +38,20 @@
<div id="list-area">
{{#unless loading}}
{{#if list.topics}}
{{#discovery-topics-list model=list refresh=(action "refresh") as |discoveryTopicList|}}
{{#discovery-topics-list
model=list
refresh=(action "refresh")
autoAddTopicsToBulkSelect=autoAddTopicsToBulkSelect
bulkSelectEnabled=bulkSelectEnabled
addTopicsToBulkSelect=(action "addTopicsToBulkSelect")
as |discoveryTopicList|}}
{{bulk-select-button selected=selected action=(action "refresh") category=category}}
{{topic-list
topics=list.topics
canBulkSelect=canBulkSelect
toggleBulkSelect=(action "toggleBulkSelect")
bulkSelectEnabled=bulkSelectEnabled
updateAutoAddTopicsToBulkSelect=(action "updateAutoAddTopicsToBulkSelect")
selected=selected
showPosters=true
order=order

View File

@ -0,0 +1,42 @@
import componentTest, {
setupRenderingTest,
} from "discourse/tests/helpers/component-test";
import {
discourseModule,
queryAll,
} from "discourse/tests/helpers/qunit-helpers";
import Topic from "discourse/models/topic";
import hbs from "htmlbars-inline-precompile";
discourseModule("Integration | Component | topic-list-item", function (hooks) {
setupRenderingTest(hooks);
componentTest("checkbox is rendered checked if topic is in selected array", {
template: hbs`{{topic-list-item
topic=topic
bulkSelectEnabled=true
selected=selected
}}
{{topic-list-item
topic=topic2
bulkSelectEnabled=true
selected=selected
}}`,
beforeEach() {
const topic = Topic.create({ id: 24234 });
const topic2 = Topic.create({ id: 24235 });
this.setProperties({
topic,
topic2,
selected: [topic],
});
},
async test(assert) {
const checkboxes = queryAll("input.bulk-select");
assert.ok(checkboxes[0].checked);
assert.ok(!checkboxes[1].checked);
},
});
});

View File

@ -0,0 +1,69 @@
import { click } from "@ember/test-helpers";
import componentTest, {
setupRenderingTest,
} from "discourse/tests/helpers/component-test";
import { discourseModule } from "discourse/tests/helpers/qunit-helpers";
import Topic from "discourse/models/topic";
import hbs from "htmlbars-inline-precompile";
discourseModule("Integration | Component | topic-list", function (hooks) {
setupRenderingTest(hooks);
componentTest("bulk select", {
template: hbs`{{topic-list
canBulkSelect=true
toggleBulkSelect=toggleBulkSelect
bulkSelectEnabled=bulkSelectEnabled
autoAddTopicsToBulkSelect=autoAddTopicsToBulkSelect
updateAutoAddTopicsToBulkSelect=updateAutoAddTopicsToBulkSelect
topics=topics
selected=selected
}}`,
beforeEach() {
const topic = Topic.create({ id: 24234 });
const topic2 = Topic.create({ id: 24235 });
this.setProperties({
topics: [topic, topic2],
selected: [],
bulkSelectEnabled: false,
autoAddTopicsToBulkSelect: false,
toggleBulkSelect() {
this.toggleProperty("bulkSelectEnabled");
},
updateAutoAddTopicsToBulkSelect(newVal) {
this.set("autoAddTopicsToBulkSelect", newVal);
},
});
},
async test(assert) {
await click("button.bulk-select");
assert.ok(this.bulkSelectEnabled, "bulk select is enabled");
await click("button.bulk-select-all");
assert.equal(
this.selected.length,
2,
"clicking Select All selects all loaded topics"
);
assert.ok(
this.autoAddTopicsToBulkSelect,
"clicking Select All turns on the autoAddTopicsToBulkSelect flag"
);
await click("button.bulk-clear-all");
assert.equal(
this.selected.length,
0,
"clicking Clear All deselects all topics"
);
assert.ok(
!this.autoAddTopicsToBulkSelect,
"clicking Clear All turns off the autoAddTopicsToBulkSelect flag"
);
},
});
});