1
0
mirror of https://github.com/flarum/core.git synced 2025-07-27 19:50:20 +02:00
Files
php-flarum/js/forum/src/components/discussion-list.js
2015-04-25 22:28:39 +09:30

198 lines
6.0 KiB
JavaScript

import Component from 'flarum/component';
import avatar from 'flarum/helpers/avatar';
import listItems from 'flarum/helpers/list-items';
import humanTime from 'flarum/utils/human-time';
import ItemList from 'flarum/utils/item-list';
import abbreviateNumber from 'flarum/utils/abbreviate-number';
import ActionButton from 'flarum/components/action-button';
import DropdownButton from 'flarum/components/dropdown-button';
import LoadingIndicator from 'flarum/components/loading-indicator';
import TerminalPost from 'flarum/components/terminal-post';
export default class DiscussionList extends Component {
constructor(props) {
super(props);
this.loading = m.prop(true);
this.moreResults = m.prop(false);
this.discussions = m.prop([]);
this.sort = m.prop(this.props.sort || 'recent');
this.sortOptions = m.prop([
{key: 'recent', value: 'Recent', sort: 'recent'},
{key: 'replies', value: 'Replies', sort: '-replies'},
{key: 'newest', value: 'Newest', sort: '-created'},
{key: 'oldest', value: 'Oldest', sort: 'created'}
]);
this.refresh();
app.session.on('loggedIn', this.loggedInHandler = this.refresh.bind(this))
}
refresh() {
m.startComputation();
this.loading(true);
this.discussions([]);
m.endComputation();
this.loadResults().then(this.parseResults.bind(this));
}
onunload() {
app.session.off('loggedIn', this.loggedInHandler);
}
terminalPostType() {
return ['newest', 'oldest'].indexOf(this.sort()) !== -1 ? 'start' : 'last'
}
countType() {
return this.sort() === 'replies' ? 'replies' : 'unread';
}
loadResults(start) {
var self = this;
var sort = this.sortOptions()[0].sort;
this.sortOptions().some(function(option) {
if (option.key === self.sort()) {
sort = option.sort;
return true;
}
});
var params = {sort, start};
return app.store.find('discussions', params);
}
loadMore() {
var self = this;
this.loading(true);
this.loadResults(this.discussions().length).then((results) => this.parseResults(results, true));
}
parseResults(results, append) {
m.startComputation();
this.loading(false);
[].push.apply(this.discussions(), results);
this.moreResults(!!results.meta.moreUrl);
m.endComputation();
return results;
}
markAsRead(discussion) {
if (discussion.isUnread()) {
discussion.save({ readNumber: discussion.lastPostNumber() });
m.redraw();
}
}
delete(discussion) {
if (confirm('Are you sure you want to delete this discussion?')) {
discussion.delete();
this.removeDiscussion(discussion);
if (app.current.discussion && app.current.discussion().id() === discussion.id()) {
app.history.back();
}
}
}
removeDiscussion(discussion) {
var index = this.discussions().indexOf(discussion);
if (index !== -1) {
this.discussions().splice(index, 1);
}
}
view() {
return m('div', [
m('ul.discussions-list', [
this.discussions().map(function(discussion) {
var startUser = discussion.startUser()
var isUnread = discussion.isUnread()
var displayUnread = this.props.countType !== 'replies' && isUnread
var jumpTo = Math.min(discussion.lastPostNumber(), (discussion.readNumber() || 0) + 1)
var controls = this.controlItems(discussion).toArray();
var discussionRoute = app.route('discussion', discussion);
var active = m.route().substr(0, discussionRoute.length) === discussionRoute;
return m('li.discussion-summary'+(isUnread ? '.unread' : '')+(active ? '.active' : ''), {key: discussion.id()}, [
controls.length ? DropdownButton.component({
items: controls,
className: 'contextual-controls',
buttonClass: 'btn btn-default btn-icon btn-sm btn-naked',
menuClass: 'pull-right'
}) : '',
m('a.author', {
href: app.route('user', startUser),
config: function(element, isInitialized, context) {
$(element).tooltip({ placement: 'right' })
m.route.call(this, element)
},
title: 'Started by '+startUser.username()+' '+humanTime(discussion.startTime())
}, [
avatar(startUser, {title: ''})
]),
m('ul.badges', listItems(discussion.badges().toArray())),
m('a.main', {href: app.route('discussion.near', {id: discussion.id(), slug: discussion.slug(), near: jumpTo}), config: m.route}, [
m('h3.title', discussion.title()),
m('ul.info', listItems(this.infoItems(discussion).toArray()))
]),
m('span.count', {onclick: this.markAsRead.bind(this, discussion)}, [
abbreviateNumber(discussion[displayUnread ? 'unreadCount' : 'repliesCount']()),
m('span.label', displayUnread ? 'unread' : 'replies')
])
])
}.bind(this))
]),
this.loading()
? LoadingIndicator.component()
: (this.moreResults() ? m('div.load-more', ActionButton.component({
label: 'Load More',
className: 'control-loadMore btn btn-default',
onclick: this.loadMore.bind(this)
})) : '')
]);
}
/**
Build an item list of info for a discussion listing. By default this is
just the first/last post indicator.
@return {ItemList}
*/
infoItems(discussion) {
var items = new ItemList();
items.add('terminalPost',
TerminalPost.component({
discussion,
lastPost: this.props.terminalPostType !== 'start'
})
);
return items;
}
/**
Build an item list of controls for a discussion listing.
@return {ItemList}
*/
controlItems(discussion) {
var items = new ItemList();
if (discussion.canDelete()) {
items.add('delete', ActionButton.component({
icon: 'times',
label: 'Delete',
onclick: this.delete.bind(this, discussion)
}));
}
return items;
}
}