mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 08:57:10 -06:00
FEATURE: Use new topic bulk actions menu for all sites (#28003)
This commit promotes the new topic bulk action
menu introduced in 89883b2f51
to the main method of bulk selecting and performing
actions on topics. The site setting flag gating this
feature is deleted, and the old bulk select code is
deleted as well.
The new modal shows a loading spinner while operations
are taking place, allows selecting the action from a dropdown
instead of having a 2-step modal flow,
and also supports additional options for some operations, e.g.
allowing Close silently.
This commit is contained in:
parent
a027ec4663
commit
0b413e2aa1
@ -1,44 +0,0 @@
|
||||
<DModal
|
||||
@title={{i18n "topics.bulk.actions"}}
|
||||
@closeModal={{@closeModal}}
|
||||
class="topic-bulk-actions-modal -large"
|
||||
>
|
||||
<p>
|
||||
{{html-safe (i18n "topics.bulk.selected" count=@model.topics.length)}}
|
||||
</p>
|
||||
|
||||
{{#if this.showProgress}}
|
||||
<p>
|
||||
{{html-safe (i18n "topics.bulk.progress" count=this.processedTopicCount)}}
|
||||
</p>
|
||||
{{else if this.activeComponent}}
|
||||
<this.activeComponent
|
||||
@loading={{this.loading}}
|
||||
@topics={{@model.topics}}
|
||||
@category={{@model.category}}
|
||||
@setComponent={{this.setComponent}}
|
||||
@forEachPerformed={{this.forEachPerformed}}
|
||||
@performAndRefresh={{this.performAndRefresh}}
|
||||
/>
|
||||
{{else}}
|
||||
<div class="bulk-buttons">
|
||||
{{#each this.buttons as |button|}}
|
||||
<DButton
|
||||
@action={{fn
|
||||
button.action
|
||||
(hash
|
||||
topics=@model.topics
|
||||
category=@model.category
|
||||
setComponent=this.setComponent
|
||||
performAndRefresh=this.performAndRefresh
|
||||
forEachPerformed=this.forEachPerformed
|
||||
)
|
||||
}}
|
||||
@label={{button.label}}
|
||||
@icon={{button.icon}}
|
||||
class={{button.class}}
|
||||
/>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</DModal>
|
@ -1,312 +0,0 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { getOwner } from "@ember/application";
|
||||
import { action } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
import { Promise } from "rsvp";
|
||||
import Topic from "discourse/models/topic";
|
||||
import I18n from "discourse-i18n";
|
||||
import AppendTags from "../bulk-actions/append-tags";
|
||||
import ChangeCategory from "../bulk-actions/change-category";
|
||||
import ChangeTags from "../bulk-actions/change-tags";
|
||||
import NotificationLevel from "../bulk-actions/notification-level";
|
||||
|
||||
const _customButtons = [];
|
||||
|
||||
export function _addBulkButton(opts) {
|
||||
_customButtons.push({
|
||||
label: opts.label,
|
||||
icon: opts.icon,
|
||||
class: opts.class,
|
||||
visible: opts.visible,
|
||||
action: opts.action,
|
||||
});
|
||||
}
|
||||
|
||||
export function clearBulkButtons() {
|
||||
_customButtons.length = 0;
|
||||
}
|
||||
|
||||
// Modal for performing bulk actions on topics
|
||||
export default class TopicBulkActions extends Component {
|
||||
@service currentUser;
|
||||
@service siteSettings;
|
||||
@service dialog;
|
||||
|
||||
@tracked loading = false;
|
||||
@tracked showProgress = false;
|
||||
@tracked processedTopicCount = 0;
|
||||
@tracked activeComponent = null;
|
||||
|
||||
defaultButtons = [
|
||||
{
|
||||
label: "topics.bulk.change_category",
|
||||
icon: "pencil-alt",
|
||||
class: "btn-default bulk-actions__change-category",
|
||||
visible: ({ topics }) => !topics.some((t) => t.isPrivateMessage),
|
||||
action({ setComponent }) {
|
||||
setComponent(ChangeCategory);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.close_topics",
|
||||
icon: "lock",
|
||||
class: "btn-default bulk-actions__close-topics",
|
||||
visible: ({ topics }) => !topics.some((t) => t.isPrivateMessage),
|
||||
action({ forEachPerformed }) {
|
||||
forEachPerformed({ type: "close" }, (t) => t.set("closed", true));
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.archive_topics",
|
||||
icon: "folder",
|
||||
class: "btn-default bulk-actions__archive-topics",
|
||||
visible: ({ topics }) => !topics.some((t) => t.isPrivateMessage),
|
||||
action({ forEachPerformed }) {
|
||||
forEachPerformed({ type: "archive" }, (t) => t.set("archived", true));
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.archive_topics",
|
||||
icon: "folder",
|
||||
class: "btn-default bulk-actions__archive-topics",
|
||||
visible: ({ topics }) => topics.some((t) => t.isPrivateMessage),
|
||||
action: ({ performAndRefresh }) => {
|
||||
const userPrivateMessages = getOwner(this).lookup(
|
||||
"controller:user-private-messages"
|
||||
);
|
||||
let params = { type: "archive_messages" };
|
||||
|
||||
if (userPrivateMessages.isGroup) {
|
||||
params.group = userPrivateMessages.groupFilter;
|
||||
}
|
||||
|
||||
performAndRefresh(params);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.move_messages_to_inbox",
|
||||
icon: "folder",
|
||||
class: "btn-default bulk-actions__move-messages-to-inbox",
|
||||
visible: ({ topics }) => topics.some((t) => t.isPrivateMessage),
|
||||
action: ({ performAndRefresh }) => {
|
||||
const userPrivateMessages = getOwner(this).lookup(
|
||||
"controller:user-private-messages"
|
||||
);
|
||||
let params = { type: "move_messages_to_inbox" };
|
||||
|
||||
if (userPrivateMessages.isGroup) {
|
||||
params.group = userPrivateMessages.groupFilter;
|
||||
}
|
||||
|
||||
performAndRefresh(params);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.notification_level",
|
||||
icon: "d-regular",
|
||||
class: "btn-default bulk-actions__notification-level",
|
||||
action({ setComponent }) {
|
||||
setComponent(NotificationLevel);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.defer",
|
||||
icon: "circle",
|
||||
class: "btn-default bulk-actions__defer",
|
||||
visible: ({ currentUser }) => currentUser.user_option.enable_defer,
|
||||
action({ performAndRefresh }) {
|
||||
performAndRefresh({ type: "destroy_post_timing" });
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.unlist_topics",
|
||||
icon: "far-eye-slash",
|
||||
class: "btn-default bulk-actions__unlist",
|
||||
visible: ({ topics }) =>
|
||||
topics.some((t) => t.visible) &&
|
||||
!topics.some((t) => t.isPrivateMessage),
|
||||
action({ forEachPerformed }) {
|
||||
forEachPerformed({ type: "unlist" }, (t) => t.set("visible", false));
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.relist_topics",
|
||||
icon: "far-eye",
|
||||
class: "btn-default bulk-actions__relist",
|
||||
visible: ({ topics }) =>
|
||||
topics.some((t) => !t.visible) &&
|
||||
!topics.some((t) => t.isPrivateMessage),
|
||||
action({ forEachPerformed }) {
|
||||
forEachPerformed({ type: "relist" }, (t) => t.set("visible", true));
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.reset_bump_dates",
|
||||
icon: "anchor",
|
||||
class: "btn-default bulk-actions__reset-bump-dates",
|
||||
visible: ({ currentUser }) => currentUser.canManageTopic,
|
||||
action({ performAndRefresh }) {
|
||||
performAndRefresh({ type: "reset_bump_dates" });
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.change_tags",
|
||||
icon: "tag",
|
||||
class: "btn-default bulk-actions__change-tags",
|
||||
visible: ({ currentUser, siteSettings }) =>
|
||||
siteSettings.tagging_enabled && currentUser.canManageTopic,
|
||||
action({ setComponent }) {
|
||||
setComponent(ChangeTags);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.append_tags",
|
||||
icon: "tag",
|
||||
class: "btn-default bulk-actions__append-tags",
|
||||
visible: ({ currentUser, siteSettings }) =>
|
||||
siteSettings.tagging_enabled && currentUser.canManageTopic,
|
||||
action({ setComponent }) {
|
||||
setComponent(AppendTags);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.remove_tags",
|
||||
icon: "tag",
|
||||
class: "btn-default bulk-actions__remove-tags",
|
||||
visible: ({ currentUser, siteSettings }) =>
|
||||
siteSettings.tagging_enabled && currentUser.canManageTopic,
|
||||
action: ({ performAndRefresh, topics }) => {
|
||||
this.dialog.deleteConfirm({
|
||||
message: I18n.t("topics.bulk.confirm_remove_tags", {
|
||||
count: topics.length,
|
||||
}),
|
||||
didConfirm: () => performAndRefresh({ type: "remove_tags" }),
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "topics.bulk.delete",
|
||||
icon: "trash-alt",
|
||||
class: "btn-danger delete-topics bulk-actions__delete",
|
||||
visible: ({ currentUser }) => currentUser.staff,
|
||||
action({ performAndRefresh }) {
|
||||
performAndRefresh({ type: "delete" });
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
if (this.args.model.initialAction === "set-component") {
|
||||
this.setComponent(this.args.model.initialComponent);
|
||||
}
|
||||
}
|
||||
|
||||
get buttons() {
|
||||
return [...this.defaultButtons, ..._customButtons].filter(({ visible }) => {
|
||||
if (visible) {
|
||||
return visible({
|
||||
topics: this.args.model.topics,
|
||||
category: this.args.model.category,
|
||||
currentUser: this.currentUser,
|
||||
siteSettings: this.siteSettings,
|
||||
});
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async perform(operation) {
|
||||
this.loading = true;
|
||||
|
||||
if (this.args.model.topics.length > 20) {
|
||||
this.showProgress = true;
|
||||
}
|
||||
|
||||
try {
|
||||
return this._processChunks(operation);
|
||||
} catch {
|
||||
this.dialog.alert(I18n.t("generic_error"));
|
||||
} finally {
|
||||
this.loading = false;
|
||||
this.processedTopicCount = 0;
|
||||
this.showProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
_generateTopicChunks(allTopics) {
|
||||
let startIndex = 0;
|
||||
const chunkSize = 30;
|
||||
const chunks = [];
|
||||
|
||||
while (startIndex < allTopics.length) {
|
||||
const topics = allTopics.slice(startIndex, startIndex + chunkSize);
|
||||
chunks.push(topics);
|
||||
startIndex += chunkSize;
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
_processChunks(operation) {
|
||||
const allTopics = this.args.model.topics;
|
||||
const topicChunks = this._generateTopicChunks(allTopics);
|
||||
const topicIds = [];
|
||||
|
||||
const tasks = topicChunks.map((topics) => async () => {
|
||||
const result = await Topic.bulkOperation(topics, operation);
|
||||
this.processedTopicCount = this.processedTopicCount + topics.length;
|
||||
return result;
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const resolveNextTask = async () => {
|
||||
if (tasks.length === 0) {
|
||||
const topics = topicIds.map((id) => allTopics.findBy("id", id));
|
||||
return resolve(topics);
|
||||
}
|
||||
|
||||
const task = tasks.shift();
|
||||
|
||||
try {
|
||||
const result = await task();
|
||||
if (result?.topic_ids) {
|
||||
topicIds.push(...result.topic_ids);
|
||||
}
|
||||
resolveNextTask();
|
||||
} catch {
|
||||
reject();
|
||||
}
|
||||
};
|
||||
|
||||
resolveNextTask();
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
setComponent(component) {
|
||||
this.activeComponent = component;
|
||||
}
|
||||
|
||||
@action
|
||||
async forEachPerformed(operation, cb) {
|
||||
const topics = await this.perform(operation);
|
||||
|
||||
if (topics) {
|
||||
topics.forEach(cb);
|
||||
this.args.model.refreshClosure?.();
|
||||
this.args.closeModal();
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
async performAndRefresh(operation) {
|
||||
await this.perform(operation);
|
||||
|
||||
this.args.model.refreshClosure?.();
|
||||
this.args.closeModal();
|
||||
}
|
||||
}
|
@ -15,7 +15,6 @@
|
||||
listTitle=this.listTitle
|
||||
bulkSelectEnabled=this.bulkSelectEnabled
|
||||
bulkSelectHelper=this.bulkSelectHelper
|
||||
experimentalTopicBulkActionsEnabled=this.experimentalTopicBulkActionsEnabled
|
||||
canDoBulkActions=this.canDoBulkActions
|
||||
showTopicsAndRepliesToggle=this.showTopicsAndRepliesToggle
|
||||
newListSubset=this.newListSubset
|
||||
|
@ -5,7 +5,6 @@ import { on } from "@ember/object/evented";
|
||||
import { service } from "@ember/service";
|
||||
import LoadMore from "discourse/mixins/load-more";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import TopicBulkActions from "./modal/topic-bulk-actions";
|
||||
|
||||
export default Component.extend(LoadMore, {
|
||||
modal: service(),
|
||||
@ -50,11 +49,6 @@ export default Component.extend(LoadMore, {
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
experimentalTopicBulkActionsEnabled() {
|
||||
return this.currentUser?.use_experimental_topic_bulk_actions;
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
sortable() {
|
||||
return !!this.changeSort;
|
||||
@ -196,16 +190,6 @@ export default Component.extend(LoadMore, {
|
||||
this.rerender();
|
||||
});
|
||||
|
||||
onClick("button.bulk-select-actions", () => {
|
||||
this.modal.show(TopicBulkActions, {
|
||||
model: {
|
||||
topics: this.bulkSelectHelper.selected,
|
||||
category: this.category,
|
||||
refreshClosure: () => this.router.refresh(),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
onClick("button.topics-replies-toggle", (element) => {
|
||||
if (element.classList.contains("--all")) {
|
||||
this.changeNewListSubset(null);
|
||||
|
@ -32,10 +32,6 @@ export default class TopicList extends Component {
|
||||
return !this.bulkSelectEnabled && this.args.canBulkSelect;
|
||||
}
|
||||
|
||||
get experimentalTopicBulkActionsEnabled() {
|
||||
return this.currentUser?.use_experimental_topic_bulk_actions;
|
||||
}
|
||||
|
||||
get sortable() {
|
||||
return !!this.args.changeSort;
|
||||
}
|
||||
@ -118,7 +114,6 @@ export default class TopicList extends Component {
|
||||
@listTitle={{or @listTitle "topic.title"}}
|
||||
@bulkSelectEnabled={{this.bulkSelectEnabled}}
|
||||
@bulkSelectHelper={{@bulkSelectHelper}}
|
||||
@experimentalTopicBulkActionsEnabled={{this.experimentalTopicBulkActionsEnabled}}
|
||||
@canDoBulkActions={{this.canDoBulkActions}}
|
||||
@showTopicsAndRepliesToggle={{@showTopicsAndRepliesToggle}}
|
||||
@newListSubset={{@newListSubset}}
|
||||
|
@ -2,7 +2,6 @@ import Component from "@glimmer/component";
|
||||
import { on } from "@ember/modifier";
|
||||
import { action } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
import TopicBulkActions from "discourse/components/modal/topic-bulk-actions";
|
||||
import NewListHeaderControls from "discourse/components/topic-list/new-list-header-controls";
|
||||
import TopicBulkSelectDropdown from "discourse/components/topic-list/topic-bulk-select-dropdown";
|
||||
import concatClass from "discourse/helpers/concat-class";
|
||||
@ -48,17 +47,6 @@ export default class TopicListHeaderColumn extends Component {
|
||||
.forEach((el) => el.click());
|
||||
}
|
||||
|
||||
@action
|
||||
bulkSelectActions() {
|
||||
this.modal.show(TopicBulkActions, {
|
||||
model: {
|
||||
topics: this.args.bulkSelectHelper.selected,
|
||||
category: this.category,
|
||||
refreshClosure: () => this.router.refresh(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
onClick() {
|
||||
this.args.changeSort(this.args.order);
|
||||
@ -100,24 +88,17 @@ export default class TopicListHeaderColumn extends Component {
|
||||
title={{i18n "topics.bulk.toggle"}}
|
||||
class="btn-flat bulk-select"
|
||||
>
|
||||
{{icon (if @experimentalTopicBulkActionsEnabled "tasks" "list")}}
|
||||
{{icon "tasks"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
{{#if @bulkSelectEnabled}}
|
||||
<span class="bulk-select-topics">
|
||||
{{#if @canDoBulkActions}}
|
||||
{{#if @experimentalTopicBulkActionsEnabled}}
|
||||
<TopicBulkSelectDropdown
|
||||
@bulkSelectHelper={{@bulkSelectHelper}}
|
||||
@afterBulkActionComplete={{this.afterBulkActionComplete}}
|
||||
/>
|
||||
{{else}}
|
||||
<button
|
||||
{{on "click" this.bulkSelectActions}}
|
||||
class="btn btn-icon no-text bulk-select-actions"
|
||||
>{{icon "cog"}}​</button>
|
||||
{{/if}}
|
||||
<TopicBulkSelectDropdown
|
||||
@bulkSelectHelper={{@bulkSelectHelper}}
|
||||
@afterBulkActionComplete={{this.afterBulkActionComplete}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
<button
|
||||
|
@ -16,7 +16,7 @@ const TopicListHeader = <template>
|
||||
title={{i18n "topics.bulk.toggle"}}
|
||||
class="btn-flat bulk-select"
|
||||
>
|
||||
{{icon (if @experimentalTopicBulkActionsEnabled "tasks" "list")}}
|
||||
{{icon "tasks"}}
|
||||
</button>
|
||||
{{/if}}
|
||||
</th>
|
||||
@ -37,7 +37,6 @@ const TopicListHeader = <template>
|
||||
@newListSubset={{@newListSubset}}
|
||||
@newRepliesCount={{@newRepliesCount}}
|
||||
@newTopicsCount={{@newTopicsCount}}
|
||||
@experimentalTopicBulkActionsEnabled={{@experimentalTopicBulkActionsEnabled}}
|
||||
@bulkSelectHelper={{@bulkSelectHelper}}
|
||||
@changeNewListSubset={{@changeNewListSubset}}
|
||||
/>
|
||||
|
@ -4,7 +4,6 @@ import { gt, or } from "@ember/object/computed";
|
||||
import { service } from "@ember/service";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import { Promise } from "rsvp";
|
||||
import TopicBulkActions from "discourse/components/modal/topic-bulk-actions";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import BulkSelectHelper from "discourse/lib/bulk-select-helper";
|
||||
import { search as searchCategoryTag } from "discourse/lib/category-tag-search";
|
||||
@ -232,11 +231,6 @@ export default Controller.extend({
|
||||
}
|
||||
},
|
||||
|
||||
@discourseComputed("currentUser.use_experimental_topic_bulk_actions")
|
||||
useNewBulkActions() {
|
||||
return this.currentUser?.use_experimental_topic_bulk_actions;
|
||||
},
|
||||
|
||||
@discourseComputed("q")
|
||||
showLikeCount(q) {
|
||||
return q?.includes("order:likes");
|
||||
@ -549,15 +543,6 @@ export default Controller.extend({
|
||||
this.bulkSelectHelper.selected.clear();
|
||||
},
|
||||
|
||||
showBulkActions() {
|
||||
this.modal.show(TopicBulkActions, {
|
||||
model: {
|
||||
topics: this.bulkSelectHelper.selected,
|
||||
refreshClosure: this._search,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
search(options = {}) {
|
||||
if (this.searching) {
|
||||
return;
|
||||
|
@ -14,7 +14,6 @@ import { forceDropdownForMenuPanels as glimmerForceDropdownForMenuPanels } from
|
||||
import { addGlobalNotice } from "discourse/components/global-notice";
|
||||
import { headerButtonsDAG } from "discourse/components/header";
|
||||
import { headerIconsDAG } from "discourse/components/header/icons";
|
||||
import { _addBulkButton } from "discourse/components/modal/topic-bulk-actions";
|
||||
import MountWidget, {
|
||||
addWidgetCleanCallback,
|
||||
} from "discourse/components/mount-widget";
|
||||
@ -3036,7 +3035,6 @@ class PluginApi {
|
||||
* @param {string} opts.actionType - type of the action, either performanAndRefresh or setComponent
|
||||
*/
|
||||
addBulkActionButton(opts) {
|
||||
_addBulkButton(opts);
|
||||
addBulkDropdownButton(opts);
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,12 @@
|
||||
<th data-sort-order='{{order}}' class='{{view.className}} topic-list-data' scope="col" {{#if view.ariaSort}}aria-sort='{{view.ariaSort}}'{{/if}}>
|
||||
{{~#if canBulkSelect}}
|
||||
{{~#if showBulkToggle}}
|
||||
{{~#if experimentalTopicBulkActionsEnabled }}
|
||||
{{raw "flat-button" class="bulk-select" icon="tasks" title="topics.bulk.toggle"}}
|
||||
{{else}}
|
||||
{{raw "flat-button" class="bulk-select" icon="list" title="topics.bulk.toggle"}}
|
||||
{{/if ~}}
|
||||
{{raw "flat-button" class="bulk-select" icon="tasks" title="topics.bulk.toggle"}}
|
||||
{{/if ~}}
|
||||
{{~#if bulkSelectEnabled}}
|
||||
<span class='bulk-select-topics'>
|
||||
{{~#if canDoBulkActions}}
|
||||
{{~#if experimentalTopicBulkActionsEnabled }}
|
||||
{{raw "topic-bulk-select-dropdown" bulkSelectHelper=bulkSelectHelper}}
|
||||
{{else}}
|
||||
<button class='btn btn-icon no-text bulk-select-actions'>{{d-icon "cog"}}​</button>
|
||||
{{/if ~}}
|
||||
{{raw "topic-bulk-select-dropdown" bulkSelectHelper=bulkSelectHelper}}
|
||||
{{/if ~}}
|
||||
<button class='btn btn-default bulk-select-all'>{{i18n "topics.bulk.select_all"}}</button>
|
||||
<button class='btn btn-default bulk-clear-all'>{{i18n "topics.bulk.clear_all"}}</button>
|
||||
|
@ -2,15 +2,11 @@
|
||||
{{#if bulkSelectEnabled}}
|
||||
<th class="bulk-select topic-list-data">
|
||||
{{#if canBulkSelect}}
|
||||
{{#if experimentalTopicBulkActionsEnabled }}
|
||||
{{raw "flat-button" class="bulk-select" icon="tasks" title="topics.bulk.toggle"}}
|
||||
{{else}}
|
||||
{{raw "flat-button" class="bulk-select" icon="list" title="topics.bulk.toggle"}}
|
||||
{{/if}}
|
||||
{{raw "flat-button" class="bulk-select" icon="tasks" title="topics.bulk.toggle"}}
|
||||
{{/if}}
|
||||
</th>
|
||||
{{/if}}
|
||||
{{raw "topic-list-header-column" order='default' name=listTitle bulkSelectEnabled=bulkSelectEnabled showBulkToggle=toggleInTitle canBulkSelect=canBulkSelect canDoBulkActions=canDoBulkActions showTopicsAndRepliesToggle=showTopicsAndRepliesToggle newListSubset=newListSubset newRepliesCount=newRepliesCount newTopicsCount=newTopicsCount experimentalTopicBulkActionsEnabled=experimentalTopicBulkActionsEnabled bulkSelectHelper=bulkSelectHelper }}
|
||||
{{raw "topic-list-header-column" order='default' name=listTitle bulkSelectEnabled=bulkSelectEnabled showBulkToggle=toggleInTitle canBulkSelect=canBulkSelect canDoBulkActions=canDoBulkActions showTopicsAndRepliesToggle=showTopicsAndRepliesToggle newListSubset=newListSubset newRepliesCount=newRepliesCount newTopicsCount=newTopicsCount bulkSelectHelper=bulkSelectHelper }}
|
||||
{{raw-plugin-outlet name="topic-list-header-after-main-link"}}
|
||||
{{#if showPosters}}
|
||||
{{raw "topic-list-header-column" name='posters' screenreaderOnly='true'}}
|
||||
|
@ -110,19 +110,10 @@
|
||||
class="btn-default bulk-select"
|
||||
/>
|
||||
{{#if this.bulkSelectHelper.selected}}
|
||||
{{#if this.useNewBulkActions}}
|
||||
<TopicList::TopicBulkSelectDropdown
|
||||
@bulkSelectHelper={{this.bulkSelectHelper}}
|
||||
@afterBulkActionComplete={{this.afterBulkActionComplete}}
|
||||
/>
|
||||
{{else}}
|
||||
<DButton
|
||||
@selected={{this.bulkSelectHelper.selected}}
|
||||
@action={{action "showBulkActions"}}
|
||||
@icon="wrench"
|
||||
class="btn-default bulk-select-btn"
|
||||
/>
|
||||
{{/if}}
|
||||
<TopicList::TopicBulkSelectDropdown
|
||||
@bulkSelectHelper={{this.bulkSelectHelper}}
|
||||
@afterBulkActionComplete={{this.afterBulkActionComplete}}
|
||||
/>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
|
@ -1,130 +0,0 @@
|
||||
import { click, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import {
|
||||
acceptance,
|
||||
query,
|
||||
queryAll,
|
||||
updateCurrentUser,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
acceptance("Topic - Bulk Actions - Mobile", function (needs) {
|
||||
needs.user();
|
||||
needs.mobileView();
|
||||
|
||||
needs.settings({ tagging_enabled: true });
|
||||
needs.pretender((server, helper) => {
|
||||
server.put("/topics/bulk", () => {
|
||||
return helper.response({
|
||||
topic_ids: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("bulk select - modal", async function (assert) {
|
||||
updateCurrentUser({ moderator: true, user_option: { enable_defer: true } });
|
||||
await visit("/latest");
|
||||
await click("button.bulk-select");
|
||||
|
||||
await click(queryAll("input.bulk-select")[0]);
|
||||
await click(queryAll("input.bulk-select")[1]);
|
||||
|
||||
await click(".bulk-select-actions");
|
||||
|
||||
assert.ok(
|
||||
query("#discourse-modal-title").innerHTML.includes(
|
||||
I18n.t("topics.bulk.actions")
|
||||
),
|
||||
"it opens bulk-select modal"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(
|
||||
I18n.t("topics.bulk.change_category")
|
||||
),
|
||||
"it shows an option to change category"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(
|
||||
I18n.t("topics.bulk.close_topics")
|
||||
),
|
||||
"it shows an option to close topics"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(
|
||||
I18n.t("topics.bulk.archive_topics")
|
||||
),
|
||||
"it shows an option to archive topics"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(
|
||||
I18n.t("topics.bulk.notification_level")
|
||||
),
|
||||
"it shows an option to update notification level"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(I18n.t("topics.bulk.defer")),
|
||||
"it shows an option to reset read"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(
|
||||
I18n.t("topics.bulk.unlist_topics")
|
||||
),
|
||||
"it shows an option to unlist topics"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(
|
||||
I18n.t("topics.bulk.reset_bump_dates")
|
||||
),
|
||||
"it shows an option to reset bump dates"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(
|
||||
I18n.t("topics.bulk.change_tags")
|
||||
),
|
||||
"it shows an option to replace tags"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(
|
||||
I18n.t("topics.bulk.append_tags")
|
||||
),
|
||||
"it shows an option to append tags"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(
|
||||
I18n.t("topics.bulk.remove_tags")
|
||||
),
|
||||
"it shows an option to remove all tags"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
query(".bulk-buttons").innerHTML.includes(I18n.t("topics.bulk.delete")),
|
||||
"it shows an option to delete topics"
|
||||
);
|
||||
});
|
||||
|
||||
test("bulk select - delete topics", async function (assert) {
|
||||
updateCurrentUser({ moderator: true });
|
||||
await visit("/latest");
|
||||
await click("button.bulk-select");
|
||||
|
||||
await click(queryAll("input.bulk-select")[0]);
|
||||
await click(queryAll("input.bulk-select")[1]);
|
||||
|
||||
await click(".bulk-select-actions");
|
||||
await click(".d-modal__body .delete-topics");
|
||||
|
||||
assert
|
||||
.dom(".topic-bulk-actions-modal")
|
||||
.doesNotExist("it closes the bulk select modal");
|
||||
});
|
||||
});
|
@ -8,7 +8,6 @@ import {
|
||||
import { acceptance, selectDate } from "discourse/tests/helpers/qunit-helpers";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
|
||||
let lastBody;
|
||||
let searchResultClickTracked = false;
|
||||
|
||||
acceptance("Search - Full Page", function (needs) {
|
||||
@ -87,11 +86,6 @@ acceptance("Search - Full Page", function (needs) {
|
||||
});
|
||||
});
|
||||
|
||||
server.put("/topics/bulk", (request) => {
|
||||
lastBody = helper.parsePostData(request.requestBody);
|
||||
return helper.response({ topic_ids: [130] });
|
||||
});
|
||||
|
||||
server.post("/search/click", () => {
|
||||
searchResultClickTracked = true;
|
||||
return helper.response({ success: "OK" });
|
||||
@ -541,17 +535,6 @@ acceptance("Search - Full Page", function (needs) {
|
||||
.isVisible("clicking on element expands filters");
|
||||
});
|
||||
|
||||
test("bulk operations work", async function (assert) {
|
||||
await visit("/search");
|
||||
await fillIn(".search-query", "discourse");
|
||||
await click(".search-cta");
|
||||
await click(".bulk-select"); // toggle bulk
|
||||
await click(".bulk-select-visible .btn:nth-child(2)"); // select all
|
||||
await click(".bulk-select-btn"); // show bulk actions
|
||||
await click(".topic-bulk-actions-modal .btn.bulk-actions__close-topics");
|
||||
assert.deepEqual(lastBody["topic_ids[]"], ["130"]);
|
||||
});
|
||||
|
||||
test("adds visited class to visited topics", async function (assert) {
|
||||
await visit("/search");
|
||||
|
||||
|
@ -1,265 +0,0 @@
|
||||
import { click, triggerEvent, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import {
|
||||
acceptance,
|
||||
count,
|
||||
queryAll,
|
||||
updateCurrentUser,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
acceptance("Topic - Bulk Actions", function (needs) {
|
||||
needs.user();
|
||||
needs.settings({ tagging_enabled: true });
|
||||
needs.pretender((server, helper) => {
|
||||
server.put("/topics/bulk", () => {
|
||||
return helper.response({
|
||||
topic_ids: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("bulk select - modal", async function (assert) {
|
||||
updateCurrentUser({
|
||||
moderator: true,
|
||||
user_option: { enable_defer: true },
|
||||
});
|
||||
await visit("/latest");
|
||||
await click("button.bulk-select");
|
||||
|
||||
await click(queryAll("input.bulk-select")[0]);
|
||||
await click(queryAll("input.bulk-select")[1]);
|
||||
|
||||
await click(".bulk-select-actions");
|
||||
|
||||
assert
|
||||
.dom("#discourse-modal-title")
|
||||
.hasText(I18n.t("topics.bulk.actions"), "it opens bulk-select modal");
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.change_category"),
|
||||
"it shows an option to change category"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.close_topics"),
|
||||
"it shows an option to close topics"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.archive_topics"),
|
||||
"it shows an option to archive topics"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.notification_level"),
|
||||
"it shows an option to update notification level"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.defer"),
|
||||
"it shows an option to reset read"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.unlist_topics"),
|
||||
"it shows an option to unlist topics"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.reset_bump_dates"),
|
||||
"it shows an option to reset bump dates"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.change_tags"),
|
||||
"it shows an option to replace tags"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.append_tags"),
|
||||
"it shows an option to append tags"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.remove_tags"),
|
||||
"it shows an option to remove all tags"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.delete"),
|
||||
"it shows an option to delete topics"
|
||||
);
|
||||
});
|
||||
|
||||
test("bulk select - delete topics", async function (assert) {
|
||||
updateCurrentUser({ moderator: true });
|
||||
await visit("/latest");
|
||||
await click("button.bulk-select");
|
||||
|
||||
await click(queryAll("input.bulk-select")[0]);
|
||||
await click(queryAll("input.bulk-select")[1]);
|
||||
|
||||
await click(".bulk-select-actions");
|
||||
await click(".d-modal__body .delete-topics");
|
||||
|
||||
assert
|
||||
.dom(".topic-bulk-actions-modal")
|
||||
.doesNotExist("it closes the bulk select modal");
|
||||
});
|
||||
|
||||
test("bulk select - Shift click selection", async function (assert) {
|
||||
updateCurrentUser({ moderator: true });
|
||||
await visit("/latest");
|
||||
await click("button.bulk-select");
|
||||
|
||||
await click(queryAll("input.bulk-select")[0]);
|
||||
await triggerEvent(queryAll("input.bulk-select")[3], "click", {
|
||||
shiftKey: true,
|
||||
});
|
||||
assert.strictEqual(
|
||||
count("input.bulk-select:checked"),
|
||||
4,
|
||||
"Shift click selects a range"
|
||||
);
|
||||
|
||||
await click("button.bulk-clear-all");
|
||||
|
||||
await click(queryAll("input.bulk-select")[5]);
|
||||
await triggerEvent(queryAll("input.bulk-select")[1], "click", {
|
||||
shiftKey: true,
|
||||
});
|
||||
assert.strictEqual(
|
||||
count("input.bulk-select:checked"),
|
||||
5,
|
||||
"Bottom-up Shift click range selection works"
|
||||
);
|
||||
});
|
||||
|
||||
test("bulk select is not available for users who are not staff or TL4", async function (assert) {
|
||||
updateCurrentUser({ moderator: false, admin: false, trust_level: 1 });
|
||||
await visit("/latest");
|
||||
assert
|
||||
.dom(".button.bulk-select")
|
||||
.doesNotExist("non-staff and < TL4 users cannot bulk select");
|
||||
});
|
||||
|
||||
test("TL4 users can bulk select", async function (assert) {
|
||||
updateCurrentUser({
|
||||
moderator: false,
|
||||
admin: false,
|
||||
trust_level: 4,
|
||||
user_option: { enable_defer: false },
|
||||
});
|
||||
|
||||
await visit("/latest");
|
||||
await click("button.bulk-select");
|
||||
|
||||
await click(queryAll("input.bulk-select")[0]);
|
||||
await click(queryAll("input.bulk-select")[1]);
|
||||
await click(".bulk-select-actions");
|
||||
|
||||
assert
|
||||
.dom("#discourse-modal-title")
|
||||
.hasText(I18n.t("topics.bulk.actions"), "it opens bulk-select modal");
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.change_category"),
|
||||
"it shows an option to change category"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.close_topics"),
|
||||
"it shows an option to close topics"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.archive_topics"),
|
||||
"it shows an option to archive topics"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.notification_level"),
|
||||
"it shows an option to update notification level"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.doesNotIncludeText(
|
||||
I18n.t("topics.bulk.defer"),
|
||||
"it does not show an option to reset read"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.unlist_topics"),
|
||||
"it shows an option to unlist topics"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.reset_bump_dates"),
|
||||
"it shows an option to reset bump dates"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.change_tags"),
|
||||
"it shows an option to replace tags"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.append_tags"),
|
||||
"it shows an option to append tags"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.includesText(
|
||||
I18n.t("topics.bulk.remove_tags"),
|
||||
"it shows an option to remove all tags"
|
||||
);
|
||||
|
||||
assert
|
||||
.dom(".bulk-buttons")
|
||||
.doesNotIncludeText(
|
||||
I18n.t("topics.bulk.delete"),
|
||||
"it does not show an option to delete topics"
|
||||
);
|
||||
});
|
||||
});
|
@ -22,9 +22,8 @@ acceptance("User Activity / Read - bulk actions", function (needs) {
|
||||
await click("button.bulk-select");
|
||||
await click(queryAll("input.bulk-select")[0]);
|
||||
await click(queryAll("input.bulk-select")[1]);
|
||||
await click("button.bulk-select-actions");
|
||||
|
||||
await click("div.bulk-buttons button.bulk-actions__close-topics");
|
||||
await click(".bulk-select-topics-dropdown-trigger");
|
||||
await click(".dropdown-menu__item .close-topics");
|
||||
|
||||
assert
|
||||
.dom("div.bulk-buttons")
|
||||
|
@ -26,9 +26,8 @@ acceptance("User Activity / Topics - bulk actions", function (needs) {
|
||||
await click("button.bulk-select");
|
||||
await click(queryAll("input.bulk-select")[0]);
|
||||
await click(queryAll("input.bulk-select")[1]);
|
||||
await click("button.bulk-select-actions");
|
||||
|
||||
await click("div.bulk-buttons button:nth-child(2)"); // the Close Topics button
|
||||
await click(".bulk-select-topics-dropdown-trigger");
|
||||
await click(".dropdown-menu__item .close-topics");
|
||||
|
||||
assert.notOk(
|
||||
exists("div.bulk-buttons"),
|
||||
|
@ -20,7 +20,6 @@ import {
|
||||
import { clearToolbarCallbacks } from "discourse/components/d-editor";
|
||||
import { clearExtraHeaderButtons as clearExtraGlimmerHeaderButtons } from "discourse/components/header";
|
||||
import { clearExtraHeaderIcons as clearExtraGlimmerHeaderIcons } from "discourse/components/header/icons";
|
||||
import { clearBulkButtons } from "discourse/components/modal/topic-bulk-actions";
|
||||
import { resetWidgetCleanCallbacks } from "discourse/components/mount-widget";
|
||||
import { resetDecorators as resetPluginOutletDecorators } from "discourse/components/plugin-connector";
|
||||
import { resetItemSelectCallbacks } from "discourse/components/search-menu/results/assistant-item";
|
||||
@ -244,7 +243,6 @@ export function testCleanup(container, app) {
|
||||
resetMentions();
|
||||
cleanupTemporaryModuleRegistrations();
|
||||
cleanupCssGeneratorTags();
|
||||
clearBulkButtons();
|
||||
resetBeforeAuthCompleteCallbacks();
|
||||
clearPopupMenuOptions();
|
||||
clearAdditionalAdminSidebarSectionLinks();
|
||||
|
@ -72,7 +72,6 @@ class CurrentUserSerializer < BasicUserSerializer
|
||||
:sidebar_category_ids,
|
||||
:sidebar_sections,
|
||||
:new_new_view_enabled?,
|
||||
:use_experimental_topic_bulk_actions?,
|
||||
:use_admin_sidebar,
|
||||
:can_view_raw_email,
|
||||
:use_glimmer_topic_list?,
|
||||
@ -323,10 +322,6 @@ class CurrentUserSerializer < BasicUserSerializer
|
||||
Reviewable.unseen_reviewable_count(object)
|
||||
end
|
||||
|
||||
def use_experimental_topic_bulk_actions?
|
||||
scope.user.in_any_groups?(SiteSetting.experimental_topic_bulk_actions_enabled_groups_map)
|
||||
end
|
||||
|
||||
def can_view_raw_email
|
||||
scope.user.in_any_groups?(SiteSetting.view_raw_email_allowed_groups_map)
|
||||
end
|
||||
|
@ -2679,7 +2679,6 @@ en:
|
||||
experimental_form_templates: "EXPERIMENTAL: Enable the form templates feature. <b>After enabled,</b> manage the templates at <a href='%{base_path}/admin/customize/form-templates'>Customize / Templates</a>."
|
||||
admin_sidebar_enabled_groups: "Enable sidebar navigation for the admin UI for the specified groups, which replaces the top-level admin navigation buttons."
|
||||
lazy_load_categories_groups: "EXPERIMENTAL: Lazy load category information only for users of these groups. This improves performance on sites with many categories."
|
||||
experimental_topic_bulk_actions_enabled_groups: "EXPERIMENTAL: Enable the new bulk actions dropdown."
|
||||
|
||||
page_loading_indicator: "Configure the loading indicator which appears during page navigations within Discourse. 'Spinner' is a full page indicator. 'Slider' shows a narrow bar at the top of the screen."
|
||||
show_user_menu_avatars: "Show user avatars in the user menu"
|
||||
|
@ -2425,12 +2425,6 @@ developer:
|
||||
default: ""
|
||||
client: true
|
||||
hidden: true
|
||||
experimental_topic_bulk_actions_enabled_groups:
|
||||
default: ""
|
||||
type: group_list
|
||||
list_type: compact
|
||||
allow_any: false
|
||||
refresh: true
|
||||
experimental_flags_admin_page_enabled_groups:
|
||||
default: ""
|
||||
type: group_list
|
||||
|
@ -143,51 +143,22 @@ describe "Search", type: :system do
|
||||
|
||||
after { SearchIndexer.disable }
|
||||
|
||||
context "when experimental_topic_bulk_actions_enabled_groups is enabled" do
|
||||
before do
|
||||
SiteSetting.experimental_topic_bulk_actions_enabled_groups =
|
||||
Group::AUTO_GROUPS[:trust_level_1]
|
||||
end
|
||||
|
||||
it "allows the user to perform bulk actions on the topic search results" do
|
||||
visit("/search?q=test")
|
||||
expect(page).to have_content(topic.title)
|
||||
find(".search-info .bulk-select").click
|
||||
find(".fps-result .fps-topic[data-topic-id=\"#{topic.id}\"] .bulk-select input").click
|
||||
find(".search-info .bulk-select-topics-dropdown-trigger").click
|
||||
find(".bulk-select-topics-dropdown-content .append-tags").click
|
||||
expect(topic_bulk_actions_modal).to be_open
|
||||
tag_selector = PageObjects::Components::SelectKit.new(".tag-chooser")
|
||||
tag_selector.search(tag1.name)
|
||||
tag_selector.select_row_by_value(tag1.name)
|
||||
tag_selector.collapse
|
||||
topic_bulk_actions_modal.click_bulk_topics_confirm
|
||||
expect(
|
||||
find(".fps-result .fps-topic[data-topic-id=\"#{topic.id}\"] .discourse-tags"),
|
||||
).to have_content(tag1.name)
|
||||
end
|
||||
end
|
||||
|
||||
context "when experimental_topic_bulk_actions_enabled_groups is not enabled" do
|
||||
before { SiteSetting.experimental_topic_bulk_actions_enabled_groups = "" }
|
||||
|
||||
it "allows the user to perform bulk actions on the topic search results" do
|
||||
visit("/search?q=test")
|
||||
expect(page).to have_content(topic.title)
|
||||
find(".search-info .bulk-select").click
|
||||
find(".fps-result .fps-topic[data-topic-id=\"#{topic.id}\"] .bulk-select input").click
|
||||
find(".search-info .bulk-select-btn").click
|
||||
expect(topic_bulk_actions_modal).to be_open
|
||||
find(".bulk-buttons .bulk-actions__append-tags").click
|
||||
tag_selector = PageObjects::Components::SelectKit.new(".tag-chooser")
|
||||
tag_selector.search(tag1.name)
|
||||
tag_selector.select_row_by_value(tag1.name)
|
||||
tag_selector.collapse
|
||||
find(".topic-bulk-actions__append-tags").click
|
||||
expect(
|
||||
find(".fps-result .fps-topic[data-topic-id=\"#{topic.id}\"] .discourse-tags"),
|
||||
).to have_content(tag1.name)
|
||||
end
|
||||
it "allows the user to perform bulk actions on the topic search results" do
|
||||
visit("/search?q=test")
|
||||
expect(page).to have_content(topic.title)
|
||||
find(".search-info .bulk-select").click
|
||||
find(".fps-result .fps-topic[data-topic-id=\"#{topic.id}\"] .bulk-select input").click
|
||||
find(".search-info .bulk-select-topics-dropdown-trigger").click
|
||||
find(".bulk-select-topics-dropdown-content .append-tags").click
|
||||
expect(topic_bulk_actions_modal).to be_open
|
||||
tag_selector = PageObjects::Components::SelectKit.new(".tag-chooser")
|
||||
tag_selector.search(tag1.name)
|
||||
tag_selector.select_row_by_value(tag1.name)
|
||||
tag_selector.collapse
|
||||
topic_bulk_actions_modal.click_bulk_topics_confirm
|
||||
expect(
|
||||
find(".fps-result .fps-topic[data-topic-id=\"#{topic.id}\"] .discourse-tags"),
|
||||
).to have_content(tag1.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,7 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe "Topic bulk select", type: :system do
|
||||
before { SiteSetting.experimental_topic_bulk_actions_enabled_groups = "1" }
|
||||
fab!(:topics) { Fabricate.times(10, :post).map(&:topic) }
|
||||
fab!(:admin)
|
||||
fab!(:user)
|
||||
|
Loading…
Reference in New Issue
Block a user