mirror of
https://github.com/discourse/discourse.git
synced 2024-11-26 03:23:38 +08:00
DEV: Refactor gjs topic-list (#29792)
Based on the initial review in #28934
This commit is contained in:
parent
bfe0eccdd9
commit
433543a516
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
|
||||
{{#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}}
|
||||
/>
|
||||
|
||||
<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}}
|
||||
/>
|
||||
{{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}}">
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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() {
|
|
@ -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;
|
|
@ -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
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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>;
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -15,4 +15,5 @@ export const VALUE_TRANSFORMERS = Object.freeze([
|
|||
"more-topics-tabs",
|
||||
"post-menu-buttons",
|
||||
"small-user-attrs",
|
||||
"topic-list-columns",
|
||||
]);
|
||||
|
|
Loading…
Reference in New Issue
Block a user