1
0
mirror of https://github.com/flarum/core.git synced 2025-08-04 07:27:39 +02:00

WIP: move some things around

This commit is contained in:
Toby Zerner
2017-06-27 14:01:19 +09:30
parent 8b3971f202
commit fd3f484eaf
22 changed files with 124 additions and 319 deletions

View File

@@ -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();
// }
// }
}

View File

@@ -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;
}

View File

@@ -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()
});
};
}

View File

@@ -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()
// });
// };
}

View File

@@ -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('/');
}
}

View File

@@ -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
View File

@@ -0,0 +1,3 @@
export default class DocumentTitle {
}

View File

@@ -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
});
}

View File

@@ -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;
}