mirror of
https://github.com/flarum/core.git
synced 2025-08-01 22:20:21 +02:00
Webpack (#1367)
* Replace gulp with webpack and npm scripts for JS compilation * Set up Travis CI to commit compiled JS * Restructure `js` directory; only one instance of npm, forum/admin are "submodules" * Refactor JS initializers into Application subclasses * Maintain partial compatibility API (importing from absolute paths) for extensions * Remove minification responsibility from PHP asset compiler * Restructure `less` directory
This commit is contained in:
167
js/src/forum/ForumApplication.js
Normal file
167
js/src/forum/ForumApplication.js
Normal file
@@ -0,0 +1,167 @@
|
||||
import History from './utils/History';
|
||||
import Pane from './utils/Pane';
|
||||
import Search from './components/Search';
|
||||
import ReplyComposer from './components/ReplyComposer';
|
||||
import DiscussionPage from './components/DiscussionPage';
|
||||
import SignUpModal from './components/SignUpModal';
|
||||
import HeaderPrimary from './components/HeaderPrimary';
|
||||
import HeaderSecondary from './components/HeaderSecondary';
|
||||
import Composer from './components/Composer';
|
||||
import DiscussionRenamedNotification from './components/DiscussionRenamedNotification';
|
||||
import CommentPost from './components/CommentPost';
|
||||
import DiscussionRenamedPost from './components/DiscussionRenamedPost';
|
||||
import routes from './routes';
|
||||
import alertEmailConfirmation from './utils/alertEmailConfirmation';
|
||||
import Application from '../common/Application';
|
||||
import Navigation from '../common/components/Navigation';
|
||||
|
||||
export default class ForumApplication extends Application {
|
||||
/**
|
||||
* A map of notification types to their components.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
notificationComponents = {
|
||||
discussionRenamed: DiscussionRenamedNotification
|
||||
};
|
||||
/**
|
||||
* A map of post types to their components.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
postComponents = {
|
||||
comment: CommentPost,
|
||||
discussionRenamed: DiscussionRenamedPost
|
||||
};
|
||||
|
||||
/**
|
||||
* The page's search component instance.
|
||||
*
|
||||
* @type {SearchBox}
|
||||
*/
|
||||
search = new Search();
|
||||
|
||||
/**
|
||||
* An object which controls the state of the page's side pane.
|
||||
*
|
||||
* @type {Pane}
|
||||
*/
|
||||
pane = null;
|
||||
|
||||
/**
|
||||
* An object which controls the state of the page's drawer.
|
||||
*
|
||||
* @type {Drawer}
|
||||
*/
|
||||
drawer = null;
|
||||
|
||||
/**
|
||||
* The app's history stack, which keeps track of which routes the user visits
|
||||
* so that they can easily navigate back to the previous route.
|
||||
*
|
||||
* @type {History}
|
||||
*/
|
||||
history = new History();
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
boot(data) {
|
||||
routes(this);
|
||||
|
||||
super.boot(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
mount() {
|
||||
// Get the configured default route and update that route's path to be '/'.
|
||||
// Push the homepage as the first route, so that the user will always be
|
||||
// able to click on the 'back' button to go home, regardless of which page
|
||||
// they started on.
|
||||
const defaultRoute = this.forum.attribute('defaultRoute');
|
||||
let defaultAction = 'index';
|
||||
|
||||
for (const i in this.routes) {
|
||||
if (this.routes[i].path === defaultRoute) defaultAction = i;
|
||||
}
|
||||
|
||||
this.routes[defaultAction].path = '/';
|
||||
this.history.push(defaultAction, this.translator.trans('core.forum.header.back_to_index_tooltip'), '/');
|
||||
|
||||
m.mount(document.getElementById('app-navigation'), Navigation.component({className: 'App-backControl', drawer: true}));
|
||||
m.mount(document.getElementById('header-navigation'), Navigation.component());
|
||||
m.mount(document.getElementById('header-primary'), HeaderPrimary.component());
|
||||
m.mount(document.getElementById('header-secondary'), HeaderSecondary.component());
|
||||
|
||||
this.pane = new Pane(document.getElementById('app'));
|
||||
this.composer = m.mount(document.getElementById('composer'), Composer.component());
|
||||
|
||||
m.route.mode = 'pathname';
|
||||
super.mount();
|
||||
|
||||
alertEmailConfirmation(this);
|
||||
|
||||
// Route the home link back home when clicked. We do not want it to register
|
||||
// if the user is opening it in a new tab, however.
|
||||
$('#home-link').click(e => {
|
||||
if (e.ctrlKey || e.metaKey || e.which === 2) return;
|
||||
e.preventDefault();
|
||||
app.history.home();
|
||||
|
||||
// Reload the current user so that their unread notification count is refreshed.
|
||||
if (app.session.user) {
|
||||
app.store.find('users', app.session.user.id());
|
||||
m.redraw();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not the user is currently composing a reply to a
|
||||
* discussion.
|
||||
*
|
||||
* @param {Discussion} discussion
|
||||
* @return {Boolean}
|
||||
*/
|
||||
composingReplyTo(discussion) {
|
||||
return this.composer.component instanceof ReplyComposer &&
|
||||
this.composer.component.props.discussion === discussion &&
|
||||
this.composer.position !== Composer.PositionEnum.HIDDEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not the user is currently viewing a discussion.
|
||||
*
|
||||
* @param {Discussion} discussion
|
||||
* @return {Boolean}
|
||||
*/
|
||||
viewingDiscussion(discussion) {
|
||||
return this.current instanceof DiscussionPage &&
|
||||
this.current.discussion === discussion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for when an external authenticator (social login) action has
|
||||
* completed.
|
||||
*
|
||||
* If the payload indicates that the user has been logged in, then the page
|
||||
* will be reloaded. Otherwise, a SignUpModal will be opened, prefilled
|
||||
* with the provided details.
|
||||
*
|
||||
* @param {Object} payload A dictionary of props to pass into the sign up
|
||||
* modal. A truthy `authenticated` prop indicates that the user has logged
|
||||
* in, and thus the page is reloaded.
|
||||
* @public
|
||||
*/
|
||||
authenticationComplete(payload) {
|
||||
if (payload.authenticated) {
|
||||
window.location.reload();
|
||||
} else {
|
||||
const modal = new SignUpModal(payload);
|
||||
this.modal.show(modal);
|
||||
modal.$('[name=password]').focus();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user