mirror of
https://github.com/flarum/core.git
synced 2025-08-04 15:37:51 +02:00
WIP: move some things around
This commit is contained in:
@@ -1,9 +1,15 @@
|
||||
import * as m from 'mithril';
|
||||
import Application from './lib/Application';
|
||||
import routes from './routes';
|
||||
import Nav from './components/Nav';
|
||||
import Search from './components/Search';
|
||||
|
||||
export default class ForumApplication extends Application {
|
||||
/**
|
||||
* The page's search component instance.
|
||||
*
|
||||
* @type {SearchBox}
|
||||
*/
|
||||
search = new Search();
|
||||
|
||||
/**
|
||||
* A map of notification types to their components.
|
||||
*
|
||||
@@ -18,23 +24,10 @@ export default class ForumApplication extends Application {
|
||||
*/
|
||||
postComponents = {};
|
||||
|
||||
/**
|
||||
* The page's search component instance.
|
||||
*
|
||||
* @type {SearchBox}
|
||||
*/
|
||||
search = new Search();
|
||||
//app.postComponents.comment = CommentPost;
|
||||
//app.postComponents.discussionRenamed = DiscussionRenamedPost;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
mount() {
|
||||
m.route.prefix('#');
|
||||
|
||||
super.mount();
|
||||
|
||||
m.mount(document.getElementById('nav'), <Nav/>);
|
||||
}
|
||||
// app.notificationComponents.discussionRenamed = DiscussionRenamedNotification;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
@@ -43,50 +36,51 @@ export default class ForumApplication extends Application {
|
||||
routes(router);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
// TODO: work out where to put these helper functions
|
||||
// /**
|
||||
// * 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();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@@ -1,16 +0,0 @@
|
||||
import CommentPost from 'flarum/components/CommentPost';
|
||||
import DiscussionRenamedPost from 'flarum/components/DiscussionRenamedPost';
|
||||
import DiscussionRenamedNotification from 'flarum/components/DiscussionRenamedNotification';
|
||||
|
||||
/**
|
||||
* The `components` initializer registers components to display the default post
|
||||
* types, activity types, and notifications type with the application.
|
||||
*
|
||||
* @param {ForumApp} app
|
||||
*/
|
||||
export default function components(app) {
|
||||
app.postComponents.comment = CommentPost;
|
||||
app.postComponents.discussionRenamed = DiscussionRenamedPost;
|
||||
|
||||
app.notificationComponents.discussionRenamed = DiscussionRenamedNotification;
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
import IndexPage from 'flarum/components/IndexPage';
|
||||
import DiscussionPage from 'flarum/components/DiscussionPage';
|
||||
import PostsUserPage from 'flarum/components/PostsUserPage';
|
||||
import DiscussionsUserPage from 'flarum/components/DiscussionsUserPage';
|
||||
import SettingsPage from 'flarum/components/SettingsPage';
|
||||
import NotificationsPage from 'flarum/components/NotificationsPage';
|
||||
|
||||
/**
|
||||
* The `routes` initializer defines the forum app's routes.
|
||||
*
|
||||
* @param {App} app
|
||||
*/
|
||||
export default function(app) {
|
||||
app.routes = {
|
||||
'index': {path: '/all', component: IndexPage.component()},
|
||||
'index.filter': {path: '/:filter', component: IndexPage.component()},
|
||||
|
||||
'discussion': {path: '/d/:id', component: DiscussionPage.component()},
|
||||
'discussion.near': {path: '/d/:id/:near', component: DiscussionPage.component()},
|
||||
|
||||
'user': {path: '/u/:username', component: PostsUserPage.component()},
|
||||
'user.posts': {path: '/u/:username', component: PostsUserPage.component()},
|
||||
'user.discussions': {path: '/u/:username/discussions', component: DiscussionsUserPage.component()},
|
||||
|
||||
'settings': {path: '/settings', component: SettingsPage.component()},
|
||||
'notifications': {path: '/notifications', component: NotificationsPage.component()}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a URL to a discussion.
|
||||
*
|
||||
* @param {Discussion} discussion
|
||||
* @param {Integer} [near]
|
||||
* @return {String}
|
||||
*/
|
||||
app.route.discussion = (discussion, near) => {
|
||||
return app.route(near && near !== 1 ? 'discussion.near' : 'discussion', {
|
||||
id: discussion.id() + '-' + discussion.slug(),
|
||||
near: near && near !== 1 ? near : undefined
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a URL to a post.
|
||||
*
|
||||
* @param {Post} post
|
||||
* @return {String}
|
||||
*/
|
||||
app.route.post = post => {
|
||||
return app.route.discussion(post.discussion(), post.number());
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a URL to a user.
|
||||
*
|
||||
* @param {User} user
|
||||
* @return {String}
|
||||
*/
|
||||
app.route.user = user => {
|
||||
return app.route('user', {
|
||||
username: user.username()
|
||||
});
|
||||
};
|
||||
}
|
@@ -1,15 +1,58 @@
|
||||
import DashboardPage from './components/DashboardPage';
|
||||
import BasicsPage from './components/BasicsPage';
|
||||
import PermissionsPage from './components/PermissionsPage';
|
||||
import AppearancePage from './components/AppearancePage';
|
||||
import ExtensionsPage from './components/ExtensionsPage';
|
||||
import MailPage from './components/MailPage';
|
||||
import IndexPage from './components/IndexPage';
|
||||
import DiscussionPage from './components/DiscussionPage';
|
||||
import PostsUserPage from './components/PostsUserPage';
|
||||
import DiscussionsUserPage from './components/DiscussionsUserPage';
|
||||
import SettingsPage from './components/SettingsPage';
|
||||
import NotificationsPage from './components/NotificationsPage';
|
||||
|
||||
export default function(router) {
|
||||
router.add('dashboard', '/', DashboardPage);
|
||||
router.add('basics', '/basics', BasicsPage);
|
||||
router.add('permissions', '/permissions', PermissionsPage);
|
||||
router.add('appearance', '/appearance', AppearancePage);
|
||||
router.add('extensions', '/extensions', ExtensionsPage);
|
||||
router.add('mail', '/mail', MailPage);
|
||||
router.add('index', '/all', IndexPage);
|
||||
router.add('index.filter', '/:filter', IndexPage);
|
||||
|
||||
router.add('discussion', '/d/:id', DiscussionPage);
|
||||
router.add('discussion.near', '/d/:id/:near', DiscussionPage);
|
||||
|
||||
router.add('user', '/u/:username', PostsUserPage);
|
||||
router.add('user.posts', '/u/:username', PostsUserPage);
|
||||
router.add('user.discussions', '/u/:username/discussions', DiscussionsUserPage);
|
||||
|
||||
router.add('settings', '/settings', SettingsPage);
|
||||
router.add('notifications', '/notifications', NotificationsPage);
|
||||
|
||||
// TODO: work out where to put these shortcut functions
|
||||
// /**
|
||||
// * Generate a URL to a discussion.
|
||||
// *
|
||||
// * @param {Discussion} discussion
|
||||
// * @param {Integer} [near]
|
||||
// * @return {String}
|
||||
// */
|
||||
// app.route.discussion = (discussion, near) => {
|
||||
// return app.route(near && near !== 1 ? 'discussion.near' : 'discussion', {
|
||||
// id: discussion.id() + '-' + discussion.slug(),
|
||||
// near: near && near !== 1 ? near : undefined
|
||||
// });
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * Generate a URL to a post.
|
||||
// *
|
||||
// * @param {Post} post
|
||||
// * @return {String}
|
||||
// */
|
||||
// app.route.post = post => {
|
||||
// return app.route.discussion(post.discussion(), post.number());
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * Generate a URL to a user.
|
||||
// *
|
||||
// * @param {User} user
|
||||
// * @return {String}
|
||||
// */
|
||||
// app.route.user = user => {
|
||||
// return app.route('user', {
|
||||
// username: user.username()
|
||||
// });
|
||||
// };
|
||||
}
|
||||
|
@@ -1,115 +0,0 @@
|
||||
/**
|
||||
* The `History` class keeps track and manages a stack of routes that the user
|
||||
* has navigated to in their session.
|
||||
*
|
||||
* An item can be pushed to the top of the stack using the `push` method. An
|
||||
* item in the stack has a name and a URL. The name need not be unique; if it is
|
||||
* the same as the item before it, that will be overwritten with the new URL. In
|
||||
* this way, if a user visits a discussion, and then visits another discussion,
|
||||
* popping the history stack will still take them back to the discussion list
|
||||
* rather than the previous discussion.
|
||||
*/
|
||||
export default class History {
|
||||
constructor(defaultRoute) {
|
||||
/**
|
||||
* The stack of routes that have been navigated to.
|
||||
*
|
||||
* @type {Array}
|
||||
* @protected
|
||||
*/
|
||||
this.stack = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the item on the top of the stack.
|
||||
*
|
||||
* @return {Object}
|
||||
* @public
|
||||
*/
|
||||
getCurrent() {
|
||||
return this.stack[this.stack.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the previous item on the stack.
|
||||
*
|
||||
* @return {Object}
|
||||
* @public
|
||||
*/
|
||||
getPrevious() {
|
||||
return this.stack[this.stack.length - 2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an item to the top of the stack.
|
||||
*
|
||||
* @param {String} name The name of the route.
|
||||
* @param {String} title The title of the route.
|
||||
* @param {String} [url] The URL of the route. The current URL will be used if
|
||||
* not provided.
|
||||
* @public
|
||||
*/
|
||||
push(name, title, url = m.route()) {
|
||||
// If we're pushing an item with the same name as second-to-top item in the
|
||||
// stack, we will assume that the user has clicked the 'back' button in
|
||||
// their browser. In this case, we don't want to push a new item, so we will
|
||||
// pop off the top item, and then the second-to-top item will be overwritten
|
||||
// below.
|
||||
const secondTop = this.stack[this.stack.length - 2];
|
||||
if (secondTop && secondTop.name === name) {
|
||||
this.stack.pop();
|
||||
}
|
||||
|
||||
// If we're pushing an item with the same name as the top item in the stack,
|
||||
// then we'll overwrite it with the new URL.
|
||||
const top = this.getCurrent();
|
||||
if (top && top.name === name) {
|
||||
Object.assign(top, {url, title});
|
||||
} else {
|
||||
this.stack.push({name, url, title});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not the history stack is able to be popped.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @public
|
||||
*/
|
||||
canGoBack() {
|
||||
return this.stack.length > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go back to the previous route in the history stack.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
back() {
|
||||
this.stack.pop();
|
||||
|
||||
m.route(this.getCurrent().url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL of the previous page.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
backUrl() {
|
||||
const secondTop = this.stack[this.stack.length - 2];
|
||||
|
||||
return secondTop.url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to the first route in the history stack.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
home() {
|
||||
this.stack.splice(0);
|
||||
|
||||
m.route('/');
|
||||
}
|
||||
}
|
@@ -1,3 +1,4 @@
|
||||
import * as m from 'mithril';
|
||||
import ItemList from 'flarum/utils/ItemList';
|
||||
import Alert from 'flarum/components/Alert';
|
||||
import Button from 'flarum/components/Button';
|
||||
@@ -19,6 +20,7 @@ export default class Application {
|
||||
constructor() {
|
||||
/**
|
||||
* [data description]
|
||||
*
|
||||
* @type {[type]}
|
||||
*/
|
||||
this.data = null;
|
||||
@@ -33,6 +35,7 @@ export default class Application {
|
||||
|
||||
/**
|
||||
* [router description]
|
||||
*
|
||||
* @type {Router}
|
||||
*/
|
||||
this.router = new Router();
|
||||
@@ -72,12 +75,14 @@ export default class Application {
|
||||
|
||||
/**
|
||||
* [title description]
|
||||
*
|
||||
* @type {DocumentTitle}
|
||||
*/
|
||||
this.title = new DocumentTitle();
|
||||
|
||||
/**
|
||||
* [ajax description]
|
||||
*
|
||||
* @type {Ajax}
|
||||
*/
|
||||
this.ajax = new Ajax();
|
||||
@@ -91,6 +96,7 @@ export default class Application {
|
||||
|
||||
/**
|
||||
* [loadModules description]
|
||||
*
|
||||
* @param {[type]} modules [description]
|
||||
* @return {[type]}
|
||||
*/
|
||||
@@ -98,11 +104,11 @@ export default class Application {
|
||||
|
||||
}
|
||||
|
||||
*
|
||||
/**
|
||||
* Boot the application by running all of the registered initializers.
|
||||
*
|
||||
* @public
|
||||
|
||||
*/
|
||||
boot(data) {
|
||||
this.data = data;
|
||||
|
||||
|
3
js/lib/DocumentTitle.tsx
Normal file
3
js/lib/DocumentTitle.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
export default class DocumentTitle {
|
||||
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
import Store from 'flarum/Store';
|
||||
import Forum from 'flarum/models/Forum';
|
||||
import User from 'flarum/models/User';
|
||||
import Discussion from 'flarum/models/Discussion';
|
||||
import Post from 'flarum/models/Post';
|
||||
import Group from 'flarum/models/Group';
|
||||
import Activity from 'flarum/models/Activity';
|
||||
import Notification from 'flarum/models/Notification';
|
||||
|
||||
/**
|
||||
* The `store` initializer creates the application's data store and registers
|
||||
* the default resource types to their models.
|
||||
*
|
||||
* @param {App} app
|
||||
*/
|
||||
export default function store(app) {
|
||||
app.store = new Store({
|
||||
forums: Forum,
|
||||
users: User,
|
||||
discussions: Discussion,
|
||||
posts: Post,
|
||||
groups: Group,
|
||||
activity: Activity,
|
||||
notifications: Notification
|
||||
});
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* The `mixin` utility assigns the properties of a set of 'mixin' objects to
|
||||
* the prototype of a parent object.
|
||||
*
|
||||
* @example
|
||||
* class MyClass extends mixin(ExistingClass, evented, etc) {}
|
||||
*
|
||||
* @param {Class} Parent The class to extend the new class from.
|
||||
* @param {...Object} mixins The objects to mix in.
|
||||
* @return {Class} A new class that extends Parent and contains the mixins.
|
||||
*/
|
||||
export default function mixin(Parent, ...mixins) {
|
||||
class Mixed extends Parent {}
|
||||
|
||||
mixins.forEach(object => {
|
||||
Object.assign(Mixed.prototype, object);
|
||||
});
|
||||
|
||||
return Mixed;
|
||||
}
|
Reference in New Issue
Block a user