mirror of
https://github.com/flarum/core.git
synced 2025-10-10 22:44:25 +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:
BIN
.deploy.enc
Normal file
BIN
.deploy.enc
Normal file
Binary file not shown.
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -1,6 +1,8 @@
|
|||||||
.gitattributes export-ignore
|
.gitattributes export-ignore
|
||||||
.gitignore export-ignore
|
.gitignore export-ignore
|
||||||
.gitmodules export-ignore
|
.gitmodules export-ignore
|
||||||
|
.github export-ignore
|
||||||
|
.travis export-ignore
|
||||||
.travis.yml export-ignore
|
.travis.yml export-ignore
|
||||||
.editorconfig export-ignore
|
.editorconfig export-ignore
|
||||||
.styleci.yml export-ignore
|
.styleci.yml export-ignore
|
||||||
@@ -8,4 +10,4 @@
|
|||||||
phpunit.xml export-ignore
|
phpunit.xml export-ignore
|
||||||
tests export-ignore
|
tests export-ignore
|
||||||
|
|
||||||
js/*/dist/*.js -diff
|
js/dist/* -diff
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
/vendor
|
/vendor
|
||||||
composer.lock
|
composer.lock
|
||||||
composer.phar
|
composer.phar
|
||||||
|
node_modules
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
/tests/tmp
|
/tests/tmp
|
||||||
|
67
.travis.yml
67
.travis.yml
@@ -1,44 +1,45 @@
|
|||||||
language: php
|
language: php
|
||||||
|
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
env:
|
cache:
|
||||||
global:
|
directories:
|
||||||
- DB=mariadb
|
- $HOME/.composer/cache
|
||||||
|
- $HOME/.npm
|
||||||
|
|
||||||
addons:
|
install:
|
||||||
mariadb: '10.2'
|
|
||||||
|
|
||||||
php:
|
|
||||||
- 7.1
|
|
||||||
- 7.2
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
include:
|
|
||||||
- php: 7.1
|
|
||||||
addons: # to prevent mariadb
|
|
||||||
services: mysql
|
|
||||||
env:
|
|
||||||
- DB=mysql
|
|
||||||
- php: 7.2
|
|
||||||
addons: # to prevent mariadb
|
|
||||||
services: mysql
|
|
||||||
env:
|
|
||||||
- DB=mysql
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- mysql -e 'CREATE DATABASE flarum;'
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- composer self-update
|
|
||||||
- composer install
|
- composer install
|
||||||
|
- mysql -e 'CREATE DATABASE flarum;'
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- vendor/bin/phpunit --coverage-clover=coverage.xml
|
- vendor/bin/phpunit --coverage-clover=coverage.xml
|
||||||
|
|
||||||
notifications:
|
|
||||||
email:
|
|
||||||
on_failure: change
|
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
include:
|
||||||
|
- php: 7.1
|
||||||
|
env: DB=mysql
|
||||||
|
|
||||||
|
- php: 7.2
|
||||||
|
env: DB=mysql
|
||||||
|
|
||||||
|
- php: 7.1
|
||||||
|
addons:
|
||||||
|
mariadb: '10.2'
|
||||||
|
env: DB=mariadb
|
||||||
|
|
||||||
|
- php: 7.2
|
||||||
|
addons:
|
||||||
|
mariadb: '10.2'
|
||||||
|
env: DB=mariadb
|
||||||
|
|
||||||
|
- stage: build
|
||||||
|
language: generic
|
||||||
|
if: branch = master AND type = push
|
||||||
|
install: skip
|
||||||
|
script: bash .travis/build.sh
|
||||||
|
-k $encrypted_678139e2bc67_key
|
||||||
|
-i $encrypted_678139e2bc67_iv
|
||||||
|
after_success: skip
|
||||||
|
32
.travis/build.sh
Executable file
32
.travis/build.sh
Executable file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
main() {
|
||||||
|
while getopts ":k:i:" opt; do
|
||||||
|
case $opt in
|
||||||
|
k) encrypted_key="$OPTARG"
|
||||||
|
;;
|
||||||
|
i) encrypted_iv="$OPTARG"
|
||||||
|
;;
|
||||||
|
\?) echo "Invalid option -$OPTARG" >&2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
cd js
|
||||||
|
npm i -g npm@6.1.0
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
git add dist/* -f
|
||||||
|
git commit -m "Bundled output for commit $TRAVIS_COMMIT [skip ci]"
|
||||||
|
|
||||||
|
eval `ssh-agent -s`
|
||||||
|
openssl aes-256-cbc -K $encrypted_key -iv $encrypted_iv -in ../.deploy.enc -d | ssh-add -
|
||||||
|
|
||||||
|
git config user.name "flarum-bot"
|
||||||
|
git config user.email "bot@flarum.org"
|
||||||
|
|
||||||
|
git push git@github.com:$TRAVIS_REPO_SLUG.git $TRAVIS_BRANCH
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
1
js/.gitignore
vendored
1
js/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
bower_components
|
|
11
js/admin.js
Normal file
11
js/admin.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './src/common';
|
||||||
|
export * from './src/admin';
|
1
js/admin/.gitignore
vendored
1
js/admin/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
node_modules
|
|
@@ -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'
|
|
||||||
});
|
|
24217
js/admin/dist/app.js
vendored
24217
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"
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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,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,15 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "flarum",
|
|
||||||
"dependencies": {
|
|
||||||
"jquery": "~2.1.3",
|
|
||||||
"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",
|
|
||||||
"m.attrs.bidi": "tobscure/m.attrs.bidi",
|
|
||||||
"punycode": "http://cdnjs.cloudflare.com/ajax/libs/punycode/1.4.1/punycode.js"
|
|
||||||
}
|
|
||||||
}
|
|
40
js/dist/admin.js
vendored
Normal file
40
js/dist/admin.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
js/dist/admin.js.map
vendored
Normal file
1
js/dist/admin.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
67
js/dist/forum.js
vendored
Normal file
67
js/dist/forum.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
js/dist/forum.js.map
vendored
Normal file
1
js/dist/forum.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
11
js/forum.js
Normal file
11
js/forum.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './src/common';
|
||||||
|
export * from './src/forum';
|
1
js/forum/.gitignore
vendored
1
js/forum/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
node_modules
|
|
@@ -1,34 +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 + '/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 + '/punycode/index.js'
|
|
||||||
],
|
|
||||||
modules: {
|
|
||||||
'flarum': [
|
|
||||||
'src/**/*.js',
|
|
||||||
'../lib/**/*.js'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
outputFile: 'dist/app.js'
|
|
||||||
});
|
|
32178
js/forum/dist/app.js
vendored
32178
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,103 +0,0 @@
|
|||||||
import History from 'flarum/utils/History';
|
|
||||||
import App from 'flarum/App';
|
|
||||||
import Search from 'flarum/components/Search';
|
|
||||||
import Composer from 'flarum/components/Composer';
|
|
||||||
import ReplyComposer from 'flarum/components/ReplyComposer';
|
|
||||||
import DiscussionPage from 'flarum/components/DiscussionPage';
|
|
||||||
import SignUpModal from 'flarum/components/SignUpModal';
|
|
||||||
|
|
||||||
export default class ForumApp extends App {
|
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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}
|
|
||||||
*/
|
|
||||||
this.history = new History();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An object which controls the state of the page's side pane.
|
|
||||||
*
|
|
||||||
* @type {Pane}
|
|
||||||
*/
|
|
||||||
this.pane = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The page's search component instance.
|
|
||||||
*
|
|
||||||
* @type {SearchBox}
|
|
||||||
*/
|
|
||||||
this.search = new Search();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An object which controls the state of the page's drawer.
|
|
||||||
*
|
|
||||||
* @type {Drawer}
|
|
||||||
*/
|
|
||||||
this.drawer = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A map of post types to their components.
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
this.postComponents = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A map of notification types to their components.
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
this.notificationComponents = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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,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,86 +0,0 @@
|
|||||||
/*global FastClick*/
|
|
||||||
|
|
||||||
import ScrollListener from 'flarum/utils/ScrollListener';
|
|
||||||
import Pane from 'flarum/utils/Pane';
|
|
||||||
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 Composer from 'flarum/components/Composer';
|
|
||||||
import ModalManager from 'flarum/components/ModalManager';
|
|
||||||
import AlertManager from 'flarum/components/AlertManager';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `boot` initializer boots up the forum app. It initializes some app
|
|
||||||
* globals, mounts components to the page, and begins routing.
|
|
||||||
*
|
|
||||||
* @param {ForumApp} app
|
|
||||||
*/
|
|
||||||
export default function boot(app) {
|
|
||||||
// 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 = app.forum.attribute('defaultRoute');
|
|
||||||
let defaultAction = 'index';
|
|
||||||
|
|
||||||
for (const i in app.routes) {
|
|
||||||
if (app.routes[i].path === defaultRoute) defaultAction = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.routes[defaultAction].path = '/';
|
|
||||||
app.history.push(defaultAction, app.translator.trans('core.forum.header.back_to_index_tooltip'), '/');
|
|
||||||
|
|
||||||
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());
|
|
||||||
|
|
||||||
app.pane = new Pane(document.getElementById('app'));
|
|
||||||
app.drawer = new Drawer();
|
|
||||||
app.composer = m.mount(document.getElementById('composer'), Composer.component());
|
|
||||||
app.modal = m.mount(document.getElementById('modal'), ModalManager.component());
|
|
||||||
app.alerts = m.mount(document.getElementById('alerts'), AlertManager.component());
|
|
||||||
|
|
||||||
const basePath = app.forum.attribute('basePath');
|
|
||||||
m.route.mode = 'pathname';
|
|
||||||
m.route(
|
|
||||||
document.getElementById('content'),
|
|
||||||
basePath + '/',
|
|
||||||
mapRoutes(app.routes, basePath)
|
|
||||||
);
|
|
||||||
|
|
||||||
m.endComputation();
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
if (app.session.user) {
|
|
||||||
app.store.find('users', app.session.user.id());
|
|
||||||
m.redraw();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 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');
|
|
||||||
});
|
|
||||||
|
|
||||||
app.booted = true;
|
|
||||||
}
|
|
@@ -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,24 +0,0 @@
|
|||||||
import Session from 'flarum/Session';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `preload` initializer creates the application session and preloads it
|
|
||||||
* with data that has been set on the application's `preload` property. It also
|
|
||||||
* preloads any data on the application's `preload` property into the store.
|
|
||||||
* Finally, it sets the application's `forum` instance to the one that was
|
|
||||||
* preloaded.
|
|
||||||
*
|
|
||||||
* `app.preload.session` should be the same as the response from the /api/token
|
|
||||||
* endpoint: it should contain `token` and `userId` keys.
|
|
||||||
*
|
|
||||||
* @param {App} app
|
|
||||||
*/
|
|
||||||
export default function preload(app) {
|
|
||||||
app.store.pushPayload({data: app.data.resources});
|
|
||||||
|
|
||||||
app.forum = app.store.getById('forums', 1);
|
|
||||||
|
|
||||||
app.session = new Session(
|
|
||||||
app.store.getById('users', app.data.session.userId),
|
|
||||||
app.data.session.csrfToken
|
|
||||||
);
|
|
||||||
}
|
|
@@ -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
|
|
||||||
});
|
|
||||||
}
|
|
7792
js/package-lock.json
generated
Normal file
7792
js/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
js/package.json
Normal file
25
js/package.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "@flarum/core",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^3.3.7",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"color-thief-browser": "^2.0.2",
|
||||||
|
"expose-loader": "^0.7.5",
|
||||||
|
"flarum-webpack-config": "^0.1.0-beta.8",
|
||||||
|
"jquery": "^3.3.1",
|
||||||
|
"jquery.hotkeys": "^0.1.0",
|
||||||
|
"m.attrs.bidi": "github:tobscure/m.attrs.bidi",
|
||||||
|
"mithril": "^0.2.8",
|
||||||
|
"moment": "^2.22.2",
|
||||||
|
"punycode": "^2.1.1",
|
||||||
|
"spin.js": "^3.1.0",
|
||||||
|
"webpack": "^4.0.0",
|
||||||
|
"webpack-cli": "^2.1.5",
|
||||||
|
"webpack-merge": "^4.1.2"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "webpack --mode production",
|
||||||
|
"watch": "webpack --mode development --watch"
|
||||||
|
}
|
||||||
|
}
|
66
js/src/admin/AdminApplication.js
Normal file
66
js/src/admin/AdminApplication.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import HeaderPrimary from './components/HeaderPrimary';
|
||||||
|
import HeaderSecondary from './components/HeaderSecondary';
|
||||||
|
import routes from './routes';
|
||||||
|
import Application from '../common/Application';
|
||||||
|
import Navigation from '../common/components/Navigation';
|
||||||
|
import AdminNav from './components/AdminNav';
|
||||||
|
|
||||||
|
export default class AdminApplication extends Application {
|
||||||
|
extensionSettings = {};
|
||||||
|
|
||||||
|
history = {
|
||||||
|
canGoBack: () => true,
|
||||||
|
getPrevious: () => {},
|
||||||
|
backUrl: () => this.forum.attribute('baseUrl'),
|
||||||
|
back: function() {
|
||||||
|
window.location = this.backUrl();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
boot(data) {
|
||||||
|
routes(this);
|
||||||
|
|
||||||
|
super.boot(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
mount() {
|
||||||
|
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());
|
||||||
|
|
||||||
|
m.route.mode = 'hash';
|
||||||
|
super.mount();
|
||||||
|
|
||||||
|
// If an extension has just been enabled, then we will run its settings
|
||||||
|
// callback.
|
||||||
|
const enabled = localStorage.getItem('enabledExtension');
|
||||||
|
if (enabled && this.extensionSettings[enabled]) {
|
||||||
|
this.extensionSettings[enabled]();
|
||||||
|
localStorage.removeItem('enabledExtension');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
63
js/src/admin/compat.js
Normal file
63
js/src/admin/compat.js
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import compat from '../common/compat';
|
||||||
|
|
||||||
|
import saveSettings from './utils/saveSettings';
|
||||||
|
import SettingDropdown from './components/SettingDropdown';
|
||||||
|
import EditCustomFooterModal from './components/EditCustomFooterModal';
|
||||||
|
import SessionDropdown from './components/SessionDropdown';
|
||||||
|
import HeaderPrimary from './components/HeaderPrimary';
|
||||||
|
import AppearancePage from './components/AppearancePage';
|
||||||
|
import Page from './components/Page';
|
||||||
|
import StatusWidget from './components/StatusWidget';
|
||||||
|
import HeaderSecondary from './components/HeaderSecondary';
|
||||||
|
import SettingsModal from './components/SettingsModal';
|
||||||
|
import DashboardWidget from './components/DashboardWidget';
|
||||||
|
import AddExtensionModal from './components/AddExtensionModal';
|
||||||
|
import ExtensionsPage from './components/ExtensionsPage';
|
||||||
|
import AdminLinkButton from './components/AdminLinkButton';
|
||||||
|
import PermissionGrid from './components/PermissionGrid';
|
||||||
|
import Widget from './components/Widget';
|
||||||
|
import MailPage from './components/MailPage';
|
||||||
|
import UploadImageButton from './components/UploadImageButton';
|
||||||
|
import LoadingModal from './components/LoadingModal';
|
||||||
|
import DashboardPage from './components/DashboardPage';
|
||||||
|
import BasicsPage from './components/BasicsPage';
|
||||||
|
import EditCustomHeaderModal from './components/EditCustomHeaderModal';
|
||||||
|
import PermissionsPage from './components/PermissionsPage';
|
||||||
|
import PermissionDropdown from './components/PermissionDropdown';
|
||||||
|
import AdminNav from './components/AdminNav';
|
||||||
|
import EditCustomCssModal from './components/EditCustomCssModal';
|
||||||
|
import EditGroupModal from './components/EditGroupModal';
|
||||||
|
import routes from './routes';
|
||||||
|
import AdminApplication from './AdminApplication';
|
||||||
|
|
||||||
|
export default Object.assign(compat, {
|
||||||
|
'utils/saveSettings': saveSettings,
|
||||||
|
'components/SettingDropdown': SettingDropdown,
|
||||||
|
'components/EditCustomFooterModal': EditCustomFooterModal,
|
||||||
|
'components/SessionDropdown': SessionDropdown,
|
||||||
|
'components/HeaderPrimary': HeaderPrimary,
|
||||||
|
'components/AppearancePage': AppearancePage,
|
||||||
|
'components/Page': Page,
|
||||||
|
'components/StatusWidget': StatusWidget,
|
||||||
|
'components/HeaderSecondary': HeaderSecondary,
|
||||||
|
'components/SettingsModal': SettingsModal,
|
||||||
|
'components/DashboardWidget': DashboardWidget,
|
||||||
|
'components/AddExtensionModal': AddExtensionModal,
|
||||||
|
'components/ExtensionsPage': ExtensionsPage,
|
||||||
|
'components/AdminLinkButton': AdminLinkButton,
|
||||||
|
'components/PermissionGrid': PermissionGrid,
|
||||||
|
'components/Widget': Widget,
|
||||||
|
'components/MailPage': MailPage,
|
||||||
|
'components/UploadImageButton': UploadImageButton,
|
||||||
|
'components/LoadingModal': LoadingModal,
|
||||||
|
'components/DashboardPage': DashboardPage,
|
||||||
|
'components/BasicsPage': BasicsPage,
|
||||||
|
'components/EditCustomHeaderModal': EditCustomHeaderModal,
|
||||||
|
'components/PermissionsPage': PermissionsPage,
|
||||||
|
'components/PermissionDropdown': PermissionDropdown,
|
||||||
|
'components/AdminNav': AdminNav,
|
||||||
|
'components/EditCustomCssModal': EditCustomCssModal,
|
||||||
|
'components/EditGroupModal': EditGroupModal,
|
||||||
|
'routes': routes,
|
||||||
|
'AdminApplication': AdminApplication
|
||||||
|
});
|
@@ -7,7 +7,7 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Modal from 'flarum/components/Modal';
|
import Modal from '../../common/components/Modal';
|
||||||
|
|
||||||
export default class AddExtensionModal extends Modal {
|
export default class AddExtensionModal extends Modal {
|
||||||
className() {
|
className() {
|
@@ -7,7 +7,7 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import LinkButton from 'flarum/components/LinkButton';
|
import LinkButton from '../../common/components/LinkButton';
|
||||||
|
|
||||||
export default class AdminLinkButton extends LinkButton {
|
export default class AdminLinkButton extends LinkButton {
|
||||||
getButtonContent() {
|
getButtonContent() {
|
@@ -7,11 +7,10 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Component from 'flarum/Component';
|
import Component from '../../common/Component';
|
||||||
import AdminLinkButton from 'flarum/components/AdminLinkButton';
|
import AdminLinkButton from './AdminLinkButton';
|
||||||
import SelectDropdown from 'flarum/components/SelectDropdown';
|
import SelectDropdown from '../../common/components/SelectDropdown';
|
||||||
|
import ItemList from '../../common/utils/ItemList';
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
|
||||||
|
|
||||||
export default class AdminNav extends Component {
|
export default class AdminNav extends Component {
|
||||||
view() {
|
view() {
|
@@ -1,11 +1,11 @@
|
|||||||
import Page from 'flarum/components/Page';
|
import Page from './Page';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Switch from 'flarum/components/Switch';
|
import Switch from '../../common/components/Switch';
|
||||||
import EditCustomCssModal from 'flarum/components/EditCustomCssModal';
|
import EditCustomCssModal from './EditCustomCssModal';
|
||||||
import EditCustomHeaderModal from 'flarum/components/EditCustomHeaderModal';
|
import EditCustomHeaderModal from './EditCustomHeaderModal';
|
||||||
import EditCustomFooterModal from 'flarum/components/EditCustomFooterModal';
|
import EditCustomFooterModal from './EditCustomFooterModal';
|
||||||
import UploadImageButton from 'flarum/components/UploadImageButton';
|
import UploadImageButton from './UploadImageButton';
|
||||||
import saveSettings from 'flarum/utils/saveSettings';
|
import saveSettings from '../utils/saveSettings';
|
||||||
|
|
||||||
export default class AppearancePage extends Page {
|
export default class AppearancePage extends Page {
|
||||||
init() {
|
init() {
|
@@ -1,11 +1,11 @@
|
|||||||
import Page from 'flarum/components/Page';
|
import Page from './Page';
|
||||||
import FieldSet from 'flarum/components/FieldSet';
|
import FieldSet from '../../common/components/FieldSet';
|
||||||
import Select from 'flarum/components/Select';
|
import Select from '../../common/components/Select';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Alert from 'flarum/components/Alert';
|
import Alert from '../../common/components/Alert';
|
||||||
import saveSettings from 'flarum/utils/saveSettings';
|
import saveSettings from '../utils/saveSettings';
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
import Switch from 'flarum/components/Switch';
|
import Switch from '../../common/components/Switch';
|
||||||
|
|
||||||
export default class BasicsPage extends Page {
|
export default class BasicsPage extends Page {
|
||||||
init() {
|
init() {
|
@@ -1,5 +1,5 @@
|
|||||||
import Page from 'flarum/components/Page';
|
import Page from './Page';
|
||||||
import StatusWidget from 'flarum/components/StatusWidget';
|
import StatusWidget from './StatusWidget';
|
||||||
|
|
||||||
export default class DashboardPage extends Page {
|
export default class DashboardPage extends Page {
|
||||||
view() {
|
view() {
|
@@ -7,7 +7,7 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Component from 'flarum/Component';
|
import Component from '../../common/Component';
|
||||||
|
|
||||||
export default class Widget extends Component {
|
export default class Widget extends Component {
|
||||||
view() {
|
view() {
|
@@ -1,4 +1,4 @@
|
|||||||
import SettingsModal from 'flarum/components/SettingsModal';
|
import SettingsModal from './SettingsModal';
|
||||||
|
|
||||||
export default class EditCustomCssModal extends SettingsModal {
|
export default class EditCustomCssModal extends SettingsModal {
|
||||||
className() {
|
className() {
|
@@ -1,4 +1,4 @@
|
|||||||
import SettingsModal from 'flarum/components/SettingsModal';
|
import SettingsModal from './SettingsModal';
|
||||||
|
|
||||||
export default class EditCustomFooterModal extends SettingsModal {
|
export default class EditCustomFooterModal extends SettingsModal {
|
||||||
className() {
|
className() {
|
@@ -1,4 +1,4 @@
|
|||||||
import SettingsModal from 'flarum/components/SettingsModal';
|
import SettingsModal from './SettingsModal';
|
||||||
|
|
||||||
export default class EditCustomHeaderModal extends SettingsModal {
|
export default class EditCustomHeaderModal extends SettingsModal {
|
||||||
className() {
|
className() {
|
@@ -1,7 +1,7 @@
|
|||||||
import Modal from 'flarum/components/Modal';
|
import Modal from '../../common/components/Modal';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Badge from 'flarum/components/Badge';
|
import Badge from '../../common/components/Badge';
|
||||||
import Group from 'flarum/models/Group';
|
import Group from '../../common/models/Group';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `EditGroupModal` component shows a modal dialog which allows the user
|
* The `EditGroupModal` component shows a modal dialog which allows the user
|
@@ -1,13 +1,13 @@
|
|||||||
import Page from 'flarum/components/Page';
|
import Page from './Page';
|
||||||
import LinkButton from 'flarum/components/LinkButton';
|
import LinkButton from '../../common/components/LinkButton';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Dropdown from 'flarum/components/Dropdown';
|
import Dropdown from '../../common/components/Dropdown';
|
||||||
import Separator from 'flarum/components/Separator';
|
import Separator from '../../common/components/Separator';
|
||||||
import AddExtensionModal from 'flarum/components/AddExtensionModal';
|
import AddExtensionModal from './AddExtensionModal';
|
||||||
import LoadingModal from 'flarum/components/LoadingModal';
|
import LoadingModal from './LoadingModal';
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../../common/helpers/icon';
|
||||||
import listItems from 'flarum/helpers/listItems';
|
import listItems from '../../common/helpers/listItems';
|
||||||
|
|
||||||
export default class ExtensionsPage extends Page {
|
export default class ExtensionsPage extends Page {
|
||||||
view() {
|
view() {
|
@@ -1,6 +1,6 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../../common/Component';
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
import listItems from 'flarum/helpers/listItems';
|
import listItems from '../../common/helpers/listItems';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `HeaderPrimary` component displays primary header controls. On the
|
* The `HeaderPrimary` component displays primary header controls. On the
|
@@ -1,7 +1,7 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../../common/Component';
|
||||||
import SessionDropdown from 'flarum/components/SessionDropdown';
|
import SessionDropdown from './SessionDropdown';
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
import listItems from 'flarum/helpers/listItems';
|
import listItems from '../../common/helpers/listItems';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `HeaderSecondary` component displays secondary header controls.
|
* The `HeaderSecondary` component displays secondary header controls.
|
@@ -1,4 +1,4 @@
|
|||||||
import Modal from 'flarum/components/Modal';
|
import Modal from '../../common/components/Modal';
|
||||||
|
|
||||||
export default class LoadingModal extends Modal {
|
export default class LoadingModal extends Modal {
|
||||||
isDismissible() {
|
isDismissible() {
|
@@ -1,8 +1,8 @@
|
|||||||
import Page from 'flarum/components/Page';
|
import Page from './Page';
|
||||||
import FieldSet from 'flarum/components/FieldSet';
|
import FieldSet from '../../common/components/FieldSet';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Alert from 'flarum/components/Alert';
|
import Alert from '../../common/components/Alert';
|
||||||
import saveSettings from 'flarum/utils/saveSettings';
|
import saveSettings from '../utils/saveSettings';
|
||||||
|
|
||||||
export default class MailPage extends Page {
|
export default class MailPage extends Page {
|
||||||
init() {
|
init() {
|
@@ -1,4 +1,4 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../../common/Component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Page` component
|
* The `Page` component
|
@@ -1,9 +1,9 @@
|
|||||||
import Dropdown from 'flarum/components/Dropdown';
|
import Dropdown from '../../common/components/Dropdown';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import Separator from 'flarum/components/Separator';
|
import Separator from '../../common/components/Separator';
|
||||||
import Group from 'flarum/models/Group';
|
import Group from '../../common/models/Group';
|
||||||
import Badge from 'flarum/components/Badge';
|
import Badge from '../../common/components/Badge';
|
||||||
import GroupBadge from 'flarum/components/GroupBadge';
|
import GroupBadge from '../../common/components/GroupBadge';
|
||||||
|
|
||||||
function badgeForId(id) {
|
function badgeForId(id) {
|
||||||
const group = app.store.getById('groups', id);
|
const group = app.store.getById('groups', id);
|
@@ -1,9 +1,9 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../../common/Component';
|
||||||
import PermissionDropdown from 'flarum/components/PermissionDropdown';
|
import PermissionDropdown from './PermissionDropdown';
|
||||||
import SettingDropdown from 'flarum/components/SettingDropdown';
|
import SettingDropdown from './SettingDropdown';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../../common/helpers/icon';
|
||||||
|
|
||||||
export default class PermissionGrid extends Component {
|
export default class PermissionGrid extends Component {
|
||||||
init() {
|
init() {
|
@@ -1,9 +1,9 @@
|
|||||||
import Page from 'flarum/components/Page';
|
import Page from './Page';
|
||||||
import GroupBadge from 'flarum/components/GroupBadge';
|
import GroupBadge from '../../common/components/GroupBadge';
|
||||||
import EditGroupModal from 'flarum/components/EditGroupModal';
|
import EditGroupModal from './EditGroupModal';
|
||||||
import Group from 'flarum/models/Group';
|
import Group from '../../common/models/Group';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../../common/helpers/icon';
|
||||||
import PermissionGrid from 'flarum/components/PermissionGrid';
|
import PermissionGrid from './PermissionGrid';
|
||||||
|
|
||||||
export default class PermissionsPage extends Page {
|
export default class PermissionsPage extends Page {
|
||||||
view() {
|
view() {
|
@@ -1,8 +1,8 @@
|
|||||||
import avatar from 'flarum/helpers/avatar';
|
import avatar from '../../common/helpers/avatar';
|
||||||
import username from 'flarum/helpers/username';
|
import username from '../../common/helpers/username';
|
||||||
import Dropdown from 'flarum/components/Dropdown';
|
import Dropdown from '../../common/components/Dropdown';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `SessionDropdown` component shows a button with the current user's
|
* The `SessionDropdown` component shows a button with the current user's
|
@@ -1,6 +1,6 @@
|
|||||||
import SelectDropdown from 'flarum/components/SelectDropdown';
|
import SelectDropdown from '../../common/components/SelectDropdown';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import saveSettings from 'flarum/utils/saveSettings';
|
import saveSettings from '../utils/saveSettings';
|
||||||
|
|
||||||
export default class SettingDropdown extends SelectDropdown {
|
export default class SettingDropdown extends SelectDropdown {
|
||||||
static initProps(props) {
|
static initProps(props) {
|
@@ -1,6 +1,6 @@
|
|||||||
import Modal from 'flarum/components/Modal';
|
import Modal from '../../common/components/Modal';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
import saveSettings from 'flarum/utils/saveSettings';
|
import saveSettings from '../utils/saveSettings';
|
||||||
|
|
||||||
export default class SettingsModal extends Modal {
|
export default class SettingsModal extends Modal {
|
||||||
init() {
|
init() {
|
@@ -7,10 +7,10 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import DashboardWidget from 'flarum/components/DashboardWidget';
|
import DashboardWidget from './DashboardWidget';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../../common/helpers/icon';
|
||||||
import listItems from 'flarum/helpers/listItems';
|
import listItems from '../../common/helpers/listItems';
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
|
|
||||||
export default class StatusWidget extends DashboardWidget {
|
export default class StatusWidget extends DashboardWidget {
|
||||||
className() {
|
className() {
|
@@ -1,4 +1,4 @@
|
|||||||
import Button from 'flarum/components/Button';
|
import Button from '../../common/components/Button';
|
||||||
|
|
||||||
export default class UploadImageButton extends Button {
|
export default class UploadImageButton extends Button {
|
||||||
init() {
|
init() {
|
@@ -7,7 +7,7 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Component from 'flarum/Component';
|
import Component from '../../common/Component';
|
||||||
|
|
||||||
export default class DashboardWidget extends Component {
|
export default class DashboardWidget extends Component {
|
||||||
view() {
|
view() {
|
28
js/src/admin/index.js
Normal file
28
js/src/admin/index.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import 'expose-loader?$!expose-loader?jQuery!jquery';
|
||||||
|
import 'expose-loader?m!mithril';
|
||||||
|
import 'expose-loader?moment!moment';
|
||||||
|
import 'expose-loader?m.bidi!m.attrs.bidi';
|
||||||
|
import 'bootstrap/js/affix';
|
||||||
|
import 'bootstrap/js/dropdown';
|
||||||
|
import 'bootstrap/js/modal';
|
||||||
|
import 'bootstrap/js/tooltip';
|
||||||
|
import 'bootstrap/js/transition';
|
||||||
|
|
||||||
|
import AdminApplication from './AdminApplication';
|
||||||
|
|
||||||
|
const app = new AdminApplication();
|
||||||
|
|
||||||
|
// Backwards compatibility
|
||||||
|
window.app = app;
|
||||||
|
|
||||||
|
export { app };
|
||||||
|
|
||||||
|
// Export public API
|
||||||
|
|
||||||
|
|
||||||
|
// Export compat API
|
||||||
|
import compat from './compat';
|
||||||
|
|
||||||
|
compat.app = app;
|
||||||
|
|
||||||
|
export { compat };
|
@@ -1,12 +1,12 @@
|
|||||||
import DashboardPage from 'flarum/components/DashboardPage';
|
import DashboardPage from './components/DashboardPage';
|
||||||
import BasicsPage from 'flarum/components/BasicsPage';
|
import BasicsPage from './components/BasicsPage';
|
||||||
import PermissionsPage from 'flarum/components/PermissionsPage';
|
import PermissionsPage from './components/PermissionsPage';
|
||||||
import AppearancePage from 'flarum/components/AppearancePage';
|
import AppearancePage from './components/AppearancePage';
|
||||||
import ExtensionsPage from 'flarum/components/ExtensionsPage';
|
import ExtensionsPage from './components/ExtensionsPage';
|
||||||
import MailPage from 'flarum/components/MailPage';
|
import MailPage from './components/MailPage';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `routes` initializer defines the admin app's routes.
|
* The `routes` initializer defines the forum app's routes.
|
||||||
*
|
*
|
||||||
* @param {App} app
|
* @param {App} app
|
||||||
*/
|
*/
|
@@ -1,118 +1,171 @@
|
|||||||
import ItemList from 'flarum/utils/ItemList';
|
import ItemList from './utils/ItemList';
|
||||||
import Alert from 'flarum/components/Alert';
|
import Alert from './components/Alert';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from './components/Button';
|
||||||
import RequestErrorModal from 'flarum/components/RequestErrorModal';
|
import ModalManager from './components/ModalManager';
|
||||||
import ConfirmPasswordModal from 'flarum/components/ConfirmPasswordModal';
|
import AlertManager from './components/AlertManager';
|
||||||
import Translator from 'flarum/Translator';
|
import RequestErrorModal from './components/RequestErrorModal';
|
||||||
import extract from 'flarum/utils/extract';
|
import Translator from './Translator';
|
||||||
import patchMithril from 'flarum/utils/patchMithril';
|
import Store from './Store';
|
||||||
import RequestError from 'flarum/utils/RequestError';
|
import Session from './Session';
|
||||||
import { extend } from 'flarum/extend';
|
import extract from './utils/extract';
|
||||||
|
import Drawer from './utils/Drawer';
|
||||||
|
import mapRoutes from './utils/mapRoutes';
|
||||||
|
import patchMithril from './utils/patchMithril';
|
||||||
|
import RequestError from './utils/RequestError';
|
||||||
|
import ScrollListener from './utils/ScrollListener';
|
||||||
|
import { extend } from './extend';
|
||||||
|
|
||||||
|
import Forum from './models/Forum';
|
||||||
|
import User from './models/User';
|
||||||
|
import Discussion from './models/Discussion';
|
||||||
|
import Post from './models/Post';
|
||||||
|
import Group from './models/Group';
|
||||||
|
import Notification from './models/Notification';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `App` class provides a container for an application, as well as various
|
* The `App` class provides a container for an application, as well as various
|
||||||
* utilities for the rest of the app to use.
|
* utilities for the rest of the app to use.
|
||||||
*/
|
*/
|
||||||
export default class App {
|
export default class Application {
|
||||||
constructor() {
|
|
||||||
patchMithril(window);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The forum model for this application.
|
|
||||||
*
|
|
||||||
* @type {Forum}
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
this.forum = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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()};
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
this.routes = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An ordered list of initializers to bootstrap the application.
|
|
||||||
*
|
|
||||||
* @type {ItemList}
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
this.initializers = new ItemList();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The app's session.
|
|
||||||
*
|
|
||||||
* @type {Session}
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
this.session = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The app's translator.
|
|
||||||
*
|
|
||||||
* @type {Translator}
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
this.translator = new Translator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The app's data store.
|
|
||||||
*
|
|
||||||
* @type {Store}
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
this.store = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A local cache that can be used to store data at the application level, so
|
|
||||||
* that is persists between different routes.
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
this.cache = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the app has been booted.
|
|
||||||
*
|
|
||||||
* @type {Boolean}
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
this.booted = 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.
|
|
||||||
*
|
|
||||||
* @type {null|Alert}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.requestError = null;
|
|
||||||
|
|
||||||
this.title = '';
|
|
||||||
this.titleCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boot the application by running all of the registered initializers.
|
* The forum model for this application.
|
||||||
*
|
*
|
||||||
|
* @type {Forum}
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
forum = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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()};
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
routes = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An ordered list of initializers to bootstrap the application.
|
||||||
|
*
|
||||||
|
* @type {ItemList}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
initializers = new ItemList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The app's session.
|
||||||
|
*
|
||||||
|
* @type {Session}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
session = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The app's translator.
|
||||||
|
*
|
||||||
|
* @type {Translator}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
translator = new Translator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The app's data store.
|
||||||
|
*
|
||||||
|
* @type {Store}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
store = new Store({
|
||||||
|
forums: Forum,
|
||||||
|
users: User,
|
||||||
|
discussions: Discussion,
|
||||||
|
posts: Post,
|
||||||
|
groups: Group,
|
||||||
|
notifications: Notification
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A local cache that can be used to store data at the application level, so
|
||||||
|
* that is persists between different routes.
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
cache = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the app has been booted.
|
||||||
|
*
|
||||||
|
* @type {Boolean}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
booted = 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.
|
||||||
|
*
|
||||||
|
* @type {null|Alert}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
requestError = null;
|
||||||
|
|
||||||
|
title = '';
|
||||||
|
titleCount = 0;
|
||||||
|
|
||||||
boot(data) {
|
boot(data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
|
||||||
this.translator.locale = data.locale;
|
this.translator.locale = data.locale;
|
||||||
|
|
||||||
|
patchMithril(window);
|
||||||
|
|
||||||
this.initializers.toArray().forEach(initializer => initializer(this));
|
this.initializers.toArray().forEach(initializer => initializer(this));
|
||||||
|
|
||||||
|
this.store.pushPayload({data: this.data.resources});
|
||||||
|
|
||||||
|
this.forum = this.store.getById('forums', 1);
|
||||||
|
|
||||||
|
this.session = new Session(
|
||||||
|
this.store.getById('users', this.data.session.userId),
|
||||||
|
this.data.session.csrfToken
|
||||||
|
);
|
||||||
|
|
||||||
|
this.mount();
|
||||||
|
}
|
||||||
|
|
||||||
|
mount() {
|
||||||
|
this.modal = m.mount(document.getElementById('modal'), <ModalManager/>);
|
||||||
|
this.alerts = m.mount(document.getElementById('alerts'), <AlertManager/>);
|
||||||
|
|
||||||
|
this.drawer = new Drawer();
|
||||||
|
|
||||||
|
const basePath = this.forum.attribute('basePath');
|
||||||
|
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');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,6 +177,7 @@ export default class App {
|
|||||||
preloadedDocument() {
|
preloadedDocument() {
|
||||||
if (this.data.document) {
|
if (this.data.document) {
|
||||||
const results = this.store.pushPayload(this.data.document);
|
const results = this.store.pushPayload(this.data.document);
|
||||||
|
|
||||||
this.data.document = null;
|
this.data.document = null;
|
||||||
|
|
||||||
return results;
|
return results;
|
@@ -1,7 +1,7 @@
|
|||||||
import User from 'flarum/models/User';
|
import User from './models/User';
|
||||||
import username from 'flarum/helpers/username';
|
import username from './helpers/username';
|
||||||
import extractText from 'flarum/utils/extractText';
|
import extractText from './utils/extractText';
|
||||||
import extract from 'flarum/utils/extract';
|
import extract from './utils/extract';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translator with the same API as Symfony's.
|
* Translator with the same API as Symfony's.
|
127
js/src/common/compat.js
Normal file
127
js/src/common/compat.js
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import * as extend from './extend';
|
||||||
|
import Session from './Session';
|
||||||
|
import Store from './Store';
|
||||||
|
import evented from './utils/evented';
|
||||||
|
import liveHumanTimes from './utils/liveHumanTimes';
|
||||||
|
import ItemList from './utils/ItemList';
|
||||||
|
import mixin from './utils/mixin';
|
||||||
|
import humanTime from './utils/humanTime';
|
||||||
|
import computed from './utils/computed';
|
||||||
|
import Drawer from './utils/Drawer';
|
||||||
|
import anchorScroll from './utils/anchorScroll';
|
||||||
|
import RequestError from './utils/RequestError';
|
||||||
|
import abbreviateNumber from './utils/abbreviateNumber';
|
||||||
|
import * as string from './utils/string';
|
||||||
|
import SubtreeRetainer from './utils/SubtreeRetainer';
|
||||||
|
import extract from './utils/extract';
|
||||||
|
import ScrollListener from './utils/ScrollListener';
|
||||||
|
import stringToColor from './utils/stringToColor';
|
||||||
|
import patchMithril from './utils/patchMithril';
|
||||||
|
import classList from './utils/classList';
|
||||||
|
import extractText from './utils/extractText';
|
||||||
|
import formatNumber from './utils/formatNumber';
|
||||||
|
import mapRoutes from './utils/mapRoutes';
|
||||||
|
import Notification from './models/Notification';
|
||||||
|
import User from './models/User';
|
||||||
|
import Post from './models/Post';
|
||||||
|
import Discussion from './models/Discussion';
|
||||||
|
import Group from './models/Group';
|
||||||
|
import Forum from './models/Forum';
|
||||||
|
import Component from './Component';
|
||||||
|
import Translator from './Translator';
|
||||||
|
import AlertManager from './components/AlertManager';
|
||||||
|
import Switch from './components/Switch';
|
||||||
|
import Badge from './components/Badge';
|
||||||
|
import LoadingIndicator from './components/LoadingIndicator';
|
||||||
|
import Placeholder from './components/Placeholder';
|
||||||
|
import Separator from './components/Separator';
|
||||||
|
import Dropdown from './components/Dropdown';
|
||||||
|
import SplitDropdown from './components/SplitDropdown';
|
||||||
|
import RequestErrorModal from './components/RequestErrorModal';
|
||||||
|
import FieldSet from './components/FieldSet';
|
||||||
|
import Select from './components/Select';
|
||||||
|
import Navigation from './components/Navigation';
|
||||||
|
import Alert from './components/Alert';
|
||||||
|
import LinkButton from './components/LinkButton';
|
||||||
|
import Checkbox from './components/Checkbox';
|
||||||
|
import SelectDropdown from './components/SelectDropdown';
|
||||||
|
import ModalManager from './components/ModalManager';
|
||||||
|
import Button from './components/Button';
|
||||||
|
import Modal from './components/Modal';
|
||||||
|
import GroupBadge from './components/GroupBadge';
|
||||||
|
import Model from './Model';
|
||||||
|
import Application from './Application';
|
||||||
|
import fullTime from './helpers/fullTime';
|
||||||
|
import avatar from './helpers/avatar';
|
||||||
|
import icon from './helpers/icon';
|
||||||
|
import humanTimeHelper from './helpers/humanTime';
|
||||||
|
import punctuateSeries from './helpers/punctuateSeries';
|
||||||
|
import highlight from './helpers/highlight';
|
||||||
|
import username from './helpers/username';
|
||||||
|
import userOnline from './helpers/userOnline';
|
||||||
|
import listItems from './helpers/listItems';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
'extend': extend,
|
||||||
|
'Session': Session,
|
||||||
|
'Store': Store,
|
||||||
|
'utils/evented': evented,
|
||||||
|
'utils/liveHumanTimes': liveHumanTimes,
|
||||||
|
'utils/ItemList': ItemList,
|
||||||
|
'utils/mixin': mixin,
|
||||||
|
'utils/humanTime': humanTime,
|
||||||
|
'utils/computed': computed,
|
||||||
|
'utils/Drawer': Drawer,
|
||||||
|
'utils/anchorScroll': anchorScroll,
|
||||||
|
'utils/RequestError': RequestError,
|
||||||
|
'utils/abbreviateNumber': abbreviateNumber,
|
||||||
|
'utils/string': string,
|
||||||
|
'utils/SubtreeRetainer': SubtreeRetainer,
|
||||||
|
'utils/extract': extract,
|
||||||
|
'utils/ScrollListener': ScrollListener,
|
||||||
|
'utils/stringToColor': stringToColor,
|
||||||
|
'utils/patchMithril': patchMithril,
|
||||||
|
'utils/classList': classList,
|
||||||
|
'utils/extractText': extractText,
|
||||||
|
'utils/formatNumber': formatNumber,
|
||||||
|
'utils/mapRoutes': mapRoutes,
|
||||||
|
'models/Notification': Notification,
|
||||||
|
'models/User': User,
|
||||||
|
'models/Post': Post,
|
||||||
|
'models/Discussion': Discussion,
|
||||||
|
'models/Group': Group,
|
||||||
|
'models/Forum': Forum,
|
||||||
|
'Component': Component,
|
||||||
|
'Translator': Translator,
|
||||||
|
'components/AlertManager': AlertManager,
|
||||||
|
'components/Switch': Switch,
|
||||||
|
'components/Badge': Badge,
|
||||||
|
'components/LoadingIndicator': LoadingIndicator,
|
||||||
|
'components/Placeholder': Placeholder,
|
||||||
|
'components/Separator': Separator,
|
||||||
|
'components/Dropdown': Dropdown,
|
||||||
|
'components/SplitDropdown': SplitDropdown,
|
||||||
|
'components/RequestErrorModal': RequestErrorModal,
|
||||||
|
'components/FieldSet': FieldSet,
|
||||||
|
'components/Select': Select,
|
||||||
|
'components/Navigation': Navigation,
|
||||||
|
'components/Alert': Alert,
|
||||||
|
'components/LinkButton': LinkButton,
|
||||||
|
'components/Checkbox': Checkbox,
|
||||||
|
'components/SelectDropdown': SelectDropdown,
|
||||||
|
'components/ModalManager': ModalManager,
|
||||||
|
'components/Button': Button,
|
||||||
|
'components/Modal': Modal,
|
||||||
|
'components/GroupBadge': GroupBadge,
|
||||||
|
'Model': Model,
|
||||||
|
'Application': Application,
|
||||||
|
'helpers/fullTime': fullTime,
|
||||||
|
'helpers/avatar': avatar,
|
||||||
|
'helpers/icon': icon,
|
||||||
|
'helpers/humanTime': humanTimeHelper,
|
||||||
|
'helpers/punctuateSeries': punctuateSeries,
|
||||||
|
'helpers/highlight': highlight,
|
||||||
|
'helpers/username': username,
|
||||||
|
'helpers/userOnline': userOnline,
|
||||||
|
'helpers/listItems': listItems
|
||||||
|
};
|
@@ -1,7 +1,7 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from './Button';
|
||||||
import listItems from 'flarum/helpers/listItems';
|
import listItems from '../helpers/listItems';
|
||||||
import extract from 'flarum/utils/extract';
|
import extract from '../utils/extract';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Alert` component represents an alert box, which contains a message,
|
* The `Alert` component represents an alert box, which contains a message,
|
@@ -1,5 +1,5 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import Alert from 'flarum/components/Alert';
|
import Alert from './Alert';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `AlertManager` component provides an area in which `Alert` components can
|
* The `AlertManager` component provides an area in which `Alert` components can
|
@@ -1,6 +1,6 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../helpers/icon';
|
||||||
import extract from 'flarum/utils/extract';
|
import extract from '../utils/extract';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Badge` component represents a user/discussion badge, indicating some
|
* The `Badge` component represents a user/discussion badge, indicating some
|
@@ -1,8 +1,8 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../helpers/icon';
|
||||||
import extract from 'flarum/utils/extract';
|
import extract from '../utils/extract';
|
||||||
import extractText from 'flarum/utils/extractText';
|
import extractText from '../utils/extractText';
|
||||||
import LoadingIndicator from 'flarum/components/LoadingIndicator';
|
import LoadingIndicator from './LoadingIndicator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Button` component defines an element which, when clicked, performs an
|
* The `Button` component defines an element which, when clicked, performs an
|
@@ -1,6 +1,6 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import LoadingIndicator from 'flarum/components/LoadingIndicator';
|
import LoadingIndicator from './LoadingIndicator';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../helpers/icon';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Checkbox` component defines a checkbox input.
|
* The `Checkbox` component defines a checkbox input.
|
@@ -1,6 +1,6 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../helpers/icon';
|
||||||
import listItems from 'flarum/helpers/listItems';
|
import listItems from '../helpers/listItems';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Dropdown` component displays a button which, when clicked, shows a
|
* The `Dropdown` component displays a button which, when clicked, shows a
|
@@ -1,5 +1,5 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import listItems from 'flarum/helpers/listItems';
|
import listItems from '../helpers/listItems';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `FieldSet` component defines a collection of fields, displayed in a list
|
* The `FieldSet` component defines a collection of fields, displayed in a list
|
@@ -1,4 +1,4 @@
|
|||||||
import Badge from 'flarum/components/Badge';
|
import Badge from './Badge';
|
||||||
|
|
||||||
export default class GroupBadge extends Badge {
|
export default class GroupBadge extends Badge {
|
||||||
static initProps(props) {
|
static initProps(props) {
|
@@ -1,4 +1,4 @@
|
|||||||
import Button from 'flarum/components/Button';
|
import Button from './Button';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `LinkButton` component defines a `Button` which links to a route.
|
* The `LinkButton` component defines a `Button` which links to a route.
|
@@ -1,4 +1,5 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
|
import { Spinner } from 'spin.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `LoadingIndicator` component displays a loading spinner with spin.js. It
|
* The `LoadingIndicator` component displays a loading spinner with spin.js. It
|
||||||
@@ -19,9 +20,17 @@ export default class LoadingIndicator extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config() {
|
config() {
|
||||||
const size = this.props.size || 'small';
|
const options = { zIndex: 'auto', color: this.$().css('color') };
|
||||||
|
|
||||||
$.fn.spin.presets[size].zIndex = 'auto';
|
switch (this.props.size) {
|
||||||
this.$().spin(size);
|
case 'large':
|
||||||
|
Object.assign(options, { lines: 10, length: 8, width: 4, radius: 8 });
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Object.assign(options, { lines: 8, length: 4, width: 3, radius: 5 });
|
||||||
|
}
|
||||||
|
|
||||||
|
new Spinner(options).spin(this.element);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import Alert from 'flarum/components/Alert';
|
import Alert from './Alert';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from './Button';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Modal` component displays a modal dialog, wrapped in a form. Subclasses
|
* The `Modal` component displays a modal dialog, wrapped in a form. Subclasses
|
@@ -1,5 +1,5 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import Modal from 'flarum/components/Modal';
|
import Modal from './Modal';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `ModalManager` component manages a modal dialog. Only one modal dialog
|
* The `ModalManager` component manages a modal dialog. Only one modal dialog
|
@@ -1,6 +1,6 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from './Button';
|
||||||
import LinkButton from 'flarum/components/LinkButton';
|
import LinkButton from './LinkButton';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Navigation` component displays a set of navigation buttons. Typically
|
* The `Navigation` component displays a set of navigation buttons. Typically
|
@@ -1,4 +1,4 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Placeholder` component displays a muted text with some call to action,
|
* The `Placeholder` component displays a muted text with some call to action,
|
@@ -1,4 +1,4 @@
|
|||||||
import Modal from 'flarum/components/Modal';
|
import Modal from './Modal';
|
||||||
|
|
||||||
export default class RequestErrorModal extends Modal {
|
export default class RequestErrorModal extends Modal {
|
||||||
className() {
|
className() {
|
@@ -1,5 +1,5 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../helpers/icon';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Select` component displays a <select> input, surrounded with some extra
|
* The `Select` component displays a <select> input, surrounded with some extra
|
@@ -1,5 +1,5 @@
|
|||||||
import Dropdown from 'flarum/components/Dropdown';
|
import Dropdown from './Dropdown';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../helpers/icon';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `SelectDropdown` component is the same as a `Dropdown`, except the toggle
|
* The `SelectDropdown` component is the same as a `Dropdown`, except the toggle
|
@@ -1,4 +1,4 @@
|
|||||||
import Component from 'flarum/Component';
|
import Component from '../Component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Separator` component defines a menu separator item.
|
* The `Separator` component defines a menu separator item.
|
@@ -1,6 +1,6 @@
|
|||||||
import Dropdown from 'flarum/components/Dropdown';
|
import Dropdown from './Dropdown';
|
||||||
import Button from 'flarum/components/Button';
|
import Button from './Button';
|
||||||
import icon from 'flarum/helpers/icon';
|
import icon from '../helpers/icon';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `SplitDropdown` component is similar to `Dropdown`, but the first child
|
* The `SplitDropdown` component is similar to `Dropdown`, but the first child
|
@@ -1,4 +1,4 @@
|
|||||||
import Checkbox from 'flarum/components/Checkbox';
|
import Checkbox from './Checkbox';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Switch` component is a `Checkbox`, but with a switch display instead of
|
* The `Switch` component is a `Checkbox`, but with a switch display instead of
|
@@ -1,4 +1,4 @@
|
|||||||
import { truncate } from 'flarum/utils/string';
|
import { truncate } from '../utils/string';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `highlight` helper searches for a word phrase in a string, and wraps
|
* The `highlight` helper searches for a word phrase in a string, and wraps
|
@@ -1,4 +1,4 @@
|
|||||||
import humanTimeUtil from 'flarum/utils/humanTime';
|
import humanTimeUtil from '../utils/humanTime';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `humanTime` helper displays a time in a human-friendly time-ago format
|
* The `humanTime` helper displays a time in a human-friendly time-ago format
|
@@ -1,5 +1,5 @@
|
|||||||
import Separator from 'flarum/components/Separator';
|
import Separator from '../components/Separator';
|
||||||
import classList from 'flarum/utils/classList';
|
import classList from '../utils/classList';
|
||||||
|
|
||||||
function isSeparator(item) {
|
function isSeparator(item) {
|
||||||
return item && item.component === Separator;
|
return item && item.component === Separator;
|
@@ -1,4 +1,4 @@
|
|||||||
import icon from 'flarum/helpers/icon';
|
import icon from './icon';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `useronline` helper displays a green circle if the user is online
|
* The `useronline` helper displays a green circle if the user is online
|
0
js/src/common/index.js
Normal file
0
js/src/common/index.js
Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user