1
0
mirror of https://github.com/flarum/core.git synced 2025-10-10 14:34:30 +02:00
Files
php-flarum/js/forum/src/components/index-page.js

241 lines
6.6 KiB
JavaScript

import Component from 'flarum/component';
import ItemList from 'flarum/utils/item-list';
import listItems from 'flarum/helpers/list-items';
import Discussion from 'flarum/models/discussion';
import mixin from 'flarum/utils/mixin';
import DiscussionList from 'flarum/components/discussion-list';
import WelcomeHero from 'flarum/components/welcome-hero';
import ComposerDiscussion from 'flarum/components/composer-discussion';
import LoginModal from 'flarum/components/login-modal';
import DiscussionPage from 'flarum/components/discussion-page';
import SelectInput from 'flarum/components/select-input';
import ActionButton from 'flarum/components/action-button';
import NavItem from 'flarum/components/nav-item';
import LoadingIndicator from 'flarum/components/loading-indicator';
import DropdownSelect from 'flarum/components/dropdown-select';
export default class IndexPage extends Component {
constructor(props) {
super(props);
var params = this.params();
if (app.cache.discussionList) {
app.cache.discussionList.subtrees.map(subtree => subtree.invalidate());
Object.keys(params).some(key => {
if (app.cache.discussionList.props.params[key] !== params[key]) {
app.cache.discussionList = null;
return true;
}
});
}
if (!app.cache.discussionList) {
app.cache.discussionList = new DiscussionList({params});
}
if (app.current instanceof DiscussionPage) {
this.lastDiscussion = app.current.discussion();
}
app.history.push('index');
app.current = this;
}
onunload() {
app.cache.scrollTop = $(window).scrollTop();
app.composer.minimize();
}
/**
Params that stick between filter changes
*/
stickyParams() {
return {
sort: m.route.param('sort'),
show: m.route.param('show'),
q: m.route.param('q')
}
}
/**
Params which are passed to the DiscussionList
*/
params() {
var params = this.stickyParams();
params.filter = m.route.param('filter');
return params;
}
reorder(sort) {
var params = this.params();
if (sort === 'recent') {
delete params.sort;
} else {
params.sort = sort;
}
m.route(app.route(this.props.routeName, params));
}
/**
Render the component.
@method view
@return void
*/
view() {
var sortOptions = {};
for (var i in app.cache.discussionList.sortMap()) {
sortOptions[i] = i.substr(0, 1).toUpperCase()+i.substr(1);
}
return m('div.index-area', {config: this.onload.bind(this)}, [
WelcomeHero.component(),
m('div.container', [
m('nav.side-nav.index-nav', {config: this.affixSidebar}, [
m('ul', listItems(this.sidebarItems().toArray()))
]),
m('div.offset-content.index-results', [
m('div.index-toolbar', [
m('div.index-toolbar-view', [
SelectInput.component({
options: sortOptions,
value: m.route.param('sort'),
onchange: this.reorder.bind(this)
}),
]),
m('div.index-toolbar-action', [
ActionButton.component({
title: 'Mark All as Read',
icon: 'check',
className: 'control-markAllAsRead btn btn-default btn-icon',
onclick: this.markAllAsRead.bind(this)
})
])
]),
app.cache.discussionList.view()
])
])
])
}
onload(element, isInitialized, context) {
if (isInitialized) { return; }
this.element(element);
$('body').addClass('index-page');
context.onunload = function() {
$('body').removeClass('index-page');
}
var scrollTop = app.cache.scrollTop;
$(window).scrollTop(scrollTop);
if (this.lastDiscussion) {
var $discussion = this.$('.discussion-summary[data-id='+this.lastDiscussion.id()+']');
if ($discussion.length) {
var indexTop = $('#header').outerHeight();
var discussionTop = $discussion.offset().top;
if (discussionTop < scrollTop + indexTop || discussionTop + $discussion.outerHeight() > scrollTop + $(window).height()) {
$(window).scrollTop(discussionTop - indexTop);
}
}
}
app.setTitle('');
}
newDiscussion() {
if (app.session.user()) {
app.composer.load(new ComposerDiscussion({ user: app.session.user() }));
app.composer.show();
return true;
} else {
app.modal.show(new LoginModal({
message: 'You must be logged in to do that.',
callback: this.newDiscussion.bind(this)
}));
}
}
markAllAsRead() {
app.session.user().save({ readTime: new Date() });
}
/**
Build an item list for the sidebar of the index page. By default this is a
"New Discussion" button, and then a DropdownSelect component containing a
list of navigation items (see this.navItems).
@return {ItemList}
*/
sidebarItems() {
var items = new ItemList();
items.add('newDiscussion',
ActionButton.component({
label: 'Start a Discussion',
icon: 'edit',
className: 'btn btn-primary new-discussion',
wrapperClass: 'primary-control',
onclick: this.newDiscussion.bind(this)
})
);
items.add('nav',
DropdownSelect.component({
items: this.navItems(this).toArray(),
wrapperClass: 'title-control'
})
);
return items;
}
/**
Build an item list for the navigation in the sidebar of the index page. By
default this is just the 'All Discussions' link.
@return {ItemList}
*/
navItems() {
var items = new ItemList();
var params = {sort: m.route.param('sort')};
items.add('allDiscussions',
NavItem.component({
href: app.route('index', params),
label: 'All Discussions',
icon: 'comments-o'
})
);
return items;
}
/**
Setup the sidebar DOM element to be affixed to the top of the viewport
using Bootstrap's affix plugin.
@param {DOMElement} element
@param {Boolean} isInitialized
@return {void}
*/
affixSidebar(element, isInitialized) {
if (isInitialized) { return; }
var $sidebar = $(element);
// Don't affix the sidebar if it is taller than the viewport (otherwise
// there would be no way to scroll through its content).
if ($sidebar.outerHeight(true) > $(window).height() - $('.global-header').outerHeight(true)) return;
$sidebar.find('> ul').affix({
offset: {
top: () => $sidebar.offset().top - $('.global-header').outerHeight(true) - parseInt($sidebar.css('margin-top')),
bottom: () => (this.bottom = $('.global-footer').outerHeight(true))
}
});
}
};