revert Application implementation from experimental breaking change to use existing implementation in master

This commit is contained in:
David Sevilla Martin 2020-03-14 11:41:00 -04:00
parent 4484f3e35f
commit ef47e09300
No known key found for this signature in database
GPG Key ID: F764F1417E16B15F
7 changed files with 31261 additions and 1227 deletions

32237
js/dist/forum.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,5 @@
import Mithril from 'mithril';
import Bus from './Bus';
import Translator from './Translator';
import Session from './Session';
import Store from './Store';
@ -10,6 +9,8 @@ import extract from './utils/extract';
import mapRoutes from './utils/mapRoutes';
import Drawer from './utils/Drawer';
import RequestError from './utils/RequestError';
import ItemList from './utils/ItemList';
import ScrollListener from './utils/ScrollListener';
import Forum from './models/Forum';
import Discussion from './models/Discussion';
@ -23,6 +24,8 @@ import Button from './components/Button';
import ModalManager from './components/ModalManager';
import RequestErrorModal from './components/RequestErrorModal';
import { flattenDeep } from 'lodash-es';
export type ApplicationData = {
apiDocument: any;
locale: string;
@ -35,22 +38,39 @@ export default abstract class Application {
/**
* The forum model for this application.
*/
forum: Forum;
public forum!: Forum;
data: ApplicationData;
/**
* A map of routes, keyed by a unique route name. Each route is an object
* containing the following properties:
*
* - `path` The path that the route is accessed at.
* - `component` The Mithril component to render when this route is active.
*
* @example
* app.routes.discussion = {path: '/d/:id', component: DiscussionPage.component()};
*/
public routes: { [key: string]: { path: string; component: any; [key: string]: any } } = {};
translator = new Translator();
bus = new Bus();
/**
* An ordered list of initializers to bootstrap the application.
*/
public initializers = new ItemList();
/**
* The app's session.
*/
session: Session;
public session!: Session;
/**
* The app's translator.
*/
public translator = new Translator();
/**
* The app's data store.
*/
store = new Store({
public store = new Store({
forums: Forum,
users: User,
discussions: Discussion,
@ -59,37 +79,38 @@ export default abstract class Application {
notifications: Notification,
});
drawer = new Drawer();
modal: ModalManager;
/**
* A local cache that can be used to store data at the application level, so
* that is persists between different routes.
*/
cache: { [key: string]: any } = {};
public cache: { [key: string]: any } = {};
routes = {};
title = '';
titleCount = 0;
/**
* Whether or not the app has been booted.
*/
public booted: boolean = false;
/**
* An Alert that was shown as a result of an AJAX request error. If present,
* it will be dismissed on the next successful request.
*/
private requestError: Alert = null;
private requestError: Alert | null = null;
mount(basePath = '') {
m.mount(document.getElementById('modal'), new ModalManager());
data!: ApplicationData;
// this.alerts = m.mount(document.getElementById('alerts'), <AlertManager />);
title = '';
titleCount = 0;
m.route(document.getElementById('content'), basePath + '/', mapRoutes(this.routes, basePath));
drawer = new Drawer();
modal!: ModalManager;
load(payload) {
this.data = payload;
this.translator.locale = payload.locale;
}
boot(payload: any) {
this.data = payload;
boot() {
this.initializers.toArray().forEach(initializer => initializer(this));
this.store.pushPayload({ data: this.data.resources });
@ -97,26 +118,42 @@ export default abstract class Application {
this.session = new Session(this.store.getById('users', this.data.session.userId), this.data.session.csrfToken);
this.locale();
this.plugins();
this.setupRoutes();
this.mount();
this.bus.dispatch('app.booting');
this.booted = true;
}
locale() {
this.translator.locale = this.data.locale;
bootExtensions(extensions) {
Object.keys(extensions).forEach(name => {
const extension = extensions[name];
this.bus.dispatch('app.locale');
const extenders = flattenDeep(extension.extend);
for (const extender of extenders) {
extender.extend(this, { name, exports: extension });
}
});
}
plugins() {
this.bus.dispatch('app.plugins');
}
mount(basePath = '') {
m.mount(document.getElementById('modal'), new ModalManager());
setupRoutes() {
this.bus.dispatch('app.routes');
// this.alerts = m.mount(document.getElementById('alerts'), <AlertManager />);
m.route(document.getElementById('content'), basePath + '/', mapRoutes(this.routes, basePath));
// Add a class to the body which indicates that the page has been scrolled
// down.
new ScrollListener(top => {
const $app = $('#app');
const offset = $app.offset().top;
$app.toggleClass('affix', top >= offset).toggleClass('scrolled', top > offset);
}).start();
$(() => {
$('body').addClass('ontouchstart' in window ? 'touch' : 'no-touch');
});
}
/**

View File

@ -3,44 +3,24 @@ import History from './utils/History';
import HeaderPrimary from './components/HeaderPrimary';
import HeaderSecondary from './components/HeaderSecondary';
import Page from './components/Page';
import IndexPage from './components/IndexPage';
import DiscussionList from './components/DiscussionList';
import DiscussionPage from './components/DiscussionPage';
import PostsUserPage from './components/PostsUserPage';
import DiscussionsUserPage from './components/DiscussionsUserPage';
import SettingsPage from './components/SettingsPage';
import CommentPost from './components/CommentPost';
import User from '../common/models/User';
import Post from '../common/models/Post';
import Discussion from '../common/models/Discussion';
import Notification from '../common/models/Notification';
import routes from './routes';
export default class Forum extends Application {
routes = {
index: { path: '/all', component: IndexPage },
discussion: { path: '/d/:id', component: DiscussionPage },
'discussion.near': { path: '/d/:id/:near', component: DiscussionPage },
user: { path: '/u/:username', component: PostsUserPage },
'user.posts': { path: '/u/:username', component: PostsUserPage },
'user.discussions': { path: '/u/:username/discussions', component: DiscussionsUserPage },
settings: { path: '/settings', component: SettingsPage },
'index.filter': { path: '/:filter', component: IndexPage },
};
/**
* 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.
*/
history: History = new History();
/**
* {@inheritdoc}
*/
cache: {
notifications?: Notification[][];
discussionList?: DiscussionList;
@ -55,6 +35,12 @@ export default class Forum extends Application {
previous: Page;
current: Page;
constructor() {
super();
routes(this);
}
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
@ -97,36 +83,4 @@ export default class Forum extends Application {
}
});
}
setupRoutes() {
super.setupRoutes();
this.route.discussion = (discussion: Discussion, near?: number): string => {
const slug = discussion?.slug();
const hasNear = near && near !== 1;
const params = {
id: discussion.id() + (slug.trim() ? '-' + slug : ''),
};
if (hasNear) params['near'] = near;
return this.route(near && near !== 1 ? 'discussion.near' : 'discussion', params);
};
/**
* Generate a URL to a post.
*/
this.route.post = (post: Post): string => {
return this.route.discussion(post.discussion(), post.number());
};
/**
* Generate a URL to a user.
*/
this.route.user = (user: User): string => {
return this.route('user', {
username: user.username(),
});
};
}
}

View File

@ -5,17 +5,6 @@ const app = new Forum();
// @ts-ignore
window.app = app;
app.bus.subscribe('app.plugins', () => {
// @ts-ignore
const extensions = flarum.extensions;
Object.keys(extensions).forEach(name => {
const extension = extensions[name];
// if (typeof extension === 'function') extension();
});
});
export { app };
// Export compat API

57
js/src/forum/routes.ts Normal file
View File

@ -0,0 +1,57 @@
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 Discussion from '../common/models/Discussion';
import Post from '../common/models/Post';
import User from '../common/models/User';
export default app => {
app.routes = {
index: { path: '/all', component: IndexPage },
discussion: { path: '/d/:id', component: DiscussionPage },
'discussion.near': { path: '/d/:id/:near', component: DiscussionPage },
user: { path: '/u/:username', component: PostsUserPage },
'user.posts': { path: '/u/:username', component: PostsUserPage },
'user.discussions': { path: '/u/:username/discussions', component: DiscussionsUserPage },
settings: { path: '/settings', component: SettingsPage },
'index.filter': { path: '/:filter', component: IndexPage },
};
/**
* Generate a URL to a discussion.
*/
app.route.discussion = (discussion: Discussion, near?: number): string => {
const slug = discussion?.slug();
const hasNear = near && near !== 1;
const params = {
id: discussion.id() + (slug.trim() ? '-' + slug : ''),
};
if (hasNear) params['near'] = near;
return app.route(hasNear ? 'discussion.near' : 'discussion', params);
};
/**
* Generate a URL to a post.
*/
app.route.post = (post: Post): string => {
return app.route.discussion(post.discussion(), post.number());
};
/**
* Generate a URL to a user.
*/
app.route.user = (user: User): string => {
return app.route('user', {
username: user.username(),
});
};
};

View File

@ -25,9 +25,9 @@
document.getElementById('flarum-loading').style.display = 'none';
try {
app.boot(@json($payload));
// flarum.core.app.bootExtensions(flarum.extensions);
// flarum.core.app.boot();
flarum.core.app.load(@json($payload));
flarum.core.app.bootExtensions(flarum.extensions);
flarum.core.app.boot();
} catch (e) {
var error = document.getElementById('flarum-loading-error');
error.innerHTML += document.getElementById('flarum-content').textContent;