mirror of
https://github.com/flarum/core.git
synced 2025-08-05 07:57:46 +02:00
WIP: set up webpack, TypeScript environment, start JS app refactor
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,3 +5,5 @@ Thumbs.db
|
|||||||
tests/_output/*
|
tests/_output/*
|
||||||
.vagrant
|
.vagrant
|
||||||
.idea/*
|
.idea/*
|
||||||
|
node_modules
|
||||||
|
bower_components
|
1
js/.gitignore
vendored
1
js/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
bower_components
|
|
2
js/admin/.gitignore
vendored
2
js/admin/.gitignore
vendored
@@ -1 +1 @@
|
|||||||
node_modules
|
dist
|
@@ -1,31 +0,0 @@
|
|||||||
var gulp = require('flarum-gulp');
|
|
||||||
|
|
||||||
var bowerDir = '../bower_components';
|
|
||||||
|
|
||||||
gulp({
|
|
||||||
includeHelpers: true,
|
|
||||||
files: [
|
|
||||||
bowerDir + '/es6-micro-loader/dist/system-polyfill.js',
|
|
||||||
|
|
||||||
bowerDir + '/mithril/mithril.js',
|
|
||||||
bowerDir + '/m.attrs.bidi/bidi.js',
|
|
||||||
bowerDir + '/jquery/dist/jquery.js',
|
|
||||||
bowerDir + '/moment/moment.js',
|
|
||||||
|
|
||||||
bowerDir + '/bootstrap/js/affix.js',
|
|
||||||
bowerDir + '/bootstrap/js/dropdown.js',
|
|
||||||
bowerDir + '/bootstrap/js/modal.js',
|
|
||||||
bowerDir + '/bootstrap/js/tooltip.js',
|
|
||||||
bowerDir + '/bootstrap/js/transition.js',
|
|
||||||
|
|
||||||
bowerDir + '/spin.js/spin.js',
|
|
||||||
bowerDir + '/spin.js/jquery.spin.js'
|
|
||||||
],
|
|
||||||
modules: {
|
|
||||||
'flarum': [
|
|
||||||
'src/**/*.js',
|
|
||||||
'../lib/**/*.js'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
outputFile: 'dist/app.js'
|
|
||||||
});
|
|
25004
js/admin/dist/app.js
vendored
25004
js/admin/dist/app.js
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"private": true,
|
|
||||||
"devDependencies": {
|
|
||||||
"gulp": "^3.9.1",
|
|
||||||
"flarum-gulp": "^0.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
53
js/admin/src/AdminApplication.tsx
Normal file
53
js/admin/src/AdminApplication.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import * as m from 'mithril';
|
||||||
|
import Application from './lib/Application';
|
||||||
|
import routes from './routes';
|
||||||
|
import Nav from './components/Nav';
|
||||||
|
|
||||||
|
export default class AdminApplication extends Application {
|
||||||
|
/**
|
||||||
|
* A map of extension names to their settings callbacks.
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
extensionSettings = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a list of permissions required to have the given permission.
|
||||||
|
*
|
||||||
|
* @param {String} permission
|
||||||
|
* @return {Array}
|
||||||
|
*/
|
||||||
|
getRequiredPermissions(permission) {
|
||||||
|
const required = [];
|
||||||
|
|
||||||
|
if (permission === 'startDiscussion' || permission.indexOf('discussion.') === 0) {
|
||||||
|
required.push('viewDiscussions');
|
||||||
|
}
|
||||||
|
if (permission === 'discussion.delete') {
|
||||||
|
required.push('discussion.hide');
|
||||||
|
}
|
||||||
|
if (permission === 'discussion.deletePosts') {
|
||||||
|
required.push('discussion.editPosts');
|
||||||
|
}
|
||||||
|
|
||||||
|
return required;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
mount() {
|
||||||
|
m.route.prefix('#');
|
||||||
|
|
||||||
|
super.mount();
|
||||||
|
|
||||||
|
m.mount(document.getElementById('nav'), <Nav/>);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
registerDefaultRoutes(router) {
|
||||||
|
routes(router);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,33 +0,0 @@
|
|||||||
import App from 'flarum/App';
|
|
||||||
import store from 'flarum/initializers/store';
|
|
||||||
import preload from 'flarum/initializers/preload';
|
|
||||||
import routes from 'flarum/initializers/routes';
|
|
||||||
import boot from 'flarum/initializers/boot';
|
|
||||||
|
|
||||||
const app = new App();
|
|
||||||
|
|
||||||
app.initializers.add('store', store);
|
|
||||||
app.initializers.add('routes', routes);
|
|
||||||
|
|
||||||
app.initializers.add('preload', preload, -100);
|
|
||||||
app.initializers.add('boot', boot, -100);
|
|
||||||
|
|
||||||
app.extensionSettings = {};
|
|
||||||
|
|
||||||
app.getRequiredPermissions = function(permission) {
|
|
||||||
const required = [];
|
|
||||||
|
|
||||||
if (permission === 'startDiscussion' || permission.indexOf('discussion.') === 0) {
|
|
||||||
required.push('viewDiscussions');
|
|
||||||
}
|
|
||||||
if (permission === 'discussion.delete') {
|
|
||||||
required.push('discussion.hide');
|
|
||||||
}
|
|
||||||
if (permission === 'discussion.deletePosts') {
|
|
||||||
required.push('discussion.editPosts');
|
|
||||||
}
|
|
||||||
|
|
||||||
return required;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default app;
|
|
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import Modal from 'flarum/components/Modal';
|
|
||||||
|
|
||||||
export default class AddExtensionModal extends Modal {
|
|
||||||
className() {
|
|
||||||
return 'AddExtensionModal Modal--small';
|
|
||||||
}
|
|
||||||
|
|
||||||
title() {
|
|
||||||
return app.translator.trans('core.admin.add_extension.title');
|
|
||||||
}
|
|
||||||
|
|
||||||
content() {
|
|
||||||
return (
|
|
||||||
<div className="Modal-body">
|
|
||||||
<p>{app.translator.trans('core.admin.add_extension.temporary_text')}</p>
|
|
||||||
<p>{app.translator.trans('core.admin.add_extension.install_text', {a: <a href="https://discuss.flarum.org/t/extensions" target="_blank"/>})}</p>
|
|
||||||
<p>{app.translator.trans('core.admin.add_extension.developer_text', {a: <a href="http://flarum.org/docs/extend" target="_blank"/>})}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
40
js/admin/src/components/AddExtensionModal.tsx
Normal file
40
js/admin/src/components/AddExtensionModal.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import flarum from 'flarum';
|
||||||
|
import Modal from 'flarum/lib/components/Modal';
|
||||||
|
|
||||||
|
export default class AddExtensionModal extends Modal {
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
className() {
|
||||||
|
return super.className() + ' AddExtensionModal Modal--small';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
title() {
|
||||||
|
return flarum.translator.trans('admin.add_extension.title');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
content() {
|
||||||
|
return (
|
||||||
|
<div className="Modal-body">
|
||||||
|
<p>{flarum.translator.trans('admin.add_extension.temporary_text')}</p>
|
||||||
|
<p>{flarum.translator.trans('admin.add_extension.install_text', {a: <a href="https://discuss.flarum.org/t/extensions" target="_blank"/>})}</p>
|
||||||
|
<p>{flarum.translator.trans('admin.add_extension.developer_text', {a: <a href="http://flarum.org/docs/extend" target="_blank"/>})}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import LinkButton from 'flarum/components/LinkButton';
|
|
||||||
|
|
||||||
export default class AdminLinkButton extends LinkButton {
|
|
||||||
getButtonContent() {
|
|
||||||
const content = super.getButtonContent();
|
|
||||||
|
|
||||||
content.push(
|
|
||||||
<div className="AdminLinkButton-description">
|
|
||||||
{this.props.description}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
}
|
|
33
js/admin/src/components/AdminLinkButton.tsx
Normal file
33
js/admin/src/components/AdminLinkButton.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import LinkButton from 'flarum/lib/components/LinkButton';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export default class AdminLinkButton extends LinkButton {
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
className() {
|
||||||
|
return super.className() + ' AdminLinkButton';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
content() {
|
||||||
|
const content = super.content();
|
||||||
|
|
||||||
|
content.push(<div className="AdminLinkButton-description">{this.attrs.description}</div>);
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import Component from 'flarum/Component';
|
|
||||||
import AdminLinkButton from 'flarum/components/AdminLinkButton';
|
|
||||||
import SelectDropdown from 'flarum/components/SelectDropdown';
|
|
||||||
|
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
|
||||||
|
|
||||||
export default class AdminNav extends Component {
|
|
||||||
view() {
|
|
||||||
return (
|
|
||||||
<SelectDropdown
|
|
||||||
className="AdminNav App-titleControl"
|
|
||||||
buttonClassName="Button"
|
|
||||||
children={this.items().toArray()}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an item list of links to show in the admin navigation.
|
|
||||||
*
|
|
||||||
* @return {ItemList}
|
|
||||||
*/
|
|
||||||
items() {
|
|
||||||
const items = new ItemList();
|
|
||||||
|
|
||||||
items.add('dashboard', AdminLinkButton.component({
|
|
||||||
href: app.route('dashboard'),
|
|
||||||
icon: 'bar-chart',
|
|
||||||
children: app.translator.trans('core.admin.nav.dashboard_button'),
|
|
||||||
description: app.translator.trans('core.admin.nav.dashboard_text')
|
|
||||||
}));
|
|
||||||
|
|
||||||
items.add('basics', AdminLinkButton.component({
|
|
||||||
href: app.route('basics'),
|
|
||||||
icon: 'pencil',
|
|
||||||
children: app.translator.trans('core.admin.nav.basics_button'),
|
|
||||||
description: app.translator.trans('core.admin.nav.basics_text')
|
|
||||||
}));
|
|
||||||
|
|
||||||
items.add('mail', AdminLinkButton.component({
|
|
||||||
href: app.route('mail'),
|
|
||||||
icon: 'envelope',
|
|
||||||
children: app.translator.trans('core.admin.nav.email_button'),
|
|
||||||
description: app.translator.trans('core.admin.nav.email_text')
|
|
||||||
}));
|
|
||||||
|
|
||||||
items.add('permissions', AdminLinkButton.component({
|
|
||||||
href: app.route('permissions'),
|
|
||||||
icon: 'key',
|
|
||||||
children: app.translator.trans('core.admin.nav.permissions_button'),
|
|
||||||
description: app.translator.trans('core.admin.nav.permissions_text')
|
|
||||||
}));
|
|
||||||
|
|
||||||
items.add('appearance', AdminLinkButton.component({
|
|
||||||
href: app.route('appearance'),
|
|
||||||
icon: 'paint-brush',
|
|
||||||
children: app.translator.trans('core.admin.nav.appearance_button'),
|
|
||||||
description: app.translator.trans('core.admin.nav.appearance_text')
|
|
||||||
}));
|
|
||||||
|
|
||||||
items.add('extensions', AdminLinkButton.component({
|
|
||||||
href: app.route('extensions'),
|
|
||||||
icon: 'puzzle-piece',
|
|
||||||
children: app.translator.trans('core.admin.nav.extensions_button'),
|
|
||||||
description: app.translator.trans('core.admin.nav.extensions_text')
|
|
||||||
}));
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
}
|
|
52
js/admin/src/components/AdminNav.tsx
Normal file
52
js/admin/src/components/AdminNav.tsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Component from 'flarum/lib/Component';
|
||||||
|
import ItemList from 'flarum/lib/utils/ItemList';
|
||||||
|
import AdminLinkButton from 'flarum/components/AdminLinkButton';
|
||||||
|
import SelectDropdown from 'flarum/components/SelectDropdown';
|
||||||
|
|
||||||
|
function addLink(items, route, icon) {
|
||||||
|
items.add(route, <AdminLinkButton
|
||||||
|
href={flarum.router.to(route)}
|
||||||
|
icon={icon}
|
||||||
|
children={flarum.translator.trans(`admin.nav.${route}_button`)}
|
||||||
|
description={flarum.translator.trans(`admin.nav.${route}_text`)}/>);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export default class Nav extends Component {
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
view() {
|
||||||
|
return <SelectDropdown className="Nav" buttonClassName="Button" children={this.items().toArray()}/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an item list of links to show in the admin navigation.
|
||||||
|
*
|
||||||
|
* @return {ItemList}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
items() {
|
||||||
|
const items = new ItemList();
|
||||||
|
|
||||||
|
addLink(items, 'dashboard', 'bar-chart'));
|
||||||
|
addLink(items, 'basics', 'pencil'));
|
||||||
|
addLink(items, 'mail', 'envelope'));
|
||||||
|
addLink(items, 'permissions', 'key'));
|
||||||
|
addLink(items, 'appearance', 'paint-brush'));
|
||||||
|
addLink(items, 'extensions', 'puzzle-piece'));
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
25
js/admin/src/components/Header.tsx
Normal file
25
js/admin/src/components/Header.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import Component from 'flarum/Component';
|
||||||
|
import ItemList from 'flarum/utils/ItemList';
|
||||||
|
import SessionDropdown from './SessionDropdown';
|
||||||
|
|
||||||
|
export default class Header extends Component {
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
view() {
|
||||||
|
return this.items().toVnodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an item list for the header contents.
|
||||||
|
*
|
||||||
|
* @return {ItemList}
|
||||||
|
*/
|
||||||
|
items() {
|
||||||
|
const items = new ItemList();
|
||||||
|
|
||||||
|
items.add('session', <SessionDropdown/>);
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,37 +0,0 @@
|
|||||||
import Component from 'flarum/Component';
|
|
||||||
import SessionDropdown from 'flarum/components/SessionDropdown';
|
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
|
||||||
import listItems from 'flarum/helpers/listItems';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `HeaderSecondary` component displays secondary header controls.
|
|
||||||
*/
|
|
||||||
export default class HeaderSecondary extends Component {
|
|
||||||
view() {
|
|
||||||
return (
|
|
||||||
<ul className="Header-controls">
|
|
||||||
{listItems(this.items().toArray())}
|
|
||||||
</ul>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
config(isInitialized, context) {
|
|
||||||
// Since this component is 'above' the content of the page (that is, it is a
|
|
||||||
// part of the global UI that persists between routes), we will flag the DOM
|
|
||||||
// to be retained across route changes.
|
|
||||||
context.retain = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an item list for the controls.
|
|
||||||
*
|
|
||||||
* @return {ItemList}
|
|
||||||
*/
|
|
||||||
items() {
|
|
||||||
const items = new ItemList();
|
|
||||||
|
|
||||||
items.add('session', SessionDropdown.component());
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
}
|
|
9
js/admin/src/index.ts
Normal file
9
js/admin/src/index.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import AdminApplication from './AdminApplication';
|
||||||
|
|
||||||
|
export const app = new AdminApplication();
|
||||||
|
|
||||||
|
export const extensions = [];
|
||||||
|
|
||||||
|
// Export public API
|
||||||
|
// export { default as Extend } from './Extend';
|
||||||
|
// export { IndexPage, DicsussionList } from './components';
|
@@ -1,66 +0,0 @@
|
|||||||
/*global FastClick*/
|
|
||||||
|
|
||||||
import ScrollListener from 'flarum/utils/ScrollListener';
|
|
||||||
import Drawer from 'flarum/utils/Drawer';
|
|
||||||
import mapRoutes from 'flarum/utils/mapRoutes';
|
|
||||||
|
|
||||||
import Navigation from 'flarum/components/Navigation';
|
|
||||||
import HeaderPrimary from 'flarum/components/HeaderPrimary';
|
|
||||||
import HeaderSecondary from 'flarum/components/HeaderSecondary';
|
|
||||||
import AdminNav from 'flarum/components/AdminNav';
|
|
||||||
import ModalManager from 'flarum/components/ModalManager';
|
|
||||||
import AlertManager from 'flarum/components/AlertManager';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `boot` initializer boots up the admin app. It initializes some app
|
|
||||||
* globals, mounts components to the page, and begins routing.
|
|
||||||
*
|
|
||||||
* @param {ForumApp} app
|
|
||||||
*/
|
|
||||||
export default function boot(app) {
|
|
||||||
m.startComputation();
|
|
||||||
|
|
||||||
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());
|
|
||||||
m.mount(document.getElementById('admin-navigation'), AdminNav.component());
|
|
||||||
|
|
||||||
app.drawer = new Drawer();
|
|
||||||
app.modal = m.mount(document.getElementById('modal'), ModalManager.component());
|
|
||||||
app.alerts = m.mount(document.getElementById('alerts'), AlertManager.component());
|
|
||||||
app.history = {
|
|
||||||
canGoBack: () => true,
|
|
||||||
getPrevious: () => {},
|
|
||||||
backUrl: () => app.forum.attribute('baseUrl'),
|
|
||||||
back: function() {
|
|
||||||
window.location = this.backUrl();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
m.route.mode = 'hash';
|
|
||||||
m.route(document.getElementById('content'), '/', mapRoutes(app.routes));
|
|
||||||
|
|
||||||
m.endComputation();
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
app.booted = true;
|
|
||||||
|
|
||||||
// If an extension has just been enabled, then we will run its settings
|
|
||||||
// callback.
|
|
||||||
const enabled = localStorage.getItem('enabledExtension');
|
|
||||||
if (enabled && app.extensionSettings[enabled]) {
|
|
||||||
app.extensionSettings[enabled]();
|
|
||||||
localStorage.removeItem('enabledExtension');
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,22 +0,0 @@
|
|||||||
import DashboardPage from 'flarum/components/DashboardPage';
|
|
||||||
import BasicsPage from 'flarum/components/BasicsPage';
|
|
||||||
import PermissionsPage from 'flarum/components/PermissionsPage';
|
|
||||||
import AppearancePage from 'flarum/components/AppearancePage';
|
|
||||||
import ExtensionsPage from 'flarum/components/ExtensionsPage';
|
|
||||||
import MailPage from 'flarum/components/MailPage';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `routes` initializer defines the admin app's routes.
|
|
||||||
*
|
|
||||||
* @param {App} app
|
|
||||||
*/
|
|
||||||
export default function(app) {
|
|
||||||
app.routes = {
|
|
||||||
'dashboard': {path: '/', component: DashboardPage.component()},
|
|
||||||
'basics': {path: '/basics', component: BasicsPage.component()},
|
|
||||||
'permissions': {path: '/permissions', component: PermissionsPage.component()},
|
|
||||||
'appearance': {path: '/appearance', component: AppearancePage.component()},
|
|
||||||
'extensions': {path: '/extensions', component: ExtensionsPage.component()},
|
|
||||||
'mail': {path: '/mail', component: MailPage.component()}
|
|
||||||
};
|
|
||||||
}
|
|
1
js/admin/src/lib
Symbolic link
1
js/admin/src/lib
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
/Users/toby/Projects/Flarum/app/packages/core/js/lib
|
15
js/admin/src/routes.ts
Normal file
15
js/admin/src/routes.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
@@ -1,14 +0,0 @@
|
|||||||
export default function saveSettings(settings) {
|
|
||||||
const oldSettings = JSON.parse(JSON.stringify(app.data.settings));
|
|
||||||
|
|
||||||
Object.assign(app.data.settings, settings);
|
|
||||||
|
|
||||||
return app.request({
|
|
||||||
method: 'POST',
|
|
||||||
url: app.forum.attribute('apiUrl') + '/settings',
|
|
||||||
data: settings
|
|
||||||
}).catch(error => {
|
|
||||||
app.data.settings = oldSettings;
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
}
|
|
22
js/admin/src/utils/saveSettings.tsx
Normal file
22
js/admin/src/utils/saveSettings.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import flarum from 'flarum';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a request to save the given settings to the database.
|
||||||
|
*
|
||||||
|
* @param {Object} settings
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
export default function saveSettings(settings) {
|
||||||
|
const oldSettings = JSON.parse(JSON.stringify(flarum.data.settings));
|
||||||
|
|
||||||
|
Object.assign(flarum.data.settings, settings);
|
||||||
|
|
||||||
|
return flarum.ajax.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: flarum.forum.apiUrl + '/settings',
|
||||||
|
data: settings
|
||||||
|
}).catch(error => {
|
||||||
|
flarum.data.settings = oldSettings;
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
}
|
23
js/admin/tsconfig.json
Normal file
23
js/admin/tsconfig.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./dist/",
|
||||||
|
"sourceMap": true,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es5",
|
||||||
|
"jsx": "react",
|
||||||
|
"jsxFactory": "m",
|
||||||
|
"declaration": true,
|
||||||
|
"lib": ["dom", "es2015"],
|
||||||
|
"types": [
|
||||||
|
"mithril",
|
||||||
|
"classnames"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"./src/**/*"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
30
js/admin/webpack.config.js
Normal file
30
js/admin/webpack.config.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const { CheckerPlugin } = require('awesome-typescript-loader');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: path.resolve(__dirname, 'src/index.tsx'),
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.ts', '.tsx', '.js', '.jsx']
|
||||||
|
},
|
||||||
|
devtool: 'source-map',
|
||||||
|
output: {
|
||||||
|
filename: 'bundle.js',
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
library: 'flarum',
|
||||||
|
libraryTarget: 'var'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
loader: 'awesome-typescript-loader'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new CheckerPlugin()
|
||||||
|
],
|
||||||
|
externals: {
|
||||||
|
mithril: 'm'
|
||||||
|
}
|
||||||
|
};
|
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "flarum",
|
|
||||||
"dependencies": {
|
|
||||||
"jquery": "~3.1.1",
|
|
||||||
"jquery.hotkeys": "jeresig/jquery.hotkeys#0.2.0",
|
|
||||||
"bootstrap": "~3.3.2",
|
|
||||||
"spin.js": "~2.0.1",
|
|
||||||
"moment": "~2.8.4",
|
|
||||||
"color-thief": "v2.0",
|
|
||||||
"mithril": "lhorie/mithril.js#v0.2.5",
|
|
||||||
"es6-micro-loader": "caridy/es6-micro-loader#v0.2.1",
|
|
||||||
"fastclick": "~1.0.6",
|
|
||||||
"autolink": "~1.0.0",
|
|
||||||
"m.attrs.bidi": "tobscure/m.attrs.bidi",
|
|
||||||
"punycode": "http://cdnjs.cloudflare.com/ajax/libs/punycode/1.4.1/punycode.js"
|
|
||||||
}
|
|
||||||
}
|
|
2
js/forum/.gitignore
vendored
2
js/forum/.gitignore
vendored
@@ -1 +1 @@
|
|||||||
node_modules
|
dist
|
@@ -1,36 +0,0 @@
|
|||||||
var gulp = require('flarum-gulp');
|
|
||||||
|
|
||||||
var bowerDir = '../bower_components';
|
|
||||||
|
|
||||||
gulp({
|
|
||||||
includeHelpers: true,
|
|
||||||
files: [
|
|
||||||
bowerDir + '/es6-micro-loader/dist/system-polyfill.js',
|
|
||||||
|
|
||||||
bowerDir + '/mithril/mithril.js',
|
|
||||||
bowerDir + '/m.attrs.bidi/bidi.js',
|
|
||||||
bowerDir + '/jquery/dist/jquery.js',
|
|
||||||
bowerDir + '/jquery.hotkeys/jquery.hotkeys.js',
|
|
||||||
bowerDir + '/color-thief/src/color-thief.js',
|
|
||||||
bowerDir + '/moment/moment.js',
|
|
||||||
bowerDir + '/autolink/autolink-min.js',
|
|
||||||
|
|
||||||
bowerDir + '/bootstrap/js/affix.js',
|
|
||||||
bowerDir + '/bootstrap/js/dropdown.js',
|
|
||||||
bowerDir + '/bootstrap/js/modal.js',
|
|
||||||
bowerDir + '/bootstrap/js/tooltip.js',
|
|
||||||
bowerDir + '/bootstrap/js/transition.js',
|
|
||||||
|
|
||||||
bowerDir + '/spin.js/spin.js',
|
|
||||||
bowerDir + '/spin.js/jquery.spin.js',
|
|
||||||
bowerDir + '/fastclick/lib/fastclick.js',
|
|
||||||
bowerDir + '/punycode/index.js'
|
|
||||||
],
|
|
||||||
modules: {
|
|
||||||
'flarum': [
|
|
||||||
'src/**/*.js',
|
|
||||||
'../lib/**/*.js'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
outputFile: 'dist/app.js'
|
|
||||||
});
|
|
33996
js/forum/dist/app.js
vendored
33996
js/forum/dist/app.js
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"private": true,
|
|
||||||
"devDependencies": {
|
|
||||||
"gulp": "^3.9.1",
|
|
||||||
"flarum-gulp": "^0.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,57 +1,46 @@
|
|||||||
import History from 'flarum/utils/History';
|
import * as m from 'mithril';
|
||||||
import App from 'flarum/App';
|
import Application from './lib/Application';
|
||||||
import Search from 'flarum/components/Search';
|
import routes from './routes';
|
||||||
import Composer from 'flarum/components/Composer';
|
import Nav from './components/Nav';
|
||||||
import ReplyComposer from 'flarum/components/ReplyComposer';
|
|
||||||
import DiscussionPage from 'flarum/components/DiscussionPage';
|
|
||||||
import SignUpModal from 'flarum/components/SignUpModal';
|
|
||||||
|
|
||||||
export default class ForumApp extends App {
|
export default class ForumApplication extends Application {
|
||||||
constructor(...args) {
|
/**
|
||||||
super(...args);
|
* A map of notification types to their components.
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
notificationComponents = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The app's history stack, which keeps track of which routes the user visits
|
* A map of post types to their components.
|
||||||
* so that they can easily navigate back to the previous route.
|
*
|
||||||
*
|
* @type {Object}
|
||||||
* @type {History}
|
*/
|
||||||
*/
|
postComponents = {};
|
||||||
this.history = new History();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object which controls the state of the page's side pane.
|
* The page's search component instance.
|
||||||
*
|
*
|
||||||
* @type {Pane}
|
* @type {SearchBox}
|
||||||
*/
|
*/
|
||||||
this.pane = null;
|
search = new Search();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The page's search component instance.
|
* @inheritdoc
|
||||||
*
|
*/
|
||||||
* @type {SearchBox}
|
mount() {
|
||||||
*/
|
m.route.prefix('#');
|
||||||
this.search = new Search();
|
|
||||||
|
|
||||||
/**
|
super.mount();
|
||||||
* An object which controls the state of the page's drawer.
|
|
||||||
*
|
|
||||||
* @type {Drawer}
|
|
||||||
*/
|
|
||||||
this.drawer = null;
|
|
||||||
|
|
||||||
/**
|
m.mount(document.getElementById('nav'), <Nav/>);
|
||||||
* A map of post types to their components.
|
}
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
this.postComponents = {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A map of notification types to their components.
|
* @inheritdoc
|
||||||
*
|
*/
|
||||||
* @type {Object}
|
registerDefaultRoutes(router) {
|
||||||
*/
|
routes(router);
|
||||||
this.notificationComponents = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
@@ -1,21 +0,0 @@
|
|||||||
import ForumApp from 'flarum/ForumApp';
|
|
||||||
import store from 'flarum/initializers/store';
|
|
||||||
import preload from 'flarum/initializers/preload';
|
|
||||||
import routes from 'flarum/initializers/routes';
|
|
||||||
import components from 'flarum/initializers/components';
|
|
||||||
import humanTime from 'flarum/initializers/humanTime';
|
|
||||||
import boot from 'flarum/initializers/boot';
|
|
||||||
import alertEmailConfirmation from 'flarum/initializers/alertEmailConfirmation';
|
|
||||||
|
|
||||||
const app = new ForumApp();
|
|
||||||
|
|
||||||
app.initializers.add('store', store);
|
|
||||||
app.initializers.add('routes', routes);
|
|
||||||
app.initializers.add('components', components);
|
|
||||||
app.initializers.add('humanTime', humanTime);
|
|
||||||
|
|
||||||
app.initializers.add('preload', preload, -100);
|
|
||||||
app.initializers.add('boot', boot, -100);
|
|
||||||
app.initializers.add('alertEmailConfirmation', alertEmailConfirmation, -100);
|
|
||||||
|
|
||||||
export default app;
|
|
@@ -1,33 +0,0 @@
|
|||||||
import Component from 'flarum/Component';
|
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
|
||||||
import listItems from 'flarum/helpers/listItems';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `HeaderPrimary` component displays primary header controls. On the
|
|
||||||
* default skin, these are shown just to the right of the forum title.
|
|
||||||
*/
|
|
||||||
export default class HeaderPrimary extends Component {
|
|
||||||
view() {
|
|
||||||
return (
|
|
||||||
<ul className="Header-controls">
|
|
||||||
{listItems(this.items().toArray())}
|
|
||||||
</ul>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
config(isInitialized, context) {
|
|
||||||
// Since this component is 'above' the content of the page (that is, it is a
|
|
||||||
// part of the global UI that persists between routes), we will flag the DOM
|
|
||||||
// to be retained across route changes.
|
|
||||||
context.retain = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an item list for the controls.
|
|
||||||
*
|
|
||||||
* @return {ItemList}
|
|
||||||
*/
|
|
||||||
items() {
|
|
||||||
return new ItemList();
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user