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

Compare commits

...

142 Commits

Author SHA1 Message Date
Toby Zerner
fd3f484eaf WIP: move some things around 2017-06-27 14:01:19 +09:30
Toby Zerner
8b3971f202 WIP: set up webpack, TypeScript environment, start JS app refactor 2017-06-24 23:00:43 +09:30
Sajjad Hashemian
5b68b80e73 Remove depricated function bind 2017-06-24 10:50:03 +02:00
Sajjad Hashemian
ef4c9d4f8a Upgrade to jQuery 3.1.1 2017-06-24 10:49:47 +02:00
Toby Zerner
4585002118 Prevent crash if extension loads an empty module 2017-06-24 10:49:33 +02:00
Toby Zerner
5451aac693 Clean up Group model 2017-06-24 10:49:21 +02:00
Franz Liedke
01b56eecdb Merge pull request #1201 from Luceos/patch-3
Update AbstractSerializer.php
2017-06-23 00:02:16 +02:00
Franz Liedke
bcdcb8c20e Merge pull request #1202 from Luceos/patch-4
Update WebAppView.php
2017-06-23 00:02:02 +02:00
Daniël Klabbers
d6c99eccdb Update WebAppView.php
Added argument type hinting where absent.
2017-06-22 16:27:10 +02:00
Daniël Klabbers
01cb8ab79d Update AbstractSerializer.php
Fixes missing argument in method. Verified it has to be a string.
2017-06-22 14:28:51 +02:00
Franz Liedke
877aed215b Merge pull request #1199 from Luceos/patch-2
Update StartSession.php
2017-06-20 08:17:39 +02:00
Daniël Klabbers
57570d960e Update StartSession.php
Fixed CookieFactory typo in phpdoc.
2017-06-19 16:47:20 +02:00
Daniël Klabbers
04c4806f6f making posts and discussions private (#1153)
* flagrow/byobu#11 making posts and discussions private

* tested migrations and tested setting is_private on discussion and post manually

* added phpdoc for Post and Discussion and added the casting for these attributes

* satisfying styleci

* fixes for review

* added new private discussion event and included it in the access policy

* added new private post event and included it in the access policy
2017-05-27 14:19:15 +09:30
Davis
4c0339c30e Allow JSON to be used for Install Command (#1193)
* Allow JSON to be used for Install Command

* Return configuration as array instead of object.

* Update InstallCommand.php
2017-05-27 14:18:09 +09:30
David Sevilla Martín
e64dc4ea45 Add viewUserList permission (#1190) 2017-05-24 22:06:56 +09:30
Franz Liedke
305076814f Merge pull request #1189 from datitisev/762-exclude-files-from-distribution
Update .gitattributes to exclude files for distribution
2017-05-20 13:42:34 +02:00
David Sevilla Martin
e31edd29d2 Exclude files for distribution using .gitignore 2017-05-18 18:46:55 -04:00
David Sevilla Martín
23b423c6ce #1184 Fix /api/posts returning 500 (#1188)
* Fix ListPostsController::applyFilters not receiving array if argument not present

* Whoops! Use `[]` instead of `array()`

* Update AbstractSerializeController.php

* Update ListPostsController.php
2017-05-18 22:04:00 +02:00
Franz Liedke
1af1f472f9 Recompile dist JavaScript 2017-05-18 09:14:06 +02:00
Franz Liedke
7c86f7a34c Merge pull request #1186 from flarum/Luceos-patch-1
Update UserControls.js
2017-05-18 09:13:28 +02:00
Daniël Klabbers
14e49269d6 Update UserControls.js
Possibly c/p mistake with argument name. UserControls using argument discussion in controls method.
2017-05-17 14:07:38 +02:00
Zeokat
7837fff107 Support PNG avatars with transparent backgrounds and fix EXIF rotation (#1168)
As `orientate` requires the EXIF extension, we can only call it if the extension is installed.

Fixes #1161 and #1163.
2017-05-10 21:23:08 +02:00
Franz Liedke
3dfa6bc8cb Merge pull request #1179 from flarum/Luceos-patch-1
Update mixin.js
2017-05-09 23:07:16 +02:00
Daniël Klabbers
e47fe288fa Update mixin.js
Typo fixed
2017-05-09 13:58:07 +02:00
Franz Liedke
03e30d7d4f Merge pull request #1178 from flarum/Luceos-patch-1
Update HandleErrors.php
2017-05-09 08:57:26 +02:00
Daniël Klabbers
9836ff6c54 Update HandleErrors.php
@franzliedke forgot to make variables available to the method, just triggered this but got a warning that all three variables are undefined.
2017-05-08 16:45:58 +02:00
issyrocks12
bb1c655c90 Change to switch to fit style 2017-05-04 22:36:37 +02:00
Franz Liedke
bf20fe595a Fix incorrect sort field name
Closes #1175.
2017-05-04 21:37:03 +02:00
Franz Liedke
b5db57156b Merge pull request #1172 from tpokorra/fixDefaultLanguageSelection
Admin: fix default language selector
2017-05-02 08:37:32 +02:00
Timotheus Pokorra
a7d3bdf244 Admin: fix default language selector
the binding of the control to the value was missing
fixes #1164
2017-05-01 18:46:12 +02:00
Franz Liedke
c82f0bde61 Merge pull request #1155 from ssfinney/feature/mediumtext_for_post_content_column
Change content column from TEXT to MEDIUMTEXT
2017-04-13 08:04:05 +02:00
Stephen Finney
986102c1d3 Change content column from TEXT to MEDIUMTEXT
Fixes #1044
2017-04-09 16:12:34 -04:00
Franz Liedke
2140619c0b Prevent reverting editable user bio on click
Turns out the click handler was bound to the surrounding element
rather than the one that wraps the rendered bio when it is not
being edited.

Fixes #1145.
2017-03-17 22:14:51 +01:00
Franz Liedke
2f714a01ed Cookies: Set expires flag for remember cookies
Without this, session remembering would not work in Internet
Explorer (and Edge?).

Fixes #1127.
2017-03-14 22:25:20 +01:00
Franz Liedke
231d018de5 Add link() and setCanonicalUrl() methods to the WebAppView
These make it easier for controllers to define relationships from
the current to other pages, which is important for SEO mostly.
2017-03-13 18:08:32 +01:00
Franz Liedke
5d62231004 Fix comment typo 2017-03-13 12:52:25 +01:00
Franz Liedke
123c3a93f5 Fix indentation 2017-03-12 23:05:04 +01:00
Franz Liedke
c1eec2b261 Fix indentation 2017-03-12 23:03:46 +01:00
David Sevilla Martín
60d3d6ef99 Add option to hide the language selector (#1106)
* Added option to hide the language selector in the header
* Added `hide_language_selector` Switch to BasicsPage
* Added `hideLanguageSelector` property to ForumSerializer
* Apparently fixed the "Add Extension" button locale.... someone must not have compiled their changes :P

* Changed hideLanguageSelector (and such) to showLanguageSelector

* Change `core.admin.basics.show_language_selector_heading` to be `_label`

* Change showLanguageSelector in ForumSerializer to be boolean, default: true

* Ooops! Remove console.log 🤦‍♂️
2017-03-07 10:04:44 +10:30
Toby Zerner
7862bd32dd Merge pull request #1141 from sijad/fix-logout-redirect
prevent unsafe redirect via logout controller
2017-03-04 22:10:18 +10:30
Sajjad Hashemian
92b555a246 prevent unsafe redirect via logout controller 2017-03-04 14:51:21 +03:30
Toby Zerner
687ec6a199 Merge pull request #1131 from flarum/866/affixSidebar-resize
Affix sidebar when window is resized
2017-03-03 15:24:13 +10:30
Franz Liedke
f788a0a972 Fix nesting of rename_discussion translations
Refs flarum/flarum-ext-english#98.
2017-02-28 22:42:41 +01:00
Franz Liedke
e7bec9fe29 Merge pull request #1135 from sijad/add-noindex-header
Prevent crawlers to index nojs pages
2017-02-27 18:13:38 +01:00
Franz Liedke
57da4e24cb Rename translation key 2017-02-26 23:47:20 +01:00
Franz Liedke
7d1a22bcb5 Rename modal component 2017-02-26 23:44:57 +01:00
Sajjad Hashemian
8cc117d89d Prevent crawlers to index nojs pages 2017-02-26 19:48:33 +03:30
Franz Liedke
31ef02dc2c Compile dist JS 2017-02-17 00:19:33 +01:00
Franz Liedke
95c9ff9243 Affix sidebar when window is resized
Fixes #866.
2017-02-17 00:08:20 +01:00
Franz Liedke
9718f54683 Merge pull request #1130 from clarkwinkelmann/patch-1
Fix asset path when unpublishing
2017-02-16 09:17:32 +01:00
Clark Winkelmann
bb1e3278de Fix asset path when unpublishing 2017-02-16 01:51:33 +01:00
Franz Liedke
bbcc33b5b5 Turn a few setters/getters into public attributes
There were no type hints etc. going on, and we would have needed
the getters anyway.

See https://github.com/flarum/core/pull/1105#issuecomment-279310998.
2017-02-14 22:56:17 +01:00
Franz Liedke
30076547e5 Merge pull request #1126 from janga1997/hideCompiledDiff
Hide diff for compiled diff files
2017-02-12 17:46:12 +01:00
janga
7b710d5898 Hide diff for compiled diff files 2017-02-12 10:26:10 +05:30
Franz Liedke
d02b5c9db7 Merge pull request #1124 from Luceos/master
fixed issues with $extension visibility and typehinting
2017-02-12 00:53:50 +01:00
Daniël Klabbers
cd70819fd5 fixed issues with $extension visibility and typehinting 2017-02-11 21:14:44 +01:00
Franz Liedke
20b4619e75 Fix Stratigility deprecation, for real this time 2017-02-07 20:52:06 +01:00
Franz Liedke
fdec2fd094 Recompile dist JS 2017-02-04 00:08:16 +01:00
Franz Liedke
d7e4ae09b3 Merge pull request #1113 from oanhnn/patch-1
Correct image orientation according to Exif data
2017-02-03 23:50:04 +01:00
David Sevilla Martín
fcfc1b2a37 Add more attributes in app.blade.php and add a setDescription method. (#1105)
* Added `language` and `direction` properties to WebAppView

* Use properties `language` and `direction` in app.blade.php

* Added WebAppView::setDescription to set the meta description

* Whoops! Changed "ltr" to \'ltr\'. Thanks StyleCI :)

* Removed unnecessary `= null` for

* Changed `.. ? .. : ..` to `.. ?: ..`. Useful thing right there ;)
2017-02-03 23:09:22 +01:00
Franz Liedke
01eba18164 Merge pull request #1100 from flarum/stratigility-update
Update to Zend Stratigility 1.3
2017-02-03 22:03:55 +01:00
Franz Liedke
0dcf7d6aa9 Travis: Run tests on PHP 7.1 as well 2017-02-03 21:53:39 +01:00
Franz Liedke
015967a76c Require PHP 5.6 2017-02-03 21:53:20 +01:00
renyuneyun
3cd59e12f5 Allow to manually activate users (#1093)
* Allow to manually activate users

* Use resources instead of hard-coded strings
2017-02-03 21:13:32 +01:00
David Sevilla Martín
26d07699e9 Turn "Rename Discussion" dialog into a modal, closes #616 (#1083)
* Changed "Rename Discussion" prompt into a modal.
* Added DiscussionRenameModal component (Modal)
* Changed DiscussionControls.renameAction to use the modal (I may have removed the ability to return a promise)

* Added punycode.js back to js/forum dist

* Fixed some formatting, removed some unnecessary variables
2017-02-03 20:56:28 +01:00
Franz Liedke
b7d6ba4893 Trim lines 2017-02-03 20:28:04 +01:00
Franz Liedke
d3753d94ae Throw HTTP 403 on extension validation error
The way I read it, HTTP 405 is a generic statement about the
resource. Once a language pack is not the default, this is not
true anymore, so I figured 403 is more correct.
2017-02-03 20:25:21 +01:00
Franz Liedke
9349ed13fc Make event attributes public
Without this, reading the extension information would not be
possible for the validator.
2017-02-03 20:23:24 +01:00
Franz Liedke
91ace15f6d Merge pull request #1032 from dav-is/patch-1
Prevent deletion of default/all locale(s)
2017-02-03 20:21:19 +01:00
Franz Liedke
7c1b0bfcf2 Clarify condition
I want to make it a little more clear that we are checking exactly
for these two values. That may also help preventing further confusion
as to why we are not using empty() here.

Amendment to PR #1033.
2017-02-03 18:53:21 +01:00
Franz Liedke
542bae6277 Merge pull request #1033 from dav-is/patch-2
Prevent Overwriting of User's Attributes on Register (#897)
2017-02-03 18:51:11 +01:00
Franz Liedke
275c14ee7f Merge pull request #1009 2017-02-03 18:44:03 +01:00
Franz Liedke
bccc970231 Try to extract port from host when installing in console
The very last suggestion broght up in pull request #989.
2017-02-03 18:15:52 +01:00
Franz Liedke
da6f79b34a Ask for database port when installing via console 2017-02-03 18:15:15 +01:00
Franz Liedke
a3cbec25db Make MySQL port field optional
Last fix for pull request #989.
2017-02-03 17:56:02 +01:00
Franz Liedke
2225fdec72 Merge pull request #989 from nielstholenaar/master
Fixes #825
2017-02-03 17:51:07 +01:00
Oanh Nguyen
6a532ec14e Correct image orientation according to Exif data
When using mobile, take a photo and upload it as avatar, it's orientation is incorrect.
This commit will fix this problem.
2017-01-25 11:49:14 +07:00
Franz Liedke
9416d16ebb Clean up gambit 2017-01-03 21:22:19 +01:00
Li Ji
d6857b0fe5 Add group gambit to support search user by group name (#1073)
Add group gambit to support search user by group name

/api/users?filter[q]=group:admin
/api/users?filter[q]=group:admin,mod

refer to #256
2017-01-03 21:13:58 +01:00
Franz Liedke
2c7e7f5b39 Merge pull request #1094 from milescellar/patch-1
Make Add Extension modal's title translatable
2017-01-03 21:02:38 +01:00
Franz Liedke
b5b18dd436 Update to Zend Stratigility 1.3
* Fix dependency version constraint. (Reverts #1066.)
* Allow exceptions to be raised when dispatching middleware.
* Fix our error handler middleware (do not implement Stratigility's
  error handler interface, catch exceptions instead).

See https://docs.zendframework.com/zend-stratigility/migration/to-v2/.

Closes #1069.
2017-01-02 22:57:09 +01:00
Daniël Klabbers
4778ae5f74 Merge pull request #1099 from milescellar/patch-3
Update year
2017-01-02 08:22:43 +01:00
Miles Cellar
0936a630ef Update year 2017-01-01 22:41:35 +01:00
Franz Liedke
ec8ae6e03b Remove unnecessary method call
This is already the default value in the base SetCookie class.
2016-12-29 11:17:27 +01:00
Franz Liedke
9ffdeff608 Make StyleCI happy 2016-12-29 11:07:23 +01:00
Franz Liedke
8540932638 Clean up and document code 2016-12-28 23:01:49 +01:00
Franz Liedke
974f45e4e8 Remove unnecessary parameters 2016-12-28 23:01:27 +01:00
Miles Cellar
32ac48c6a9 Make Add Extension modal's title translatable 2016-12-27 01:52:54 +01:00
Toby Zerner
af5b86806a Merge pull request #1092 from sijad/cookie-helper
Add cookie helper
2016-12-22 20:30:46 +10:30
Sajjad Hashemian
aeef45b3cd Add cookie factory 2016-12-22 12:00:56 +03:30
Toby Zerner
8aa70de765 Merge pull request #1085 from krnch/krnch-patch-2
Cookies set with Secure flag in HTTPS mode #1084
2016-12-11 18:16:04 +10:30
karan
076a71c621 Update StartSession.php 2016-12-10 02:46:07 -05:00
Sajjad Hashemian
06c32b668d Remember checkbox (#1075)
* Add session option to Rememberer class

* Update session login function to allow send additional data

* Add Remember me checkbox

* Cleanup login modal
2016-11-29 18:02:12 +10:30
Toby Zerner
7af4b8d45f Merge pull request #1049 from JoshyPHP/TextFormatter-0.8.0
Updated s9e\TextFormatter to 0.8.1
2016-11-29 16:36:10 +10:30
Toby Zerner
cbba325a87 Add punycode. ref #1049 2016-11-29 16:35:45 +10:30
Toby Zerner
b7d7e8b18a Merge pull request #1077 from flarum/analysis-Xan0ZZ
Apply fixes from StyleCI
2016-11-29 15:46:14 +10:30
Toby Zerner
1031826a3d Apply fixes from StyleCI
[ci skip] [skip ci]
2016-11-29 05:03:53 +00:00
Toby Zerner
3612ca7aca Allow accessing the session via the actor
This is a bit sloppy (might come up with a better solution yet), but since most events provide access to the actor but not the request, this was the easiest/quickest way to allow extensions to access the session.
2016-11-28 11:45:55 +10:30
Toby Zerner
c2ee84a115 Don't rely on a successful forum API call to enable debug mode 2016-11-28 11:45:55 +10:30
Toby Zerner
060745ecb7 Support module prefixing of locale resources
In preparation for upcoming changes, allow locale resources to have a module prefix added when they are loaded from a file.
2016-11-28 11:45:55 +10:30
Toby Zerner
dd209b1747 Eager load discussion relationships
Since extensions may add nested includes, we need to make sure they are eager-loaded to avoid excessive queries. For example, when the tags extension adds "tags" and "tags.state".
2016-11-28 11:45:55 +10:30
Toby Zerner
aeb0a411b9 Add specific message for username validation 2016-11-28 11:45:55 +10:30
Toby Zerner
1ebb8bf39a Merge pull request #1074 from datitisev/specify-text-inputs-type
Added search input types to 3 inputs total, closes #726
2016-11-28 11:13:39 +10:30
David Sevilla Martin
fcdf36b3d0 Added search input types to 3 inputs total, closes #726
* Added type search to search bar (forum)
* Added CSS `box-sizing: inherit` to search <input> because bootstrap styles mess up the search box
* Added type color to both color settings in appearance (admin)
2016-11-27 19:39:47 -05:00
Toby Zerner
ab912ba1ad Update StyleCI rules 2016-11-16 15:47:12 +10:30
Toby Zerner
4b8eb5d6e4 Make reset password form look slightly nicer
(Still needs a proper makeover!)
2016-11-13 09:01:38 +10:30
Toby Zerner
0e20949eb0 Prevent notice if bootstrapping app in command line environment 2016-11-13 08:57:39 +10:30
Toby Zerner
b2c691a03d Improve password reset validation/error handling 2016-11-13 08:51:38 +10:30
Toby Zerner
dde0de046a Merge pull request #1066 from Luceos/patch-1
Update composer.json
2016-11-12 12:44:07 +10:30
Daniël Klabbers
7a9795fbc3 Update composer.json
fixes #1065 , this is a temporary fix until compatibility with 1.3.0 is guaranteed by refactoring
2016-11-12 01:20:10 +01:00
Toby Zerner
f30fac6a94 Merge pull request #1063 from sijad/default-export
Fix syntax errors when compiling js files
2016-11-08 08:03:26 +10:30
Sajjad Hashemian
1fb8092987 Fix syntax errors when compiling js files 2016-11-08 00:32:44 +03:30
Toby Zerner
ea6b943dbd Make getApp available to the public 2016-11-07 21:23:31 +10:30
Toby Zerner
b9918e6c40 Add missing parameter 2016-11-07 18:22:20 +10:30
Toby Zerner
b3e1a023c2 Add event to allow custom user password validation 2016-11-07 18:03:49 +10:30
JoshyPHP
96926a180a Updated s9e\TextFormatter to 0.8.1 2016-10-10 01:58:40 +02:00
Davis
f3bdc163fa $extension was undefined 2016-10-05 12:46:14 -05:00
Davis
0df6eee10f Change exception message 2016-10-04 15:09:43 -05:00
Davis
258a4b352d Change == to === 2016-09-13 14:48:21 -05:00
Davis
24580ced7a Wish it was automatic :/ 2016-09-13 05:56:13 -05:00
Davis
8e90d9f9e2 Anything for Stylecl's green check 2016-09-13 05:55:00 -05:00
Davis
af36ef3fa9 StyleCl and the space after <?php is annoying 2016-09-13 05:53:46 -05:00
Davis
eef63745e6 Prevent overwriting of user's attributes on register 2016-09-13 02:22:09 -05:00
Davis
c702e911b3 StyleCl is making me hate myself 2016-09-12 22:31:55 -05:00
Davis
73d2ee825b Forgot to subscribe 2016-09-12 22:31:03 -05:00
Davis
9f99610542 StyleCl FINALLY! 2016-09-12 22:28:50 -05:00
Davis
1192867c4f StyleCl 2016-09-12 22:28:03 -05:00
Davis
b048498b84 StyleCl 2016-09-12 22:27:18 -05:00
Davis
81f7a39a31 StyleCl 2016-09-12 22:26:22 -05:00
Davis
ea12bbaf48 StyleCL 2016-09-12 22:24:57 -05:00
Davis
c8122a7879 Make StyleCL Happy 2016-09-12 22:23:31 -05:00
Davis
1a5d7a337d Remove useless code 2016-09-12 22:19:47 -05:00
Davis
c29ea98d48 Add WillBe Modifiers 2016-09-12 22:17:54 -05:00
Davis
3702ffa998 Create ExtensionValidator.php 2016-09-12 19:14:30 -05:00
Davis
58f9c22375 Create ExtensionWillBeEnabled.php 2016-09-12 17:07:00 -05:00
Davis
939a1e9ca8 Forgot the extension :/ 2016-09-12 17:05:41 -05:00
Davis
736f22a31a Create ExtensionWillBeDisabled 2016-09-12 16:57:24 -05:00
David Sevilla Martin
592dd6a927 Fixed error when user is not logged in; fixed notification count not updating when clicking home link (added m.redraw) 2016-08-30 10:35:31 -04:00
David Sevilla Martin
2c5aa138cd Bringing back those "use strict";. Sorry 'bout that 2016-07-28 10:47:09 -04:00
David Sevilla Martin
53fd7b66b4 Commiting dist/app.js 2016-07-26 11:34:47 -04:00
David Sevilla Martin
a1a22aa4ce Refresh notifications with discussion list refresh
* When clicking "refresh" button for discussion list (on homepage) refresh notifications
* When clicking forum title (on homepage) refresh notifications
2016-07-26 11:25:05 -04:00
Niels Tholenaar
05c9ce335e Fixes #825 2016-06-20 12:34:41 +02:00
596 changed files with 4362 additions and 57560 deletions

7
.gitattributes vendored
View File

@@ -2,3 +2,10 @@
.gitignore export-ignore
.gitmodules export-ignore
.travis.yml export-ignore
.editorconfig export-ignore
.styleci.yml export-ignore
phpunit.xml export-ignore
tests export-ignore
js/*/dist/*.js -diff

2
.gitignore vendored
View File

@@ -5,3 +5,5 @@ Thumbs.db
tests/_output/*
.vagrant
.idea/*
node_modules
bower_components

View File

@@ -5,6 +5,7 @@ enabled:
disabled:
- align_double_arrow
- blank_line_after_opening_tag
- multiline_array_trailing_comma
- new_with_braces
- phpdoc_align

View File

@@ -1,9 +1,9 @@
language: php
php:
- 5.5
- 5.6
- 7.0
- 7.1
- hhvm
matrix:

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014-2016 Toby Zerner
Copyright (c) 2014-2017 Toby Zerner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -20,7 +20,7 @@
"docs": "http://flarum.org/docs"
},
"require": {
"php": ">=5.5.9",
"php": ">=5.6.0",
"dflydev/fig-cookies": "^1.0.2",
"doctrine/dbal": "^2.5",
"components/font-awesome": "^4.6",
@@ -50,10 +50,10 @@
"symfony/http-foundation": "^2.7",
"symfony/translation": "^2.7",
"symfony/yaml": "^2.7",
"s9e/text-formatter": "^0.6.1",
"s9e/text-formatter": "^0.8.1",
"tobscure/json-api": "^0.3.0",
"zendframework/zend-diactoros": "^1.1",
"zendframework/zend-stratigility": "^1.1"
"zendframework/zend-stratigility": "^1.3"
},
"require-dev": {
"mockery/mockery": "^0.9.4",

1
js/.gitignore vendored
View File

@@ -1 +0,0 @@
bower_components

2
js/admin/.gitignore vendored
View File

@@ -1 +1 @@
node_modules
dist

View File

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

23804
js/admin/dist/app.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +0,0 @@
{
"private": true,
"devDependencies": {
"gulp": "^3.9.1",
"flarum-gulp": "^0.2.0"
}
}

View File

@@ -0,0 +1,53 @@
import * as m from 'mithril';
import Application from './lib/Application';
import routes from './routes';
import Nav from './components/Nav';
export default class AdminApplication extends Application {
/**
* A map of extension names to their settings callbacks.
*
* @type {Object}
*/
extensionSettings = {};
/**
* Construct a list of permissions required to have the given permission.
*
* @param {String} permission
* @return {Array}
*/
getRequiredPermissions(permission) {
const required = [];
if (permission === 'startDiscussion' || permission.indexOf('discussion.') === 0) {
required.push('viewDiscussions');
}
if (permission === 'discussion.delete') {
required.push('discussion.hide');
}
if (permission === 'discussion.deletePosts') {
required.push('discussion.editPosts');
}
return required;
}
/**
* @inheritdoc
*/
mount() {
m.route.prefix('#');
super.mount();
m.mount(document.getElementById('nav'), <Nav/>);
}
/**
* @inheritdoc
*/
registerDefaultRoutes(router) {
routes(router);
}
}

View File

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

View File

@@ -1,30 +0,0 @@
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import Modal from 'flarum/components/Modal';
export default class AddExtensionModal extends Modal {
className() {
return 'AddExtensionModal Modal--small';
}
title() {
return 'Add Extension';
}
content() {
return (
<div className="Modal-body">
<p>{app.translator.trans('core.admin.add_extension.temporary_text')}</p>
<p>{app.translator.trans('core.admin.add_extension.install_text', {a: <a href="https://discuss.flarum.org/t/extensions" target="_blank"/>})}</p>
<p>{app.translator.trans('core.admin.add_extension.developer_text', {a: <a href="http://flarum.org/docs/extend" target="_blank"/>})}</p>
</div>
);
}
}

View File

@@ -0,0 +1,40 @@
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import flarum from 'flarum';
import Modal from 'flarum/lib/components/Modal';
export default class AddExtensionModal extends Modal {
/**
* @inheritdoc
*/
className() {
return super.className() + ' AddExtensionModal Modal--small';
}
/**
* @inheritdoc
*/
title() {
return flarum.translator.trans('admin.add_extension.title');
}
/**
* @inheritdoc
*/
content() {
return (
<div className="Modal-body">
<p>{flarum.translator.trans('admin.add_extension.temporary_text')}</p>
<p>{flarum.translator.trans('admin.add_extension.install_text', {a: <a href="https://discuss.flarum.org/t/extensions" target="_blank"/>})}</p>
<p>{flarum.translator.trans('admin.add_extension.developer_text', {a: <a href="http://flarum.org/docs/extend" target="_blank"/>})}</p>
</div>
);
}
}

View File

@@ -1,24 +0,0 @@
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import LinkButton from 'flarum/components/LinkButton';
export default class AdminLinkButton extends LinkButton {
getButtonContent() {
const content = super.getButtonContent();
content.push(
<div className="AdminLinkButton-description">
{this.props.description}
</div>
);
return content;
}
}

View File

@@ -0,0 +1,33 @@
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import LinkButton from 'flarum/lib/components/LinkButton';
/**
*
*/
export default class AdminLinkButton extends LinkButton {
/**
* @inheritdoc
*/
className() {
return super.className() + ' AdminLinkButton';
}
/**
* @inheritdoc
*/
content() {
const content = super.content();
content.push(<div className="AdminLinkButton-description">{this.attrs.description}</div>);
return content;
}
}

View File

@@ -1,79 +0,0 @@
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import Component from 'flarum/Component';
import AdminLinkButton from 'flarum/components/AdminLinkButton';
import SelectDropdown from 'flarum/components/SelectDropdown';
import ItemList from 'flarum/utils/ItemList';
export default class AdminNav extends Component {
view() {
return (
<SelectDropdown
className="AdminNav App-titleControl"
buttonClassName="Button"
children={this.items().toArray()}
/>
);
}
/**
* Build an item list of links to show in the admin navigation.
*
* @return {ItemList}
*/
items() {
const items = new ItemList();
items.add('dashboard', AdminLinkButton.component({
href: app.route('dashboard'),
icon: 'bar-chart',
children: app.translator.trans('core.admin.nav.dashboard_button'),
description: app.translator.trans('core.admin.nav.dashboard_text')
}));
items.add('basics', AdminLinkButton.component({
href: app.route('basics'),
icon: 'pencil',
children: app.translator.trans('core.admin.nav.basics_button'),
description: app.translator.trans('core.admin.nav.basics_text')
}));
items.add('mail', AdminLinkButton.component({
href: app.route('mail'),
icon: 'envelope',
children: app.translator.trans('core.admin.nav.email_button'),
description: app.translator.trans('core.admin.nav.email_text')
}));
items.add('permissions', AdminLinkButton.component({
href: app.route('permissions'),
icon: 'key',
children: app.translator.trans('core.admin.nav.permissions_button'),
description: app.translator.trans('core.admin.nav.permissions_text')
}));
items.add('appearance', AdminLinkButton.component({
href: app.route('appearance'),
icon: 'paint-brush',
children: app.translator.trans('core.admin.nav.appearance_button'),
description: app.translator.trans('core.admin.nav.appearance_text')
}));
items.add('extensions', AdminLinkButton.component({
href: app.route('extensions'),
icon: 'puzzle-piece',
children: app.translator.trans('core.admin.nav.extensions_button'),
description: app.translator.trans('core.admin.nav.extensions_text')
}));
return items;
}
}

View File

@@ -0,0 +1,52 @@
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import Component from 'flarum/lib/Component';
import ItemList from 'flarum/lib/utils/ItemList';
import AdminLinkButton from 'flarum/components/AdminLinkButton';
import SelectDropdown from 'flarum/components/SelectDropdown';
function addLink(items, route, icon) {
items.add(route, <AdminLinkButton
href={flarum.router.to(route)}
icon={icon}
children={flarum.translator.trans(`admin.nav.${route}_button`)}
description={flarum.translator.trans(`admin.nav.${route}_text`)}/>);
}
/**
*
*/
export default class Nav extends Component {
/**
* @inheritdoc
*/
view() {
return <SelectDropdown className="Nav" buttonClassName="Button" children={this.items().toArray()}/>;
}
/**
* Build an item list of links to show in the admin navigation.
*
* @return {ItemList}
* @public
*/
items() {
const items = new ItemList();
addLink(items, 'dashboard', 'bar-chart'));
addLink(items, 'basics', 'pencil'));
addLink(items, 'mail', 'envelope'));
addLink(items, 'permissions', 'key'));
addLink(items, 'appearance', 'paint-brush'));
addLink(items, 'extensions', 'puzzle-piece'));
return items;
}
}

View File

@@ -28,8 +28,8 @@ export default class AppearancePage extends Page {
</div>
<div className="AppearancePage-colors-input">
<input className="FormControl" placeholder="#aaaaaa" value={this.primaryColor()} onchange={m.withAttr('value', this.primaryColor)}/>
<input className="FormControl" placeholder="#aaaaaa" value={this.secondaryColor()} onchange={m.withAttr('value', this.secondaryColor)}/>
<input className="FormControl" type="color" placeholder="#aaaaaa" value={this.primaryColor()} onchange={m.withAttr('value', this.primaryColor)}/>
<input className="FormControl" type="color" placeholder="#aaaaaa" value={this.secondaryColor()} onchange={m.withAttr('value', this.secondaryColor)}/>
</div>
{Switch.component({

View File

@@ -5,6 +5,7 @@ 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';
export default class BasicsPage extends Page {
init() {
@@ -16,6 +17,7 @@ export default class BasicsPage extends Page {
'forum_title',
'forum_description',
'default_locale',
'show_language_selector',
'default_route',
'welcome_title',
'welcome_message'
@@ -23,13 +25,15 @@ export default class BasicsPage extends Page {
this.values = {};
const settings = app.data.settings;
this.fields.forEach(key => this.values[key] = m.prop(settings[key]));
this.fields.forEach(key => this.values[key] = m.prop(settings[key] || false));
this.localeOptions = {};
const locales = app.data.locales;
for (const i in locales) {
this.localeOptions[i] = `${locales[i]} (${i})`;
}
if (typeof this.values.show_language_selector() !== "number") this.values.show_language_selector(1);
}
view() {
@@ -60,12 +64,21 @@ export default class BasicsPage extends Page {
children: [
Select.component({
options: this.localeOptions,
value: this.values.default_locale(),
onchange: this.values.default_locale
})
]
})
: ''}
{Switch.component({
state: this.values.show_language_selector(),
onchange: this.values.show_language_selector,
children: app.translator.trans('core.admin.basics.show_language_selector_label'),
})}
<br/>
{FieldSet.component({
label: app.translator.trans('core.admin.basics.home_page_heading'),
className: 'BasicsPage-homePage',

View File

@@ -0,0 +1,25 @@
import Component from 'flarum/Component';
import ItemList from 'flarum/utils/ItemList';
import SessionDropdown from './SessionDropdown';
export default class Header extends Component {
/**
* @inheritdoc
*/
view() {
return this.items().toVnodes();
}
/**
* Build an item list for the header contents.
*
* @return {ItemList}
*/
items() {
const items = new ItemList();
items.add('session', <SessionDropdown/>);
return items;
}
}

View File

@@ -1,37 +0,0 @@
import Component from 'flarum/Component';
import SessionDropdown from 'flarum/components/SessionDropdown';
import ItemList from 'flarum/utils/ItemList';
import listItems from 'flarum/helpers/listItems';
/**
* The `HeaderSecondary` component displays secondary header controls.
*/
export default class HeaderSecondary extends Component {
view() {
return (
<ul className="Header-controls">
{listItems(this.items().toArray())}
</ul>
);
}
config(isInitialized, context) {
// Since this component is 'above' the content of the page (that is, it is a
// part of the global UI that persists between routes), we will flag the DOM
// to be retained across route changes.
context.retain = true;
}
/**
* Build an item list for the controls.
*
* @return {ItemList}
*/
items() {
const items = new ItemList();
items.add('session', SessionDropdown.component());
return items;
}
}

View File

@@ -91,6 +91,13 @@ export default class PermissionGrid extends Component {
allowGuest: true
}, 100);
items.add('viewUserList', {
icon: 'users',
label: app.translator.trans('core.admin.permissions.view_user_list_label'),
permission: 'viewUserList',
allowGuest: true
}, 100);
items.add('signUp', {
icon: 'user-plus',
label: app.translator.trans('core.admin.permissions.sign_up_label'),

9
js/admin/src/index.ts Normal file
View File

@@ -0,0 +1,9 @@
import AdminApplication from './AdminApplication';
export const app = new AdminApplication();
export const extensions = [];
// Export public API
// export { default as Extend } from './Extend';
// export { IndexPage, DicsussionList } from './components';

View File

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

View File

@@ -1,22 +0,0 @@
import DashboardPage from 'flarum/components/DashboardPage';
import BasicsPage from 'flarum/components/BasicsPage';
import PermissionsPage from 'flarum/components/PermissionsPage';
import AppearancePage from 'flarum/components/AppearancePage';
import ExtensionsPage from 'flarum/components/ExtensionsPage';
import MailPage from 'flarum/components/MailPage';
/**
* The `routes` initializer defines the admin app's routes.
*
* @param {App} app
*/
export default function(app) {
app.routes = {
'dashboard': {path: '/', component: DashboardPage.component()},
'basics': {path: '/basics', component: BasicsPage.component()},
'permissions': {path: '/permissions', component: PermissionsPage.component()},
'appearance': {path: '/appearance', component: AppearancePage.component()},
'extensions': {path: '/extensions', component: ExtensionsPage.component()},
'mail': {path: '/mail', component: MailPage.component()}
};
}

1
js/admin/src/lib Symbolic link
View File

@@ -0,0 +1 @@
/Users/toby/Projects/Flarum/app/packages/core/js/lib

15
js/admin/src/routes.ts Normal file
View File

@@ -0,0 +1,15 @@
import DashboardPage from './components/DashboardPage';
import BasicsPage from './components/BasicsPage';
import PermissionsPage from './components/PermissionsPage';
import AppearancePage from './components/AppearancePage';
import ExtensionsPage from './components/ExtensionsPage';
import MailPage from './components/MailPage';
export default function(router) {
router.add('dashboard', '/', DashboardPage);
router.add('basics', '/basics', BasicsPage);
router.add('permissions', '/permissions', PermissionsPage);
router.add('appearance', '/appearance', AppearancePage);
router.add('extensions', '/extensions', ExtensionsPage);
router.add('mail', '/mail', MailPage);
}

View File

@@ -1,14 +0,0 @@
export default function saveSettings(settings) {
const oldSettings = JSON.parse(JSON.stringify(app.data.settings));
Object.assign(app.data.settings, settings);
return app.request({
method: 'POST',
url: app.forum.attribute('apiUrl') + '/settings',
data: settings
}).catch(error => {
app.data.settings = oldSettings;
throw error;
});
}

View File

@@ -0,0 +1,22 @@
import flarum from 'flarum';
/**
* Make a request to save the given settings to the database.
*
* @param {Object} settings
* @return {Promise}
*/
export default function saveSettings(settings) {
const oldSettings = JSON.parse(JSON.stringify(flarum.data.settings));
Object.assign(flarum.data.settings, settings);
return flarum.ajax.request({
method: 'POST',
url: flarum.forum.apiUrl + '/settings',
data: settings
}).catch(error => {
flarum.data.settings = oldSettings;
throw error;
});
}

23
js/admin/tsconfig.json Normal file
View File

@@ -0,0 +1,23 @@
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": false,
"module": "commonjs",
"target": "es5",
"jsx": "react",
"jsxFactory": "m",
"declaration": true,
"lib": ["dom", "es2015"],
"types": [
"mithril",
"classnames"
]
},
"include": [
"./src/**/*"
],
"exclude": [
"node_modules"
]
}

View File

@@ -0,0 +1,30 @@
const path = require('path');
const { CheckerPlugin } = require('awesome-typescript-loader');
module.exports = {
entry: path.resolve(__dirname, 'src/index.tsx'),
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
devtool: 'source-map',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
library: 'flarum',
libraryTarget: 'var'
},
module: {
loaders: [
{
test: /\.tsx?$/,
loader: 'awesome-typescript-loader'
}
]
},
plugins: [
new CheckerPlugin()
],
externals: {
mithril: 'm'
}
};

View File

@@ -1,16 +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",
"fastclick": "~1.0.6",
"autolink": "~1.0.0",
"m.attrs.bidi": "tobscure/m.attrs.bidi"
}
}

2
js/forum/.gitignore vendored
View File

@@ -1 +1 @@
node_modules
dist

View File

@@ -1,35 +0,0 @@
var gulp = require('flarum-gulp');
var bowerDir = '../bower_components';
gulp({
includeHelpers: true,
files: [
bowerDir + '/es6-micro-loader/dist/system-polyfill.js',
bowerDir + '/mithril/mithril.js',
bowerDir + '/m.attrs.bidi/bidi.js',
bowerDir + '/jquery/dist/jquery.js',
bowerDir + '/jquery.hotkeys/jquery.hotkeys.js',
bowerDir + '/color-thief/src/color-thief.js',
bowerDir + '/moment/moment.js',
bowerDir + '/autolink/autolink-min.js',
bowerDir + '/bootstrap/js/affix.js',
bowerDir + '/bootstrap/js/dropdown.js',
bowerDir + '/bootstrap/js/modal.js',
bowerDir + '/bootstrap/js/tooltip.js',
bowerDir + '/bootstrap/js/transition.js',
bowerDir + '/spin.js/spin.js',
bowerDir + '/spin.js/jquery.spin.js',
bowerDir + '/fastclick/lib/fastclick.js'
],
modules: {
'flarum': [
'src/**/*.js',
'../lib/**/*.js'
]
},
outputFile: 'dist/app.js'
});

32117
js/forum/dist/app.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +0,0 @@
{
"private": true,
"devDependencies": {
"gulp": "^3.9.1",
"flarum-gulp": "^0.2.0"
}
}

View File

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

View File

@@ -0,0 +1,86 @@
import Application from './lib/Application';
import routes from './routes';
import Search from './components/Search';
export default class ForumApplication extends Application {
/**
* The page's search component instance.
*
* @type {SearchBox}
*/
search = new Search();
/**
* A map of notification types to their components.
*
* @type {Object}
*/
notificationComponents = {};
/**
* A map of post types to their components.
*
* @type {Object}
*/
postComponents = {};
//app.postComponents.comment = CommentPost;
//app.postComponents.discussionRenamed = DiscussionRenamedPost;
// app.notificationComponents.discussionRenamed = DiscussionRenamedNotification;
/**
* @inheritdoc
*/
registerDefaultRoutes(router) {
routes(router);
}
// TODO: work out where to put these helper functions
// /**
// * Check whether or not the user is currently composing a reply to a
// * discussion.
// *
// * @param {Discussion} discussion
// * @return {Boolean}
// */
// composingReplyTo(discussion) {
// return this.composer.component instanceof ReplyComposer &&
// this.composer.component.props.discussion === discussion &&
// this.composer.position !== Composer.PositionEnum.HIDDEN;
// }
//
// /**
// * Check whether or not the user is currently viewing a discussion.
// *
// * @param {Discussion} discussion
// * @return {Boolean}
// */
// viewingDiscussion(discussion) {
// return this.current instanceof DiscussionPage &&
// this.current.discussion === discussion;
// }
//
// /**
// * Callback for when an external authenticator (social login) action has
// * completed.
// *
// * If the payload indicates that the user has been logged in, then the page
// * will be reloaded. Otherwise, a SignUpModal will be opened, prefilled
// * with the provided details.
// *
// * @param {Object} payload A dictionary of props to pass into the sign up
// * modal. A truthy `authenticated` prop indicates that the user has logged
// * in, and thus the page is reloaded.
// * @public
// */
// authenticationComplete(payload) {
// if (payload.authenticated) {
// window.location.reload();
// } else {
// const modal = new SignUpModal(payload);
// this.modal.show(modal);
// modal.$('[name=password]').focus();
// }
// }
}

View File

@@ -1,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;

View File

@@ -150,7 +150,7 @@ class Composer extends Component {
const composer = this;
$(element).css('cursor', 'row-resize')
.bind('dragstart mousedown', e => e.preventDefault())
.on('dragstart mousedown', e => e.preventDefault())
.mousedown(function(e) {
composer.mouseStart = e.clientY;
composer.heightStart = composer.$().height();

View File

@@ -15,6 +15,7 @@ export default class EditUserModal extends Modal {
this.username = m.prop(user.username() || '');
this.email = m.prop(user.email() || '');
this.isActivated = m.prop(user.isActivated() || false);
this.setPassword = m.prop(false);
this.password = m.prop(user.password() || '');
this.groups = {};
@@ -37,22 +38,32 @@ export default class EditUserModal extends Modal {
<div className="Modal-body">
<div className="Form">
<div className="Form-group">
<label>Username</label>
<label>{app.translator.trans('core.forum.edit_user.username_heading')}</label>
<input className="FormControl" placeholder={extractText(app.translator.trans('core.forum.edit_user.username_label'))}
bidi={this.username} />
</div>
{app.session.user !== this.props.user ? [
<div className="Form-group">
<label>Email</label>
<label>{app.translator.trans('core.forum.edit_user.email_heading')}</label>
<div>
<input className="FormControl" placeholder={extractText(app.translator.trans('core.forum.edit_user.email_label'))}
bidi={this.email} />
</div>
{!this.isActivated() ? (
<div>
{Button.component({
className: 'Button Button--block',
children: app.translator.trans('core.forum.edit_user.activate_button'),
loading: this.loading,
onclick: this.activate.bind(this)
})}
</div>
) : ''}
</div>,
<div className="Form-group">
<label>Password</label>
<label>{app.translator.trans('core.forum.edit_user.password_heading')}</label>
<div>
<label className="checkbox">
<input type="checkbox" checked={this.setPassword()} onchange={e => {
@@ -61,7 +72,7 @@ export default class EditUserModal extends Modal {
if (e.target.checked) this.$('[name=password]').select();
m.redraw.strategy('none');
}}/>
Set new password
{app.translator.trans('core.forum.edit_user.set_password_label')}
</label>
{this.setPassword() ? (
<input className="FormControl" type="password" name="password" placeholder={extractText(app.translator.trans('core.forum.edit_user.password_label'))}
@@ -72,7 +83,7 @@ export default class EditUserModal extends Modal {
] : ''}
<div className="Form-group EditUserModal-groups">
<label>Groups</label>
<label>{app.translator.trans('core.forum.edit_user.groups_heading')}</label>
<div>
{Object.keys(this.groups)
.map(id => app.store.getById('groups', id))
@@ -100,6 +111,24 @@ export default class EditUserModal extends Modal {
);
}
activate() {
this.loading = true;
const data = {
username: this.username(),
isActivated: true,
};
this.props.user.save(data, {errorHandler: this.onerror.bind(this)})
.then(() => {
this.isActivated(true);
this.loading = false;
m.redraw();
})
.catch(() => {
this.loading = false;
m.redraw();
});
}
data() {
const groups = Object.keys(this.groups)
.filter(id => this.groups[id]())

View File

@@ -1,33 +0,0 @@
import Component from 'flarum/Component';
import ItemList from 'flarum/utils/ItemList';
import listItems from 'flarum/helpers/listItems';
/**
* The `HeaderPrimary` component displays primary header controls. On the
* default skin, these are shown just to the right of the forum title.
*/
export default class HeaderPrimary extends Component {
view() {
return (
<ul className="Header-controls">
{listItems(this.items().toArray())}
</ul>
);
}
config(isInitialized, context) {
// Since this component is 'above' the content of the page (that is, it is a
// part of the global UI that persists between routes), we will flag the DOM
// to be retained across route changes.
context.retain = true;
}
/**
* Build an item list for the controls.
*
* @return {ItemList}
*/
items() {
return new ItemList();
}
}

View File

@@ -39,7 +39,7 @@ export default class HeaderSecondary extends Component {
items.add('search', app.search.render(), 30);
if (Object.keys(app.data.locales).length > 1) {
if (app.forum.attribute("showLanguageSelector") && Object.keys(app.data.locales).length > 1) {
const locales = [];
for (const locale in app.data.locales) {

View File

@@ -236,7 +236,13 @@ export default class IndexPage extends Page {
title: app.translator.trans('core.forum.index.refresh_tooltip'),
icon: 'refresh',
className: 'Button Button--icon',
onclick: () => app.cache.discussionList.refresh()
onclick: () => {
app.cache.discussionList.refresh();
if (app.session.user) {
app.store.find('users', app.session.user.id());
m.redraw();
}
}
})
);

View File

@@ -4,6 +4,7 @@ import SignUpModal from 'flarum/components/SignUpModal';
import Alert from 'flarum/components/Alert';
import Button from 'flarum/components/Button';
import LogInButtons from 'flarum/components/LogInButtons';
import Switch from 'flarum/components/Switch';
import extractText from 'flarum/utils/extractText';
/**
@@ -11,7 +12,7 @@ import extractText from 'flarum/utils/extractText';
*
* ### Props
*
* - `email`
* - `identification`
* - `password`
*/
export default class LogInModal extends Modal {
@@ -19,11 +20,11 @@ export default class LogInModal extends Modal {
super.init();
/**
* The value of the email input.
* The value of the identification input.
*
* @type {Function}
*/
this.email = m.prop(this.props.email || '');
this.identification = m.prop(this.props.identification || '');
/**
* The value of the password input.
@@ -31,6 +32,13 @@ export default class LogInModal extends Modal {
* @type {Function}
*/
this.password = m.prop(this.props.password || '');
/**
* The value of the remember me input.
*
* @type {Function}
*/
this.remember = m.prop(this.props.remember && true);
}
className() {
@@ -48,8 +56,8 @@ export default class LogInModal extends Modal {
<div className="Form Form--centered">
<div className="Form-group">
<input className="FormControl" name="email" type="text" placeholder={extractText(app.translator.trans('core.forum.log_in.username_or_email_placeholder'))}
bidi={this.email}
<input className="FormControl" name="identification" type="text" placeholder={extractText(app.translator.trans('core.forum.log_in.username_or_email_placeholder'))}
bidi={this.identification}
disabled={this.loading} />
</div>
@@ -58,6 +66,15 @@ export default class LogInModal extends Modal {
bidi={this.password}
disabled={this.loading} />
</div>
<div className="Form-group">
{Switch.component({
children: app.translator.trans('core.forum.log_in.remember_me_label'),
disabled: this.loading,
onchange: this.remember,
state: this.remember()
})}
</div>
<div className="Form-group">
{Button.component({
@@ -90,7 +107,7 @@ export default class LogInModal extends Modal {
* @public
*/
forgotPassword() {
const email = this.email();
const email = this.identification();
const props = email.indexOf('@') !== -1 ? {email} : undefined;
app.modal.show(new ForgotPasswordModal(props));
@@ -104,14 +121,14 @@ export default class LogInModal extends Modal {
*/
signUp() {
const props = {password: this.password()};
const email = this.email();
props[email.indexOf('@') !== -1 ? 'email' : 'username'] = email;
const identification = this.identification();
props[identification.indexOf('@') !== -1 ? 'email' : 'username'] = identification;
app.modal.show(new SignUpModal(props));
}
onready() {
this.$('[name=' + (this.email() ? 'password' : 'email') + ']').select();
this.$('[name=' + (this.identification() ? 'password' : 'identification') + ']').select();
}
onsubmit(e) {
@@ -119,13 +136,15 @@ export default class LogInModal extends Modal {
this.loading = true;
const email = this.email();
const identification = this.identification();
const password = this.password();
const remember = this.remember();
app.session.login(email, password, {errorHandler: this.onerror.bind(this)}).then(
() => window.location.reload(),
this.loaded.bind(this)
);
app.session.login({identification, password, remember}, {errorHandler: this.onerror.bind(this)})
.then(
() => window.location.reload(),
this.loaded.bind(this)
);
}
onerror(error) {

View File

@@ -89,12 +89,12 @@ export default class NotificationGrid extends Component {
config(isInitialized) {
if (isInitialized) return;
this.$('thead .NotificationGrid-groupToggle').bind('mouseenter mouseleave', function(e) {
this.$('thead .NotificationGrid-groupToggle').on('mouseenter mouseleave', function(e) {
const i = parseInt($(this).index(), 10) + 1;
$(this).parents('table').find('td:nth-child(' + i + ')').toggleClass('highlighted', e.type === 'mouseenter');
});
this.$('tbody .NotificationGrid-groupToggle').bind('mouseenter mouseleave', function(e) {
this.$('tbody .NotificationGrid-groupToggle').on('mouseenter mouseleave', function(e) {
$(this).parent().find('td').toggleClass('highlighted', e.type === 'mouseenter');
});
}

View File

@@ -258,12 +258,12 @@ export default class PostStreamScrubber extends Component {
// When any part of the whole scrollbar is clicked, we want to jump to
// that position.
this.$('.Scrubber-scrollbar')
.bind('click', this.onclick.bind(this))
.click(this.onclick.bind(this))
// Now we want to make the scrollbar handle draggable. Let's start by
// preventing default browser events from messing things up.
.css({ cursor: 'pointer', 'user-select': 'none' })
.bind('dragstart mousedown touchstart', e => e.preventDefault());
.on('dragstart mousedown touchstart', e => e.preventDefault());
// When the mouse is pressed on the scrollbar handle, we capture some
// information about its current position. We will store this
@@ -275,7 +275,7 @@ export default class PostStreamScrubber extends Component {
this.$('.Scrubber-handle')
.css('cursor', 'move')
.bind('mousedown touchstart', this.onmousedown.bind(this))
.on('mousedown touchstart', this.onmousedown.bind(this))
// Exempt the scrollbar handle from the 'jump to' click event.
.click(e => e.stopPropagation());

View File

@@ -0,0 +1,67 @@
import Modal from 'flarum/components/Modal';
import Button from 'flarum/components/Button';
/**
* The 'RenameDiscussionModal' displays a modal dialog with an input to rename a discussion
*/
export default class RenameDiscussionModal extends Modal {
init() {
super.init();
this.discussion = this.props.discussion;
this.currentTitle = this.props.currentTitle;
this.newTitle = m.prop(this.currentTitle);
}
className() {
return 'RenameDiscussionModal Modal--small';
}
title() {
return app.translator.trans('core.forum.rename_discussion.title');
}
content() {
return (
<div className="Modal-body">
<div className="Form">
<div className="Form-group">
<input className="FormControl title" placeholder={this.currentTitle} bidi={this.newTitle} />
</div>
<div className="Form-group">
{Button.component({
className: 'Button Button--primary',
type: 'submit',
loading: this.loading,
children: app.translator.trans('core.forum.rename_discussion.submit_button')
})}
</div>
</div>
</div>
)
}
onsubmit(e) {
e.preventDefault();
this.loading = true;
const title = this.newTitle;
const currentTitle = this.currentTitle;
// If the title is different to what it was before, then save it. After the
// save has completed, update the post stream as there will be a new post
// indicating that the discussion was renamed.
if (title && title !== currentTitle) {
return this.discussion.save({title}).then(() => {
if (app.viewingDiscussion(this.discussion)) {
app.current.stream.update();
}
m.redraw();
this.hide();
});
} else {
this.hide();
}
}
}

Some files were not shown because too many files have changed in this diff Show More