mirror of
https://github.com/flarum/framework.git
synced 2024-11-22 12:48:28 +08: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:
parent
d234badbb2
commit
3f683dd6ee
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
|
||||
.gitignore export-ignore
|
||||
.gitmodules export-ignore
|
||||
.github export-ignore
|
||||
.travis export-ignore
|
||||
.travis.yml export-ignore
|
||||
.editorconfig export-ignore
|
||||
.styleci.yml export-ignore
|
||||
|
@ -8,4 +10,4 @@
|
|||
phpunit.xml export-ignore
|
||||
tests export-ignore
|
||||
|
||||
js/*/dist/*.js -diff
|
||||
js/dist/* -diff
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
|||
/vendor
|
||||
composer.lock
|
||||
composer.phar
|
||||
node_modules
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
/tests/tmp
|
||||
|
|
67
.travis.yml
67
.travis.yml
|
@ -1,44 +1,45 @@
|
|||
language: php
|
||||
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- DB=mariadb
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
- $HOME/.npm
|
||||
|
||||
addons:
|
||||
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
|
||||
install:
|
||||
- composer install
|
||||
- mysql -e 'CREATE DATABASE flarum;'
|
||||
|
||||
script:
|
||||
- vendor/bin/phpunit --coverage-clover=coverage.xml
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_failure: change
|
||||
|
||||
after_success:
|
||||
- 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.
|
||||
*/
|
||||
|
||||
import Modal from 'flarum/components/Modal';
|
||||
import Modal from '../../common/components/Modal';
|
||||
|
||||
export default class AddExtensionModal extends Modal {
|
||||
className() {
|
|
@ -7,7 +7,7 @@
|
|||
* 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 {
|
||||
getButtonContent() {
|
|
@ -7,11 +7,10 @@
|
|||
* 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';
|
||||
import Component from '../../common/Component';
|
||||
import AdminLinkButton from './AdminLinkButton';
|
||||
import SelectDropdown from '../../common/components/SelectDropdown';
|
||||
import ItemList from '../../common/utils/ItemList';
|
||||
|
||||
export default class AdminNav extends Component {
|
||||
view() {
|
|
@ -1,11 +1,11 @@
|
|||
import Page from 'flarum/components/Page';
|
||||
import Button from 'flarum/components/Button';
|
||||
import Switch from 'flarum/components/Switch';
|
||||
import EditCustomCssModal from 'flarum/components/EditCustomCssModal';
|
||||
import EditCustomHeaderModal from 'flarum/components/EditCustomHeaderModal';
|
||||
import EditCustomFooterModal from 'flarum/components/EditCustomFooterModal';
|
||||
import UploadImageButton from 'flarum/components/UploadImageButton';
|
||||
import saveSettings from 'flarum/utils/saveSettings';
|
||||
import Page from './Page';
|
||||
import Button from '../../common/components/Button';
|
||||
import Switch from '../../common/components/Switch';
|
||||
import EditCustomCssModal from './EditCustomCssModal';
|
||||
import EditCustomHeaderModal from './EditCustomHeaderModal';
|
||||
import EditCustomFooterModal from './EditCustomFooterModal';
|
||||
import UploadImageButton from './UploadImageButton';
|
||||
import saveSettings from '../utils/saveSettings';
|
||||
|
||||
export default class AppearancePage extends Page {
|
||||
init() {
|
|
@ -1,11 +1,11 @@
|
|||
import Page from 'flarum/components/Page';
|
||||
import FieldSet from 'flarum/components/FieldSet';
|
||||
import Select from 'flarum/components/Select';
|
||||
import Button from 'flarum/components/Button';
|
||||
import Alert from 'flarum/components/Alert';
|
||||
import saveSettings from 'flarum/utils/saveSettings';
|
||||
import ItemList from 'flarum/utils/ItemList';
|
||||
import Switch from 'flarum/components/Switch';
|
||||
import Page from './Page';
|
||||
import FieldSet from '../../common/components/FieldSet';
|
||||
import Select from '../../common/components/Select';
|
||||
import Button from '../../common/components/Button';
|
||||
import Alert from '../../common/components/Alert';
|
||||
import saveSettings from '../utils/saveSettings';
|
||||
import ItemList from '../../common/utils/ItemList';
|
||||
import Switch from '../../common/components/Switch';
|
||||
|
||||
export default class BasicsPage extends Page {
|
||||
init() {
|
|
@ -1,5 +1,5 @@
|
|||
import Page from 'flarum/components/Page';
|
||||
import StatusWidget from 'flarum/components/StatusWidget';
|
||||
import Page from './Page';
|
||||
import StatusWidget from './StatusWidget';
|
||||
|
||||
export default class DashboardPage extends Page {
|
||||
view() {
|
|
@ -7,7 +7,7 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import Component from 'flarum/Component';
|
||||
import Component from '../../common/Component';
|
||||
|
||||
export default class Widget extends Component {
|
||||
view() {
|
|
@ -1,4 +1,4 @@
|
|||
import SettingsModal from 'flarum/components/SettingsModal';
|
||||
import SettingsModal from './SettingsModal';
|
||||
|
||||
export default class EditCustomCssModal extends SettingsModal {
|
||||
className() {
|
|
@ -1,4 +1,4 @@
|
|||
import SettingsModal from 'flarum/components/SettingsModal';
|
||||
import SettingsModal from './SettingsModal';
|
||||
|
||||
export default class EditCustomFooterModal extends SettingsModal {
|
||||
className() {
|
|
@ -1,4 +1,4 @@
|
|||
import SettingsModal from 'flarum/components/SettingsModal';
|
||||
import SettingsModal from './SettingsModal';
|
||||
|
||||
export default class EditCustomHeaderModal extends SettingsModal {
|
||||
className() {
|
|
@ -1,7 +1,7 @@
|
|||
import Modal from 'flarum/components/Modal';
|
||||
import Button from 'flarum/components/Button';
|
||||
import Badge from 'flarum/components/Badge';
|
||||
import Group from 'flarum/models/Group';
|
||||
import Modal from '../../common/components/Modal';
|
||||
import Button from '../../common/components/Button';
|
||||
import Badge from '../../common/components/Badge';
|
||||
import Group from '../../common/models/Group';
|
||||
|
||||
/**
|
||||
* The `EditGroupModal` component shows a modal dialog which allows the user
|
|
@ -1,13 +1,13 @@
|
|||
import Page from 'flarum/components/Page';
|
||||
import LinkButton from 'flarum/components/LinkButton';
|
||||
import Button from 'flarum/components/Button';
|
||||
import Dropdown from 'flarum/components/Dropdown';
|
||||
import Separator from 'flarum/components/Separator';
|
||||
import AddExtensionModal from 'flarum/components/AddExtensionModal';
|
||||
import LoadingModal from 'flarum/components/LoadingModal';
|
||||
import ItemList from 'flarum/utils/ItemList';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import listItems from 'flarum/helpers/listItems';
|
||||
import Page from './Page';
|
||||
import LinkButton from '../../common/components/LinkButton';
|
||||
import Button from '../../common/components/Button';
|
||||
import Dropdown from '../../common/components/Dropdown';
|
||||
import Separator from '../../common/components/Separator';
|
||||
import AddExtensionModal from './AddExtensionModal';
|
||||
import LoadingModal from './LoadingModal';
|
||||
import ItemList from '../../common/utils/ItemList';
|
||||
import icon from '../../common/helpers/icon';
|
||||
import listItems from '../../common/helpers/listItems';
|
||||
|
||||
export default class ExtensionsPage extends Page {
|
||||
view() {
|
|
@ -1,6 +1,6 @@
|
|||
import Component from 'flarum/Component';
|
||||
import ItemList from 'flarum/utils/ItemList';
|
||||
import listItems from 'flarum/helpers/listItems';
|
||||
import Component from '../../common/Component';
|
||||
import ItemList from '../../common/utils/ItemList';
|
||||
import listItems from '../../common/helpers/listItems';
|
||||
|
||||
/**
|
||||
* The `HeaderPrimary` component displays primary header controls. On the
|
|
@ -1,7 +1,7 @@
|
|||
import Component from 'flarum/Component';
|
||||
import SessionDropdown from 'flarum/components/SessionDropdown';
|
||||
import ItemList from 'flarum/utils/ItemList';
|
||||
import listItems from 'flarum/helpers/listItems';
|
||||
import Component from '../../common/Component';
|
||||
import SessionDropdown from './SessionDropdown';
|
||||
import ItemList from '../../common/utils/ItemList';
|
||||
import listItems from '../../common/helpers/listItems';
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
isDismissible() {
|
|
@ -1,8 +1,8 @@
|
|||
import Page from 'flarum/components/Page';
|
||||
import FieldSet from 'flarum/components/FieldSet';
|
||||
import Button from 'flarum/components/Button';
|
||||
import Alert from 'flarum/components/Alert';
|
||||
import saveSettings from 'flarum/utils/saveSettings';
|
||||
import Page from './Page';
|
||||
import FieldSet from '../../common/components/FieldSet';
|
||||
import Button from '../../common/components/Button';
|
||||
import Alert from '../../common/components/Alert';
|
||||
import saveSettings from '../utils/saveSettings';
|
||||
|
||||
export default class MailPage extends Page {
|
||||
init() {
|
|
@ -1,4 +1,4 @@
|
|||
import Component from 'flarum/Component';
|
||||
import Component from '../../common/Component';
|
||||
|
||||
/**
|
||||
* The `Page` component
|
|
@ -1,9 +1,9 @@
|
|||
import Dropdown from 'flarum/components/Dropdown';
|
||||
import Button from 'flarum/components/Button';
|
||||
import Separator from 'flarum/components/Separator';
|
||||
import Group from 'flarum/models/Group';
|
||||
import Badge from 'flarum/components/Badge';
|
||||
import GroupBadge from 'flarum/components/GroupBadge';
|
||||
import Dropdown from '../../common/components/Dropdown';
|
||||
import Button from '../../common/components/Button';
|
||||
import Separator from '../../common/components/Separator';
|
||||
import Group from '../../common/models/Group';
|
||||
import Badge from '../../common/components/Badge';
|
||||
import GroupBadge from '../../common/components/GroupBadge';
|
||||
|
||||
function badgeForId(id) {
|
||||
const group = app.store.getById('groups', id);
|
|
@ -1,9 +1,9 @@
|
|||
import Component from 'flarum/Component';
|
||||
import PermissionDropdown from 'flarum/components/PermissionDropdown';
|
||||
import SettingDropdown from 'flarum/components/SettingDropdown';
|
||||
import Button from 'flarum/components/Button';
|
||||
import ItemList from 'flarum/utils/ItemList';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import Component from '../../common/Component';
|
||||
import PermissionDropdown from './PermissionDropdown';
|
||||
import SettingDropdown from './SettingDropdown';
|
||||
import Button from '../../common/components/Button';
|
||||
import ItemList from '../../common/utils/ItemList';
|
||||
import icon from '../../common/helpers/icon';
|
||||
|
||||
export default class PermissionGrid extends Component {
|
||||
init() {
|
|
@ -1,9 +1,9 @@
|
|||
import Page from 'flarum/components/Page';
|
||||
import GroupBadge from 'flarum/components/GroupBadge';
|
||||
import EditGroupModal from 'flarum/components/EditGroupModal';
|
||||
import Group from 'flarum/models/Group';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import PermissionGrid from 'flarum/components/PermissionGrid';
|
||||
import Page from './Page';
|
||||
import GroupBadge from '../../common/components/GroupBadge';
|
||||
import EditGroupModal from './EditGroupModal';
|
||||
import Group from '../../common/models/Group';
|
||||
import icon from '../../common/helpers/icon';
|
||||
import PermissionGrid from './PermissionGrid';
|
||||
|
||||
export default class PermissionsPage extends Page {
|
||||
view() {
|
|
@ -1,8 +1,8 @@
|
|||
import avatar from 'flarum/helpers/avatar';
|
||||
import username from 'flarum/helpers/username';
|
||||
import Dropdown from 'flarum/components/Dropdown';
|
||||
import Button from 'flarum/components/Button';
|
||||
import ItemList from 'flarum/utils/ItemList';
|
||||
import avatar from '../../common/helpers/avatar';
|
||||
import username from '../../common/helpers/username';
|
||||
import Dropdown from '../../common/components/Dropdown';
|
||||
import Button from '../../common/components/Button';
|
||||
import ItemList from '../../common/utils/ItemList';
|
||||
|
||||
/**
|
||||
* The `SessionDropdown` component shows a button with the current user's
|
|
@ -1,6 +1,6 @@
|
|||
import SelectDropdown from 'flarum/components/SelectDropdown';
|
||||
import Button from 'flarum/components/Button';
|
||||
import saveSettings from 'flarum/utils/saveSettings';
|
||||
import SelectDropdown from '../../common/components/SelectDropdown';
|
||||
import Button from '../../common/components/Button';
|
||||
import saveSettings from '../utils/saveSettings';
|
||||
|
||||
export default class SettingDropdown extends SelectDropdown {
|
||||
static initProps(props) {
|
|
@ -1,6 +1,6 @@
|
|||
import Modal from 'flarum/components/Modal';
|
||||
import Button from 'flarum/components/Button';
|
||||
import saveSettings from 'flarum/utils/saveSettings';
|
||||
import Modal from '../../common/components/Modal';
|
||||
import Button from '../../common/components/Button';
|
||||
import saveSettings from '../utils/saveSettings';
|
||||
|
||||
export default class SettingsModal extends Modal {
|
||||
init() {
|
|
@ -7,10 +7,10 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import DashboardWidget from 'flarum/components/DashboardWidget';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import listItems from 'flarum/helpers/listItems';
|
||||
import ItemList from 'flarum/utils/ItemList';
|
||||
import DashboardWidget from './DashboardWidget';
|
||||
import icon from '../../common/helpers/icon';
|
||||
import listItems from '../../common/helpers/listItems';
|
||||
import ItemList from '../../common/utils/ItemList';
|
||||
|
||||
export default class StatusWidget extends DashboardWidget {
|
||||
className() {
|
|
@ -1,4 +1,4 @@
|
|||
import Button from 'flarum/components/Button';
|
||||
import Button from '../../common/components/Button';
|
||||
|
||||
export default class UploadImageButton extends Button {
|
||||
init() {
|
|
@ -7,7 +7,7 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import Component from 'flarum/Component';
|
||||
import Component from '../../common/Component';
|
||||
|
||||
export default class DashboardWidget extends Component {
|
||||
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 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';
|
||||
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';
|
||||
|
||||
/**
|
||||
* The `routes` initializer defines the admin app's routes.
|
||||
* The `routes` initializer defines the forum app's routes.
|
||||
*
|
||||
* @param {App} app
|
||||
*/
|
|
@ -1,118 +1,171 @@
|
|||
import ItemList from 'flarum/utils/ItemList';
|
||||
import Alert from 'flarum/components/Alert';
|
||||
import Button from 'flarum/components/Button';
|
||||
import RequestErrorModal from 'flarum/components/RequestErrorModal';
|
||||
import ConfirmPasswordModal from 'flarum/components/ConfirmPasswordModal';
|
||||
import Translator from 'flarum/Translator';
|
||||
import extract from 'flarum/utils/extract';
|
||||
import patchMithril from 'flarum/utils/patchMithril';
|
||||
import RequestError from 'flarum/utils/RequestError';
|
||||
import { extend } from 'flarum/extend';
|
||||
import ItemList from './utils/ItemList';
|
||||
import Alert from './components/Alert';
|
||||
import Button from './components/Button';
|
||||
import ModalManager from './components/ModalManager';
|
||||
import AlertManager from './components/AlertManager';
|
||||
import RequestErrorModal from './components/RequestErrorModal';
|
||||
import Translator from './Translator';
|
||||
import Store from './Store';
|
||||
import Session from './Session';
|
||||
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
|
||||
* utilities for the rest of the app to use.
|
||||
*/
|
||||
export default class App {
|
||||
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;
|
||||
}
|
||||
|
||||
export default class Application {
|
||||
/**
|
||||
* Boot the application by running all of the registered initializers.
|
||||
* The forum model for this application.
|
||||
*
|
||||
* @type {Forum}
|
||||
* @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) {
|
||||
this.data = data;
|
||||
|
||||
this.translator.locale = data.locale;
|
||||
|
||||
patchMithril(window);
|
||||
|
||||
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() {
|
||||
if (this.data.document) {
|
||||
const results = this.store.pushPayload(this.data.document);
|
||||
|
||||
this.data.document = null;
|
||||
|
||||
return results;
|
|
@ -1,7 +1,7 @@
|
|||
import User from 'flarum/models/User';
|
||||
import username from 'flarum/helpers/username';
|
||||
import extractText from 'flarum/utils/extractText';
|
||||
import extract from 'flarum/utils/extract';
|
||||
import User from './models/User';
|
||||
import username from './helpers/username';
|
||||
import extractText from './utils/extractText';
|
||||
import extract from './utils/extract';
|
||||
|
||||
/**
|
||||
* 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 Button from 'flarum/components/Button';
|
||||
import listItems from 'flarum/helpers/listItems';
|
||||
import extract from 'flarum/utils/extract';
|
||||
import Component from '../Component';
|
||||
import Button from './Button';
|
||||
import listItems from '../helpers/listItems';
|
||||
import extract from '../utils/extract';
|
||||
|
||||
/**
|
||||
* The `Alert` component represents an alert box, which contains a message,
|
|
@ -1,5 +1,5 @@
|
|||
import Component from 'flarum/Component';
|
||||
import Alert from 'flarum/components/Alert';
|
||||
import Component from '../Component';
|
||||
import Alert from './Alert';
|
||||
|
||||
/**
|
||||
* The `AlertManager` component provides an area in which `Alert` components can
|
|
@ -1,6 +1,6 @@
|
|||
import Component from 'flarum/Component';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import extract from 'flarum/utils/extract';
|
||||
import Component from '../Component';
|
||||
import icon from '../helpers/icon';
|
||||
import extract from '../utils/extract';
|
||||
|
||||
/**
|
||||
* The `Badge` component represents a user/discussion badge, indicating some
|
|
@ -1,8 +1,8 @@
|
|||
import Component from 'flarum/Component';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import extract from 'flarum/utils/extract';
|
||||
import extractText from 'flarum/utils/extractText';
|
||||
import LoadingIndicator from 'flarum/components/LoadingIndicator';
|
||||
import Component from '../Component';
|
||||
import icon from '../helpers/icon';
|
||||
import extract from '../utils/extract';
|
||||
import extractText from '../utils/extractText';
|
||||
import LoadingIndicator from './LoadingIndicator';
|
||||
|
||||
/**
|
||||
* The `Button` component defines an element which, when clicked, performs an
|
|
@ -1,6 +1,6 @@
|
|||
import Component from 'flarum/Component';
|
||||
import LoadingIndicator from 'flarum/components/LoadingIndicator';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import Component from '../Component';
|
||||
import LoadingIndicator from './LoadingIndicator';
|
||||
import icon from '../helpers/icon';
|
||||
|
||||
/**
|
||||
* The `Checkbox` component defines a checkbox input.
|
|
@ -1,6 +1,6 @@
|
|||
import Component from 'flarum/Component';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import listItems from 'flarum/helpers/listItems';
|
||||
import Component from '../Component';
|
||||
import icon from '../helpers/icon';
|
||||
import listItems from '../helpers/listItems';
|
||||
|
||||
/**
|
||||
* The `Dropdown` component displays a button which, when clicked, shows a
|
|
@ -1,5 +1,5 @@
|
|||
import Component from 'flarum/Component';
|
||||
import listItems from 'flarum/helpers/listItems';
|
||||
import Component from '../Component';
|
||||
import listItems from '../helpers/listItems';
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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.
|
|
@ -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
|
||||
|
@ -19,9 +20,17 @@ export default class LoadingIndicator extends Component {
|
|||
}
|
||||
|
||||
config() {
|
||||
const size = this.props.size || 'small';
|
||||
const options = { zIndex: 'auto', color: this.$().css('color') };
|
||||
|
||||
$.fn.spin.presets[size].zIndex = 'auto';
|
||||
this.$().spin(size);
|
||||
switch (this.props.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 Alert from 'flarum/components/Alert';
|
||||
import Button from 'flarum/components/Button';
|
||||
import Component from '../Component';
|
||||
import Alert from './Alert';
|
||||
import Button from './Button';
|
||||
|
||||
/**
|
||||
* The `Modal` component displays a modal dialog, wrapped in a form. Subclasses
|
|
@ -1,5 +1,5 @@
|
|||
import Component from 'flarum/Component';
|
||||
import Modal from 'flarum/components/Modal';
|
||||
import Component from '../Component';
|
||||
import Modal from './Modal';
|
||||
|
||||
/**
|
||||
* The `ModalManager` component manages a modal dialog. Only one modal dialog
|
|
@ -1,6 +1,6 @@
|
|||
import Component from 'flarum/Component';
|
||||
import Button from 'flarum/components/Button';
|
||||
import LinkButton from 'flarum/components/LinkButton';
|
||||
import Component from '../Component';
|
||||
import Button from './Button';
|
||||
import LinkButton from './LinkButton';
|
||||
|
||||
/**
|
||||
* 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,
|
|
@ -1,4 +1,4 @@
|
|||
import Modal from 'flarum/components/Modal';
|
||||
import Modal from './Modal';
|
||||
|
||||
export default class RequestErrorModal extends Modal {
|
||||
className() {
|
|
@ -1,5 +1,5 @@
|
|||
import Component from 'flarum/Component';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import Component from '../Component';
|
||||
import icon from '../helpers/icon';
|
||||
|
||||
/**
|
||||
* The `Select` component displays a <select> input, surrounded with some extra
|
|
@ -1,5 +1,5 @@
|
|||
import Dropdown from 'flarum/components/Dropdown';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import Dropdown from './Dropdown';
|
||||
import icon from '../helpers/icon';
|
||||
|
||||
/**
|
||||
* 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.
|
|
@ -1,6 +1,6 @@
|
|||
import Dropdown from 'flarum/components/Dropdown';
|
||||
import Button from 'flarum/components/Button';
|
||||
import icon from 'flarum/helpers/icon';
|
||||
import Dropdown from './Dropdown';
|
||||
import Button from './Button';
|
||||
import icon from '../helpers/icon';
|
||||
|
||||
/**
|
||||
* 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
|
|
@ -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
|
|
@ -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
|
|
@ -1,5 +1,5 @@
|
|||
import Separator from 'flarum/components/Separator';
|
||||
import classList from 'flarum/utils/classList';
|
||||
import Separator from '../components/Separator';
|
||||
import classList from '../utils/classList';
|
||||
|
||||
function isSeparator(item) {
|
||||
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
|
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
Loading…
Reference in New Issue
Block a user