1
0
mirror of https://github.com/flarum/core.git synced 2025-08-13 11:54:32 +02:00

Compare commits

...

864 Commits

Author SHA1 Message Date
Daniël Klabbers
34079108c8 update version to v0.1.0-beta.8.2 2019-06-12 16:12:01 +02:00
Daniël Klabbers
f7a8b76fa8 fixes font awesome issues in flarum 0.1.0-beta.8.1 2019-06-12 16:11:00 +02:00
Franz Liedke
bbe62f400f Release version 0.1.0-beta.8.1 2018-12-06 00:47:38 +01:00
Franz Liedke
fc5977f86f Do not create tables as InnoDB automatically, rely on connection default
As argued in #1675, this makes us slightly less reliant on MySQL.
2018-12-06 00:34:43 +01:00
Toby Zerner
796b57753d Don't output empty html tag attributes
From https://discuss.flarum.org/d/17817-meta-description-is-empty/8
ref #1677
2018-12-04 09:47:49 +10:30
Toby Zerner
88e43cc694 Fix empty meta description tag. Fixes #1677 2018-12-04 09:28:24 +10:30
Toby Zerner
6370f7ecff Set the default engine in the installer
The installer doesn't use DatabaseServiceProvider, so we need to set
the default engine in the config here too.

Fixes #1675
2018-12-04 09:12:19 +10:30
Toby Zerner
d9d7027ed0 Fix oopsie in fb6b51b1cf 2018-12-04 08:54:33 +10:30
flarum-bot
1106a2e3a3 Bundled output for commit b7f666525c [skip ci] 2018-12-02 22:26:12 +00:00
Toby Zerner
b7f666525c Update changelog 2018-12-03 08:51:27 +10:30
Toby Zerner
40dc6ac604 Fix discussion list scroll position not being maintained when hero is not visible 2018-12-03 08:50:54 +10:30
Toby Zerner
15e1a154e5 Add changelog 2018-12-02 08:08:44 +10:30
Franz Liedke
57d5846b64 Migrations: Fix dropping foreign keys
Passing an array to dropForeign does not mean dropping multiple indices,
but rather dropping a key on multiple tables.

Passing a string means that this string will be interpreted as index
name, not as name of the indexed column. Passing an array with one
string is therefore correct, in order to benefit from automatic index
name generation.
2018-11-30 14:02:37 +01:00
Franz Liedke
fb6b51b1cf Set InnoDB for DB connection and new tables
Refs #1661.
2018-11-29 23:21:58 +01:00
Franz Liedke
57f73c9638 Installer: Fix invalid join time of admin user
Fixes #1664.
2018-11-29 22:56:56 +01:00
Franz Liedke
7705a2b7d7 Fix search with database prefix
wrap() only adds a table prefix when referencing a column with a table
name (such as `foo.bar`) - when only a single identifier is provided, it
is assumed to be a column name, which does not need a prefix.

Fixes #1659.
2018-11-29 22:50:32 +01:00
Franz Liedke
f591585d02 Fix live output in ResetCommand
This was forgotten in 9e487b4.

