DEV: Refactor gjs topic-list (#29792)

Based on the initial review in #28934
This commit is contained in:
Jarek Radosz 2024-11-25 14:15:34 +01:00 committed by GitHub
parent bfe0eccdd9
commit 433543a516
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 375 additions and 254 deletions

View File

@ -0,0 +1,26 @@
const Header = <template>
<tr>
{{#each @columns as |entry|}}
<entry.value.header
@sortable={{@sortable}}
@activeOrder={{@order}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@category={{@category}}
@name={{@listTitle}}
@bulkSelectEnabled={{@bulkSelectEnabled}}
@showBulkToggle={{@toggleInTitle}}
@canBulkSelect={{@canBulkSelect}}
@canDoBulkActions={{@canDoBulkActions}}
@showTopicsAndRepliesToggle={{@showTopicsAndRepliesToggle}}
@newListSubset={{@newListSubset}}
@newRepliesCount={{@newRepliesCount}}
@newTopicsCount={{@newTopicsCount}}
@bulkSelectHelper={{@bulkSelectHelper}}
@changeNewListSubset={{@changeNewListSubset}}
/>
{{/each}}
</tr>
</template>;
export default Header;

View File

@ -0,0 +1,15 @@
import SortableColumn from "./sortable-column";
const ActivityCell = <template>
<SortableColumn
@sortable={{@sortable}}
@number="true"
@order="activity"
@activeOrder={{@activeOrder}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="activity"
/>
</template>;
export default ActivityCell;

View File

@ -0,0 +1,19 @@
import { on } from "@ember/modifier";
import icon from "discourse-common/helpers/d-icon";
import { i18n } from "discourse-i18n";
const BulkSelectCell = <template>
<th class="bulk-select topic-list-data">
{{#if @canBulkSelect}}
<button
{{on "click" @bulkSelectHelper.toggleBulkSelect}}
title={{i18n "topics.bulk.toggle"}}
class="btn-flat bulk-select"
>
{{icon "list-check"}}
</button>
{{/if}}
</th>
</template>;
export default BulkSelectCell;

View File

@ -0,0 +1,15 @@
import SortableColumn from "./sortable-column";
const LikesCell = <template>
<SortableColumn
@sortable={{@sortable}}
@number="true"
@order="likes"
@activeOrder={{@activeOrder}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="likes"
/>
</template>;
export default LikesCell;

View File

@ -0,0 +1,15 @@
import SortableColumn from "./sortable-column";
const OpLikesCell = <template>
<SortableColumn
@sortable={{@sortable}}
@number="true"
@order="op_likes"
@activeOrder={{@activeOrder}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="likes"
/>
</template>;
export default OpLikesCell;

View File

@ -0,0 +1,16 @@
import { i18n } from "discourse-i18n";
import SortableColumn from "./sortable-column";
const PostersCell = <template>
<SortableColumn
@order="posters"
@activeOrder={{@activeOrder}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="posters"
@screenreaderOnly={{true}}
aria-label={{i18n "category.sort_options.posters"}}
/>
</template>;
export default PostersCell;

View File

@ -0,0 +1,15 @@
import SortableColumn from "./sortable-column";
const RepliesCell = <template>
<SortableColumn
@sortable={{@sortable}}
@number="true"
@order="posts"
@activeOrder={{@activeOrder}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="replies"
/>
</template>;
export default RepliesCell;

View File

@ -10,7 +10,7 @@ import concatClass from "discourse/helpers/concat-class";
import icon from "discourse-common/helpers/d-icon";
import { i18n } from "discourse-i18n";
export default class TopicListHeaderColumn extends Component {
export default class SortableColumn extends Component {
@service router;
get localizedName() {
@ -49,7 +49,8 @@ export default class TopicListHeaderColumn extends Component {
}
@action
onClick() {
onClick(event) {
event.preventDefault();
this.args.changeSort(this.args.order);
}

View File

@ -0,0 +1,24 @@
import SortableColumn from "./sortable-column";
const TopicCell = <template>
<SortableColumn
@order="default"
@category={{@category}}
@activeOrder={{@activeOrder}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name={{@name}}
@bulkSelectEnabled={{@bulkSelectEnabled}}
@showBulkToggle={{@showBulkToggle}}
@canBulkSelect={{@canBulkSelect}}
@canDoBulkActions={{@canDoBulkActions}}
@showTopicsAndRepliesToggle={{@showTopicsAndRepliesToggle}}
@newListSubset={{@newListSubset}}
@newRepliesCount={{@newRepliesCount}}
@newTopicsCount={{@newTopicsCount}}
@bulkSelectHelper={{@bulkSelectHelper}}
@changeNewListSubset={{@changeNewListSubset}}
/>
</template>;
export default TopicCell;

View File

@ -0,0 +1,15 @@
import SortableColumn from "./sortable-column";
const ViewsCell = <template>
<SortableColumn
@sortable={{@sortable}}
@number="true"
@order="views"
@activeOrder={{@activeOrder}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="views"
/>
</template>;
export default ViewsCell;

View File

@ -6,13 +6,9 @@ import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import { next } from "@ember/runloop";
import { service } from "@ember/service";
import { modifier } from "ember-modifier";
import { eq, gt } from "truth-helpers";
import { eq } from "truth-helpers";
import PluginOutlet from "discourse/components/plugin-outlet";
import ActivityColumn from "discourse/components/topic-list/activity-column";
import PostCountOrBadges from "discourse/components/topic-list/post-count-or-badges";
import PostersColumn from "discourse/components/topic-list/posters-column";
import PostsCountColumn from "discourse/components/topic-list/posts-count-column";
import TopicCell from "discourse/components/topic-list/topic-cell";
import TopicExcerpt from "discourse/components/topic-list/topic-excerpt";
import TopicLink from "discourse/components/topic-list/topic-link";
import TopicStatus from "discourse/components/topic-status";
@ -22,14 +18,12 @@ import categoryLink from "discourse/helpers/category-link";
import concatClass from "discourse/helpers/concat-class";
import discourseTags from "discourse/helpers/discourse-tags";
import formatDate from "discourse/helpers/format-date";
import number from "discourse/helpers/number";
import topicFeaturedLink from "discourse/helpers/topic-featured-link";
import { wantsNewWindow } from "discourse/lib/intercept-click";
import DiscourseURL from "discourse/lib/url";
import icon from "discourse-common/helpers/d-icon";
import { i18n } from "discourse-i18n";
export default class TopicListItem extends Component {
export default class Item extends Component {
@service historyStore;
@service site;
@service siteSettings;
@ -119,13 +113,11 @@ export default class TopicListItem extends Component {
if (e.target.checked) {
this.args.selected.addObject(this.args.topic);
if (this.args.lastCheckedElementId && e.shiftKey) {
const bulkSelects = Array.from(
document.querySelectorAll("input.bulk-select")
);
if (this.args.bulkSelectHelper.lastCheckedElementId && e.shiftKey) {
const bulkSelects = [...document.querySelectorAll("input.bulk-select")];
const from = bulkSelects.indexOf(e.target);
const to = bulkSelects.findIndex(
(el) => el.id === this.args.lastCheckedElementId
(el) => el.id === this.args.bulkSelectHelper.lastCheckedElementId
);
const start = Math.min(from, to);
const end = Math.max(from, to);
@ -136,10 +128,10 @@ export default class TopicListItem extends Component {
.forEach((checkbox) => checkbox.click());
}
this.args.updateLastCheckedElementId(e.target.id);
this.args.bulkSelectHelper.lastCheckedElementId = e.target.id;
} else {
this.args.selected.removeObject(this.args.topic);
this.args.updateLastCheckedElementId(null);
this.args.bulkSelectHelper.lastCheckedElementId = null;
}
}
@ -223,78 +215,20 @@ export default class TopicListItem extends Component {
@outletArgs={{hash topic=@topic}}
/>
{{#if this.site.desktopView}}
{{! TODO: column DAG "topic-list-before-columns" }}
{{#if @bulkSelectEnabled}}
<td class="bulk-select topic-list-data">
<label for="bulk-select-{{@topic.id}}">
<input
{{on "click" this.onBulkSelectToggle}}
checked={{this.isSelected}}
type="checkbox"
id="bulk-select-{{@topic.id}}"
class="bulk-select"
/>
</label>
</td>
{{/if}}
<TopicCell
@topic={{@topic}}
@showTopicPostBadges={{@showTopicPostBadges}}
@hideCategory={{@hideCategory}}
@tagsForUser={{@tagsForUser}}
@expandPinned={{this.expandPinned}}
/>
<PluginOutlet
@name="topic-list-after-main-link"
@outletArgs={{hash topic=@topic}}
/>
{{#if @showPosters}}
<PostersColumn @posters={{@topic.featuredUsers}} />
{{/if}}
<PostsCountColumn @topic={{@topic}} />
{{#if @showLikes}}
<td class="num likes topic-list-data">
{{#if (gt @topic.like_count 0)}}
<a href={{@topic.summaryUrl}}>
{{number @topic.like_count}}
{{icon "heart"}}
</a>
{{/if}}
</td>
{{/if}}
{{#if @showOpLikes}}
<td class="num likes">
{{#if (gt @topic.op_like_count 0)}}
<a href={{@topic.summaryUrl}}>
{{number @topic.op_like_count}}
{{icon "heart"}}
</a>
{{/if}}
</td>
{{/if}}
<td class={{concatClass "num views topic-list-data" @topic.viewsHeat}}>
<PluginOutlet
@name="topic-list-before-view-count"
@outletArgs={{hash topic=@topic}}
{{#each @columns as |entry|}}
<entry.value.item
@topic={{@topic}}
@bulkSelectEnabled={{@bulkSelectEnabled}}
@onBulkSelectToggle={{this.onBulkSelectToggle}}
@isSelected={{this.isSelected}}
@showTopicPostBadges={{@showTopicPostBadges}}
@hideCategory={{@hideCategory}}
@tagsForUser={{@tagsForUser}}
@expandPinned={{this.expandPinned}}
/>
{{number @topic.views numberKey="views_long"}}
</td>
<ActivityColumn @topic={{@topic}} class="num topic-list-data" />
{{! TODO: column DAG "topic-list-after-columns" }}
{{/each}}
{{else}}
<td class="topic-list-data">
{{! TODO: column DAG "topic-list-before-columns" }}
<div class="pull-left">
{{#if @bulkSelectEnabled}}
<label for="bulk-select-{{@topic.id}}">

View File

@ -5,20 +5,17 @@ import coldAgeClass from "discourse/helpers/cold-age-class";
import concatClass from "discourse/helpers/concat-class";
import formatDate from "discourse/helpers/format-date";
const ActivityColumn = <template>
const ActivityCell = <template>
<td
title={{htmlSafe @topic.bumpedAtTitle}}
class={{concatClass
"activity"
"activity num topic-list-data"
(coldAgeClass @topic.createdAt startDate=@topic.bumpedAt class="")
}}
...attributes
>
<a
href={{@topic.lastPostUrl}}
class="post-activity"
>{{! no whitespace
}}<PluginOutlet
<a href={{@topic.lastPostUrl}} class="post-activity">
{{~! no whitespace ~}}
<PluginOutlet
@name="topic-list-before-relative-date"
@outletArgs={{hash topic=@topic}}
/>
@ -26,4 +23,5 @@ const ActivityColumn = <template>
</a>
</td>
</template>;
export default ActivityColumn;
export default ActivityCell;

View File

@ -0,0 +1,17 @@
import { on } from "@ember/modifier";
const BulkSelectCell = <template>
<td class="bulk-select topic-list-data">
<label for="bulk-select-{{@topic.id}}">
<input
{{on "click" @onBulkSelectToggle}}
checked={{@isSelected}}
type="checkbox"
id="bulk-select-{{@topic.id}}"
class="bulk-select"
/>
</label>
</td>
</template>;
export default BulkSelectCell;

View File

@ -0,0 +1,16 @@
import { gt } from "truth-helpers";
import number from "discourse/helpers/number";
import icon from "discourse-common/helpers/d-icon";
const LikesCell = <template>
<td class="num likes topic-list-data">
{{#if (gt @topic.like_count 0)}}
<a href={{@topic.summaryUrl}}>
{{number @topic.like_count}}
{{icon "heart"}}
</a>
{{/if}}
</td>
</template>;
export default LikesCell;

View File

@ -0,0 +1,16 @@
import { gt } from "truth-helpers";
import number from "discourse/helpers/number";
import icon from "discourse-common/helpers/d-icon";
const OpLikesCell = <template>
<td class="num likes">
{{#if (gt @topic.op_like_count 0)}}
<a href={{@topic.summaryUrl}}>
{{number @topic.op_like_count}}
{{icon "heart"}}
</a>
{{/if}}
</td>
</template>;
export default OpLikesCell;

View File

@ -1,8 +1,8 @@
import avatar from "discourse/helpers/avatar";
const PostersColumn = <template>
const PostersCell = <template>
<td class="posters topic-list-data">
{{#each @posters as |poster|}}
{{#each @topic.featuredUsers as |poster|}}
{{#if poster.moreCount}}
<a class="posters-more-count">{{poster.moreCount}}</a>
{{else}}
@ -22,4 +22,4 @@ const PostersColumn = <template>
</td>
</template>;
export default PostersColumn;
export default PostersCell;

View File

@ -6,7 +6,7 @@ import element from "discourse/helpers/element";
import number from "discourse/helpers/number";
import I18n from "discourse-i18n";
export default class PostsCountColumn extends Component {
export default class RepliesCell extends Component {
@service siteSettings;
get ratio() {

View File

@ -0,0 +1,16 @@
import { hash } from "@ember/helper";
import PluginOutlet from "discourse/components/plugin-outlet";
import concatClass from "discourse/helpers/concat-class";
import number from "discourse/helpers/number";
const ViewsCell = <template>
<td class={{concatClass "num views topic-list-data" @topic.viewsHeat}}>
<PluginOutlet
@name="topic-list-before-view-count"
@outletArgs={{hash topic=@topic}}
/>
{{number @topic.views numberKey="views_long"}}
</td>
</template>;
export default ViewsCell;

View File

@ -1,7 +1,7 @@
import Component from "@glimmer/component";
import { concat, hash } from "@ember/helper";
import PluginOutlet from "discourse/components/plugin-outlet";
import PostsCountColumn from "discourse/components/topic-list/posts-count-column";
import ItemRepliesCell from "discourse/components/topic-list/item/replies-cell";
import TopicPostBadges from "discourse/components/topic-post-badges";
import TopicStatus from "discourse/components/topic-status";
import UserAvatarFlair from "discourse/components/user-avatar-flair";
@ -75,7 +75,7 @@ export default class LatestTopicListItem extends Component {
@outletArgs={{hash topic=@topic}}
/>
<PostsCountColumn @topic={{@topic}} @tagName="div" />
<ItemRepliesCell @topic={{@topic}} @tagName="div" />
<div class="topic-last-activity">
<a

View File

@ -1,18 +1,109 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { fn, hash } from "@ember/helper";
import { cached } from "@glimmer/tracking";
import { hash } from "@ember/helper";
import { service } from "@ember/service";
import { eq, or } from "truth-helpers";
import PluginOutlet from "discourse/components/plugin-outlet";
import TopicListHeader from "discourse/components/topic-list/topic-list-header";
import TopicListItem from "discourse/components/topic-list/topic-list-item";
import Header from "discourse/components/topic-list/header";
import Item from "discourse/components/topic-list/item";
import concatClass from "discourse/helpers/concat-class";
import DAG from "discourse/lib/dag";
import { applyValueTransformer } from "discourse/lib/transformer";
import { i18n } from "discourse-i18n";
import HeaderActivityCell from "./header/activity-cell";
import HeaderBulkSelectCell from "./header/bulk-select-cell";
import HeaderLikesCell from "./header/likes-cell";
import HeaderOpLikesCell from "./header/op-likes-cell";
import HeaderPostersCell from "./header/posters-cell";
import HeaderRepliesCell from "./header/replies-cell";
import HeaderTopicCell from "./header/topic-cell";
import HeaderViewsCell from "./header/views-cell";
import ItemActivityCell from "./item/activity-cell";
import ItemBulkSelectCell from "./item/bulk-select-cell";
import ItemLikesCell from "./item/likes-cell";
import ItemOpLikesCell from "./item/op-likes-cell";
import ItemPostersCell from "./item/posters-cell";
import ItemRepliesCell from "./item/replies-cell";
import ItemTopicCell from "./item/topic-cell";
import ItemViewsCell from "./item/views-cell";
export default class TopicList extends Component {
@service currentUser;
@service topicTrackingState;
@tracked lastCheckedElementId;
@cached
get columns() {
const defaultColumns = new DAG({
// Allow customizations to replace just a header cell or just an item cell
onReplaceItem(_, newValue, oldValue) {
newValue.header ??= oldValue.header;
newValue.item ??= oldValue.item;
},
});
if (this.bulkSelectEnabled) {
defaultColumns.add("bulk-select", {
header: HeaderBulkSelectCell,
item: ItemBulkSelectCell,
});
}
defaultColumns.add("topic", {
header: HeaderTopicCell,
item: ItemTopicCell,
});
if (this.args.showPosters) {
defaultColumns.add("posters", {
header: HeaderPostersCell,
item: ItemPostersCell,
});
}
defaultColumns.add("replies", {
header: HeaderRepliesCell,
item: ItemRepliesCell,
});
if (this.args.order === "likes") {
defaultColumns.add("likes", {
header: HeaderLikesCell,
item: ItemLikesCell,
});
} else if (this.args.order === "op_likes") {
defaultColumns.add("op-likes", {
header: HeaderOpLikesCell,
item: ItemOpLikesCell,
});
}
defaultColumns.add("views", {
header: HeaderViewsCell,
item: ItemViewsCell,
});
defaultColumns.add("activity", {
header: HeaderActivityCell,
item: ItemActivityCell,
});
const self = this;
const context = {
get category() {
return self.topicTrackingState.get("filterCategory");
},
get filter() {
return self.topicTrackingState.get("filter");
},
};
return applyValueTransformer(
"topic-list-columns",
defaultColumns,
context
).resolve();
}
get selected() {
return this.args.bulkSelectHelper?.selected;
@ -34,12 +125,8 @@ export default class TopicList extends Component {
return !!this.args.changeSort;
}
get showLikes() {
return this.args.order === "likes";
}
get showOpLikes() {
return this.args.order === "op_likes";
get showTopicPostBadges() {
return this.args.showTopicPostBadges ?? true;
}
get lastVisitedTopic() {
@ -83,10 +170,6 @@ export default class TopicList extends Component {
return lastVisitedTopic;
}
get showTopicPostBadges() {
return this.args.showTopicPostBadges ?? true;
}
<template>
{{! template-lint-disable table-groups }}
<table
@ -97,21 +180,19 @@ export default class TopicList extends Component {
>
<caption class="sr-only">{{i18n "sr_topic_list_caption"}}</caption>
<thead class="topic-list-header">
<TopicListHeader
<Header
@columns={{this.columns}}
@canBulkSelect={{@canBulkSelect}}
@toggleInTitle={{this.toggleInTitle}}
@category={{@category}}
@hideCategory={{@hideCategory}}
@showPosters={{@showPosters}}
@showLikes={{this.showLikes}}
@showOpLikes={{this.showOpLikes}}
@order={{@order}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@sortable={{this.sortable}}
@listTitle={{or @listTitle "topic.title"}}
@bulkSelectEnabled={{this.bulkSelectEnabled}}
@bulkSelectHelper={{@bulkSelectHelper}}
@bulkSelectEnabled={{this.bulkSelectEnabled}}
@canDoBulkActions={{this.canDoBulkActions}}
@showTopicsAndRepliesToggle={{@showTopicsAndRepliesToggle}}
@newListSubset={{@newListSubset}}
@ -135,20 +216,17 @@ export default class TopicList extends Component {
<tbody class="topic-list-body">
{{#each @topics as |topic index|}}
<TopicListItem
<Item
@columns={{this.columns}}
@topic={{topic}}
@bulkSelectHelper={{@bulkSelectHelper}}
@bulkSelectEnabled={{this.bulkSelectEnabled}}
@showTopicPostBadges={{this.showTopicPostBadges}}
@hideCategory={{@hideCategory}}
@showPosters={{@showPosters}}
@showLikes={{this.showLikes}}
@showOpLikes={{this.showOpLikes}}
@expandGloballyPinned={{@expandGloballyPinned}}
@expandAllPinned={{@expandAllPinned}}
@lastVisitedTopic={{this.lastVisitedTopic}}
@selected={{this.selected}}
@lastCheckedElementId={{this.lastCheckedElementId}}
@updateLastCheckedElementId={{fn (mut this.lastCheckedElementId)}}
@tagsForUser={{@tagsForUser}}
@focusLastVisitedTopic={{@focusLastVisitedTopic}}
@index={{index}}

View File

@ -1,5 +1,5 @@
import { and } from "truth-helpers";
import PostsCountColumn from "discourse/components/topic-list/posts-count-column";
import ItemRepliesCell from "discourse/components/topic-list/item/replies-cell";
import TopicPostBadges from "discourse/components/topic-post-badges";
const PostCountOrBadges = <template>
@ -10,7 +10,7 @@ const PostCountOrBadges = <template>
@url={{@topic.lastUnreadUrl}}
/>
{{else}}
<PostsCountColumn @topic={{@topic}} @tagName="div" />
<ItemRepliesCell @topic={{@topic}} @tagName="div" />
{{/if}}
</template>;

View File

@ -1,116 +0,0 @@
import { on } from "@ember/modifier";
import PluginOutlet from "discourse/components/plugin-outlet";
import TopicListHeaderColumn from "discourse/components/topic-list/topic-list-header-column";
import icon from "discourse-common/helpers/d-icon";
import { i18n } from "discourse-i18n";
const TopicListHeader = <template>
<tr>
<PluginOutlet @name="topic-list-header-before" />
{{#if @bulkSelectEnabled}}
<th class="bulk-select topic-list-data">
{{#if @canBulkSelect}}
<button
{{on "click" @bulkSelectHelper.toggleBulkSelect}}
title={{i18n "topics.bulk.toggle"}}
class="btn-flat bulk-select"
>
{{icon "list-check"}}
</button>
{{/if}}
</th>
{{/if}}
<TopicListHeaderColumn
@order="default"
@category={{@category}}
@activeOrder={{@order}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name={{@listTitle}}
@bulkSelectEnabled={{@bulkSelectEnabled}}
@showBulkToggle={{@toggleInTitle}}
@canBulkSelect={{@canBulkSelect}}
@canDoBulkActions={{@canDoBulkActions}}
@showTopicsAndRepliesToggle={{@showTopicsAndRepliesToggle}}
@newListSubset={{@newListSubset}}
@newRepliesCount={{@newRepliesCount}}
@newTopicsCount={{@newTopicsCount}}
@bulkSelectHelper={{@bulkSelectHelper}}
@changeNewListSubset={{@changeNewListSubset}}
/>
<PluginOutlet @name="topic-list-header-after-main-link" />
{{#if @showPosters}}
<TopicListHeaderColumn
@order="posters"
@activeOrder={{@order}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="posters"
@screenreaderOnly={{true}}
aria-label={{i18n "category.sort_options.posters"}}
/>
{{/if}}
<TopicListHeaderColumn
@sortable={{@sortable}}
@number="true"
@order="posts"
@activeOrder={{@order}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="replies"
/>
{{#if @showLikes}}
<TopicListHeaderColumn
@sortable={{@sortable}}
@number="true"
@order="likes"
@activeOrder={{@order}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="likes"
/>
{{/if}}
{{#if @showOpLikes}}
<TopicListHeaderColumn
@sortable={{@sortable}}
@number="true"
@order="op_likes"
@activeOrder={{@order}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="likes"
/>
{{/if}}
<TopicListHeaderColumn
@sortable={{@sortable}}
@number="true"
@order="views"
@activeOrder={{@order}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="views"
/>
<TopicListHeaderColumn
@sortable={{@sortable}}
@number="true"
@order="activity"
@activeOrder={{@order}}
@changeSort={{@changeSort}}
@ascending={{@ascending}}
@name="activity"
/>
<PluginOutlet @name="topic-list-header-after" />
</tr>
</template>;
export default TopicListHeader;

View File

@ -1,10 +1,10 @@
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { getOwner, setOwner } from "@ember/owner";
import { service } from "@ember/service";
import { TrackedArray } from "@ember-compat/tracked-built-ins";
import { NotificationLevels } from "discourse/lib/notification-levels";
import Topic from "discourse/models/topic";
import { bind } from "discourse-common/utils/decorators";
export default class BulkSelectHelper {
@service router;
@ -15,6 +15,7 @@ export default class BulkSelectHelper {
@tracked bulkSelectEnabled = false;
@tracked autoAddTopicsToBulkSelect = false;
@tracked autoAddBookmarksToBulkSelect = false;
@tracked lastCheckedElementId = null;
selected = new TrackedArray();
@ -24,6 +25,7 @@ export default class BulkSelectHelper {
clear() {
this.selected.length = 0;
this.lastCheckedElementId = null;
}
addTopics(topics) {
@ -34,8 +36,9 @@ export default class BulkSelectHelper {
return this.selected.mapBy("category_id").uniq();
}
@bind
toggleBulkSelect() {
@action
toggleBulkSelect(event) {
event?.preventDefault();
this.bulkSelectEnabled = !this.bulkSelectEnabled;
this.clear();
}

View File

@ -1,10 +1,7 @@
import DAGMap from "dag-map";
import { makeArray } from "discourse-common/lib/helpers";
import { bind } from "discourse-common/utils/decorators";
function ensureArray(val) {
return Array.isArray(val) ? val : [val];
}
export default class DAG {
/**
* Creates a new DAG instance from an iterable of entries.
@ -75,10 +72,10 @@ export default class DAG {
*/
#defaultPositionForKey(key) {
const pos = { ...this.#defaultPosition };
if (ensureArray(pos.before).includes(key)) {
if (makeArray(pos.before).includes(key)) {
delete pos.before;
}
if (ensureArray(pos.after).includes(key)) {
if (makeArray(pos.after).includes(key)) {
delete pos.after;
}
return pos;

View File

@ -15,4 +15,5 @@ export const VALUE_TRANSFORMERS = Object.freeze([
"more-topics-tabs",
"post-menu-buttons",
"small-user-attrs",
"topic-list-columns",
]);