Fixes #1663.
2018-11-29 22:04:01 +01:00
Franz Liedke
45afc33eb0 Fix code style and doc block 2018-11-29 21:31:12 +01:00
Daniël Klabbers
213fd62be3 Up the version (#1582) 2018-11-29 00:34:49 +01:00
Franz Liedke
66607a5674 Always invalidate all user email tokens
Reported by B. Dhiyaneshwaran of Geek Freak.
2018-11-29 00:33:42 +01:00
Toby Zerner
546b4f01ac Merge pull request #1656 from flarum/tz/fix-index-names
Fix index names in migrations
2018-11-27 22:32:17 +10:30
Toby Zerner
96e282458b Fix index names in migrations
This can be reverted when we upgrade to Laravel 5.7.
2018-11-27 12:19:13 +10:30
David Sevilla Martín
24ff8899a0 Throw FileNotFoundException when FileSource path does not exist
Closes #1649.
2018-11-22 23:40:38 +01:00
David Sevilla Martín
1b32c7cc51 Fix frontend extender using old container & wrong class 2018-11-22 21:17:32 +01:00
Franz Liedke
6c2a4a5ff7 Remove obsolete property accessor in User model
The locale field does not exist, and the accessor code was broken.

Closes #1653.
2018-11-22 21:12:25 +01:00
Toby Zerner
2d31a6f72e Clearer delineation of installation pointer 2018-11-22 18:37:00 +10:30
Toby Zerner
9115b9e28f Include LESS mixins and variables in all frontend compilers 2018-11-22 12:09:50 +10:30
Toby Zerner
3bff2e0f5c Consolidate ControllerRouteHandler into RouteHandlerFactory
Also allow closure to be passed for frontend content when creating routes
2018-11-22 12:09:50 +10:30
Toby Zerner
edaca3160e Refactor frontend code to allow for extension of assets
- Simpler class naming:
    Frontend\CompilerFactory → Frontend\Assets
    Frontend\HtmlDocumentFactory → Frontend\Frontend
    Frontend\HtmlDocument → Frontend\Document

- Remove AssetInterface and simply collect callbacks in Frontend\Assets
  instead

- Remove ContentInterface because it serves no purpose (never type-
  hinted or type-checked)

- Commit and add asset URLs to the Document via a content callback
  instead of in the Document factory class itself

- Add translations and locale assets to Assets separate to the assets
  factory, as non-forum/admin asset bundles probably won't want them

- Update Frontend Extender to allow the creation of new asset bundles

- Make custom LESS validation listener a standalone class instead of
  extending RecompileFrontendAssets
2018-11-22 12:09:50 +10:30
flarum-bot
9e63f32105 Bundled output for commit b074f47298 [skip ci] 2018-11-21 21:38:27 +00:00
Toby Zerner
f3a5a89e12 Apply fixes from StyleCI (#1651)
[ci skip] [skip ci]
2018-11-22 08:04:41 +10:30
Toby Zerner
b074f47298 Fix build errors by updating webpack-cli 2018-11-22 08:04:08 +10:30
Toby Zerner
2ef66ac716 Add "clear cache" button to admin 2018-11-22 08:03:43 +10:30
Toby Zerner
6654894da1 Fix old session method name 2018-11-22 07:24:44 +10:30
Toby Zerner
41544c8529 Fix positioning of hamburger menu unread indicator 2018-11-22 07:24:01 +10:30
Toby Zerner
53d1b87daf Revert "Configure external links before dispatching event"
This reverts commit 4c55d278b6.

Fixes #1650
2018-11-22 07:21:16 +10:30
Toby Zerner
c11e4720d9 Change watch command to dev 2018-11-21 18:31:54 +10:30
Toby Zerner
c73d03a427 Make npm package private, update deps 2018-11-21 18:31:24 +10:30
Toby Zerner
d0d6c52839 Remove sudo: false
See https://blog.travis-ci.com/2018-11-19-required-linux-infrastructure-migration
2018-11-21 18:27:12 +10:30
Toby Zerner
9585d448d2 Update README, CONTRIBUTING 2018-11-21 18:26:32 +10:30
Toby Zerner
04d46b9925 Remove copyright year from LICENSE
So we don't have to worry about keeping it updated
2018-11-21 18:24:59 +10:30
Toby Zerner
c3b2d8e7d8 Typehint Frontend extender arguments 2018-11-16 15:19:51 +10:30
Toby Zerner
62a40036d0 Fix empty JS files not actually being empty 2018-11-16 15:17:57 +10:30
Daniël Klabbers
2764ad87cc up the font-awesome dependency (#1642)
new version of components/font-awesome was tagged, let's up the minimum to allow for more icons:

https://packagist.org/packages/components/font-awesome
2018-11-14 17:12:27 +01:00
Toby Zerner
2c1be86857 Only say that we're migrating an extension if it has migrations 2018-11-14 16:41:36 +10:30
Toby Zerner
b26eb8e609 Publish core assets when migrating 2018-11-14 16:41:07 +10:30
Toby Zerner
1f0bf33cfb Fix extension names not being displayed when running migrations 2018-11-14 16:28:00 +10:30
Toby Zerner
6fadc0b653 New heading styles 2018-11-14 13:57:31 +10:30
flarum-bot
0255393108 Bundled output for commit b474843cc2 [skip ci] 2018-11-14 01:11:59 +00:00
Toby Zerner
b474843cc2 Clear the search loading indicator after pressing Enter 2018-11-14 11:38:28 +10:30
Toby Zerner
7e95b80341 Drastically improve search performance
The previous approach of joining the posts table into the main search
query was not scaling well. Searches on discuss.flarum.org were taking
~1.5 seconds which – a significant improvement over the pre-beta 8
search, but still not acceptable.

This new approach uses a much more efficient subquery join. Searches
on discuss.flarum.org now take mere milliseconds. The search result
ranking strategy has been further refined as well so that discussions
are ranked by the collective relevance of their posts.
2018-11-14 11:19:39 +10:30
Toby Zerner
18b90d16e3 Allow users to hide their own posts just as they can edit them
This fixes a regression introduced by #1466.
2018-11-14 09:33:28 +10:30
flarum-bot
64a7e8ac3a Bundled output for commit e8b8cd0078 [skip ci] 2018-11-13 21:41:20 +00:00
David Sevilla Martín
e8b8cd0078 Move EditUserModal fields into an ItemList to make more extendable (#1593) 2018-11-14 08:00:43 +10:30
Toby Zerner
3c8262ccde Fix incorrect regex modifier, causing JS to become malformed is some cases 2018-11-14 06:45:14 +10:30
Franz Liedke
68c6638fb5 Merge pull request #1633 from flarum/tz/improve-logging
Improve logging
2018-11-13 11:03:24 +01:00
Toby Zerner
105dd093fe Remove fileinfo dependency
As per https://github.com/flarum/docs/issues/14#issuecomment-365972062
2018-11-13 17:16:47 +10:30
Toby Zerner
920802e5ae Log errors when debug mode is on too 2018-11-13 07:47:01 +10:30
flarum-bot
882c4aa105 Bundled output for commit b826f9ce36 [skip ci] 2018-11-12 10:35:23 +00:00
Toby Zerner
b826f9ce36 Trigger input event when text is programmatically inserted 2018-11-12 17:21:37 +10:30
Toby Zerner
c13dfa2228 Add a toolbar area to the TextEditor component
This is to be used for formatting buttons and the like. Although it is
displayed in the controls area at the moment, it is conceptually
different and may be relocated to the top of the text editor in the
future.
2018-11-12 17:21:15 +10:30
Toby Zerner
bf3934d16f Improve appearance of text editor buttons
- Change preview icon to Font Awesome Regular instead of Solid
- Give the preview button a tooltip
- Change submit button icon to paper plane (shown on mobile)
- Tweak mobile header button touch target
- Scroll overflowing text editor controls horizontally
2018-11-12 17:19:37 +10:30
flarum-bot
a08068b112 Bundled output for commit 60149fbe15 [skip ci] 2018-11-12 01:14:08 +00:00
Toby Zerner
60149fbe15 Merge pull request #1634 from clarkwinkelmann/fix-scrubber-index
Fix scrubber index exceeding post count
2018-11-12 11:40:29 +10:30
Clark Winkelmann
13c593cbaa Fix notification isRead value not being updated in API update response (#1635) 2018-11-12 00:14:13 +01:00
Toby Zerner
f7a320bcca Boot new application instance before enabling extensions. fixes #1587 (#1631) 2018-11-12 00:01:17 +01:00
Franz Liedke
b980c6fb7d Remove unused default constructor 2018-11-11 23:52:47 +01:00
Clark Winkelmann
0f9118fe2b Clean PostStreamScrubber code 2018-11-11 19:03:22 +01:00
Clark Winkelmann
95f0edcd80 Fix scrubber index not limited to max items count when bypassing view() 2018-11-11 19:00:51 +01:00
Toby Zerner
222e3c3fe2 Log errors that occur in the API stack
This takes place only in the FallbackExceptionHandler. Having a custom
exception handler implies that a friendly message is displayed in the
API response, in which case we can bet that the exception won't need to
be "debugged" per se.
2018-11-11 18:00:57 +10:30
Toby Zerner
903c1e329d Stop logging errors that use a custom view
Having a custom view implies that a friendly message is displayed to
the user, in which case we can bet that the exception won't need to be
"debugged" per se.
2018-11-11 17:57:55 +10:30
Toby Zerner
295a007cd5 Catch Throwables so that we handle internal PHP errors too 2018-11-11 17:54:19 +10:30
flarum-bot
66404e1f61 Bundled output for commit bf8bc0222f [skip ci] 2018-11-11 06:35:34 +00:00
Toby Zerner
64e43ec9a4 Apply fixes from StyleCI (#1632)
[ci skip] [skip ci]
2018-11-11 17:01:34 +10:30
Toby Zerner
bf8bc0222f Delete associated notifications when deleting discussions, posts, and users. fixes #1380 2018-11-11 16:59:24 +10:30
Toby Zerner
6d14d0c39b Perform visibility checks on notification subjects at the query level
This will prevent a notification from being seen by a user if its
subject is deleted or undergoes some kind of permission change (eg.
a discussion is moved into a private tag)

ref #1380
2018-11-11 16:58:08 +10:30
Toby Zerner
17fdc0ebe0 Consolidate Post visibility logic into the PostPolicy
A post can only be seen if the discussion in which it resides can be
seen. The logic for this belongs in the policy, not the model.
2018-11-11 16:54:15 +10:30
Toby Zerner
9de786d1e6 Fix notification list not displaying "empty" message 2018-11-11 16:46:54 +10:30
Toby Zerner
b92ae61294 Always allow users to see their own account. fixes #1626 2018-11-11 14:25:21 +10:30
Franz Liedke
e99f7fcdac Fix leak of private information when updating users
Fixes #1628.
2018-11-09 12:02:26 +01:00
Franz Liedke
009ddcdb63 Add regression test for email crawling vulnerability
Refs #1628.
2018-11-09 12:02:26 +01:00
Franz Liedke
d021dc2399 Move trait to base test class
This way, its properties can be overwritten in subclasses of
`ApiControllerTestCase`. This isn't allowed when those subclasses
use the trait directly.
2018-11-09 12:02:21 +01:00
Daniël Klabbers
1fff5dbbbc add security address in issue template as well (#1630)
as per suggestion by @CDK2020, let's also add an important statement in the issue template
2018-11-09 10:02:20 +01:00
Daniël Klabbers
4de5accfc1 add security email address in flarum/core readme (#1629)
Let's make the security email address even more visible.
2018-11-08 23:41:51 +01:00
Daniël Klabbers
bb0fc165af [b8] master token fix (#1622)
* fixed not being able to use master token because id column no longer holds key
* added flexibility of user_id column
* added tests to confirm the api keys actually work as intended
2018-11-07 22:34:09 +01:00
flarum-bot
fb185f70cd Bundled output for commit f283f0c7bd [skip ci] 2018-11-07 21:20:16 +00:00
Franz Liedke
3b630cb03e Restore horizontal overflow for permission grid
Refs #1627.
2018-11-07 22:17:16 +01:00
Clark Winkelmann
f283f0c7bd Use ItemList for EditGroupModal fields (#1625) 2018-11-07 22:15:19 +01:00
David Sevilla Martín
4b915c688c Remove overflow from .PermissionsPage-permissions (#1627) 2018-11-06 22:41:21 +01:00
Toby Zerner
83e99ed5a5 Merge pull request #1623 from flarum/luceos-patch-1
Update AccessToken.php
2018-11-02 07:12:23 +10:30
Daniël Klabbers
a09894a906 Update AccessToken.php
Fixes phpdoc while working on #1622
2018-11-01 10:56:45 +01:00
flarum-bot
1c7d2c3d27 Bundled output for commit 7db6cfac3f [skip ci] 2018-10-31 13:35:47 +00:00
Daniël Klabbers
7db6cfac3f Update EditGroupModal.js
fixed placeholder icon name fa 4 style to fa 5 style with `fas fa-bolt`
2018-10-31 14:28:50 +01:00
Daniël Klabbers
c446c5cc61 fixes author gambit when used with fulltext search, added test to cover (#1620)
* fixes author gambit when used with fulltext search, added test to cover

* Apply fixes from StyleCI

[ci skip] [skip ci]
2018-10-29 23:01:25 +01:00
flarum-bot
bd10ebff24 Bundled output for commit 104d3982fe [skip ci] 2018-10-28 21:00:22 +00:00
Toby Zerner
104d3982fe Fix regression in admin routing in subdirectory. fixes #1606
Because admin routing uses the "hash" strategy, the base path does not
need to be taken into account.
2018-10-29 07:25:17 +10:30
Franz Liedke
a1948e7bb8 Fix installation in subdirectory
Fixes #1604.
2018-10-26 00:27:35 +02:00
Franz Liedke
4775535421 Fix tests 2018-10-24 22:38:47 +02:00
Franz Liedke
2392e06c0e Apply fixes from StyleCI (#1616)
[ci skip] [skip ci]
2018-10-24 22:20:15 +02:00
Franz Liedke
e3e10a8fc3 Allow setting all paths when instantiating Site
Fixes #1592.
2018-10-24 22:19:09 +02:00
flarum-bot
b4dbab5df1 Bundled output for commit f062f69f00 [skip ci] 2018-10-24 20:06:14 +00:00
Clark Winkelmann
f062f69f00 Update Font Awesome icons page link (#1615) 2018-10-24 21:20:49 +02:00
Toby Zerner
0e3b0fc5a0 Update forgotten column name 2018-10-23 20:52:09 +10:30
Franz Liedke
21b3737dc2 Merge pull request #1608 from flarum/fl/1602-extend-frontend-document
New extender for adding variables to HtmlDocument payload
2018-10-21 22:34:22 +02:00
Franz Liedke
4ed1d0aaee New extender for adding variables to HtmlDocument payload
Fixes #1602.
2018-10-21 20:45:19 +02:00
Franz Liedke
86b26ce2fb Tweak ContentInterface so that callables can be used as well 2018-10-21 20:41:45 +02:00
Toby Zerner
eafc637475 Prevent long words/content from stretching the discussion list width 2018-10-21 14:47:41 +10:30
Daniël Klabbers
a03f243ca5 Fixes logging in with access token (#1605)
Seems the created_at column has no default value. This was always the case, at least that's what I can tell from a clean install and no migrations changing that default value.

```
$table->timestamp('created_at');
```
2018-10-21 01:21:34 +02:00
Toby Zerner
5f5e1c512c Load extensions in the configured order 2018-10-20 22:21:39 +10:30
Toby Zerner
a4d540f74b Don't require paths to be set in config - use sensible defaults 2018-10-18 19:27:03 +10:30
Tristian Kelly
c23af9550e Broader system font stack (#1600) 2018-10-17 23:55:41 +02:00
David Sevilla Martín
8fd3e8908c Align search icon on search bar (#1599) 2018-10-16 20:40:39 +02:00
David Sevilla Martín
cc95faa07d Add migration to add 'fa fa-' to group icons (#1597)
* Add migration to add 'fa fa-' (FA v4 shim) to group icons

* StyleCI

* Change prefix to `fas fa-`
2018-10-10 00:39:19 +02:00
flarum-bot
f1add1798b Bundled output for commit 9fa7258325 [skip ci] 2018-10-09 22:32:47 +00:00
Franz Liedke
81f6ce220e Merge pull request #1594 from datitisev/item-list
Allow ItemList method chaining (add, merge, remove, replace)
2018-10-10 00:28:03 +02:00
Franz Liedke
9fa7258325 Merge pull request #1598 from flarum/dk/log-rotation
adds log rotation, reducing file size per log file and easier to delete
2018-10-10 00:27:39 +02:00
Daniël Klabbers
4841661ee2 adds log rotation, reducing file size per log file and easier to delete 2018-10-09 19:54:52 +02:00
David Sevilla Martín
7b34636636 Allow ItemList method chaining (add, merge, remove, replace) 2018-10-05 19:30:14 -04:00
Franz Liedke
8474dfd6e2 Consistent use of private instead of protected
See discussion in 5b821b21b1 (r30752077).
2018-10-04 09:08:43 +02:00
flarum-bot
737d33826e Bundled output for commit 3006f58274 [skip ci] 2018-09-29 23:59:11 +00:00
Toby Zerner
3006f58274 The document JS payload attribute was previously renamed to apiDocument 2018-09-30 09:24:25 +09:30
Toby Zerner
d3a5e2451a Merge pull request #1581 from flarum/fl/1463-extension-install-hooks
Extension enable/disable hooks
2018-09-29 08:19:26 +09:30
Franz Liedke
f03c954dcc Extensions do not need to know whether they are enabled 2018-09-26 23:34:33 +02:00
Franz Liedke
3b70b9e76e Let extensions take care of flushing the formatter cache 2018-09-26 23:11:27 +02:00
Franz Liedke
b823a9df47 migrate: Use existing public API to filter extensions 2018-09-26 23:03:48 +02:00
Franz Liedke
8621500501 Use early returns to flatten methods 2018-09-26 22:59:48 +02:00
Franz Liedke
f48101dc04 Add a new extender interface for extension lifecycle hooks 2018-09-26 22:56:25 +02:00
Franz Liedke
3c827d2fce Tweak extender interface in preparation for adding more methods 2018-09-26 22:36:36 +02:00
Charlie
1f0e9b6280 Update ExtensionPage Style (#1560) 2018-09-26 17:00:27 +09:30
Franz Liedke
bf61753361 Merge pull request #1577 from flarum/tz/database-indices
Database indices
2018-09-24 23:49:23 +02:00
flarum-bot
70cb2f6f2e Bundled output for commit 1736fe3f58 [skip ci] 2018-09-23 00:46:47 +00:00
Toby Zerner
1736fe3f58 Clean up PostsUserPage placeholder 2018-09-23 10:12:12 +09:30
flarum-bot
ae81c4f0f1 Bundled output for commit 8c679c715c [skip ci] 2018-09-22 22:01:38 +00:00
David Sevilla Martín
8c679c715c Allow admins to see last online text (#1540)
* Allow admins to see last online text

* Use viewLastSeenAt permission

* Move permission to UserSerializer, removed from ForumSerializer

* Remove extra comma from ForumSerializer to keep diff clean

* Add permission to new seed migration
2018-09-22 23:55:53 +02:00
Toby Zerner
4236f3d49e Merge pull request #1576 from datitisev/user-posts-page
Make user posts page similar to discussion page, add empty text
2018-09-23 07:22:08 +09:30
Sajjad Hashemian
e3afb38427 fix empty base url (#1453) 2018-09-22 21:58:18 +02:00
David Sevilla Martín
26a5b107bd Make user posts page similar to discussion page, add empty text 2018-09-22 14:02:14 -04:00
Franz Liedke
aa70441632 Fix installation command, part 2 2018-09-22 17:45:38 +02:00
David Sevilla Martín
0fb9aa3940 Align icons & text in SideNav and Dropdown (#1544) 2018-09-22 21:35:45 +09:30
flarum-bot
b6a60721e2 Bundled output for commit fe868af224 [skip ci] 2018-09-22 04:58:46 +00:00
Clark Winkelmann
fe868af224 Clean composer promises (#1439)
* Remove unused login promise code

* Make promise usage consistent across composer action methods
2018-09-22 14:25:19 +09:30
flarum-bot
0984979403 Bundled output for commit fcb97b256f [skip ci] 2018-09-22 04:19:52 +00:00
Toby Zerner
5dfb9b474c Auth token and avatarUrl security improvements (#1514)
* Remove AbstractOAuth2Controller

There is no reason to provide an implementation for a specific oAuth2
library in core; it's not generic enough (eg. auth-twitter can't use it).

This code could be moved into another package which auth extensions
depend on, but it's a negligible amount of relatively simple code that
I don't think it's worth the trouble.

* Introduce login providers

Users can have many login providers (a combination of a provider name
and an identifier for that user, eg. their Facebook ID).

After retrieving user data from a provider (eg. Facebook), you pass the
login provider details into the Auth\ResponseFactory. If an associated
user is found, a response that logs them in will be returned. If not, a
registration token will be created so the user can proceed to sign up.
Once the token is fulfilled, the login provider will be associated with
the user.
2018-09-22 13:48:27 +09:30
Toby Zerner
fcb97b256f Add migration helper to drop columns 2018-09-22 13:45:41 +09:30
Toby Zerner
4429cf4eba Merge pull request #1513 from flarum/tz/1419-restrict-own-permissions
Make "own" permissions depend on the user's ability to reply
2018-09-22 12:22:03 +09:30
Toby Zerner
c54f739484 Make "own" permissions depend on the user's ability to reply
Permission to rename/hide/edit one's own discussion/post is only granted
if the user has permission to reply to the discussion. This makes sense
if you think of these actions as forms of "replying" to a discussion.

Fixes #1419 because suspended users do not have permission to reply to
discussions, therefore they will not be granted these "own" permissions.
2018-09-22 12:15:46 +09:30
Franz Liedke
6c0d73afa0 Fix tests 2018-09-22 00:40:19 +02:00
Franz Liedke
1cd8ec6873 Display only exception messages during booting
By not letting PHP render the stack trace, we prevent displaying
sensitive information (such as the database credentials). Instead,
we display a simple line with the exception message.

In the console, the full exception can still be shown, as that is
a tool only for forum admins anyway.

Fixes #1421.
2018-09-21 23:33:28 +02:00
Franz Liedke
4ed1c7a1bb Boot Flarum app in Server classes
This is in preparation for fixing #1421 - it allows us to
encapsulate the exception handling in the server classes, so that
we can keep the skeleton (flarum/flarum) lean.
2018-09-21 23:30:14 +02:00
Franz Liedke
c67f673819 Remove references to deleted property 2018-09-21 12:29:16 +02:00
flarum-bot
7917ce130e Bundled output for commit 2b174b17fc [skip ci] 2018-09-21 05:07:46 +00:00
Toby Zerner
2b174b17fc Fix tests 2018-09-21 14:32:41 +09:30
Toby Zerner
550d35e86f Apply fixes from StyleCI (#1574)
[ci skip] [skip ci]
2018-09-21 14:28:02 +09:30
Toby Zerner
64686ef7a9 Remove the "debug" button from request error alerts
Using the browser's console to debug failed requests is much more powerful
2018-09-21 14:27:39 +09:30
Toby Zerner
5ce702a5d0 Make registration errors still work properly when debug mode is on 2018-09-21 14:18:17 +09:30
flarum-bot
fdf5fdbaf3 Bundled output for commit 184ffcd991 [skip ci] 2018-09-21 02:30:05 +00:00
Toby Zerner
184ffcd991 Sort user discussion list properly 2018-09-21 11:55:00 +09:30
flarum-bot
ba946237e4 Bundled output for commit 8ec0578ddf [skip ci] 2018-09-21 02:09:25 +00:00
Toby Zerner
8ec0578ddf Fix installation command 2018-09-21 11:32:46 +09:30
Toby Zerner
c34fcecf03 Update TextFormatter deprecated API 2018-09-21 11:23:24 +09:30
Toby Zerner
9e487b4e41 Live output of migrator notes 2018-09-21 11:22:51 +09:30
Toby Zerner
986d811a16 Fix notifications crash
When loading notifications, $this->type was null and thus array_get
was returning an array instead of null. I assume this issue was
introduced in a Laravel version upgrade? Anyway, this fixes it.
2018-09-21 11:22:26 +09:30
Toby Zerner
c32af6559e Fix group badge misalignment if there is no group icon 2018-09-21 11:20:54 +09:30
Toby Zerner
07298e165d Use default system font instead of Open Sans 2018-09-21 11:20:17 +09:30
Toby Zerner
c15bbc9c5e Add "tiny" preset for LoadingIndicator
This is used in various places but had not been added since presets were
removed from Spin.js in a recent version upgrade.
2018-09-21 11:19:32 +09:30
Toby Zerner
6c8c525e57 Fix regression introduced by #1543
The Page component's config method wasn't being called, therefore the
bodyClass would not be applied.
2018-09-21 11:17:54 +09:30
Toby Zerner
93dfb6dec9 Revert "Frontend extender: Remove route registration"
This reverts commit 4770a5c906.
2018-09-21 09:05:45 +09:30
Toby Zerner
750d9d05a6 Use container events as an alternative to the ConfigureMiddleware event (#1462)
By moving the DispatchRoute middleware into an `afterResolving`
callback, this will allow a new Middleware extender to add a `resolving`
callback to the appropriate container binding, removing the need for the
ConfigureMiddleware event.

The ConfigureMiddleware event has been deprecated and should be removed
in beta 9.
2018-09-16 21:21:13 +02:00
Franz Liedke
0ce289be4c Travis: Add table prefix to build matrix (#1568)
Fixes #1564.
2018-09-16 20:59:40 +02:00
flarum-bot
7fcf556f13 Bundled output for commit 68afdd21ae [skip ci] 2018-09-16 18:51:11 +00:00
Franz Liedke
68afdd21ae Merge pull request #1344 from flarum/1236-database-changes
Database changes
2018-09-16 20:44:29 +02:00
Toby Zerner
54aa9ee3cf Add database indices. closes #127 2018-09-15 14:32:51 +09:30
Toby Zerner
5635bd26f9 Fix query error 2018-09-15 12:44:59 +09:30
Toby Zerner
622bf26510 Inline permissions migration 2018-09-15 12:40:32 +09:30
Franz Liedke
2367a45c18 Use instance variable directly instead of passing it around 2018-09-07 01:40:31 +02:00
Franz Liedke
4770a5c906 Frontend extender: Remove route registration
This can be achieved using the Route extender, which is more
flexible, as it does not necessary connect the URL with the current
frontend's router.

(Example use-case: The ext-embed frontend will be a new frontend,
however any routes using this frontend will be part of the forum
route group.)

Refs #851.
2018-09-07 01:40:31 +02:00
Franz Liedke
c61badd754 Frontend extender: Route to correct frontend
So far, we always added routes configured via this extender to the
forum frontend. Not correct.
2018-09-07 01:02:13 +02:00
Franz Liedke
14393ec53e RouteHandlerFactory: Refactor frontend parameter
By passing in just the frontend identifier, we can hide some of the
implementation details, in this case the identifier of the Frontend
instance in the IoC container.
2018-09-07 01:00:56 +02:00
Franz Liedke
96045ca390 flarum info: Try to fix STDERR redirection for Windows
See the following articles for more information:
- https://www.24k.com.sg/blog-27.html
- https://support.microsoft.com/en-us/help/110930/redirecting-error-messages-from-command-prompt-stderr-stdout

Refs #1562.
2018-09-07 00:25:26 +02:00
Franz Liedke
eb228dd7b9 flarum info: Extract extension table to function 2018-09-04 00:38:08 +02:00
Franz Liedke
092e5b9d23 flarum info: Tweak output styling 2018-09-04 00:32:54 +02:00
David Sevilla Martín
7e3980744e InfoCommand improvements (#1562)
* Ignore error output of 'git rev-parse HEAD'
* Organize extension information in a table
2018-09-04 00:24:07 +02:00
Franz Liedke
85c965afbc Use correct method from contract 2018-09-03 23:55:16 +02:00
David Sevilla Martín
43fc2c0952 Add 'oldUsername' to User\Event\Renamed (#1563) 2018-09-03 22:42:30 +02:00
Franz Liedke
5a9b47cdf7 Apply fixes from StyleCI (#1561)
[ci skip] [skip ci]
2018-09-01 23:35:37 +02:00
Franz Liedke
5374f8a352 flarum info: Display warning when in debug mode
Refs #1421.
2018-09-01 16:57:44 +02:00
Franz Liedke
5f5af894ab Load per-site extenders, if available
Closes #1559.
2018-09-01 16:27:52 +02:00
Franz Liedke
d7c283a48f Frontend extender: Work without extension, too 2018-09-01 16:15:02 +02:00
flarum-bot
c5a3715701 Bundled output for commit 710c63ba6a [skip ci] 2018-08-25 10:56:59 +00:00
Toby Zerner
710c63ba6a Update JS tooling 2018-08-25 20:18:59 +09:30
Toby Zerner
5142c639c1 Rename user methods 2018-08-24 22:13:06 +09:30
Toby Zerner
eb3232dfc9 Missed a spot 2018-08-24 22:13:06 +09:30
Toby Zerner
72d46bc461 Fix up Notification model 2018-08-24 22:13:06 +09:30
Toby Zerner
9792576464 Rename notification.sender 2018-08-24 22:13:06 +09:30
Toby Zerner
5c0c2d1c40 Rename notification.time 2018-08-24 22:13:05 +09:30
Toby Zerner
ce39bc9070 Rename user.newNotificationsCount 2018-08-24 22:13:05 +09:30
Toby Zerner
37ffd04b3f Rename user.unreadNotificationsCount 2018-08-24 22:13:05 +09:30
Toby Zerner
d8d2de438f Rename user.readTime 2018-08-24 22:13:05 +09:30
Toby Zerner
70058652b5 Rename user.isActivated 2018-08-24 22:13:05 +09:30
Toby Zerner
d9d8162684 Rename user.lastSeenTime 2018-08-24 22:13:05 +09:30
Toby Zerner
2ee10bb49f Rename user.commentCount 2018-08-24 22:13:05 +09:30
Toby Zerner
64abbde8b2 Rename user.discussionsCount 2018-08-24 22:13:05 +09:30
Toby Zerner
ca93c8c609 Rename post.hideUser 2018-08-24 22:13:05 +09:30
Toby Zerner
8248ba2f7a Rename post.editUser 2018-08-24 22:13:05 +09:30
Toby Zerner
dd65801d57 Rename post.hideTime 2018-08-24 22:13:05 +09:30
Toby Zerner
07c08ca798 Rename post.editTime 2018-08-24 22:13:05 +09:30
Toby Zerner
ae75f21b6b Rename post.time 2018-08-24 22:13:05 +09:30
Toby Zerner
d47c406d9c Rename discussion.repliesCount 2018-08-24 22:13:05 +09:30
Toby Zerner
29cef23404 Rename discussion.hideUser 2018-08-24 22:13:05 +09:30
Toby Zerner
a7ffed6778 Rename discussion.readNumber 2018-08-24 22:13:05 +09:30
Toby Zerner
9074f7e592 Rename discussion.readTime 2018-08-24 22:13:05 +09:30
Toby Zerner
99e5013ac3 Rename discussion.hideTime 2018-08-24 22:13:05 +09:30
Toby Zerner
1e9d9b8322 Rename discussion.lastTime 2018-08-24 22:13:05 +09:30
Toby Zerner
568006fe73 Rename discussion.startTime 2018-08-24 22:13:05 +09:30
Toby Zerner
4756bf1daf Rename discussion.lastPostedUser 2018-08-24 22:13:05 +09:30
Toby Zerner
8ecb67d49d Rename discussion.startUser 2018-08-24 22:13:05 +09:30
Toby Zerner
e241518506 Rename discussion.startPost 2018-08-24 22:13:05 +09:30
Toby Zerner
cbd0643540 Rename discussion.participantsCount 2018-08-24 22:13:05 +09:30
Toby Zerner
7716944616 Rename discussion.commentsCount 2018-08-24 22:13:05 +09:30
Toby Zerner
e135b7830e Fix installer 2018-08-24 22:12:45 +09:30
Toby Zerner
950ab30c29 Fix reset password 2018-08-24 21:54:46 +09:30
Toby Zerner
582054c61c Merge branch 'master' into 1236-database-changes 2018-08-24 21:07:00 +09:30
Toby Zerner
280d51e678 Merge pull request #1555 from flarum/fl/sites
Rewrite sites / app
2018-08-24 18:21:05 +09:30
Toby Zerner
e9ed935ed1 Revert method name 2018-08-24 17:09:22 +09:30
Toby Zerner
809b161d71 Merge branch 'master' into 1236-database-changes 2018-08-24 17:03:50 +09:30
Toby Zerner
6bc434c918 Remove user_user table
Since there is currently no core code that facilitates use of this table,
we are removing it for now. It can be re-added in a subsequent PR.
2018-08-24 15:15:40 +09:30
Franz Liedke
4c8908c005 Rename extension's bootstrap.php to extend.php
...while supporting the old name for a while.

Fixes #1556.
Refs #1557.
2018-08-24 00:08:56 +02:00
Franz Liedke
2d4dc02ca1 Pass container into apps, adapt path matching 2018-08-23 22:17:37 +02:00
Franz Liedke
869ec54bd0 Load middleware stacks lazily
This way, the forum middleware does not need to be loaded for
API requests, and vice-versa.
2018-08-22 09:20:47 +02:00
Franz Liedke
59b1ca9b7c Implement request handler for maintenance mode 2018-08-22 09:20:00 +02:00
Franz Liedke
7439069fe2 Use more honest method names 2018-08-22 07:58:50 +02:00
Franz Liedke
973fbcf17b Instantiate DispatchRoute manually
Since we are already providing the first and only argument
manually, we might as well instantiate the object manually.
Same effect, same coupling, less code.
2018-08-22 07:58:50 +02:00
Franz Liedke
034000ea0b Fix tests after sites refactoring 2018-08-22 07:58:50 +02:00
Franz Liedke
fb5740926a Split SessionServiceProvider from UserServiceProvider
This lets us register the former during installation, where the
latter is not yet registered.

That, in turn, means we can finally re-enable the StartSession
middleware in the installer app, which we need to log in the new
admin user when installation is complete.
2018-08-22 07:58:50 +02:00
Franz Liedke
32ad926cbc One BusServiceProvider is enough 2018-08-22 07:58:50 +02:00
Franz Liedke
626d16de6f Use zend-httphandlerrunner for marshalling requests and returning responses
Since Diactoros 1.8, the emitter and server classes have been
deprecated. They can be replaced by using this new package
directly.
2018-08-22 07:58:50 +02:00
Franz Liedke
0222692c53 Console Installer: Rely less on service providers
Most things we need, we can instantiate directly.

This means we have to do less tweaking in service providers that
are meant to provide services to a complete Flarum application
(that has already been installed properly), to make them work with
the uninstalled app.

The uninstalled app (the "installer") can now do only the
bootstrapping it needs to build a light-weight web and console
application, respectively.
2018-08-22 07:58:50 +02:00
Franz Liedke
b4b72fe62f Get rid of some Application methods
These are not necessary to be available so broadly. In fact, they
seem to make it too easy to use them, which has lead to some sub-
optimal architecture decisions.

Their equivalents have been moved to the classes where used.
2018-08-22 07:58:50 +02:00
Franz Liedke
5b821b21b1 Split up Site into several classes
Depending on the state of the Flarum installation (installed, not
installed, currently upgrading, maintenance mode), we should enable
different sets of service providers.

For example, during installation we should not resolve a setting
repository from the container. This new architecture lets us do so,
but we can easily (and cleanly) register a different implementation
during installation.

This should prevent problems such as #1370 in the future.
2018-08-22 07:58:50 +02:00
Franz Liedke
7a6e208554 Split up HandleErrors middleware into distinct classes
These are completely distinct functionalities, toggled through the
system-wide debug flag. By moving the selection of the middleware
to use to the place where the middleware pipe is built, we make
the middleware itself be unaware of these flags. The two classes
are more focused on what they are doing, with the constructor
dependencies clearly representing their requirements.

In addition, this means we can just use the HandleErrorsWithWhoops
middleware in the installer, which means we do not need to worry
about how to inject a SettingsRepositoryInterface implementation
when flarum is not yet set up.
2018-08-22 07:58:50 +02:00
flarum-bot
3a0e982df1 Bundled output for commit 6057151c29 [skip ci] 2018-08-22 00:08:57 +00:00
David Sevilla Martín
6057151c29 Fix PR issues from #1496 (#1553)
* Remove `+` added from copying a diff somewhere

* Fix font-size
2018-08-22 09:34:18 +09:30
flarum-bot
fcb9a049e9 Bundled output for commit 190bcb5e9a [skip ci] 2018-08-21 21:21:28 +00:00
Arda Çebi
190bcb5e9a Add descriptions and optimize extensions page (#1496) 2018-08-21 23:16:02 +02:00
flarum-bot
e72ac76997 Bundled output for commit 62e7a7188c [skip ci] 2018-08-19 21:48:23 +00:00
David Sevilla Martín
62e7a7188c Add a permission check to the Search sources (#1527) 2018-08-19 23:43:49 +02:00
David Sevilla Martín
ca16a23383 Installer: add check for file existence & fix path resolving (#1397) 2018-08-19 23:40:37 +02:00
Toby Zerner
195f77ff10 Apply fixes from StyleCI (#1551)
[ci skip] [skip ci]
2018-08-18 12:13:40 +09:30
Toby Zerner
5f83285442 Add extension JS as a file to allow sourcemap detection
Fixes #1538
2018-08-18 12:13:17 +09:30
Franz Liedke
c16ddf24f2 Add tokenizer to PHP extension requirements
Refs flarum/flarum.github.io#73.
2018-08-14 22:53:12 +02:00
flarum-bot
394fc4232e Bundled output for commit fd36d18729 [skip ci] 2018-08-14 20:19:39 +00:00
David Sevilla Martín
fd36d18729 Change tab title after renaming discussion (#1543)
* Change tab title after renaming discussion

* Uncommit dist

* Uncommit package-lock.json

* Fix for VDOM

* Move setTitle into DiscussionPage#config
2018-08-14 22:15:47 +02:00
Daniël Klabbers
2e16b0ce2e Update PULL_REQUEST_TEMPLATE.md (#1545)
* Update PULL_REQUEST_TEMPLATE.md

Added clarification about bundled PRs.

* Update PULL_REQUEST_TEMPLATE.md
2018-08-14 22:08:16 +02:00
flarum-bot
af47558ec2 Bundled output for commit 641079b3fe [skip ci] 2018-08-14 19:50:55 +00:00
Edward Betts
641079b3fe Correct spelling mistakes. (#1546) 2018-08-14 21:46:53 +02:00
David Sevilla Martín
df0f4e8462 Fix post composer width bug on profile (#1541) 2018-08-14 06:44:28 +09:30
flarum-bot
da0adf83ae Bundled output for commit 0452838802 [skip ci] 2018-08-13 21:07:47 +00:00
David Sevilla Martín
0452838802 ModalManager: Fix issue when app.current is not defined (#1530) 2018-08-14 06:33:39 +09:30
David Sevilla Martín
40e4c0acdd Fix wrong permission in UserPolicy#find (#1536) 2018-08-13 06:45:56 +09:30
Charlie
ef9ed7f4fa Dispatch the Deserializing event in Admin Content (#1532)
* Dispatch the Deserializing event

* Apply fixes from StyleCI (#1)
2018-08-11 17:15:11 +09:30
Franz Liedke
24fd2f32c7 Service Provider: Move loadViewsFrom() to boot()
This method relies on the "view" being bound in the IoC container.
This is only guaranteed after all register() methods have run, thus
it should be done in boot().
2018-08-03 00:53:39 +02:00
Franz Liedke
076288db21 Update zend-diactoros constraint
See security advisory ZF2018-01:
https://framework.zend.com/security/advisory/ZF2018-01
2018-08-02 23:15:24 +02:00
Clark Winkelmann
df7e24cba6 Update urls with their current canonical versions (#1524) 2018-08-02 17:39:06 +02:00
Toby Zerner
5438aea759 Apply fixes from StyleCI
[ci skip] [skip ci]
2018-08-01 03:55:21 +00:00
Toby Zerner
e46ce861dc Change TIMESTAMP columns to DATETIME manually 2018-08-01 13:24:55 +09:30
flarum-bot
01d8bd5344 Bundled output for commit 7f5080d9d5 [skip ci] 2018-07-24 15:44:53 +00:00
Toby Zerner
7f5080d9d5 Merge pull request #1520 from sijad/spinner-config
configure spinner only once
2018-07-25 01:08:50 +09:30
Sajjad Hashemian
640b93af36 configure spinner only once 2018-07-24 19:25:09 +04:30
Franz Liedke
cfc207f255 Apply fixes from StyleCI (#1518)
[ci skip] [skip ci]
2018-07-23 16:25:12 +02:00
Franz Liedke
d4a80eae5d Replace Assets with Frontend extender
This extender allows registering both assets and simple GET routes
with frontend instances.

See #851.
2018-07-23 16:24:00 +02:00
Toby Zerner
254d5d0c5b Fix group/permission seeding
Updating the Migration::addPermission helper table name means we need
to move the seed migration to after the table rename migration. We also
add a sanity check for each permission's group since the foreign key
will fail if the group doesn't exist. Of course, the only way to make
sure groups are seeded before permissions is to move them into another
migration.
2018-07-21 23:02:44 +09:30
Toby Zerner
1709d4ef2c Remove file accidentally added in merge 2018-07-21 22:09:14 +09:30
Toby Zerner
baeaa73597 Wrap column names; use whereColumn where possible 2018-07-21 22:02:54 +09:30
Toby Zerner
677a7dd2d3 Merge branch 'master' into 1236-database-changes
# Conflicts:
#	src/Forum/Controller/IndexController.php
#	src/User/UserMetadataUpdater.php
2018-07-21 21:37:49 +09:30
Toby Zerner
c562302161 Don't save in the model 2018-07-21 21:28:44 +09:30
Toby Zerner
d42f33971a Fix user list sorting 2018-07-21 18:39:32 +09:30
Toby Zerner
aa4c4b07bd Revert notifications_from table
I didn't think this change through and it's going to be too difficult
to implement right now. It can wait until we do the notifications
revamp. For now reverting back to the old structure, with the
`sender_id` column renamed to `from_user_id`.
2018-07-21 18:35:50 +09:30
Toby Zerner
420bb2efc8 Apply fixes from StyleCI
[ci skip] [skip ci]
2018-07-21 07:52:21 +00:00
Toby Zerner
ed57d6e51c Clean up attribute assignment 2018-07-21 17:22:03 +09:30
Toby Zerner
b4f6c4be1f Specify ambiguous column names 2018-07-21 17:21:37 +09:30
Toby Zerner
ff7f7681c7 Use Eloquent's latest and oldest 2018-07-21 17:21:08 +09:30
Toby Zerner
7d0813bce4 Fix some incorrect attribute names 2018-07-21 17:20:43 +09:30
Toby Zerner
4f259425b0 Fix entity deletion
Foreign keys take care of most of this for us!
2018-07-21 17:18:40 +09:30
Toby Zerner
22fadb7f9c Fix API key generation 2018-07-21 17:14:15 +09:30
Toby Zerner
d0115de771 No need for deleted_at in notifications table 2018-07-21 17:13:51 +09:30
Toby Zerner
9d790c18d6 Change TIMESTAMP columns to DATETIME 2018-07-21 17:12:51 +09:30
Toby Zerner
6f3eb3f335 Fix discussion and post list sorting 2018-07-21 17:10:02 +09:30
Toby Zerner
2d667d885d Fix email confirmation links 2018-07-21 17:08:11 +09:30
Toby Zerner
0fb81958cb Clean up Eloquent definitions 2018-07-21 17:06:42 +09:30
Toby Zerner
87bba2186e Fix to ensure we can rename columns in tables with enums
See https://github.com/laravel/framework/issues/1186
2018-07-21 15:26:12 +09:30
Toby Zerner
93b9513df2 Fix column names 2018-07-21 15:24:51 +09:30
Toby Zerner
fb6b2d05b1 Fix table name 2018-07-21 15:24:33 +09:30
Toby Zerner
fe73cf3237 Clean up migrations
* Make filenames and order more consistent

* Split foreign keys into their own migrations, add statements to ensure
  data integrity prior to adding them

* Add renameColumns helper, use other helpers where possible
2018-07-21 15:23:37 +09:30
Daniel Klabbers
c7efbba0da resetting to short annotation for dropping foreign key constraint, as per docs, must use array notation for this to work 2018-07-20 09:35:16 +02:00
Daniel Klabbers
be266a73cd fixed another foreign key drop with incorrect name 2018-07-20 09:24:42 +02:00
Daniel Klabbers
e1a282e0e1 forgot to name a few constraints properly on the dropForeign statement 2018-07-20 09:23:03 +02:00
Daniel Klabbers
5a04635e7a decided to leave the posts.discussion_id foreign key constraint to discussions out for now 2018-07-20 08:41:01 +02:00
flarum-bot
7d59b4da7e Bundled output for commit 6a6b9ac6b1 [skip ci] 2018-07-20 03:13:58 +00:00
Daniël Klabbers
f89c111f13 Update PULL_REQUEST_TEMPLATE.md (#1505) 2018-07-20 12:39:50 +09:30
Toby Zerner
6a6b9ac6b1 Use flexbox for sideNav. fixes #1408 2018-07-20 12:34:43 +09:30
Toby Zerner
cbe328cdc5 Revert Chrome image rendering tweak
The Chrome bug appears to have been fixed:
https://bugs.chromium.org/p/chromium/issues/detail?id=562162

This CSS rule makes images look very ugly in Safari, so removing it.

ref #1259
2018-07-20 12:03:49 +09:30
Toby Zerner
7b802a76ba Dissociate .sideNav--horizontal from @expand-side-nav 2018-07-20 11:38:42 +09:30
Daniel Klabbers
90792abf10 added constraints, discussions_first_post_id_foreign blocks here 2018-07-19 10:36:46 +02:00
Daniel Klabbers
5139ce647e instead of changing fulltext, use medium text schema builder change on posts.content 2018-07-19 09:52:20 +02:00
Daniel Klabbers
8779e40ec5 remove migration (initially was intended) to change settings.value to longblob 2018-07-19 09:45:29 +02:00
Daniel Klabbers
1e372f3881 split up the migration to create and seed notifications_from 2018-07-19 09:22:34 +02:00
Daniel Klabbers
b2e873ba7b undo carbon change as proposed in review 2018-07-19 09:15:59 +02:00
David Sevilla Martín
d6414cfb44 Properly set comments_count and discussions_count (#1436) 2018-07-17 19:02:37 +02:00
Franz Liedke
85ceda0b0b Remove another unused parameter 2018-07-16 15:48:48 +02:00
Franz Liedke
dc7c31e1c2 Remove incorrect attribute 2018-07-16 15:48:48 +02:00
Franz Liedke
177ac74596 Apply fixes from StyleCI (#1508)
[ci skip] [skip ci]
2018-07-16 15:13:21 +02:00
Franz Liedke
c76d9e1298 Move initial permission setup to migrations
Refs #1466.
2018-07-16 15:12:46 +02:00
Franz Liedke
dee54a008f Apply fixes from StyleCI (#1507)
[ci skip] [skip ci]
2018-07-16 01:44:50 +02:00
Franz Liedke
551ca23267 Discussion HTML: Add a canonical URL
Refs #358 and #1140.
2018-07-16 01:43:06 +02:00
Franz Liedke
3d845d5730 Discussion HTML: Fix generation of next/prev URLs 2018-07-16 01:42:36 +02:00
Franz Liedke
9b03f8c71a Make post filtering work with database prefixes 2018-07-16 01:22:13 +02:00
Franz Liedke
665f241348 Add migration for new hidePosts permission
Refs #1387 and #1466.
2018-07-16 00:41:55 +02:00
Franz Liedke
ce90d2bbdd Installer: Get rid of an instance variable
Leftover from PR #1405.
2018-07-16 00:33:32 +02:00
Franz Liedke
6e5b0f5289 Formatter: Tweak minifier setup
See discussion in PR #1457.
2018-07-14 22:57:20 +02:00
Sajjad Hashemian
fba31995b1 Upgrade text formatter (#1457)
* upgrade TextFormatter

* remove finalize options

* cleanup JsCompiler

* simplify Formatter

* refactor Formatter cache

* minify formatter js

* remove Closure Compiler
2018-07-14 22:22:14 +02:00
flarum-bot
604c789ee8 Bundled output for commit 034b82f4d4 [skip ci] 2018-07-14 20:19:52 +00:00
AFR
034b82f4d4 Create new hidePosts permission (#1466) 2018-07-14 22:15:40 +02:00
Daniel Klabbers
9be13cb1cd Revert "Update PULL_REQUEST_TEMPLATE.md"
This reverts commit 823f0263ae.
2018-07-13 10:34:09 +02:00
Daniël Klabbers
823f0263ae Update PULL_REQUEST_TEMPLATE.md
adding a requirement list
adding related required changes
added comment description
2018-07-13 10:32:57 +02:00
Toby Zerner
fb9a89f67f Use box-shadow instead of border for notifications badge
fixes #1481
closes #1500
2018-07-13 17:39:47 +09:30
Franz Liedke
7f63923aa0 Merge pull request #1503 from flarum/dk/1480
Update feature-request.md
2018-07-10 20:50:57 +02:00
Daniël Klabbers
73f8922553 Update feature-request.md 2018-07-10 06:26:29 +02:00
Daniel Klabbers
2c15597ec9 reset the relation table naming from groups_users to adhere to laravel convention group_user 2018-07-09 11:53:59 +02:00
Daniël Klabbers
7e43de25a6 Update feature-request.md
fixes #1480

This is a suggestion to improve clarification of what a feature request on our issue tracker should entail.

Changes made:

- uppercased "IMPORTANT" instead of a "Note" to clarify the importance of the comment
- removed the "serious" related information, because users often have no scale to rate seriousness against
- brought more attention to approval by a core developer or argumentation and implementation by moving that to the front
2018-07-09 10:54:37 +02:00
Franz Liedke
d42205a8ff Update doctrine/dbal version constraint
This update is needed to fix MariaDB compatibility.
See #1211.
2018-07-09 00:14:57 +02:00
Franz Liedke
00bc8fc0bc Composer: Reorder dependencies
[ci skip]
2018-06-30 23:46:10 +02:00
flarum-bot
c17af492a9 Bundled output for commit 0e73785498 [skip ci] 2018-06-30 03:05:06 +00:00
Toby Zerner
0e73785498 Frontend refactor (#1471)
Refactor Frontend + Asset code

- Use Laravel's Filesystem component for asset IO, meaning theoretically
  assets should be storable on S3 etc.

- More reliable checking for asset recompilation when debug mode is on,
  so you don't have to constantly delete the compiled assets to force
  a recompile. Should also fix issues with locale JS files being
  recompiled with the same name and cached.

- Remove JavaScript minification, because it will be done by Webpack
  (exception is for the TextFormatter JS).

- Add support for JS sourcemaps.

- Separate frontend view and assets completely. This is an important
  distinction because frontend assets are compiled independent of a
  request, whereas putting together a view depends on a request.

- Bind frontend view/asset factory instances to the container (in
  service providers) rather than subclassing. Asset and content
  populators can be added to these factories – these are simply objects
  that populate the asset compilers or the view with information.

- Add RouteHandlerFactory functions that make it easy to hook up a
  frontend controller with a frontend instance ± some content.

- Remove the need for "nojs"

- Fix cache:clear command

- Recompile assets when settings/enabled extensions change
2018-06-30 12:31:12 +09:30
Daniel Klabbers
0f5ddc1c43 phpversion minimum requirement changed in wrong location for installation 2018-06-28 11:40:34 +02:00
Daniel Klabbers
eaf98ccfc5 Revert "have install command demand php 7.1 too"
This reverts commit 9c7cc0548e.
2018-06-28 11:39:19 +02:00
Daniel Klabbers
9c7cc0548e have install command demand php 7.1 too 2018-06-28 11:23:04 +02:00
luceos
cf80cf86e5 Apply fixes from StyleCI
[ci skip] [skip ci]
2018-06-27 19:34:07 +00:00
Daniël Klabbers
a23dc0dfcd fixed some migration names and used helper where appropriate 2018-06-27 21:33:53 +02:00
Daniël Klabbers
54678e8d5c Merge branch 'master' into 1236-database-changes 2018-06-27 21:23:52 +02:00
Daniël Klabbers
4d2d7465ee Revert "migrating user preferences obviously works on empty table"
This reverts commit 066baed5b9.
2018-06-27 21:22:28 +02:00
flarum-bot
b78129b36b Bundled output for commit afe06ea750 [skip ci] 2018-06-27 19:17:31 +00:00
Franz Liedke
afe06ea750 Merge pull request #1456 from sijad/prevent-undefined
check class string before concat
2018-06-27 21:10:40 +02:00
Daniël Klabbers
9449fb4f1f not dropping bio due to not having a replacement 2018-06-27 21:09:32 +02:00
Sajjad Hashemian
aac194616a check class string before concat 2018-06-25 09:40:06 +04:30
Daniël Klabbers
d9b357c18e we need to leave the preferences column for now 2018-06-22 23:43:37 +02:00
Daniël Klabbers
48ac132959 Merge branch '1236-database-changes' of github.com:flarum/core into 1236-database-changes 2018-06-22 23:42:46 +02:00
Toby Zerner
b3f8379a15 Allow a single extender to be returned (#1469)
Casting an object to an array does not have the intended effect of
wrapping the object in an array. Instead we need to explicitly check
if the returned value is an array or not.
2018-06-22 18:10:54 +09:30
Daniel Klabbers
1800f4290a Merge branch 'master' into 1236-database-changes 2018-06-22 07:48:21 +02:00
flarum-bot
2234a81ee7 Bundled output for commit 805768a9e0 [skip ci] 2018-06-22 01:24:44 +00:00
Toby Zerner
805768a9e0 [WIP] JS Extender API foundation (#1468)
* Run extenders exported by extensions
* Add some basic extenders
* Patch Mithril as the very first thing so extension code can run safely
* Load the payload into the app before booting extensions
* Setup default routes before booting extensions
2018-06-22 10:49:46 +09:30
Franz Liedke
e3c2ddad2e Merge pull request #1465 from flarum/tz/formatter-extender
Rename and improve FormatterConfiguration extender
2018-06-21 10:11:35 +02:00
Toby Zerner
520e1550d1 Merge event listener registration 2018-06-20 23:37:27 +02:00
Toby Zerner
79b00cb94f Rename and improve FormatterConfiguration extender
In the future we may have multiple Formatters, so by moving the config
callback to its own instance method we can leave the constructor
available to specify which formatter (like Assets and Routes). This
format also allows for other methods to be added.

Additionally, this adds logic to automatically flush the Formatter cache
whenever the extension is enabled or disabled.
2018-06-20 23:37:27 +02:00
Toby Zerner
0bcc6e74a8 Checkout the branch before committing 2018-06-20 14:47:37 +09:30
Toby Zerner
542e8715ea git config before commit [skip ci] 2018-06-20 14:42:18 +09:30
Toby Zerner
3f683dd6ee 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
2018-06-20 13:20:31 +09:30
Toby Zerner
d234badbb2 New issue templates (#1459) 2018-06-20 11:16:48 +09:30
Daniel Klabbers
2cd77e231f Merge branch 'master' into 1236-database-changes 2018-06-19 09:57:47 +02:00
Toby Zerner
07eda60561 Fix discussion posts not being initialized correctly. Fixes #1455 2018-06-16 11:01:42 +09:30
Toby Zerner
2bc7c4134a Add comment explaining extension boot process 2018-06-15 19:25:40 +09:30
Toby Zerner
050496a20e Make ExtensionManager a singleton 2018-06-15 19:25:15 +09:30
Toby Zerner
3b87778fbb Prevent @ character used in searches from crashing MySQL 🙄 2018-06-15 19:24:23 +09:30
Toby Zerner
569e6c9a92 Escape string used in LIKE query 2018-06-15 19:19:43 +09:30
Toby Zerner
c498e68530 Use imported class name 2018-06-15 19:18:47 +09:30
Toby Zerner
305841ddd4 Add Interface suffix 2018-06-15 19:17:43 +09:30
Daniël Klabbers
066baed5b9 migrating user preferences obviously works on empty table 2018-06-12 21:33:17 +02:00
Franz Liedke
211e7681cc Merge pull request #1451 from sijad/create-token
rename TokenController to CreateTokenController
2018-06-06 11:51:50 +02:00
Sajjad Hashemian
22f2df3670 rename TokenController to CreateTokenController 2018-06-06 09:40:29 +04:30
Franz Liedke
3bf74eaf10 Merge pull request #1445 from flarum/fl/migrations-simplify-interface
Migrations: Simplify interface
2018-06-04 01:05:31 +02:00
Franz Liedke
d301d260c1 Simplify interface of migration-related classes
Mostly, we only need a database connection, instead of one of
Laravel's "connection resolvers".

Again, this makes our life easier during installation, where
we already instantiate a database connection. We can now use
that to instantiate our own Migrator class, instead of using
the IoC container to build one.
2018-06-03 23:13:49 +02:00
Franz Liedke
a1c3da9f8f Migrations: always pass a schema builder
This removes the funky auto-injection capability from migration
closures. While technically removing a feature, this means we do
not need a fully-wired IoC container e.g. during installation.

Instead, all migration closures simply receive a schema builder
object (which is what most of them were already doing anyway).
2018-06-03 23:13:35 +02:00
Daniël Klabbers
26b02adc9d Merge branch 'master' into 1236-database-changes 2018-06-03 21:51:01 +02:00
Franz Liedke
3ec32f8430 Composer: Sort dependencies 2018-06-02 15:07:23 +02:00
Daniël Klabbers
f137eb358f Update .travis.yml
remove conditional which is unnecessary
2018-05-30 10:36:00 +02:00
Franz Liedke
b91a3573db Merge pull request #1443 from flarum/fl/controller-to-handlers
Replace ControllerInterface with PSR-15 interface
2018-05-30 09:54:13 +02:00
Franz Liedke
b3d45fd6f8 Replace ControllerInterface with PSR-15 interface
The custom interface already had the same signature as the
one from the standard (except for the return type hint), so
why not use that one now? :)
2018-05-30 09:49:47 +02:00
Franz Liedke
e6b8ff856e Merge pull request #1441 from flarum/fl/psr-15
Use PSR-15 middleware standard
2018-05-29 20:26:31 +02:00
Franz Liedke
4a2aa7e892 Merge branch 'master' into fl/psr-15 2018-05-29 20:21:31 +02:00
Daniël Klabbers
b3cbc5d1bd [wip] 1211 mariadb compatibility (#1440)
fixes #1211 

As we've already upgraded our minimum requirement to 7.1 there's no current need to force a constraint on dbal 2.7+.
2018-05-29 05:51:22 +02:00
Franz Liedke
3680d88fb7 Use PSR-15 middleware standard
This finally adopts the new standardized interfaces instead of the
work-in-progress ones with the `Interop\` prefix.

Since we have now updated to PHP 7.1, we can also use Stratigility
3.0 as the middleware dispatcher.
2018-05-29 00:18:24 +02:00
Franz Liedke
5d0ebde6b8 travis: Remove PHP 7.0 from build matrix 2018-05-28 23:41:32 +02:00
Franz Liedke
0278d52cbe Require PHP 7.1
This will be the last PHP requirement upgrade for a while, at least
until stable (and therefore until the next major release).

We have decided to do this now, for the following reasons:
- We want to support MariaDB (and the compatible release of
  doctrine/dbal requires 7.1 as well).
- We prefer to upgrade to Laravel 5.6 sooner rather than later.
- Using the PSR-15 middleware standard is easier this way, as we do
  not have to switch from zend-stratigility to another PSR-15
  implementation. (Stratigility v3, which implements the final
  standard, requires 7.1.)
2018-05-28 23:21:22 +02:00
Daniël Klabbers
c293fdaec0 undo session interface change 2018-05-21 21:19:38 +02:00
Daniel Klabbers
4654c3eb50 Merge branch '1236-database-changes' of github.com:flarum/core into 1236-database-changes 2018-05-16 09:36:25 +02:00
Daniel Klabbers
68d1edb8fd new api tests uncovered more issues, fixed tokens and discussion posts 2018-05-16 09:36:04 +02:00
Daniel Klabbers
30358e98c0 merged api tests into branch 2018-05-16 09:27:01 +02:00
Daniël Klabbers
e226f81515 additional tests for api controllers (#1433)
* added CreatePostControllerTest

* added DeleteDiscussionControllerTest

* added ListDiscussionControllerTest

* added TokenControllerTest

* minor improvement to policy, no need for Carbon object there, added ShowDiscussionControllerTest

* added showDiscussionControllerTest but cant make Guests view the discussion created by a user

* viewing for guests tested, we might need factories
2018-05-16 09:25:48 +02:00
Toby Zerner
09938f8633 Merge pull request #1432 from clarkwinkelmann/patch-3
Configure external links before dispatching textformatter configuring event
2018-05-15 07:56:24 +09:30
Clark Winkelmann
4c55d278b6 Configure external links before dispatching event
This way extensions can override the link attributes
2018-05-15 00:12:33 +02:00
luceos
808e7a226a Apply fixes from StyleCI
[ci skip] [skip ci]
2018-05-14 11:50:06 +00:00
Daniel Klabbers
3e3e1cbde5 fixed more attributes to match beta 8 2018-05-14 13:49:52 +02:00
Daniel Klabbers
a9501ceae0 Merge branch 'master' into 1236-database-changes 2018-05-14 13:32:48 +02:00
Daniël Klabbers
2a721926d3 adds a few additional api controller tests (#1429)
* added CreatePostControllerTest

* added DeleteDiscussionControllerTest

* added ListDiscussionControllerTest

* Apply fixes from StyleCI

[ci skip] [skip ci]
2018-05-14 13:32:19 +02:00
Daniel Klabbers
81cb67e87c fixed the created_at issue from the policy caused by the setStartPost setting created_at to null 2018-05-14 11:52:01 +02:00
Daniel Klabbers
fd859e33be fixed several column changes found by tests 2018-05-14 11:34:24 +02:00
Daniel Klabbers
7539c25048 Merge branch 'master' into 1236-database-changes 2018-05-14 09:25:52 +02:00
Daniel Klabbers
0058067b1b merged master 2018-05-14 09:23:06 +02:00
Daniël Klabbers
3c41011548 allowing configurable flood gate (#1411)
* allowing configurable flood gate

* fixed review comments
2018-05-11 19:27:37 +09:30
Clark Winkelmann
49c643609c Use ItemList for signup and login modals (#1420)
* Remove unused imports

* Use body and footer methods

* Use ItemList for signup and login inputs
2018-05-11 18:59:58 +09:30
Charlie
4df0101f56 Update icons to "fas" (#1426)
* Update icons to "fas"

* Install icon change
2018-05-09 08:56:30 +02:00
Daniël Klabbers
b8632d693a fixes session during installation (#1418)
* fixes session during installation

* Apply fixes from StyleCI

[ci skip] [skip ci]

* styling of commented code, removed unnecessary import
2018-05-08 10:32:28 +02:00
Daniel Klabbers
684985c25c is email confirmed boolean fixed 2018-04-17 14:27:52 +02:00
Daniel Klabbers
a2927b725f went over most of the changed attributes from the other pr 2018-04-17 14:22:38 +02:00
Daniel Klabbers
efa3b62fb8 joined_at renamed to User 2018-04-17 13:25:11 +02:00
Daniel Klabbers
406be427ad tables renamed, auth_tokens and permissions 2018-04-17 12:21:55 +02:00
Daniel Klabbers
665ac178e9 restarted the branch using the already created migrations 2018-04-17 11:41:55 +02:00
Daniël Klabbers
c4a501f82a Improved foundational backend unit tests (#1405)
* part one of adding tests, updating core

* Apply fixes from StyleCI

[ci skip] [skip ci]

* we need xdebug for code coverage, and hhvm was already removed

* forgot about the sidecar for mysql completely 🤦

* gitignore removed this installed json we need to fake that we have extensions

* using reguarded closure
2018-04-17 11:15:28 +02:00
Daniel Klabbers
beec59232f we can move this file deeper into storage 2018-04-13 09:12:56 +02:00
luceos
371f33e99e Apply fixes from StyleCI
[ci skip] [skip ci]
2018-04-13 07:07:02 +00:00
Daniel Klabbers
264664ac79 added the create discussion test, also renamed some classes that seem to have been incorrectly renamed from the other testing branch 2018-04-13 09:06:42 +02:00
Daniel Klabbers
17f29f83c9 adds api controller tests 2018-04-13 07:52:39 +02:00
Daniel Klabbers
c9c8fa0fde gitignore removed this installed json we need to fake that we have extensions 2018-04-13 07:34:04 +02:00
Daniel Klabbers
45f28b6f72 forgot about the sidecar for mysql completely 🤦 2018-04-13 07:25:30 +02:00
Daniel Klabbers
3ef7843540 Merge branch 'unit-testing' of github.com:flarum/core into unit-testing 2018-04-13 07:17:53 +02:00
Daniel Klabbers
7d41c4e510 we need xdebug for code coverage, and hhvm was already removed 2018-04-13 07:17:39 +02:00
luceos
8574b57fc5 Apply fixes from StyleCI
[ci skip] [skip ci]
2018-04-13 05:13:32 +00:00
Daniel Klabbers
dcb3821777 part one of adding tests, updating core 2018-04-13 07:13:10 +02:00
Daniël Klabbers
043aa0f2d9 fixes log in without remember on master (#1402)
* fixes log in without remember on master

* Fix cookie name by removing prefix from session name rather than in CookieFactory

* Inline temp variable
2018-04-12 06:49:34 +09:30
Toby Zerner
f51e29ff4c Fix absence of variable reference 2018-04-11 10:03:51 +09:30
Franz Liedke
46f80e8d72 Do not load Laravel's SessionServiceProvider 2018-03-31 18:08:35 +02:00
Toby Zerner
29d6b3306f Merge pull request #1392 from datitisev/patch-2
Always return a promise in PostStream#update
2018-03-25 08:35:52 +10:30
David Sevilla Martín
4e2c32b108 remove extra space 2018-03-24 17:43:14 -04:00
David Sevilla Martín
92c8c616e1 Use m.deferred instead of native Promise 2018-03-24 17:43:03 -04:00
Franz Liedke
f42273e679 Merge pull request #1366 from flarum/illuminate-session
Use Illuminate Session component instead of Symfony
2018-03-24 20:42:58 +01:00
Toby Zerner
44376da57d Merge pull request #1378 from DogSports/patch-1
Fix modal title background in media phone
2018-03-24 18:57:36 +10:30
Franz Liedke
2b6ee50c58 Merge pull request #1396 from flarum/writable-path-check-fix
public path should not be writable, but base path should
2018-03-22 08:22:25 +01:00
Franz Liedke
155582831d Merge pull request #1398 from datitisev/patch-1
Fix 'Debug mode' in InfoCommand not showing
2018-03-22 08:15:21 +01:00
David Sevilla Martín
baa11acfa8 Fix "Debug mode" in InfoCommand not showing 2018-03-21 20:00:14 -04:00
David Sevilla Martín
4aad293284 Merge branch 'master' into patch-2 2018-03-21 17:02:43 -04:00
Daniël Klabbers
c60d6e9dee public path should not be writable, but base path should 2018-03-21 20:52:49 +01:00
Franz Liedke
0cf351edb9 List debug mode setting in info output 2018-03-19 23:28:05 +01:00
Franz Liedke
447ca18558 Recompile JavaScript 2018-03-19 23:21:57 +01:00
David Sevilla Martín
a70e6e639c Merge branch 'master' into patch-2 2018-03-19 18:20:11 -04:00
Franz Liedke
fdbf0c86a1 Return empty response
Without this, the new version of Stratigility complained about no
response being returned. Old versions were more graceful here, but
this is certainly more correct.
2018-03-19 23:06:27 +01:00
David Sevilla Martín
6ea60248e3 always return a promise in PostStream#update 2018-03-18 20:37:04 -04:00
Franz Liedke
8d2d987680 Split up Locale extender
Now we have two extenders:
- `Extend\LanguagePack` is the "convention over configuration" loader
  for complete language packs.
- `Extend\Locales` can be used to load files (by locale) from a given
  directory - useful for extensions that bring along their own locales
  in multiple different languages.

Refs #851.
2018-03-19 01:07:59 +01:00
Franz Liedke
bb49e24ffe Bind session handling to request lifecycle
With this change, session objects are no longer instantiated
globally, but instead created within a middleware during the
request lifecycle.

In addition, session garbage collection is integrated with
the already existing middleware for this purpose.
2018-03-18 15:58:31 +01:00
Toby Zerner
5672819549 Use Illuminate Session component instead of Symfony
Symfony's component relies on PHP's native session functionality, which
is not ideal. It automatically sets its own cookie headers, resulting in
this issue: https://github.com/flarum/core/issues/1084#issuecomment-364569953

The Illuminate component is more powerful and has a simpler API for
extension with other drivers and such, and fits in nicely with other
components we use (the majority of which are from Illuminate).
2018-03-18 14:43:44 +01:00
Franz Liedke
b4e093ab8a Ignore Composer's lockfile 2018-03-18 14:33:47 +01:00
Franz Liedke
5645bcbf9c Apply fixes from StyleCI (#1391)
[ci skip] [skip ci]
2018-03-18 13:53:44 +01:00
Franz Liedke
9d30be1617 Update Stratigility, use http-interop middleware 2018-03-18 13:52:16 +01:00
Toby Zerner
d5ef9486d0 Merge pull request #1384 from flarum/fix-hash-binding
fixes the broken hash & hash.driver ioc binding which is part of 5.6
2018-03-09 12:41:28 +10:30
Daniël Klabbers
0c5c322cb4 fixes the broken hash & hash.driver ioc binding which is part of 5.6 2018-03-08 14:25:25 +01:00
Toby Zerner
3f45d18383 Merge pull request #1382 from clarkwinkelmann/patch-2
Remove unused $lifetime variable
2018-03-07 11:42:41 +10:30
Clark Winkelmann
aba22b9119 Remove unused $lifetime variable 2018-03-07 01:30:23 +01:00
Franz Liedke
26dfc8ae21 Apply fixes from StyleCI (#1381)
[ci skip] [skip ci]
2018-03-04 01:18:49 +01:00
Franz Liedke
db7cd71f19 Move logic to Extension class
The gathering and execution of extenders can actually be done here
in the `Extension` class. This way, the `ExtensionManager` only
deals with the question of which extensions are enabled, the
`Extension` class actually extends the core application, and the
service provider simply calls a method, without having to know
about internals.
2018-03-04 01:16:50 +01:00
Toby Zerner
2967b5d106 Give Extenders information about which Extension they belong to 2018-03-04 10:13:12 +10:30
Franz Liedke
e8d915850d Fix test namespace 2018-03-04 00:04:43 +01:00
Franz Liedke
a061eda019 Change namespace of test classes
(as implemented by @luceos in his WIP PR)
2018-03-04 00:01:49 +01:00
Daniel Klabbers
cc22d1d6f8 dropped hhvm and gitter webhook 2018-03-03 23:54:37 +01:00
DogSports
9b1c338b68 Fix modal title background in media phone 2018-03-02 12:32:07 +01:00
Toby Zerner
571938a677 Update core container aliases 2018-02-24 10:37:21 +10:30
AFR
1a2df2d581 FontAwesome v5.0.6 (#1372)
* Update FontAwesome to v5.0.6

* Adapt DiscussionListItem-count icon to match FontAwesome 5 syntax

* Change icon name to match FontAwesome 5.0.6 fas icon

* Add font type prefix parameter to icon helper

* Add Enable Icon Prefix to show icon in Extension Page

* Fix invalid icon behavior

* Change icon name to match FontAwesome 5.0.6 far icon

* Use iconPrefix property on component

* Use full icon class name

* Update icon helper docblock

* Full icon class syntax
2018-02-23 23:42:00 +01:00
Marcel Pokrandt
0f554585ac add message to Dispatch exceptions (#1376)
Exceptions thrown while attempting to dispatch routes are now informing the exact value that was incorrect; url for not found routes and the method when the method was invalid.
2018-02-21 11:28:45 +01:00
Franz Liedke
0b478379fc Apply fixes from StyleCI (#1371)
[ci skip] [skip ci]
2018-02-15 16:57:18 +01:00
Franz Liedke
ba96f311a9 Refactor MIME type guessing to work without any PHP extension
Closes #1241.
2018-02-15 16:40:41 +01:00
Toby Zerner
34588a74e2 Merge pull request #1363 from clarkwinkelmann/extension-rollback
Add extension rollback command
2018-02-13 07:18:00 +10:30
Clark Winkelmann
58ffa27bfb Rename to reset and make extension an option 2018-02-11 20:03:54 +01:00
Franz Liedke
f0cea11e79 API: Provide forum info under /
Closes #875.
2018-02-11 16:40:05 +01:00
Toby Zerner
160493e725 fire -> dispatch
As per Illuminate\Contracts\Events\Dispatcher
2018-02-10 12:09:35 +10:30
Clark Winkelmann
5561e28286 Fix formatting 2018-02-09 18:42:43 +01:00
Clark Winkelmann
c9cfcee12a Fix formatting 2018-02-09 18:41:51 +01:00
Clark Winkelmann
479fafbf5c Add extension rollback command 2018-02-09 18:32:44 +01:00
Toby Zerner
aff1b9a5e4 Merge pull request #1361 from clarkwinkelmann/extendable-notification-methods
Extendable notification methods
2018-02-09 13:51:39 +10:30
Clark Winkelmann
a53d95a3d9 Fix jsdoc for notification types 2018-02-09 02:53:05 +01:00
Clark Winkelmann
ff10ed0ea9 Use an extendable ItemList for notification methods 2018-02-09 02:51:42 +01:00
Johann Rodríguez
7721288ac6 No slug? Then no '-' separator! (#1351)
* Stop using slug separator when there is no slug

* Changing as per upstream requirements
2018-02-09 07:22:50 +10:30
Toby Zerner
c3a6f7daef Remove excerpt margin on mobile 2018-02-08 07:18:29 +10:30
Toby Zerner
a4704b1e2e Fix CSS rule 2018-02-08 07:08:54 +10:30
Toby Zerner
0ab1f2cfe7 Fix regression: set actor before eager loading user state 2018-02-08 07:08:39 +10:30
Toby Zerner
322a84f516 Improve search performance (#1339)
* Improve fulltext gambit

* Only search in visible posts

This change relies on the `visibility-scoping` branch to be merged.

* Change posts table to use InnoDB engine

Doing a JOIN between an InnoDB table (discussions) and a MyISAM table
(posts) is very very (very) bad for performance. FULLTEXT indexes are
fully supported in InnoDB now, and it is a superior engine in every
other way, so there is no longer any reason to be using MyISAM.

* Use ::class

* Only search for comment posts

* Add fulltext index to discussions.title

* Fix migration not working if there is a table prefix

* Update frontend appearance

* Apply fixes from StyleCI

[ci skip] [skip ci]

* Show search result excerpts on mobile
2018-02-08 06:38:08 +10:30
Daniel Klabbers
80ec3b5e17 Improved the console configuring event to support any type of console command to be added 2018-02-07 13:58:31 +01:00
Clark Winkelmann
636e965873 Add console configuration event (#1349)
* Add console configuration event

* Fix comment formatting
2018-02-07 21:49:08 +10:30
Daniel Klabbers
419adb748b validation requires nullable now in order to allow null values to pass the validation 2018-02-02 11:38:06 +01:00
Toby Zerner
25154dabff Merge pull request #1358 from clarkwinkelmann/avatar-permission
Assert permission when updating avatar
2018-02-01 06:54:47 +10:30
Clark Winkelmann
2eae968a70 Assert permission when updating avatar 2018-01-31 16:36:42 +01:00
Toby Zerner
7651907f56 Don't break compatibility with extensions that return a function name
eg. s9e/mediaembed
2018-01-31 07:20:49 +10:30
Toby Zerner
557a65aadd Grant users permission to view empty discussions if they can edit posts
This fixes an issue where unapproved discussions (via
flarum-ext-approval) that were rejected became invisible to the user.

This solution is imperfect and some more substantial thought into how
flarum-ext-approval works is required in the future.
2018-01-30 11:14:25 +10:30
Toby Zerner
ad4bd3d001 Overhaul model visibility scoping (#1342)
* Overhaul the way model visibility scoping works

- Previously post visibility scoping required concrete knowledge of the
  parent discussion, ie. you needed a Discussion model on which you
  would call `postsVisibleTo($actor)`. This meant that to fetch posts
  from different discussions (eg. when listing user posts), it was a
  convoluted process, ultimately causing #1333.

  Now posts behave like any other model in terms of visibility scoping,
  and you simply call `whereVisibleTo($actor)` on a Post query. This
  scope will automatically apply a WHERE EXISTS clause that scopes the
  query to only include posts whose discussions are visible too. Thus,
  fetching posts from multiple discussions can now be done in a single
  query, simplifying things greatly and fixing #1333.

- As such, the ScopePostVisibility event has been removed. Also, the
  rest of the "Scope" events have been consolidated into a single event,
  ScopeModelVisibility. This event is called whenever a user must have
  a certain $ability in order to see a set of discussions. Typically
  this ability is just "view". But in the case of discussions which have
  been marked as `is_private`, it is "viewPrivate". And in the case of
  discussions which have been hidden, it is "hide". etc.

  The relevant API on AbstractPolicy has been refined, now providing
  `find`, `findPrivate`, `findEmpty`, and `findWithPermission` methods.
  This could probably do with further refinement and we can re-address
  it once we get around to implementing more Extenders.

- An additional change is that Discussion::comments() (the relation
  used to calculate the cached number of replies) now yields "comments
  that are not private", where before it meant "comments that are
  visible to Guests". This was flawed because eg. comments in non-public
  tags are technically not visible to Guests.

  Consequently, the Approval extension must adopt usage of `is_private`,
  so that posts which are not approved are not included in the replies
  count. Fundamentally, `is_private` now indicates that a discussion/
  post should be hidden by default and should only be visible if it
  meets certain criteria. This is in comparison to non-is_private
  entities, which are visible by default and may be hidden if they don't
  meet certain criteria.

Note that these changes have not been extensively tested, but I have
been over the logic multiple times and it seems to check out.

* Add event to determine whether a discussion `is_private`

See https://github.com/flarum/core/pull/1153#issuecomment-292693624

* Don't include hidden posts in the comments count

* Apply fixes from StyleCI (#1350)
2018-01-27 09:57:16 +10:30
Franz Liedke
4b1a299b3c Convert closures in arrays to Compat extenders as well
Refs #851.
2018-01-21 22:38:06 +01:00
Franz Liedke
fa14be591c Use cursor() fetching when deleting many posts
Refs #1319.
2018-01-21 21:53:48 +01:00
Franz Liedke
072f4f89cb Assets extender: Remove defaultAssets() method
See a7821a24a2 (r26990974).
2018-01-21 21:14:08 +01:00
Toby Zerner
ed3e833181 Fix docblocks 2018-01-21 08:28:15 +10:30
Toby Zerner
7f92838225 Fix Laravel 5.5 query scoping 2018-01-21 08:28:08 +10:30
Toby Zerner
2159107214 Merge pull request #1330 from clarkwinkelmann/signup-fields-locking
Prevent editing fields in sign up modal according to identification data
2018-01-12 08:38:49 +10:30
Clark Winkelmann
d357364712 Rename method and attribute, and remove unnecessary attribute filtering 2018-01-11 23:05:26 +01:00
Clark Winkelmann
26449a64fe Merge remote-tracking branch 'upstream/master' into signup-fields-locking 2018-01-11 22:54:41 +01:00
Toby Zerner
ae2e07e94c Remove use of event priorities
Event priorities are no longer in Laravel - see dbbfc62bef

Updated the AbstractPolicy terminology to reflect the new behaviour,
which is that there is no guarantee that the catch-all methods will run
after all specific methods have run globally. This behaviour is only
guaranteed within the policy.
2018-01-11 14:10:37 +10:30
Toby Zerner
801d619a36 Fix docblock return type 2018-01-11 12:11:48 +10:30
Toby Zerner
0befe041c7 Use whereRaw instead of Expression 2018-01-11 11:56:18 +10:30
Toby Zerner
1c87c33d4d Use ::class, update some typehints 2018-01-11 11:55:57 +10:30
Franz Liedke
3480a65989 Avoid calculations in views
Instead, look up existence of navigation links in the underlying
API document.
2018-01-10 20:39:53 +01:00
Franz Liedke
2979e8bc28 Use Blade's inject helper 2018-01-10 20:36:50 +01:00
Franz Liedke
8c470954eb Add pagination link for previous page 2018-01-10 20:35:07 +01:00
Franz Liedke
6913e8f0f8 Only display pagination link if necessary
Otherwise, search engines start indexing pages that aren't filled yet.

Refs #189.
2018-01-10 20:34:25 +01:00
Franz Liedke
30a04e7bf9 Don't use invokables with Container::call() 2018-01-10 19:37:18 +01:00
Franz Liedke
0af97c427c Re-introduce Compat extender
Turns out Container::call() does not work with invokable classes.
Thus, we need to wrap callables in a custom extender class to
support injecting any resolvable type-hint automatically.

Refs #851.
2018-01-10 19:32:57 +01:00
Toby Zerner
1c1cefa017 Update test namespaces 2018-01-11 01:25:10 +10:30
Franz Liedke
c6747b6910 Get rid of Compat extender
Now that we support any form of callable to be returned from the
bootstrap.php files, it is no longer needed.
2018-01-09 22:35:40 +01:00
Franz Liedke
1ce70eeb6e Turn extenders into callables
This simplifies the API and gives extension developers more
flexibility, for a) maintaining backwards compatibility, and
b) doing advanced stuff that extenders do not allow.

Note that only extenders are guaranteed to work across
different versions of Flarum (once the API surface is stable).

See the discussion in https://github.com/flarum/core/pull/1335.
2018-01-09 20:49:51 +01:00
Daniel Klabbers
714775cfed fixed two typehints on migrations repository 2018-01-09 16:28:50 +01:00
Toby Zerner
bdc1a100cd Merge pull request #1340 from clarkwinkelmann/fix-password-changed-on-reset
Dispatch user events after password reset
2018-01-09 13:35:24 +10:30
Clark Winkelmann
f3e29ab801 Dispatch user events after password reset
Previously PasswordChanged was never sent
2018-01-09 03:44:06 +01:00
Franz Liedke
26e53fc51b Tweak route registration extender: Use plural
This makes it more consistent with other existing extenders,
while also making registration of multiple routes more
comfortable for extension developers, and likely slightly
more performant. :-)
2018-01-07 19:50:49 +01:00
Franz Liedke
848293a7d5 Merge pull request #1338 from gwillem/fix-permissions
Remove execute permissions from php/less files
2018-01-07 18:30:40 +01:00
Willem de Groot
5af65dede1 Fix StyleCI spacing 2018-01-06 12:03:02 +01:00
Willem de Groot
e774baf32f Remove execute permissions from php/less files 2018-01-06 11:59:25 +01:00
Toby Zerner
2ac04aac8e Merge branch '0.1.0-beta.7' 2018-01-06 20:06:43 +10:30
Clark Winkelmann
c6aeeeb3c1 Always apply attributes from token when registering
The change introduced in #1033 transformed any identification attribute returned from an OAuth provider to just a default value.

When the identification attribute used by the provider is the email or username, this allowed the user to supply a different email or username and still getting an already-enabled account with the credentials he entered.

Skipping attributes with an existing value makes no sense here because it's a always a fresh user and values from AbstractOAuth2Controller::getIdentification() should always be enforced.
2018-01-06 20:04:42 +10:30
Toby Zerner
f247d8c2a6 Merge pull request #1335 from flarum/next-back-extenders
Start of PHP extenders API
2018-01-06 09:17:27 +10:30
Franz Liedke
0380536cb4 Add another newline before custom footer HTML 2018-01-05 23:46:38 +01:00
AFR
6dc96b38af Add Custom Footer HTML (#1315)
* Add Custom Footer HTML

Straight copy from Custom Header HTML

* Move Custom Footer HTML to exactly before `</body>` tag.

* Fix invalid class name

* Append CustomFooterHTML when preparing the view.

* Some consistency in placing the variable
2018-01-05 23:44:11 +01:00
Clark Winkelmann
9342723f64 Manage Composer height with overridable methods (#1272)
* Manage Composer height in a separate class with overridable methods

* Use a computed method

* Keep everything in Composer.js

* Drop usage of computed property for the Composer height
Because the Composer height also depends on the page height and is rarely called without position, height or page height changing anyway
2018-01-04 09:39:06 +10:30
Franz Liedke
8d049126d0 Add Route extender for registering routes with forum, admin or API 2018-01-03 23:19:45 +01:00
Franz Liedke
63be95fb8a Admin: Set up all event listeners in one place
See discussion in #1273.
2018-01-03 20:23:05 +01:00
Franz Liedke
1d47047d45 Add FormatterConfiguration extender for extensions working with TextFormatter 2018-01-03 09:42:11 +01:00
Franz Liedke
4e30ad5891 Add Assets extender for frontend extensions 2018-01-03 09:42:11 +01:00
Franz Liedke
f4ad227576 Add Locale extender for language pack extensions 2018-01-03 09:42:11 +01:00
Franz Liedke
5b6d043f80 Resolve extenders from ExtensionManager
Loading the activated extensions now means retrieving an array of
extenders (classes that implement a certain type of extension of a core
feature in Flarum).

For now, the only existing extender is the Compat extender which is used
to handle old-style bootstrappers that simply return a closure that
receives all of its dependencies via auto injection.

In the future, extensions will be able to return an array of extender
instances from their bootstrapper instead. These extender classes will
be implemented in the next step.
2018-01-03 09:42:11 +01:00
Franz Liedke
c41e58531a Deprecate remaining non-namespaced events
These will be replaced by etenders soon.
2018-01-03 09:42:11 +01:00
Franz Liedke
b760d113d2 Installation default data: Use more sensible defaults
Using .dev as a TLD for local development is discouraged, as at
least Chrome now enforces HTTPS for these domains.

As far as I know, by default, the MySQL root user does not have
a password on many platforms. I use it this way on my local
machine, and this makes it convenient to setup a local copy.
2018-01-03 09:41:46 +01:00
Franz Liedke
936f67e953 Use ::class instead of some hardcoded class names
This gives us better refactoring functionality in IDEs like
PhpStorm, and also more quickly surfaces typos through errors
about undefined classes. :)
2018-01-03 09:41:46 +01:00
Franz Liedke
3f7e7520b0 Clean up code, use PHP 7 feature :) 2018-01-03 09:41:46 +01:00
Clark Winkelmann
7ccb263926 Fix array_only usage 2018-01-02 00:27:13 +01:00
Toby Zerner
fe56f57e8f Fix order of array_first arguments
As per https://laravel.com/docs/5.3/upgrade (under "Arrays")
2018-01-02 09:48:50 +10:30
Clark Winkelmann
fa9d89d690 Prevent editing fields in sign up modal according to identification data 2018-01-02 00:13:33 +01:00
Toby Zerner
292fe06001 Re-add missing middleware 2018-01-01 10:45:26 +10:30
Toby Zerner
f2ce4e11e2 Fix class name 2018-01-01 10:34:19 +10:30
Miguel Piedrafita
47eb853bf9 Update year (#1328) 2017-12-31 20:48:23 +01:00
Toby Zerner
d807171c44 Fix URL generator usage 2017-12-29 21:29:04 +10:30
Toby Zerner
57a91c966d Fix view paths 2017-12-29 21:28:53 +10:30
Toby Zerner
0525f467c7 Fix class reference 2017-12-29 18:42:31 +10:30
Franz Liedke
b791790d2f Fix comment 2017-12-28 22:47:13 +01:00
Toby Zerner
ea353a2f2c Merge pull request #1308 from flarum/next-back
Next back > master
2017-12-28 12:13:40 +10:30
Toby Zerner
ac7d28ca58 Remove unused method 2017-12-27 16:17:35 +10:30
Toby Zerner
8a6344cfcf Fix some class names, clean up imports 2017-12-27 16:17:25 +10:30
Toby Zerner
a0621e85bf Fix order of array_first arguments
As per https://laravel.com/docs/5.3/upgrade (under "Arrays")
2017-12-26 20:38:15 +10:30
Franz Liedke
56231d61be Move garbage collection into middleware
This prevents garbage collection to randomly break the installer:
before installation, the models that are being accessed have no
database connection.

Now, the middleware is only mounted into the forum's middleware
stack. I want API requests to have stable performance, and the
forum middleware stack is only mounted when Flarum is installed.
2017-12-21 12:23:34 +01:00
Franz Liedke
c8a1a5fcfa Fix more incompatibilities with Laravel 5.5 2017-12-20 00:20:23 +01:00
Franz Liedke
8d5132fd5a Disable HandleErrors middleware during installation
Temporary measure until we have a real fix in place.
2017-12-20 00:00:23 +01:00
Franz Liedke
6efe2ee91a Fix previous commit
Prevent `flarum.config` from being bound in the container when the
software has not been installed yet.
2017-12-19 23:48:38 +01:00
Franz Liedke
bfd98e3371 DRY up loading of config 2017-12-19 23:16:06 +01:00
Toby Zerner
e9da1ba2f5 Remove Listener namespace
We may reverse this in the future, but for now just going for
consistency between domains (the majority do not use a Listener
namespace)
2017-12-19 18:59:14 +10:30
Toby Zerner
b2fe76c819 Merge pull request #1313 from flarum/analysis-qB0gYV
Apply fixes from StyleCI
2017-12-19 18:54:47 +10:30
Toby Zerner
2b8c66354d Apply fixes from StyleCI
[ci skip] [skip ci]
2017-12-19 08:24:06 +00:00
Toby Zerner
4cf481355f Fix usage of UrlGenerator in notifications 2017-12-19 18:52:27 +10:30
Toby Zerner
2ec183778c Pick up config when setting a new base path 2017-12-19 18:38:00 +10:30
Daniel Klabbers
1b94ef90ea the admin service provider also has to use the new HandleError logic 2017-12-15 09:35:02 +01:00
Daniel Klabbers
183a22b5c5 - FilesystemInterface no longer needed in User related handlers
- FilesystemInterface conditional ioc binding moved to AvatarUploader
- User::getAvatarAtribute failed to use the UrlGenerator properly
2017-12-15 09:29:20 +01:00
Daniel Klabbers
654fca9c2c fixed the BasicFoo vs FooBasic serializer definition issue, prevented for future using ::class 2017-12-15 08:29:07 +01:00
Daniel Klabbers
7be01119f5 and another.. 2017-12-15 08:15:08 +01:00
Daniel Klabbers
28d4cff156 satisfying sci isnt enough for it, lets please it further 2017-12-15 08:14:15 +01:00
Daniel Klabbers
2aba61668c - satisfying styleci
- cleared the merge conflict in the phpdoc
- changed some string class names to use ::class
2017-12-15 08:10:32 +01:00
Franz Liedke
fccadcc6ab Apply suggestions from StyleCI 2017-12-14 22:18:12 +01:00
Daniël Klabbers
f65e4dcba3 merges 5.5 and master into next-back 2017-12-14 01:00:16 +01:00
Franz Liedke
c6ce172caa Apply suggestions from StyleCI 2017-12-13 23:08:35 +01:00
Clark Winkelmann
d2f187716e Prevent saving invalid custom less (#1273)
* Prevent saving invalid custom less

* Fix formatting

* Fix formatting again

* Move custom less format check to its own listener

* Move listener to AdminServiceProvider

* Rename listener method
2017-12-13 22:39:09 +01:00
Daniël Klabbers
93aa3d77b5 re-using symfony translator 2017-12-13 21:45:55 +01:00
Toby Zerner
a0c95e6705 Filter out notifications with non-existent subjects
ref #1025 #1238. This should prevent the frontend from crashing when
opening the notifications menu, but we still need to make sure
notifications are deleted properly when subjects are deleted.
2017-12-13 15:54:16 +10:30
Toby Zerner
77c25ab725 Add infinite scrolling in the notifications list 2017-12-13 15:28:54 +10:30
Toby Zerner
3dcfe32b27 Extract admin dashboard statistics from core into an extension 2017-12-10 21:03:48 +10:30
Toby Zerner
617a76dda8 Fix PHP 7.2 warning 2017-12-10 21:02:47 +10:30
Toby Zerner
1a239ee93a Fix crash when post's user has been deleted 2017-12-10 21:02:35 +10:30
Toby Zerner
f8d065bd78 Merge pull request #1298 from sijad/remove-autolink
remove autolink
2017-12-03 08:15:31 +10:30
Sajjad Hashemian
0a654d1f31 remove autolink #1214 2017-11-30 13:38:45 +03:30
Toby Zerner
b806dc3db2 Move view logic into middleware 2017-11-29 22:25:57 +10:30
Toby Zerner
92de751154 Fix last commit 2017-11-29 22:22:14 +10:30
Toby Zerner
5b46ec801d Generate URL in the controller instead of the view 2017-11-29 22:20:06 +10:30
Toby Zerner
1ef9217f4d Basic implementation of dashboard widgets, statistics
Currently not user-customizable. Just needed to display statistics for a
client, so figured I'd make a start at this. Nothing too fancy for now,
but I'm sure some people will be happy to have this information at their
fingertips.
2017-11-29 17:19:20 +10:30
Toby Zerner
79fee3686f More precise permission check for email gambit 2017-11-29 17:02:49 +10:30
Toby Zerner
8edc8223e5 Fix admin error handling 2017-11-29 16:10:22 +10:30
Daniël Klabbers
6280fb2498 reverting translator contract 2017-11-29 06:26:48 +01:00
Toby Zerner
ba769e0c7e Preserve return URL when confirming logout 2017-11-29 13:47:00 +10:30
Toby Zerner
ea2fc1ff8a Add a "return home" link to 404 errors 2017-11-29 13:23:25 +10:30
Toby Zerner
b7c1cc5cef New design for error pages. closes #252 2017-11-29 13:03:55 +10:30
Toby Zerner
e8a4e5e0ef Add log out confirmation if CSRF token is invalid. fixes #1282 2017-11-29 13:03:16 +10:30
Toby Zerner
295193eb3c Use HtmlResponse in AbstractHtmlController 2017-11-29 12:54:11 +10:30
Toby Zerner
a065c8e6f5 Make URLs more verbose 2017-11-29 12:53:39 +10:30
Toby Zerner
9392e1bec3 New design for reset password view 2017-11-29 12:53:06 +10:30
Toby Zerner
479e44dd04 Restructure views
- Use Laravel's view namespacing rather than the full file path
- Organise views into directories
2017-11-29 12:51:24 +10:30
Daniel Klabbers
c01268d9ae must be an empty line 2017-11-27 14:19:18 +01:00
Daniel Klabbers
f4fc245df4 re-added a precious line 2017-11-27 14:18:28 +01:00
Daniel Klabbers
ac0b4cb2d2 patched up the Scope implementation as requested 2017-11-27 14:17:17 +01:00
Daniel Klabbers
55b945f129 Using Core Translator in Locale Manager, type hinted its methods and removed unnecessary phpdoc 2017-11-27 14:03:45 +01:00
Daniel Klabbers
4d9e2335c7 pleasing the angry god Circle 2017-11-27 11:05:15 +01:00
Daniel Klabbers
642332ffe2 replaced the Symfony\Component\Translation\TranslationInterface with the Illuminate\Contracts\Translation\Translator, deprecating the Symfony version 2017-11-27 10:42:16 +01:00
Daniel Klabbers
7b2663e0bc fixed alias/reference loading for translation strings 2017-11-27 10:35:57 +01:00
Daniel Klabbers
e2d61d1aeb applied laravel contract 2017-11-27 09:49:19 +01:00
Toby Zerner
7796580210 Actually list users returned from the API when searching 2017-11-20 10:37:21 +10:30
Toby Zerner
0aa74c987c Fix email gambit 2017-11-20 09:17:44 +10:30
Toby Zerner
55a09a2f57 Merge pull request #1261 from josephnle/drag-and-drop-avatar-upload
Add drag and drop avatar uploading
2017-11-13 01:33:29 +02:00
Toby Zerner
a28dbccf1a Performance: Assign parent discussions to posts so they don't have to be reloaded 2017-11-12 21:14:19 +10:30
Toby Zerner
3c80612d80 Performance: Load only basic information about post discussion/users 2017-11-11 23:15:36 +10:30
Toby Zerner
dedcbae359 Performance: Load only basic information about terminal/relevant posts 2017-11-11 22:57:41 +10:30
Toby Zerner
9cc67fe312 Performance: Cache translation catalogue to avoid reparsing YAML 2017-11-11 22:45:38 +10:30
Toby Zerner
5f7060fb4a Performance: Assign parent discussion to posts so it doesn't have to be reloaded 2017-11-11 22:44:45 +10:30
Toby Zerner
1a102766a9 Fix Composer textarea losing its height across route changes
There is a Mithril bug which causes context.retain to be ineffective for
children nodes. https://github.com/MithrilJS/mithril.js/issues/1300

Thus, we have to assume that the children nodes (like the textarea)
may be recreated and thus we need to update its height on each redraw.

fixes #948
2017-11-07 21:12:03 +10:30
Toby Zerner
abda11c6c5 Oops, recompile JS properly 2017-11-05 17:57:56 +10:30
Toby Zerner
b43fdec2e9 Recompile JS 2017-11-05 17:38:30 +10:30
Toby Zerner
3321b4e829 Give the mobile composer a bit more height 2017-11-05 17:35:13 +10:30
Toby Zerner
a8826dcd88 Remove FastClick. Fixes #1268
Turns out FastClick was causing textareas to be buggy on iOS Safari,
and it wasn't really doing any good.
2017-11-05 17:32:43 +10:30
Toby Zerner
15b573bd93 Update asset revision whenever custom LESS is changed
This should remove the need for a hard browser refresh whenever you
update the custom LESS.
2017-11-05 16:27:28 +10:30
Toby Zerner
41df32f66e Add a tooltip to the Preview button 2017-11-05 16:25:34 +10:30
Toby Zerner
094345de85 Improve mobile composer behaviour
- Don't scroll to the bottom of the discussion when selecting "Reply"
  from the menu if the composer is in full screen mode (ie. on mobile).
  ref #1271

- After posting a reply, scroll to the end of the discussion

- Reduce the textarea height - previously it was 100vh, but this doesn't
  account for the height of the iOS keyboard, so I've just arbitrarily
  chosen 300px instead. There may be a better solution for this.
  ref #1269
2017-11-05 16:25:21 +10:30
Toby Zerner
54597ee5eb Attempt fix for #1268
I believe the constant overlay of a loading div may be what's causing
the iOS cursor issues. This commit removes the fade animation so that
we can simply set display to none, which will hopefully fix the issue.
2017-11-05 16:21:18 +10:30
Toby Zerner
3be98b9f8e Make sure dropdowns don't go above the edge of the screen 2017-11-05 16:17:50 +10:30
Toby Zerner
257ee936f4 Revert color to text input type
#1074 changed the input type for these fields to "color", but it turns
out the browser support for this input type sucks (they give you a very
limited color picker, and make it hard to input hex codes).
2017-11-05 16:17:15 +10:30
Toby Zerner
1a928ca0ab Fix admin navigation not rendering
Not sure why this started happening now, but the admin navigation
dropdown wasn't receiving its children properly. This commit fixes a
flaw in our Mithril patch and allows an array of children to be passed
in the normal JSX way, rather than as an attribute.
2017-11-05 16:12:26 +10:30
Daniel Klabbers
0b1043c9d2 moved from boot to register 2017-11-02 10:52:52 +01:00
Daniel Klabbers
72c232d5a3 fixed the Bus command Handling forwarding the call to a matching Handler class 2017-11-02 10:48:33 +01:00
Franz Liedke
914b94b62d Remove user bio feature (#1214)
The feature is very limited in scope, and we hope for community
extensions to take over this feature and make it much better.
2017-11-02 01:12:49 +01:00
Lukas
1b7cb3bec2 The CookieFactory now also works if no configuration exists (#1258)
* Returning the $default value if there's no config

This is especially important for the CookieFactory which accesses
the configuration before the application is installed

* Injecting the configuration values into the CookieFactory
2017-11-02 00:51:31 +01:00
Daniël Klabbers
55b763a570 fixed renamed interface for Scope 2017-11-01 22:12:56 +01:00
Daniel Klabbers
d7306dedb7 array_build => array_map 2017-11-01 17:20:12 +01:00
Daniel Klabbers
3eede757bb fixed symfony translator now using catalogues 2017-11-01 17:07:22 +01:00
Daniel Klabbers
a8f8ca7f87 fixed an issue where the mail provider would not be able to instantiate 2017-11-01 17:01:50 +01:00
Daniel Klabbers
44e9007790 using blade @json directive to parse raw json into frontend` 2017-11-01 13:22:16 +01:00
Mark
eeed7c20e1 Fix blurry chrome image rendering for Avatar / Logo - closes #1259 (#1276)
* Fix blurry chrome image rendering for Avatar / Logo - closes #1259

* Add comments for Chrome css fix
2017-10-29 17:24:02 +01:00
Toby Zerner
40ebc13292 Only apply custom CSS and header HTML on forum, not admin 2017-10-25 13:40:57 +10:30
Toby Zerner
2754a8c867 Add LESS variable to configure expansion of sideNav dropdowns 2017-10-25 12:36:09 +10:30
Joseph
123c8bb73d Add drag and drop avatar uploading 2017-10-22 14:21:39 -07:00
Toby Zerner
f3b4d35587 Fix extractText breaking in some cases 2017-10-08 08:59:54 +10:30
Toby Zerner
42ecee42a1 Make sure components receive all children properly 2017-10-08 08:59:18 +10:30
Toby Zerner
5a43f915cb Let avatarUrl attribute delete the avatar as well 2017-10-07 20:28:15 +10:30
Toby Zerner
6a10b4484f Recompile JS 2017-10-07 20:12:15 +10:30
Toby Zerner
06aa37d2fd Use display names in avatars 2017-10-07 20:10:50 +10:30
Franz Liedke
cb92deee98 Fix namespace imports 2017-10-07 11:20:38 +02:00
Toby Zerner
bedf710768 Fix variable 2017-10-07 19:17:59 +10:30
Toby Zerner
3b1f8771c4 No need to set a remember cookie if only logging in for session 2017-10-07 17:51:30 +10:30
Toby Zerner
2dbcfe02d8 Consolidate avatar uploading, allow avatarUrl to be used when updating user 2017-10-07 17:39:27 +10:30
Daniel Klabbers
a7f3ca4b22 added new methods etc 2017-10-05 16:25:01 +02:00
Daniel Klabbers
3f9dc81874 satisfying styleci, undo mysql in travis 2017-10-05 14:02:54 +02:00
Daniel Klabbers
1c01145a14 fixed those exception handling tests 2017-10-05 13:57:31 +02:00
Daniel Klabbers
2037371886 lists > pluck 2017-10-05 13:39:41 +02:00
Toby Zerner
87bf84ef6e Allow configuring cookie attributes
I decided to put this in config.php because if cookie settings were to
be stored in the database and configured via admin UI, entering
incorrect settings could cause the admin session to be destroyed,
requiring manual database intervention to fix. But it's a good prompt
for discussion as to which kind of settings belong in config.php vs the
database. Thoughts?
2017-10-05 13:00:15 +10:30
Toby Zerner
096e552c74 Add the ApiKey model as a request attribute 2017-10-05 12:26:05 +10:30
Toby Zerner
8ccfb1aac6 Use a constant instead of a property 2017-10-05 12:25:30 +10:30
Toby Zerner
ea4d889b76 Fix post contentHtml sometimes breaking script parsing
<\/script> tags in post content would sometimes be recognized as
actually ending the script tag, even when escaped (not exactly sure
why). This is fixed by encoding the < > characters in unicode.
2017-10-05 11:48:10 +10:30
Toby Zerner
19d15d4302 Use display name as document title 2017-10-05 11:43:12 +10:30
Toby Zerner
43d8a9d0e8 Merge pull request #1251 from tweichart/path_methods
minor change for getting the path
2017-10-04 17:23:20 +10:30
Tobias Weichart
02377663ce minor change for getting the path
* should be used via x_path() methods + parameter
2017-10-04 08:38:36 +02:00
Franz Liedke
4f688fc9a2 Change order of service provider registration
Here, the order is relevant, because at this
point, the application has already been booted.
Hence, all boot() methods are called immediately,
which might depend on other service providers'
register() methods having run.

In this case, the DiscussionServiceProvider
depends on the Gate class being registered in the
container by the UserServiceProvider.
2017-10-03 18:54:07 +02:00
Franz Liedke
fddd134fa0 Inject settings repository in event listener
`$this->app` was not defined here anyway.

Refs #1032.
2017-10-03 18:54:07 +02:00
Franz Liedke
1215a1ef9b Use ::class constant instead of hardcoded strings 2017-10-03 18:54:07 +02:00
Franz Liedke
4aad7c1040 Cleanup code, typehints and class references 2017-10-03 18:54:07 +02:00
Franz Liedke
e46b3d54d1 Extract Flarum\Foundation\Site class
This class holds all information relevant to a local Flarum site,
such as paths and local configuration. From this information, it
is able to instantiate a Flarum\Foundation\Application instance,
which represents a Flarum installation's runtime.

This will also be useful for setting up e.g. multi-tenant
environments.
2017-10-03 18:54:07 +02:00
Franz Liedke
051bb5acb8 Fix code style 2017-10-03 18:54:07 +02:00
Franz Liedke
69b517ea79 Get rid of Server classes for Admin, API and Forum
The various middleware can be registered in the service provider,
and the rest of the logic can all go through one single front
controller (index.php in flarum/flarum, and Flarum\Http\Server in
flarum/core).

This will also simplify the necessary server setup, as only one
rewrite rule remains.
2017-10-03 18:54:07 +02:00
Franz Liedke
b4c7f8ca89 Move event to Flarum\User namespace 2017-10-03 18:54:07 +02:00
Franz Liedke
3ece3ca976 Move events to Flarum\Api namespace 2017-10-03 18:54:07 +02:00
Franz Liedke
9c77475985 Fix order of namespace imports 2017-10-03 18:54:06 +02:00
Franz Liedke
b72407440d Combine URL generator classes into one 2017-10-03 18:54:06 +02:00
Franz Liedke
f824dcfb53 Move more event classes to appropriate namespaces 2017-10-03 18:54:06 +02:00
Franz Liedke
78f3681fc1 Fix namespace orderings
(Thanks, StyleCI!)
2017-10-03 18:54:06 +02:00
Franz Liedke
5b0d0d9f0f Move command classes to domain namespaces
They will probably be refactored away at a later stage (when we get
rid of the command bus). Until then, this lets us remove the
Flarum\Core namespace and actually feels quite clean.
2017-10-03 18:52:50 +02:00
Franz Liedke
95dc7e71f4 Fix namespaces 2017-10-03 18:52:50 +02:00
Franz Liedke
a39ed6edec Rename listener class to DiscussionRenamedLogger 2017-10-03 18:52:50 +02:00
Franz Liedke
66f35d2530 Split up old CoreServiceProvider 2017-10-03 18:52:50 +02:00
Franz Liedke
e6e4531771 Fix class names in strings 2017-10-03 18:49:53 +02:00
Franz Liedke
e71deed8d5 Move ExtensionValidator class to Flarum\Extension namespace 2017-10-03 18:49:53 +02:00
Franz Liedke
8a16c1ecc8 Move UserState class to Flarum\Discussion namespace 2017-10-03 18:49:53 +02:00
Franz Liedke
b38ade986d Extract Flarum\Notification namespace 2017-10-03 18:49:53 +02:00
Franz Liedke
4a13cd8088 Move another trait out of obsolete Flarum\Core namespace 2017-10-03 18:49:53 +02:00
Franz Liedke
920a4071b6 Fix some incorrect automated refactorings 2017-10-03 18:49:53 +02:00
Franz Liedke
c22219ec20 Extract Flarum\Group namespace 2017-10-03 18:49:53 +02:00
Franz Liedke
11bf3e34b7 Extract Flarum\Search namespace 2017-10-03 18:49:53 +02:00
Franz Liedke
4fb38d6458 Extract new Flarum\Discussion namespace 2017-10-03 18:49:52 +02:00
Franz Liedke
66abd7ecfd Extract new Flarum\Post namespace 2017-10-03 18:47:23 +02:00
Franz Liedke
3481798875 Fix trait imports 2017-10-03 18:47:23 +02:00
Franz Liedke
9abc63aaac Move events to Flarum\Extension\Event namespace 2017-10-03 18:47:23 +02:00
Franz Liedke
6cd6a7d260 Move events to Flarum\Formatter\Event namespace 2017-10-03 18:47:23 +02:00
Franz Liedke
6c9ff72efb Finalize Flarum\Foundation namespace 2017-10-03 18:47:23 +02:00
Franz Liedke
33e3d757c3 Flatten Flarum\Http namespace 2017-10-03 18:47:23 +02:00
Franz Liedke
551e76f296 Move events to Flarum\Settings\Event namespace 2017-10-03 18:47:23 +02:00
Franz Liedke
564ea8ff73 Extract new Flarum\User namespace 2017-10-03 18:47:23 +02:00
Franz Liedke
fda8c597f4 Flarum\Frontend: Rename ConfigureWebApp event to Rendering 2017-10-03 18:45:41 +02:00
Franz Liedke
5d1564e0fc Flarum\Frontend: Fix view paths after renaming namespace 2017-10-03 18:45:41 +02:00
Franz Liedke
1f1b63363e Rename controller file 2017-10-03 18:45:41 +02:00
Franz Liedke
bdf455c0c6 Move ScopeVisibilityTrait to Database namespace 2017-10-03 18:45:41 +02:00
Franz Liedke
927e4ca3ed Restructure Flarum\Forum namespace 2017-10-03 18:45:40 +02:00
Franz Liedke
0be13d50bd Create new Flarum\Frontend namespace
It replaces the old Http\WebApp namespace and swallows other namespaces
and files, such as Flarum\Asset.
2017-10-03 18:45:40 +02:00
Franz Liedke
6268c3010f Fix serializer class names 2017-10-03 18:45:40 +02:00
Franz Liedke
acf43606a8 Register new MigrationServiceProvider 2017-10-03 18:45:40 +02:00
Franz Liedke
5ae2e9d232 Get rid of Flarum\Debug namespace 2017-10-03 18:45:40 +02:00
Franz Liedke
d897839097 Restructure Flarum\Database namespace 2017-10-03 18:45:40 +02:00
Franz Liedke
c6985ae31c Restructure Flarum\Console namespace 2017-10-03 18:45:40 +02:00
Franz Liedke
9b24fbd5e5 Restructure Flarum\Api namespace 2017-10-03 18:45:40 +02:00
Franz Liedke
5127514d35 Restructure Flarum\Admin namespace 2017-10-03 18:45:38 +02:00
Toby Zerner
eb72307a54 User display names (#1246)
* Introduce user display names

It is not uncommon for forums to be intergrated with sites where users
don't have a unique "handle" - they might just have their first name,
or a full name, which is not guaranteed to be unique.

This commit introduces the concept of "display names" for users. By
default display names are the same as usernames, but extensions may
override this and set them to something different. The important thing
is that all code should use `display_name` whenever intending to output
a human-readable name - `username` is reserved for cases where you want
to output a unique identifier (which may or may not be human-friendly).

The new "GetDisplayName" API is probably sub-optimal, but I didn't worry
too much because we can come up with something better in `next-back`.

ref #557

* Apply fixes from StyleCI

[ci skip] [skip ci]
2017-09-20 16:42:18 +09:30
Toby Zerner
f917d1438c Use ::class 2017-09-19 19:45:31 +09:30
Toby Zerner
ef89b1f6b1 Remove unnecessary else statement 2017-09-19 19:44:43 +09:30
Toby Zerner
377d439c47 😅 2017-09-19 19:13:02 +09:30
Toby Zerner
37cf95f94d Don't include post content in the "basic" serializer
Currently all of a post's replies are loaded in full whenever the post
is loaded, which is kind of overkill - we really just need to know that
they exist (and who posted them) in order to render the "X replied to
this" line.
2017-09-19 19:10:07 +09:30
Toby Zerner
c31c1ea062 Allow full URLs to be used as the avatar path
This is useful for forums integrating with an external website (eg. a
WordPress site), so they can reference existing avatars directly.

For alternative storage locations (eg. S3) the best practice will still
be to store a relative path and then configure an external base "assets
URL" (this is not currently possible - TODO).

Given this change, I think it would probably make sense to rename the
column to `avatar_url` in the upcoming batch of database naming changes
- then it can contain either a relative or an absolute URL -
@franzliedke do you agree?
2017-09-19 19:03:12 +09:30
Toby Zerner
084f74946d Allow setting the raw content of a CommentPost 2017-09-19 12:13:24 +09:30
Franz Liedke
1e8399c014 Update zend-diactoros to v1.6
This release contains a useful fix for Content-Length problems
that we have experienced before.

See https://github.com/zendframework/zend-diactoros/releases/tag/1.6.0.
2017-09-15 13:27:11 +02:00
Franz Liedke
ad153c8484 Issue template: Explanation first 2017-09-12 20:41:17 +02:00
epoxa
cbe4464178 Fix oauth controller wrong session method call (#1226) 2017-08-19 14:43:21 +09:30
zinsserzh
7df9594a04 Add isEmpty function to ItemList (#1218)
* Add isEmpty function to ItemList

* Fix coding style to be consistent.

* Recompiled app.js for both js/admin/ and js/forum/
2017-08-10 11:37:00 +09:30
Franz Liedke
c037658675 Don't hardcode admin URL
Fixes #1219.
2017-08-04 23:37:59 +02:00
Toby Zerner
287085dc25 Fix scrubber icon alignment 2017-07-30 09:17:50 +09:30
Franz Liedke
a2e0daed70 Remove faulty default value
Fixes #1210.
2017-07-27 00:55:33 +02:00
Toby Zerner
57f828b3f7 Fix user online icon spacing 2017-07-22 16:10:08 +09:30
Toby Zerner
7ec92813e3 Make dropdown menu icons a nicer fixed width 2017-07-22 16:09:51 +09:30
Toby Zerner
ce8a5b3e0f v0.1.0-beta.7 2017-07-22 12:48:58 +09:30
Toby Zerner
5faf0fcde5 And remove unused import 2017-07-22 12:31:23 +09:30
Toby Zerner
65c0b436c0 Fix missed instance of back button tooltip 2017-07-22 12:30:55 +09:30
Toby Zerner
8d76168bd4 Oops, forgot to correct test code 2017-07-22 12:29:03 +09:30
Toby Zerner
d16f4dbefa Recompile JS 2017-07-22 12:08:17 +09:30
Toby Zerner
e3e4786391 Simplify global back button
The behaviour is not overly intuitive, and the icon wasn't helping
(hamburger icon usually means "menu"). Now the back button always goes
back to the index, no matter where you are, and there's a tooltip that
says "Back to discussion list".
2017-07-22 12:08:09 +09:30
Toby Zerner
c1c7d4c73a Only display "show language selector" toggle if there is more than one language 2017-07-22 11:47:50 +09:30
Toby Zerner
8da8c9ac7d Clean up appearance of Rename Discussion modal
Also fix infinite loading if there's a validation error.
2017-07-22 11:47:04 +09:30
Toby Zerner
fb68aa88db Use default dropdown appearance for sort dropdown 2017-07-22 11:46:16 +09:30
Toby Zerner
afc597c189 Remove fa-fw class from all icons
Often it is desirable to NOT have this class applied, and it is easier
to apply its styles if needed rather than un-apply it.
2017-07-22 11:45:42 +09:30
Toby Zerner
4f3e67714e Fix incorrect migration notes for extensions without any migrations
When running migrations for an extension without any migrations (eg.
BBCode), the migration notes for the previous extension were being
displayed, because the Migrator never had a chance to clear them.
2017-07-22 11:43:50 +09:30
Toby Zerner
54be3ad3c8 Define the default moderator group ID
This allows extensions to add default permissions for moderators,
without having to hardcode in the default moderator group ID.
2017-07-22 11:41:20 +09:30
Toby Zerner
0b00d56416 Add a new migration helper for adding default permissions 2017-07-22 11:40:06 +09:30
Toby Zerner
89d4a1e849 Remove MySQL port field from visual installer
Port can still be specified by suffixing the host with a :

closes #825
2017-07-22 11:32:07 +09:30
Daniël Klabbers
43ee7b59a4 Update Client.php (#1198)
* Update Client.php

Now forwarding exceptions from client to page in case debug mode is on. Fixes #1120.

* Update Client.php

Satisfying .. the unsatisfiable.

* Update Client.php

Satisfying again.
2017-07-19 22:14:00 +02:00
David Sevilla Martín
d052f6b639 Use dropdown for discussion list order input (#1191)
* Use dropdown menu for index select input

* Fix space before `:`
2017-07-17 13:40:35 +09:30
Toby Zerner
4b47adabcf Oops, that should be in seconds not minutes 2017-07-08 22:35:11 +09:30
Toby Zerner
93140b8fa4 Remember users forever (5 years) rather than 2 weeks 2017-07-08 22:29:26 +09:30
Toby Zerner
ade2166310 Revise Remember Me checkbox appearance
Use a generic checkbox instead of a switch — it's more familiar and accessible.

Signed-off-by: Toby Zerner <toby.zerner@gmail.com>
2017-07-08 22:25:24 +09:30
Toby Zerner
a9969119d2 Merge branch 'master' of https://github.com/flarum/core 2017-07-08 21:52:01 +09:30
Toby Zerner
94a8eaec64 Update dependencies 2017-07-08 21:50:54 +09:30
Franz Liedke
8ea13dc826 Flatten implementation of SelfDemotionGuard listener
Refs #736 and #1195.
2017-07-06 21:57:47 +02:00
David Sevilla Martín
99d42372c3 Prevent yourself from locking yourself out of admin group (#1195) 2017-07-06 21:43:01 +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
834 changed files with 21835 additions and 65904 deletions

BIN
.deploy.enc Normal file

Binary file not shown.

View File

@@ -15,5 +15,5 @@ indent_size = 2
[*.{diff,md}]
trim_trailing_whitespace = false
[*.php]
[*.{php,xml}]
indent_size = 4

9
.gitattributes vendored
View File

@@ -1,4 +1,13 @@
.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
phpunit.xml export-ignore
tests export-ignore
js/dist/* -diff

View File

@@ -1,3 +0,0 @@
# Contributing to Flarum
Howdy! We're really excited that you are interested in contributing to Flarum. Before submitting your contribution, please take a moment and read through the [Contributing Guidelines](https://github.com/flarum/flarum/blob/master/CONTRIBUTING.md).

View File

@@ -1,26 +0,0 @@
> Issues on Github are meant for bug reporting. Please post feature requests on the [discussion forum](https://discuss.flarum.org/t/features).
---
> Try to complete the below form as far as you are able and are willing to share. Add a screenshot of the issue if you can.
## Bug report
- Version of Flarum: x.y.z
- Website URL where the bug is visible: http://example.com
- The webserver you are running: apache, nginx or something else
- PHP version: x.y.z
- Hosted environment: shared or vps
- Hosting provider: http://some-amazing-provider.com
## Flarum info
```
Output of "php flarum info", run this in terminal in your Flarum directory.
```
## Additional comments
Some additional information you'd like to share, eg what have you tried so far.
## Log files
```
Put any relevant logs here.
```

42
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@@ -0,0 +1,42 @@
---
name: "🐛 Bug Report"
about: "If something isn't working as expected"
---
<!--
IMPORTANT: If you discover a security vulnerability within Flarum, please send an email to [security@flarum.org](mailto:security@flarum.org) instead. We will address these with the utmost urgency and it will prevent vulnerabilities, which may be abused, from popping up on our issue tracker.
-->
## Bug Report
**Current Behavior**
A clear and concise description of the behavior.
**Steps to Reproduce**
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected Behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment**
- Flarum version: x.y.z
- Website URL: http://example.com
- Webserver: [e.g. apache, nginx]
- Hosting environment: [e.g. shared, vps]
- PHP version: x.y.z
- Browser: [e.g. chrome 67, safari 11]
```
Output of "php flarum info", run this in terminal in your Flarum directory.
```
**Possible Solution**
<!--- Only if you have suggestions or a fix for the bug -->
**Additional Context**
Add any other context about the problem here.

View File

@@ -0,0 +1,26 @@
---
name: "🚀 Feature Request"
about: "I have a suggestion (and may want to implement it!)"
---
<!--
IMPORTANT: Feature requests on this GitHub issue tracker are only accepted in case they have been approved by a core developer or contain extensive argumentation and directions for implementation. For all other feature requests, ideas and feedback please post in the Flarum Community: https://discuss.flarum.org/t/feedback.
-->
## Feature Request
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. eg. I have an issue when [...]
**Describe the solution you'd like**
A detailed description of your proposed solution. Include:
- How the feature would work/behave
- Any potential drawbacks
- Maybe a screenshot, design, or example code
**Justify why this feature belongs in Flarum's core, rather than in a third-party extension**
Consider who this change will be useful to  most Flarum forums, or just a few?
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

View File

@@ -0,0 +1,11 @@
---
name: "🙋‍ Support Question"
about: "If you have a question, please check out our forum or Discord!"
---
We primarily use GitHub as an issue tracker; for usage and support questions, please check out these resources below. Thanks!
* Flarum Community: https://discuss.flarum.org/
* Discord Chat: https://flarum.org/discord/
* Twitter: https://twitter.com/Flarum

24
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,24 @@
<!--
IMPORTANT: We applaud pull requests, they excite us every single time. As we have an obligation to maintain a healthy code standard and quality, we take sufficient time for reviews. Please do create a separate pull request per change/issue/feature; we will ask you to split bundled pull requests.
-->
**Fixes #0000**
**Changes proposed in this pull request:**
<!-- fill this out, mention the pages and/or components which have been impacted -->
**Reviewers should focus on:**
<!-- fill this out, ask for feedback on specific changes you are unsure about -->
**Screenshot**
<!-- include an image of the most relevant user-facing change, if any -->
**Confirmed**
- [ ] Frontend changes: tested on a local Flarum installation.
- [ ] Backend changes: tests are green (run `php vendor/bin/phpunit`).
**Required changes:**
- [ ] Related documentation PR: (Remove if irrelevant)
- [ ] Related core extension PRs: (Remove if irrelevant)

4
.gitignore vendored
View File

@@ -1,7 +1,9 @@
/vendor
composer.lock
composer.phar
node_modules
.DS_Store
Thumbs.db
tests/_output/*
/tests/tmp
.vagrant
.idea/*

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,35 +1,46 @@
language: php
php:
- 5.5
- 5.6
- 7.0
- hhvm
cache:
directories:
- $HOME/.composer/cache
- $HOME/.npm
matrix:
allow_failures:
- php: hhvm
fast_finish: true
before_script:
- if [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then phpenv config-rm xdebug.ini; fi;
- composer self-update
install:
- composer install
- mysql -e 'CREATE DATABASE flarum;'
script:
- vendor/bin/phpunit --coverage-clover=coverage.xml
notifications:
email:
on_failure: change
webhooks:
urls:
- https://webhooks.gitter.im/e/7b9e9827a03b44a16588
on_success: always
on_failure: always
on_start: false
after_success:
- bash <(curl -s https://codecov.io/bash)
sudo: false
jobs:
include:
- php: 7.1
env: DB=mysql
- php: 7.2
env: DB=mysql
- php: 7.2
env: DB=mysql PREFIX=forum_
- 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

33
.travis/build.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/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
git checkout -f $TRAVIS_BRANCH
git config user.name "flarum-bot"
git config user.email "bot@flarum.org"
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 push git@github.com:$TRAVIS_REPO_SLUG.git $TRAVIS_BRANCH
}
main "$@"

13
CHANGELOG.md Normal file
View File

@@ -0,0 +1,13 @@
# Changelog
## [0.1.0-beta.8.1](https://github.com/flarum/core/compare/v0.1.0-beta.8...v0.1.0-beta.8.1)
### Fixed
- Fix live output in `migrate:reset` command ([f591585](https://github.com/flarum/core/commit/f591585d02f8c4ff0211c5bf4413dd6baa724c05))
- Fix search with database prefix ([7705a2b](https://github.com/flarum/core/commit/7705a2b7d751943ef9d0c7379ec34f8530b99310))
- Fix invalid join time of admin user created by installer ([57f73c9](https://github.com/flarum/core/commit/57f73c9638eeb825f9e336ed3c443afccfd8995e))
- Ensure InnoDB engine is used for all tables ([fb6b51b](https://github.com/flarum/core/commit/fb6b51b1cfef0af399607fe038603c8240800b2b))
- Fix dropping foreign keys in `down` migrations ([57d5846](https://github.com/flarum/core/commit/57d5846b647881009d9e60f9ffca20b1bb77776e))
- Fix discussion list scroll position not being maintained when hero is not visible ([40dc6ac](https://github.com/flarum/core/commit/40dc6ac604c2a0973356b38217aa8d09352daae5))
- Fix empty meta description tag ([88e43cc](https://github.com/flarum/core/commit/88e43cc6940ee30d6529e9ce659471ec4fb1c474))
- Remove empty attributes on `<html>` tag ([796b577](https://github.com/flarum/core/commit/796b57753d34d4ea741dbebcbc550b17808f6c94))

3
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,3 @@
# Contributing to Flarum
Thank you for considering contributing to Flarum! Please read the **[Contributing guide](https://flarum.org/docs/contributing.html)** to learn how you can help.

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014-2016 Toby Zerner
Copyright (c) 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

@@ -1,7 +1,35 @@
# Flarum Core
<p align="center"><img src="https://flarum.org/img/logo.png"></p>
This repository contains Flarum's core code. If you want to set up a forum, visit the [main Flarum repository](http://github.com/flarum/flarum).
<p align="center">
<a href="https://travis-ci.org/flarum/core"><img src="https://travis-ci.org/flarum/core.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://poser.pugx.org/flarum/core/d/total.svg" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://poser.pugx.org/flarum/core/v/stable.svg" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://poser.pugx.org/flarum/core/license.svg" alt="License"></a>
</p>
## About Flarum
**[Flarum](https://flarum.org/) is a delightfully simple discussion platform for your website.** It's fast and easy to use, with all the features you need to run a successful community. It is designed to be:
* **Fast and simple.** No clutter, no bloat, no complex dependencies. Flarum is built with PHP so its quick and easy to deploy. The interface is powered by Mithril, a performant JavaScript framework with a tiny footprint.
* **Beautiful and responsive.** This is forum software for humans. Flarum is carefully designed to be consistent and intuitive across platforms, out-of-the-box.
* **Powerful and extensible.** Customize, extend, and integrate Flarum to suit your community. Flarums architecture is amazingly flexible, with a powerful Extension API.
## Installation
This repository contains Flarum's core code. If you want to set up a forum, visit the [Flarum skeleton repository](https://github.com/flarum/flarum).
## Contributing
Flarum is open-source and we would love your help building it! Please read the [Contributing Guide](https://github.com/flarum/flarum/blob/master/CONTRIBUTING.md) to learn how you can help.
Thank you for considering contributing to Flarum! Please read the **[Contributing guide](https://flarum.org/docs/contributing.html)** to learn how you can help.
## Security Vulnerabilities
If you discover a security vulnerability within Flarum, please send an e-mail to [security@flarum.org](mailto:security@flarum.org). All security vulnerabilities will be promptly addressed.
## License
Flarum is open-source software licensed under the [MIT License](https://github.com/flarum/flarum/blob/master/LICENSE).

View File

@@ -2,7 +2,7 @@
"name": "flarum/core",
"description": "Delightfully simple forum software.",
"keywords": ["forum", "discussion"],
"homepage": "http://flarum.org",
"homepage": "https://flarum.org/",
"license": "MIT",
"authors": [
{
@@ -17,47 +17,55 @@
"support": {
"issues": "https://github.com/flarum/core/issues",
"source": "https://github.com/flarum/core",
"docs": "http://flarum.org/docs"
"docs": "https://flarum.org/docs/"
},
"require": {
"php": ">=5.5.9",
"php": ">=7.1",
"axy/sourcemap": "^0.1.4",
"components/font-awesome": "5.9.*",
"dflydev/fig-cookies": "^1.0.2",
"doctrine/dbal": "^2.5",
"components/font-awesome": "^4.6",
"doctrine/dbal": "^2.7",
"franzl/whoops-middleware": "^0.4.0",
"illuminate/bus": "5.1.*",
"illuminate/cache": "5.1.*",
"illuminate/config": "5.1.*",
"illuminate/container": "5.1.*",
"illuminate/contracts": "5.1.*",
"illuminate/database": "^5.1.31",
"illuminate/events": "5.1.*",
"illuminate/filesystem": "5.1.*",
"illuminate/hashing": "5.1.*",
"illuminate/mail": "5.1.*",
"illuminate/support": "5.1.*",
"illuminate/validation": "5.1.*",
"illuminate/view": "5.1.*",
"illuminate/bus": "5.5.*",
"illuminate/cache": "5.5.*",
"illuminate/config": "5.5.*",
"illuminate/container": "5.5.*",
"illuminate/contracts": "5.5.*",
"illuminate/database": "5.5.*",
"illuminate/events": "5.5.*",
"illuminate/filesystem": "5.5.*",
"illuminate/hashing": "5.5.*",
"illuminate/mail": "5.5.*",
"illuminate/session": "5.5.*",
"illuminate/support": "5.5.*",
"illuminate/validation": "5.5.*",
"illuminate/view": "5.5.*",
"intervention/image": "^2.3.0",
"league/flysystem": "^1.0.11",
"league/oauth2-client": "~1.0",
"matthiasmullie/minify": "^1.3",
"middlewares/base-path": "^1.1",
"middlewares/base-path-router": "^0.2.1",
"middlewares/request-handler": "^1.2",
"monolog/monolog": "^1.16.0",
"nikic/fast-route": "^0.6",
"oyejorge/less.php": "~1.5",
"oyejorge/less.php": "^1.7",
"psr/http-message": "^1.0",
"symfony/console": "^2.7",
"symfony/http-foundation": "^2.7",
"symfony/translation": "^2.7",
"symfony/yaml": "^2.7",
"s9e/text-formatter": "^0.6.1",
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0",
"s9e/text-formatter": "^1.2.0",
"symfony/config": "^3.3",
"symfony/console": "^3.3",
"symfony/http-foundation": "^3.3",
"symfony/translation": "^3.3",
"symfony/yaml": "^3.3",
"tobscure/json-api": "^0.3.0",
"zendframework/zend-diactoros": "^1.1",
"zendframework/zend-stratigility": "^1.1"
"zendframework/zend-diactoros": "^1.8.4",
"zendframework/zend-httphandlerrunner": "^1.0",
"zendframework/zend-stratigility": "^3.0"
},
"require-dev": {
"mockery/mockery": "^0.9.4",
"phpunit/phpunit": "^4.8"
"phpunit/phpunit": "^6.0"
},
"autoload": {
"psr-4": {
@@ -69,9 +77,12 @@
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
"Flarum\\Tests\\": "tests/"
}
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "0.1.x-dev"

View File

@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>403 Forbidden</h1>
<p>You do not have permissions to access this page.</p>
</body>
</html>

View File

@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>404 Not Found</h1>
<p>Looks like this page could not be found.</p>
</body>
</html>

View File

@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>500 Internal Server Error</h1>
<p>Something went wrong on our server.</p>
</body>
</html>

View File

@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>503 Service Unavailable</h1>
<p>This forum is down for maintenance.</p>
</body>
</html>

1
js/.gitignore vendored
View File

@@ -1 +0,0 @@
bower_components

11
js/admin.js Normal file
View 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
View File

@@ -1 +0,0 @@
node_modules

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

@@ -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,22 +0,0 @@
import Page from 'flarum/components/Page';
export default class DashboardPage extends Page {
view() {
return (
<div className="DashboardPage">
<div className="container">
<h2>{app.translator.trans('core.admin.dashboard.welcome_text')}</h2>
<p>{app.translator.trans('core.admin.dashboard.version_text', {version: <strong>{app.forum.attribute('version')}</strong>})}</p>
<p>{app.translator.trans('core.admin.dashboard.beta_warning_text', {strong: <strong/>})}</p>
<ul>
<li>{app.translator.trans('core.admin.dashboard.contributing_text', {a: <a href="http://flarum.org/docs/contributing" target="_blank"/>})}</li>
<li>{app.translator.trans('core.admin.dashboard.troubleshooting_text', {a: <a href="http://flarum.org/docs/troubleshooting" target="_blank"/>})}</li>
<li>{app.translator.trans('core.admin.dashboard.support_text', {a: <a href="http://discuss.flarum.org/t/support" target="_blank"/>})}</li>
<li>{app.translator.trans('core.admin.dashboard.features_text', {a: <a href="http://discuss.flarum.org/t/features" target="_blank"/>})}</li>
<li>{app.translator.trans('core.admin.dashboard.extension_text', {a: <a href="http://flarum.org/docs/extend" target="_blank"/>})}</li>
</ul>
</div>
</div>
);
}
}

View File

@@ -1,102 +0,0 @@
import Modal from 'flarum/components/Modal';
import Button from 'flarum/components/Button';
import Badge from 'flarum/components/Badge';
import Group from 'flarum/models/Group';
/**
* The `EditGroupModal` component shows a modal dialog which allows the user
* to create or edit a group.
*/
export default class EditGroupModal extends Modal {
init() {
this.group = this.props.group || app.store.createRecord('groups');
this.nameSingular = m.prop(this.group.nameSingular() || '');
this.namePlural = m.prop(this.group.namePlural() || '');
this.icon = m.prop(this.group.icon() || '');
this.color = m.prop(this.group.color() || '');
}
className() {
return 'EditGroupModal Modal--small';
}
title() {
return [
this.color() || this.icon() ? Badge.component({
icon: this.icon(),
style: {backgroundColor: this.color()}
}) : '',
' ',
this.namePlural() || app.translator.trans('core.admin.edit_group.title')
];
}
content() {
return (
<div className="Modal-body">
<div className="Form">
<div className="Form-group">
<label>{app.translator.trans('core.admin.edit_group.name_label')}</label>
<div className="EditGroupModal-name-input">
<input className="FormControl" placeholder={app.translator.trans('core.admin.edit_group.singular_placeholder')} value={this.nameSingular()} oninput={m.withAttr('value', this.nameSingular)}/>
<input className="FormControl" placeholder={app.translator.trans('core.admin.edit_group.plural_placeholder')} value={this.namePlural()} oninput={m.withAttr('value', this.namePlural)}/>
</div>
</div>
<div className="Form-group">
<label>{app.translator.trans('core.admin.edit_group.color_label')}</label>
<input className="FormControl" placeholder="#aaaaaa" value={this.color()} oninput={m.withAttr('value', this.color)}/>
</div>
<div className="Form-group">
<label>{app.translator.trans('core.admin.edit_group.icon_label')}</label>
<div className="helpText">
{app.translator.trans('core.admin.edit_group.icon_text', {a: <a href="http://fortawesome.github.io/Font-Awesome/icons/" tabindex="-1"/>})}
</div>
<input className="FormControl" placeholder="bolt" value={this.icon()} oninput={m.withAttr('value', this.icon)}/>
</div>
<div className="Form-group">
{Button.component({
type: 'submit',
className: 'Button Button--primary EditGroupModal-save',
loading: this.loading,
children: app.translator.trans('core.admin.edit_group.submit_button')
})}
{this.group.exists && this.group.id() !== Group.ADMINISTRATOR_ID ? (
<button type="button" className="Button EditGroupModal-delete" onclick={this.deleteGroup.bind(this)}>
{app.translator.trans('core.admin.edit_group.delete_button')}
</button>
) : ''}
</div>
</div>
</div>
);
}
onsubmit(e) {
e.preventDefault();
this.loading = true;
this.group.save({
nameSingular: this.nameSingular(),
namePlural: this.namePlural(),
color: this.color(),
icon: this.icon()
}, {errorHandler: this.onerror.bind(this)})
.then(this.hide.bind(this))
.catch(() => {
this.loading = false;
m.redraw();
});
}
deleteGroup() {
if (confirm(app.translator.trans('core.admin.edit_group.delete_confirmation'))) {
this.group.delete().then(() => m.redraw());
this.hide();
}
}
}

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,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"
}
}

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

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

11
js/forum.js Normal file
View 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
View File

@@ -1 +0,0 @@
node_modules

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

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

@@ -1,136 +0,0 @@
import Modal from 'flarum/components/Modal';
import Button from 'flarum/components/Button';
import GroupBadge from 'flarum/components/GroupBadge';
import Group from 'flarum/models/Group';
import extractText from 'flarum/utils/extractText';
/**
* The `EditUserModal` component displays a modal dialog with a login form.
*/
export default class EditUserModal extends Modal {
init() {
super.init();
const user = this.props.user;
this.username = m.prop(user.username() || '');
this.email = m.prop(user.email() || '');
this.setPassword = m.prop(false);
this.password = m.prop(user.password() || '');
this.groups = {};
app.store.all('groups')
.filter(group => [Group.GUEST_ID, Group.MEMBER_ID].indexOf(group.id()) === -1)
.forEach(group => this.groups[group.id()] = m.prop(user.groups().indexOf(group) !== -1));
}
className() {
return 'EditUserModal Modal--small';
}
title() {
return app.translator.trans('core.forum.edit_user.title');
}
content() {
return (
<div className="Modal-body">
<div className="Form">
<div className="Form-group">
<label>Username</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>
<div>
<input className="FormControl" placeholder={extractText(app.translator.trans('core.forum.edit_user.email_label'))}
bidi={this.email} />
</div>
</div>,
<div className="Form-group">
<label>Password</label>
<div>
<label className="checkbox">
<input type="checkbox" checked={this.setPassword()} onchange={e => {
this.setPassword(e.target.checked);
m.redraw(true);
if (e.target.checked) this.$('[name=password]').select();
m.redraw.strategy('none');
}}/>
Set new password
</label>
{this.setPassword() ? (
<input className="FormControl" type="password" name="password" placeholder={extractText(app.translator.trans('core.forum.edit_user.password_label'))}
bidi={this.password} />
) : ''}
</div>
</div>
] : ''}
<div className="Form-group EditUserModal-groups">
<label>Groups</label>
<div>
{Object.keys(this.groups)
.map(id => app.store.getById('groups', id))
.map(group => (
<label className="checkbox">
<input type="checkbox"
bidi={this.groups[group.id()]}
disabled={this.props.user.id() === '1' && group.id() === Group.ADMINISTRATOR_ID} />
{GroupBadge.component({group, label: ''})} {group.nameSingular()}
</label>
))}
</div>
</div>
<div className="Form-group">
{Button.component({
className: 'Button Button--primary',
type: 'submit',
loading: this.loading,
children: app.translator.trans('core.forum.edit_user.submit_button')
})}
</div>
</div>
</div>
);
}
data() {
const groups = Object.keys(this.groups)
.filter(id => this.groups[id]())
.map(id => app.store.getById('groups', id));
const data = {
username: this.username(),
relationships: {groups}
};
if (app.session.user !== this.props.user) {
data.email = this.email();
}
if (this.setPassword()) {
data.password = this.password();
}
return data;
}
onsubmit(e) {
e.preventDefault();
this.loading = true;
this.props.user.save(this.data(), {errorHandler: this.onerror.bind(this)})
.then(this.hide.bind(this))
.catch(() => {
this.loading = false;
m.redraw();
});
}
}

View File

@@ -1,138 +0,0 @@
import Modal from 'flarum/components/Modal';
import ForgotPasswordModal from 'flarum/components/ForgotPasswordModal';
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 extractText from 'flarum/utils/extractText';
/**
* The `LogInModal` component displays a modal dialog with a login form.
*
* ### Props
*
* - `email`
* - `password`
*/
export default class LogInModal extends Modal {
init() {
super.init();
/**
* The value of the email input.
*
* @type {Function}
*/
this.email = m.prop(this.props.email || '');
/**
* The value of the password input.
*
* @type {Function}
*/
this.password = m.prop(this.props.password || '');
}
className() {
return 'LogInModal Modal--small';
}
title() {
return app.translator.trans('core.forum.log_in.title');
}
content() {
return [
<div className="Modal-body">
<LogInButtons/>
<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}
disabled={this.loading} />
</div>
<div className="Form-group">
<input className="FormControl" name="password" type="password" placeholder={extractText(app.translator.trans('core.forum.log_in.password_placeholder'))}
bidi={this.password}
disabled={this.loading} />
</div>
<div className="Form-group">
{Button.component({
className: 'Button Button--primary Button--block',
type: 'submit',
loading: this.loading,
children: app.translator.trans('core.forum.log_in.submit_button')
})}
</div>
</div>
</div>,
<div className="Modal-footer">
<p className="LogInModal-forgotPassword">
<a onclick={this.forgotPassword.bind(this)}>{app.translator.trans('core.forum.log_in.forgot_password_link')}</a>
</p>
{app.forum.attribute('allowSignUp') ? (
<p className="LogInModal-signUp">
{app.translator.trans('core.forum.log_in.sign_up_text', {a: <a onclick={this.signUp.bind(this)}/>})}
</p>
) : ''}
</div>
];
}
/**
* Open the forgot password modal, prefilling it with an email if the user has
* entered one.
*
* @public
*/
forgotPassword() {
const email = this.email();
const props = email.indexOf('@') !== -1 ? {email} : undefined;
app.modal.show(new ForgotPasswordModal(props));
}
/**
* Open the sign up modal, prefilling it with an email/username/password if
* the user has entered one.
*
* @public
*/
signUp() {
const props = {password: this.password()};
const email = this.email();
props[email.indexOf('@') !== -1 ? 'email' : 'username'] = email;
app.modal.show(new SignUpModal(props));
}
onready() {
this.$('[name=' + (this.email() ? 'password' : 'email') + ']').select();
}
onsubmit(e) {
e.preventDefault();
this.loading = true;
const email = this.email();
const password = this.password();
app.session.login(email, password, {errorHandler: this.onerror.bind(this)}).then(
() => window.location.reload(),
this.loaded.bind(this)
);
}
onerror(error) {
if (error.status === 401) {
error.alert.props.children = app.translator.trans('core.forum.log_in.invalid_login_message');
}
super.onerror(error);
}
}

View File

@@ -1,145 +0,0 @@
import Component from 'flarum/Component';
import listItems from 'flarum/helpers/listItems';
import Button from 'flarum/components/Button';
import LoadingIndicator from 'flarum/components/LoadingIndicator';
import Discussion from 'flarum/models/Discussion';
/**
* The `NotificationList` component displays a list of the logged-in user's
* notifications, grouped by discussion.
*/
export default class NotificationList extends Component {
init() {
/**
* Whether or not the notifications are loading.
*
* @type {Boolean}
*/
this.loading = false;
}
view() {
const groups = [];
if (app.cache.notifications) {
const discussions = {};
// Build an array of discussions which the notifications are related to,
// and add the notifications as children.
app.cache.notifications.forEach(notification => {
const subject = notification.subject();
if (typeof subject === 'undefined') return;
// Get the discussion that this notification is related to. If it's not
// directly related to a discussion, it may be related to a post or
// other entity which is related to a discussion.
let discussion = false;
if (subject instanceof Discussion) discussion = subject;
else if (subject && subject.discussion) discussion = subject.discussion();
// If the notification is not related to a discussion directly or
// indirectly, then we will assign it to a neutral group.
const key = discussion ? discussion.id() : 0;
discussions[key] = discussions[key] || {discussion: discussion, notifications: []};
discussions[key].notifications.push(notification);
if (groups.indexOf(discussions[key]) === -1) {
groups.push(discussions[key]);
}
});
}
return (
<div className="NotificationList">
<div className="NotificationList-header">
<div className="App-primaryControl">
{Button.component({
className: 'Button Button--icon Button--link',
icon: 'check',
title: app.translator.trans('core.forum.notifications.mark_all_as_read_tooltip'),
onclick: this.markAllAsRead.bind(this)
})}
</div>
<h4 className="App-titleControl App-titleControl--text">{app.translator.trans('core.forum.notifications.title')}</h4>
</div>
<div className="NotificationList-content">
{groups.length
? groups.map(group => {
const badges = group.discussion && group.discussion.badges().toArray();
return (
<div className="NotificationGroup">
{group.discussion
? (
<a className="NotificationGroup-header"
href={app.route.discussion(group.discussion)}
config={m.route}>
{badges && badges.length ? <ul className="NotificationGroup-badges badges">{listItems(badges)}</ul> : ''}
{group.discussion.title()}
</a>
) : (
<div className="NotificationGroup-header">
{app.forum.attribute('title')}
</div>
)}
<ul className="NotificationGroup-content">
{group.notifications.map(notification => {
const NotificationComponent = app.notificationComponents[notification.contentType()];
return NotificationComponent ? <li>{NotificationComponent.component({notification})}</li> : '';
})}
</ul>
</div>
);
})
: !this.loading
? <div className="NotificationList-empty">{app.translator.trans('core.forum.notifications.empty_text')}</div>
: LoadingIndicator.component({className: 'LoadingIndicator--block'})}
</div>
</div>
);
}
/**
* Load notifications into the application's cache if they haven't already
* been loaded.
*/
load() {
if (app.cache.notifications && !app.session.user.newNotificationsCount()) {
return;
}
this.loading = true;
m.redraw();
app.store.find('notifications')
.then(notifications => {
app.session.user.pushAttributes({newNotificationsCount: 0});
app.cache.notifications = notifications.sort((a, b) => b.time() - a.time());
})
.catch(() => {})
.then(() => {
this.loading = false;
m.redraw();
});
}
/**
* Mark all of the notifications as read.
*/
markAllAsRead() {
if (!app.cache.notifications) return;
app.session.user.pushAttributes({unreadNotificationsCount: 0});
app.cache.notifications.forEach(notification => notification.pushAttributes({isRead: true}));
app.request({
url: app.forum.attribute('apiUrl') + '/notifications/read',
method: 'POST'
});
}
}

View File

@@ -1,105 +0,0 @@
import Component from 'flarum/Component';
import LoadingIndicator from 'flarum/components/LoadingIndicator';
import classList from 'flarum/utils/classList';
import extractText from 'flarum/utils/extractText';
/**
* The `UserBio` component displays a user's bio, optionally letting the user
* edit it.
*/
export default class UserBio extends Component {
init() {
/**
* Whether or not the bio is currently being edited.
*
* @type {Boolean}
*/
this.editing = false;
/**
* Whether or not the bio is currently being saved.
*
* @type {Boolean}
*/
this.loading = false;
}
view() {
const user = this.props.user;
let content;
if (this.editing) {
content = <textarea className="FormControl" placeholder={extractText(app.translator.trans('core.forum.user.bio_placeholder'))} rows="3" value={user.bio()}/>;
} else {
let subContent;
if (this.loading) {
subContent = <p className="UserBio-placeholder">{LoadingIndicator.component({size: 'tiny'})}</p>;
} else {
const bioHtml = user.bioHtml();
if (bioHtml) {
subContent = m.trust(bioHtml);
} else if (this.props.editable) {
subContent = <p className="UserBio-placeholder">{app.translator.trans('core.forum.user.bio_placeholder')}</p>;
}
}
content = <div className="UserBio-content">{subContent}</div>;
}
return (
<div className={'UserBio ' + classList({
editable: this.props.editable,
editing: this.editing
})}
onclick={this.edit.bind(this)}>
{content}
</div>
);
}
/**
* Edit the bio.
*/
edit() {
if (!this.props.editable) return;
this.editing = true;
m.redraw();
const bio = this;
const save = function(e) {
if (e.shiftKey) return;
e.preventDefault();
bio.save($(this).val());
};
this.$('textarea').focus()
.bind('blur', save)
.bind('keydown', 'return', save);
}
/**
* Save the bio.
*
* @param {String} value
*/
save(value) {
const user = this.props.user;
if (user.bio() !== value) {
this.loading = true;
user.save({bio: value})
.catch(() => {})
.then(() => {
this.loading = false;
m.redraw();
});
}
this.editing = false;
m.redraw();
}
}

View File

@@ -1,87 +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 icon from 'flarum/helpers/icon';
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, icon('bars'), '/');
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();
});
// 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();
// Initialize FastClick, which makes links and buttons much more responsive on
// touch devices.
$(() => {
FastClick.attach(document.body);
$('body').addClass('ontouchstart' in window ? 'touch' : 'no-touch');
});
app.booted = true;
}

View File

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

View File

@@ -1,25 +0,0 @@
/**
* Setup the sidebar DOM element to be affixed to the top of the viewport
* using Bootstrap's affix plugin.
*
* @param {DOMElement} element
* @param {Boolean} isInitialized
*/
export default function affixSidebar(element, isInitialized) {
if (isInitialized) return;
const $sidebar = $(element);
const $header = $('#header');
const $footer = $('#footer');
// Don't affix the sidebar if it is taller than the viewport (otherwise
// there would be no way to scroll through its content).
if ($sidebar.outerHeight(true) > $(window).height() - $header.outerHeight(true)) return;
$sidebar.find('> ul').affix({
offset: {
top: () => $sidebar.offset().top - $header.outerHeight(true) - parseInt($sidebar.css('margin-top'), 10),
bottom: () => this.bottom = $footer.outerHeight(true)
}
});
}

View File

@@ -1,27 +0,0 @@
import Component from 'flarum/Component';
/**
* The `LoadingIndicator` component displays a loading spinner with spin.js. It
* may have the following special props:
*
* - `size` The spin.js size preset to use. Defaults to 'small'.
*
* All other props will be assigned as attributes on the element.
*/
export default class LoadingIndicator extends Component {
view() {
const attrs = Object.assign({}, this.props);
attrs.className = 'LoadingIndicator ' + (attrs.className || '');
delete attrs.size;
return <div {...attrs}>{m.trust('&nbsp;')}</div>;
}
config() {
const size = this.props.size || 'small';
$.fn.spin.presets[size].zIndex = 'auto';
this.$().spin(size);
}
}

View File

@@ -1,30 +0,0 @@
import Modal from 'flarum/components/Modal';
export default class RequestErrorModal extends Modal {
className() {
return 'RequestErrorModal Modal--large';
}
title() {
return this.props.error.xhr
? this.props.error.xhr.status+' '+this.props.error.xhr.statusText
: '';
}
content() {
let responseText;
try {
responseText = JSON.stringify(JSON.parse(this.props.error.responseText), null, 2);
} catch (e) {
responseText = this.props.error.responseText;
}
return <div className="Modal-body">
<pre>
{this.props.error.options.method} {this.props.error.options.url}<br/><br/>
{responseText}
</pre>
</div>;
}
}

View File

@@ -1,12 +0,0 @@
/**
* The `icon` helper displays a FontAwesome icon. The fa-fw class is applied.
*
* @param {String} name The name of the icon class, without the `fa-` prefix.
* @param {Object} attrs Any other attributes to apply.
* @return {Object}
*/
export default function icon(name, attrs = {}) {
attrs.className = 'icon fa fa-fw fa-' + name + ' ' + (attrs.className || '');
return <i {...attrs}/>;
}

View File

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

View File

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

View File

@@ -1,21 +0,0 @@
import Model from 'flarum/Model';
import computed from 'flarum/utils/computed';
export default class Notification extends Model {}
Object.assign(Notification.prototype, {
contentType: Model.attribute('contentType'),
subjectId: Model.attribute('subjectId'),
content: Model.attribute('content'),
time: Model.attribute('time', Model.date),
isRead: Model.attribute('isRead'),
unreadCount: Model.attribute('unreadCount'),
additionalUnreadCount: computed('unreadCount', unreadCount => Math.max(0, unreadCount - 1)),
user: Model.hasOne('user'),
sender: Model.hasOne('sender'),
subject: Model.hasOne('subject')
});
export default Notification;

View File

@@ -1,30 +0,0 @@
import Model from 'flarum/Model';
import computed from 'flarum/utils/computed';
import { getPlainContent } from 'flarum/utils/string';
export default class Post extends Model {}
Object.assign(Post.prototype, {
number: Model.attribute('number'),
discussion: Model.hasOne('discussion'),
time: Model.attribute('time', Model.transformDate),
user: Model.hasOne('user'),
contentType: Model.attribute('contentType'),
content: Model.attribute('content'),
contentHtml: Model.attribute('contentHtml'),
contentPlain: computed('contentHtml', getPlainContent),
editTime: Model.attribute('editTime', Model.transformDate),
editUser: Model.hasOne('editUser'),
isEdited: computed('editTime', editTime => !!editTime),
hideTime: Model.attribute('hideTime', Model.transformDate),
hideUser: Model.hasOne('hideUser'),
isHidden: computed('hideTime', hideTime => !!hideTime),
canEdit: Model.attribute('canEdit'),
canDelete: Model.attribute('canDelete')
});
export default Post;

4844
js/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

26
js/package.json Normal file
View File

@@ -0,0 +1,26 @@
{
"private": true,
"name": "@flarum/core",
"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.10",
"jquery": "^3.3.1",
"jquery.hotkeys": "^0.1.0",
"lodash-es": "^4.17.11",
"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.26.0",
"webpack-cli": "^3.1.2",
"webpack-merge": "^4.1.4"
},
"scripts": {
"dev": "webpack --mode development --watch",
"build": "webpack --mode production"
}
}

View File

@@ -0,0 +1,63 @@
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();
}
};
constructor() {
super();
routes(this);
}
/**
* @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.hidePosts');
}
return required;
};
}

63
js/src/admin/compat.js Normal file
View 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
});

View File

@@ -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() {
@@ -15,7 +15,7 @@ export default class AddExtensionModal extends Modal {
}
title() {
return 'Add Extension';
return app.translator.trans('core.admin.add_extension.title');
}
content() {

View File

@@ -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() {

View File

@@ -7,20 +7,19 @@
* 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() {
return (
<SelectDropdown
className="AdminNav App-titleControl"
buttonClassName="Button"
children={this.items().toArray()}
/>
buttonClassName="Button">
{this.items().toArray()}
</SelectDropdown>
);
}
@@ -34,42 +33,42 @@ export default class AdminNav extends Component {
items.add('dashboard', AdminLinkButton.component({
href: app.route('dashboard'),
icon: 'bar-chart',
icon: 'far fa-chart-bar',
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',
icon: 'fas fa-pencil-alt',
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',
icon: 'fas fa-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',
icon: 'fas fa-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',
icon: 'fas fa-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',
icon: 'fas fa-puzzle-piece',
children: app.translator.trans('core.admin.nav.extensions_button'),
description: app.translator.trans('core.admin.nav.extensions_text')
}));

View File

@@ -1,10 +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 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() {
@@ -28,8 +29,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="text" placeholder="#aaaaaa" value={this.primaryColor()} onchange={m.withAttr('value', this.primaryColor)}/>
<input className="FormControl" type="text" placeholder="#aaaaaa" value={this.secondaryColor()} onchange={m.withAttr('value', this.secondaryColor)}/>
</div>
{Switch.component({
@@ -81,6 +82,18 @@ export default class AppearancePage extends Page {
})}
</fieldset>
<fieldset>
<legend>{app.translator.trans('core.admin.appearance.custom_footer_heading')}</legend>
<div className="helpText">
{app.translator.trans('core.admin.appearance.custom_footer_text')}
</div>
{Button.component({
className: 'Button',
children: app.translator.trans('core.admin.appearance.edit_footer_button'),
onclick: () => app.modal.show(new EditCustomFooterModal())
})}
</fieldset>
<fieldset>
<legend>{app.translator.trans('core.admin.appearance.custom_styles_heading')}</legend>
<div className="helpText">

View File

@@ -1,10 +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 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() {
@@ -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'
@@ -30,6 +32,8 @@ export default class BasicsPage extends Page {
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,7 +64,13 @@ 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'),
})
]
})

View File

@@ -0,0 +1,18 @@
import Page from './Page';
import StatusWidget from './StatusWidget';
export default class DashboardPage extends Page {
view() {
return (
<div className="DashboardPage">
<div className="container">
{this.availableWidgets()}
</div>
</div>
);
}
availableWidgets() {
return [<StatusWidget/>];
}
}

View File

@@ -0,0 +1,38 @@
/*
* 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 '../../common/Component';
export default class Widget extends Component {
view() {
return (
<div className={"Widget "+this.className()}>
{this.content()}
</div>
);
}
/**
* Get the class name to apply to the widget.
*
* @return {String}
*/
className() {
return '';
}
/**
* Get the content of the widget.
*
* @return {VirtualElement}
*/
content() {
return [];
}
}

View File

@@ -1,4 +1,4 @@
import SettingsModal from 'flarum/components/SettingsModal';
import SettingsModal from './SettingsModal';
export default class EditCustomCssModal extends SettingsModal {
className() {

View File

@@ -0,0 +1,24 @@
import SettingsModal from './SettingsModal';
export default class EditCustomFooterModal extends SettingsModal {
className() {
return 'EditCustomFooterModal Modal--large';
}
title() {
return app.translator.trans('core.admin.edit_footer.title');
}
form() {
return [
<p>{app.translator.trans('core.admin.edit_footer.customize_text')}</p>,
<div className="Form-group">
<textarea className="FormControl" rows="30" bidi={this.setting('custom_footer')}/>
</div>
];
}
onsaved() {
window.location.reload();
}
}

View File

@@ -1,4 +1,4 @@
import SettingsModal from 'flarum/components/SettingsModal';
import SettingsModal from './SettingsModal';
export default class EditCustomHeaderModal extends SettingsModal {
className() {

View File

@@ -0,0 +1,111 @@
import Modal from '../../common/components/Modal';
import Button from '../../common/components/Button';
import Badge from '../../common/components/Badge';
import Group from '../../common/models/Group';
import ItemList from '../../common/utils/ItemList';
/**
* The `EditGroupModal` component shows a modal dialog which allows the user
* to create or edit a group.
*/
export default class EditGroupModal extends Modal {
init() {
this.group = this.props.group || app.store.createRecord('groups');
this.nameSingular = m.prop(this.group.nameSingular() || '');
this.namePlural = m.prop(this.group.namePlural() || '');
this.icon = m.prop(this.group.icon() || '');
this.color = m.prop(this.group.color() || '');
}
className() {
return 'EditGroupModal Modal--small';
}
title() {
return [
this.color() || this.icon() ? Badge.component({
icon: this.icon(),
style: {backgroundColor: this.color()}
}) : '',
' ',
this.namePlural() || app.translator.trans('core.admin.edit_group.title')
];
}
content() {
return (
<div className="Modal-body">
<div className="Form">
{this.fields().toArray()}
</div>
</div>
);
}
fields() {
const items = new ItemList();
items.add('name', <div className="Form-group">
<label>{app.translator.trans('core.admin.edit_group.name_label')}</label>
<div className="EditGroupModal-name-input">
<input className="FormControl" placeholder={app.translator.trans('core.admin.edit_group.singular_placeholder')} value={this.nameSingular()} oninput={m.withAttr('value', this.nameSingular)}/>
<input className="FormControl" placeholder={app.translator.trans('core.admin.edit_group.plural_placeholder')} value={this.namePlural()} oninput={m.withAttr('value', this.namePlural)}/>
</div>
</div>, 30);
items.add('color', <div className="Form-group">
<label>{app.translator.trans('core.admin.edit_group.color_label')}</label>
<input className="FormControl" placeholder="#aaaaaa" value={this.color()} oninput={m.withAttr('value', this.color)}/>
</div>, 20);
items.add('icon', <div className="Form-group">
<label>{app.translator.trans('core.admin.edit_group.icon_label')}</label>
<div className="helpText">
{app.translator.trans('core.admin.edit_group.icon_text', {a: <a href="https://fontawesome.com/icons?m=free" tabindex="-1"/>})}
</div>
<input className="FormControl" placeholder="fas fa-bolt" value={this.icon()} oninput={m.withAttr('value', this.icon)}/>
</div>, 10);
items.add('submit', <div className="Form-group">
{Button.component({
type: 'submit',
className: 'Button Button--primary EditGroupModal-save',
loading: this.loading,
children: app.translator.trans('core.admin.edit_group.submit_button')
})}
{this.group.exists && this.group.id() !== Group.ADMINISTRATOR_ID ? (
<button type="button" className="Button EditGroupModal-delete" onclick={this.deleteGroup.bind(this)}>
{app.translator.trans('core.admin.edit_group.delete_button')}
</button>
) : ''}
</div>, -10);
return items;
}
onsubmit(e) {
e.preventDefault();
this.loading = true;
this.group.save({
nameSingular: this.nameSingular(),
namePlural: this.namePlural(),
color: this.color(),
icon: this.icon()
}, {errorHandler: this.onerror.bind(this)})
.then(this.hide.bind(this))
.catch(() => {
this.loading = false;
m.redraw();
});
}
deleteGroup() {
if (confirm(app.translator.trans('core.admin.edit_group.delete_confirmation'))) {
this.group.delete().then(() => m.redraw());
this.hide();
}
}
}

View File

@@ -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() {
@@ -17,7 +17,7 @@ export default class ExtensionsPage extends Page {
<div className="container">
{Button.component({
children: app.translator.trans('core.admin.extensions.add_button'),
icon: 'plus',
icon: 'fas fa-plus',
className: 'Button Button--primary',
onclick: () => app.modal.show(new AddExtensionModal())
})}
@@ -42,15 +42,18 @@ export default class ExtensionsPage extends Page {
className="ExtensionListItem-controls"
buttonClassName="Button Button--icon Button--flat"
menuClassName="Dropdown-menu--right"
icon="ellipsis-h">
icon="fas fa-ellipsis-h">
{controls}
</Dropdown>
) : ''}
<label className="ExtensionListItem-title">
<input type="checkbox" checked={this.isEnabled(extension.id)} onclick={this.toggle.bind(this, extension.id)}/> {' '}
{extension.extra['flarum-extension'].title}
</label>
<div className="ExtensionListItem-version">{extension.version}</div>
<div className="ExtensionListItem-main">
<label className="ExtensionListItem-title">
<input type="checkbox" checked={this.isEnabled(extension.id)} onclick={this.toggle.bind(this, extension.id)}/> {' '}
{extension.extra['flarum-extension'].title}
</label>
<div className="ExtensionListItem-version">{extension.version}</div>
<div className="ExtensionListItem-description">{extension.description}</div>
</div>
</div>
</li>;
})}
@@ -67,7 +70,7 @@ export default class ExtensionsPage extends Page {
if (app.extensionSettings[name]) {
items.add('settings', Button.component({
icon: 'cog',
icon: 'fas fa-cog',
children: app.translator.trans('core.admin.extensions.settings_button'),
onclick: app.extensionSettings[name]
}));
@@ -75,7 +78,7 @@ export default class ExtensionsPage extends Page {
if (!enabled) {
items.add('uninstall', Button.component({
icon: 'trash-o',
icon: 'far fa-trash-alt',
children: app.translator.trans('core.admin.extensions.uninstall_button'),
onclick: () => {
app.request({

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import Modal from 'flarum/components/Modal';
import Modal from '../../common/components/Modal';
export default class LoadingModal extends Modal {
isDismissible() {

View File

@@ -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() {

View File

@@ -1,4 +1,4 @@
import Component from 'flarum/Component';
import Component from '../../common/Component';
/**
* The `Page` component

View File

@@ -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);
@@ -52,9 +52,9 @@ export default class PermissionDropdown extends Dropdown {
const adminGroup = app.store.getById('groups', Group.ADMINISTRATOR_ID);
if (everyone) {
this.props.label = Badge.component({icon: 'globe'});
this.props.label = Badge.component({icon: 'fas fa-globe'});
} else if (members) {
this.props.label = Badge.component({icon: 'user'});
this.props.label = Badge.component({icon: 'fas fa-user'});
} else {
this.props.label = [
badgeForId(Group.ADMINISTRATOR_ID),
@@ -66,8 +66,8 @@ export default class PermissionDropdown extends Dropdown {
if (this.props.allowGuest) {
this.props.children.push(
Button.component({
children: [Badge.component({icon: 'globe'}), ' ', app.translator.trans('core.admin.permissions_controls.everyone_button')],
icon: everyone ? 'check' : true,
children: [Badge.component({icon: 'fas fa-globe'}), ' ', app.translator.trans('core.admin.permissions_controls.everyone_button')],
icon: everyone ? 'fas fa-check' : true,
onclick: () => this.save([Group.GUEST_ID]),
disabled: this.isGroupDisabled(Group.GUEST_ID)
})
@@ -76,8 +76,8 @@ export default class PermissionDropdown extends Dropdown {
this.props.children.push(
Button.component({
children: [Badge.component({icon: 'user'}), ' ', app.translator.trans('core.admin.permissions_controls.members_button')],
icon: members ? 'check' : true,
children: [Badge.component({icon: 'fas fa-user'}), ' ', app.translator.trans('core.admin.permissions_controls.members_button')],
icon: members ? 'fas fa-check' : true,
onclick: () => this.save([Group.MEMBER_ID]),
disabled: this.isGroupDisabled(Group.MEMBER_ID)
}),
@@ -86,7 +86,7 @@ export default class PermissionDropdown extends Dropdown {
Button.component({
children: [badgeForId(adminGroup.id()), ' ', adminGroup.namePlural()],
icon: !everyone && !members ? 'check' : true,
icon: !everyone && !members ? 'fas fa-check' : true,
disabled: !everyone && !members,
onclick: e => {
if (e.shiftKey) e.stopPropagation();
@@ -101,7 +101,7 @@ export default class PermissionDropdown extends Dropdown {
.filter(group => [Group.ADMINISTRATOR_ID, Group.GUEST_ID, Group.MEMBER_ID].indexOf(group.id()) === -1)
.map(group => Button.component({
children: [badgeForId(group.id()), ' ', group.namePlural()],
icon: groupIds.indexOf(group.id()) !== -1 ? 'check' : true,
icon: groupIds.indexOf(group.id()) !== -1 ? 'fas fa-check' : true,
onclick: (e) => {
if (e.shiftKey) e.stopPropagation();
this.toggle(group.id());

View File

@@ -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() {
@@ -29,7 +29,7 @@ export default class PermissionGrid extends Component {
{scopes.map(scope => (
<th>
{scope.label}{' '}
{scope.onremove ? Button.component({icon: 'times', className: 'Button Button--text PermissionGrid-removeScope', onclick: scope.onremove}) : ''}
{scope.onremove ? Button.component({icon: 'fas fa-times', className: 'Button Button--text PermissionGrid-removeScope', onclick: scope.onremove}) : ''}
</th>
))}
<th>{this.scopeControlItems().toArray()}</th>
@@ -85,14 +85,21 @@ export default class PermissionGrid extends Component {
const items = new ItemList();
items.add('viewDiscussions', {
icon: 'eye',
icon: 'fas fa-eye',
label: app.translator.trans('core.admin.permissions.view_discussions_label'),
permission: 'viewDiscussions',
allowGuest: true
}, 100);
items.add('viewUserList', {
icon: 'fas fa-users',
label: app.translator.trans('core.admin.permissions.view_user_list_label'),
permission: 'viewUserList',
allowGuest: true
}, 100);
items.add('signUp', {
icon: 'user-plus',
icon: 'fas fa-user-plus',
label: app.translator.trans('core.admin.permissions.sign_up_label'),
setting: () => SettingDropdown.component({
key: 'allow_sign_up',
@@ -103,6 +110,12 @@ export default class PermissionGrid extends Component {
})
}, 90);
items.add('viewLastSeenAt', {
icon: 'far fa-clock',
label: app.translator.trans('core.admin.permissions.view_last_seen_at_label'),
permission: 'user.viewLastSeenAt',
});
return items;
}
@@ -110,13 +123,13 @@ export default class PermissionGrid extends Component {
const items = new ItemList();
items.add('start', {
icon: 'edit',
icon: 'fas fa-edit',
label: app.translator.trans('core.admin.permissions.start_discussions_label'),
permission: 'startDiscussion'
}, 100);
items.add('allowRenaming', {
icon: 'i-cursor',
icon: 'fas fa-i-cursor',
label: app.translator.trans('core.admin.permissions.allow_renaming_label'),
setting: () => {
const minutes = parseInt(app.data.settings.allow_renaming, 10);
@@ -142,13 +155,13 @@ export default class PermissionGrid extends Component {
const items = new ItemList();
items.add('reply', {
icon: 'reply',
icon: 'fas fa-reply',
label: app.translator.trans('core.admin.permissions.reply_to_discussions_label'),
permission: 'discussion.reply'
}, 100);
items.add('allowPostEditing', {
icon: 'pencil',
icon: 'fas fa-pencil-alt',
label: app.translator.trans('core.admin.permissions.allow_post_editing_label'),
setting: () => {
const minutes = parseInt(app.data.settings.allow_post_editing, 10);
@@ -174,37 +187,43 @@ export default class PermissionGrid extends Component {
const items = new ItemList();
items.add('viewIpsPosts', {
icon: 'bullseye',
icon: 'fas fa-bullseye',
label: app.translator.trans('core.admin.permissions.view_post_ips_label'),
permission: 'discussion.viewIpsPosts'
}, 110);
items.add('renameDiscussions', {
icon: 'i-cursor',
icon: 'fas fa-i-cursor',
label: app.translator.trans('core.admin.permissions.rename_discussions_label'),
permission: 'discussion.rename'
}, 100);
items.add('hideDiscussions', {
icon: 'trash-o',
icon: 'far fa-trash-alt',
label: app.translator.trans('core.admin.permissions.delete_discussions_label'),
permission: 'discussion.hide'
}, 90);
items.add('deleteDiscussions', {
icon: 'times',
icon: 'fas fa-times',
label: app.translator.trans('core.admin.permissions.delete_discussions_forever_label'),
permission: 'discussion.delete'
}, 80);
items.add('editPosts', {
icon: 'pencil',
label: app.translator.trans('core.admin.permissions.edit_and_delete_posts_label'),
icon: 'fas fa-pencil-alt',
label: app.translator.trans('core.admin.permissions.edit_posts_label'),
permission: 'discussion.editPosts'
}, 70);
items.add('hidePosts', {
icon: 'far fa-trash-alt',
label: app.translator.trans('core.admin.permissions.delete_posts_label'),
permission: 'discussion.hidePosts'
}, 60);
items.add('deletePosts', {
icon: 'times',
icon: 'fas fa-times',
label: app.translator.trans('core.admin.permissions.delete_posts_forever_label'),
permission: 'discussion.deletePosts'
}, 60);

View File

@@ -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() {
@@ -24,7 +24,7 @@ export default class PermissionsPage extends Page {
</button>
))}
<button className="Button Group Group--add" onclick={() => app.modal.show(new EditGroupModal())}>
{icon('plus', {className: 'Group-icon'})}
{icon('fas fa-plus', {className: 'Group-icon'})}
<span className="Group-name">{app.translator.trans('core.admin.permissions.new_group_button')}</span>
</button>
</div>

View File

@@ -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
@@ -42,7 +42,7 @@ export default class SessionDropdown extends Dropdown {
items.add('logOut',
Button.component({
icon: 'sign-out',
icon: 'fas fa-sign-out-alt',
children: app.translator.trans('core.admin.header.log_out_button'),
onclick: app.session.logout.bind(app.session)
}),

View File

@@ -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) {
@@ -8,7 +8,7 @@ export default class SettingDropdown extends SelectDropdown {
props.className = 'SettingDropdown';
props.buttonClassName = 'Button Button--text';
props.caretIcon = 'caret-down';
props.caretIcon = 'fas fa-caret-down';
props.defaultLabel = 'Custom';
props.children = props.options.map(({value, label}) => {
@@ -16,7 +16,7 @@ export default class SettingDropdown extends SelectDropdown {
return Button.component({
children: label,
icon: active ? 'check' : true,
icon: active ? 'fas fa-check' : true,
onclick: saveSettings.bind(this, {[props.key]: value}),
active
});

View File

@@ -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() {

View File

@@ -0,0 +1,58 @@
/*
* 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 DashboardWidget from './DashboardWidget';
import listItems from '../../common/helpers/listItems';
import ItemList from '../../common/utils/ItemList';
import Dropdown from '../../common/components/Dropdown';
import Button from '../../common/components/Button';
import LoadingModal from './LoadingModal';
export default class StatusWidget extends DashboardWidget {
className() {
return 'StatusWidget';
}
content() {
return (
<ul>{listItems(this.items().toArray())}</ul>
);
}
items() {
const items = new ItemList();
items.add('tools', (
<Dropdown
label={app.translator.trans('core.admin.dashboard.tools_button')}
icon="fas fa-cog"
buttonClassName="Button"
menuClassName="Dropdown-menu--right">
<Button onclick={this.handleClearCache.bind(this)}>
{app.translator.trans('core.admin.dashboard.clear_cache_button')}
</Button>
</Dropdown>
));
items.add('version-flarum', [<strong>Flarum</strong>, <br/>, app.forum.attribute('version')]);
items.add('version-php', [<strong>PHP</strong>, <br/>, app.data.phpVersion]);
items.add('version-mysql', [<strong>MySQL</strong>, <br/>, app.data.mysqlVersion]);
return items;
}
handleClearCache(e) {
app.modal.show(new LoadingModal());
app.request({
method: 'DELETE',
url: app.forum.attribute('apiUrl') + '/cache'
}).then(() => window.location.reload());
}
}

View File

@@ -1,4 +1,4 @@
import Button from 'flarum/components/Button';
import Button from '../../common/components/Button';
export default class UploadImageButton extends Button {
init() {

View File

@@ -0,0 +1,38 @@
/*
* 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 '../../common/Component';
export default class DashboardWidget extends Component {
view() {
return (
<div className={"DashboardWidget "+this.className()}>
{this.content()}
</div>
);
}
/**
* Get the class name to apply to the widget.
*
* @return {String}
*/
className() {
return '';
}
/**
* Get the content of the widget.
*
* @return {VirtualElement}
*/
content() {
return [];
}
}

18
js/src/admin/index.js Normal file
View File

@@ -0,0 +1,18 @@
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 };

View File

@@ -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
*/

View File

@@ -1,118 +1,181 @@
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 ModalManager from './components/ModalManager';
import AlertManager from './components/AlertManager';
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 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';
import { flattenDeep } from 'lodash-es';
/**
* 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
*/
boot(data) {
this.data = data;
forum = null;
this.translator.locale = data.locale;
/**
* 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;
data;
title = '';
titleCount = 0;
load(payload) {
this.data = payload;
this.translator.locale = payload.locale;
}
boot() {
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();
}
bootExtensions(extensions) {
Object.keys(extensions).forEach(name => {
const extension = extensions[name];
const extenders = flattenDeep(extension.extend);
for (const extender of extenders) {
extender.extend(this, { name, exports: extension });
}
});
}
mount(basePath = '') {
this.modal = m.mount(document.getElementById('modal'), <ModalManager/>);
this.alerts = m.mount(document.getElementById('alerts'), <AlertManager/>);
this.drawer = new Drawer();
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');
});
}
/**
@@ -121,10 +184,11 @@ export default class App {
* @return {Object|null}
* @public
*/
preloadedDocument() {
if (this.data.document) {
const results = this.store.pushPayload(this.data.document);
this.data.document = null;
preloadedApiDocument() {
if (this.data.apiDocument) {
const results = this.store.pushPayload(this.data.apiDocument);
this.data.apiDocument = null;
return results;
}
@@ -266,10 +330,7 @@ export default class App {
error.alert = new Alert({
type: 'error',
children,
controls: app.forum.attribute('debug') ? [
<Button className="Button Button--link" onclick={this.showDebug.bind(this, error)}>Debug</Button>
] : undefined
children
});
try {
@@ -284,16 +345,6 @@ export default class App {
return deferred.promise;
}
/**
* @param {RequestError} error
* @private
*/
showDebug(error) {
this.alerts.dismiss(this.requestErrorAlert);
this.modal.show(new RequestErrorModal({error}));
}
/**
* Construct a URL to the route with the given name.
*

View File

@@ -30,11 +30,11 @@ export default class Session {
* @return {Promise}
* @public
*/
login(identification, password, options = {}) {
login(data, options = {}) {
return app.request(Object.assign({
method: 'POST',
url: app.forum.attribute('baseUrl') + '/login',
data: {identification, password}
data
}, options));
}

View File

@@ -75,7 +75,7 @@ export default class Store {
* Make a request to the API to find record(s) of a specific type.
*
* @param {String} type The resource type.
* @param {Integer|Integer[]|Object} [id] The ID(s) of the model(s) to retreive.
* @param {Integer|Integer[]|Object} [id] The ID(s) of the model(s) to retrieve.
* Alternatively, if an object is passed, it will be handled as the
* `query` parameter.
* @param {Object} [query]

View File

@@ -1,7 +1,6 @@
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 extract from './utils/extract';
/**
* Translator with the same API as Symfony's.
@@ -23,6 +22,10 @@ export default class Translator {
this.locale = null;
}
addTranslations(translations) {
Object.assign(this.translations, translations);
}
trans(id, parameters) {
const translation = this.translations[id];

125
js/src/common/compat.js Normal file
View File

@@ -0,0 +1,125 @@
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 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/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
};

View File

@@ -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,
@@ -37,7 +37,7 @@ export default class Alert extends Component {
if (dismissible || dismissible === undefined) {
dismissControl.push(
<Button
icon="times"
icon="fas fa-times"
className="Button Button--link Button--icon Alert-dismiss"
onclick={ondismiss}/>
);

View File

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

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