1
0
mirror of https://github.com/flarum/core.git synced 2025-08-15 04:44:08 +02:00

Compare commits

..

90 Commits

Author SHA1 Message Date
KyrneDev
8a529d3753 Updates 2021-04-28 15:57:42 -07:00
KyrneDev
f900e1165f Format 2021-04-23 13:54:42 -07:00
KyrneDev
3b2d3dc8bc Registry and webpack 2021-04-23 13:52:42 -07:00
KyrneDev
a18e64c47f Merge branch 'ck/code-splitting' of https://github.com/flarum/core into ck/code-splitting 2021-04-20 17:02:50 -07:00
KyrneDev
5e7a260853 Revert dayjs change 2021-04-20 17:02:30 -07:00
luceos
3a1803ee0f Apply fixes from StyleCI
[ci skip] [skip ci]
2021-04-20 23:51:17 +00:00
KyrneDev
008206738f Code Split 2021-04-20 16:50:40 -07:00
David Wheatley
c006931798 Cache npm cache between JS build runs (#2710) 2021-04-08 20:29:37 +01:00
flarum-bot
a5ec39b5cf Bundled output for commit c75db75efe [skip ci] 2021-04-08 11:36:26 +00:00
David Wheatley
c75db75efe Bump dependencies, add missing typing libraries (#2753)
* Bump dependencies and add missing typing libraries

* Fix expose-loader breaking changes

* Expose jQuery using its own typings instead of ours

* Extend jQuery typings with our own custom $.fn helpers

* Use jQuery typings for Component's `this.$` attribute

* Format webpack config file

* Use Spin.js 3.1.0
2021-04-08 12:35:10 +01:00
David Wheatley
300dadff60 Add code scanning workflow to identify common issues (#2744)
* Add code scanning workflow to identify common issues

* Don't run CodeQL if the only changes in a push/PR are .less or .md files

* Change cron

* Change workflow name to include language

* Make indents consistent with other workflows
2021-04-08 12:15:27 +01:00
Alexander Skvortsov
94d69fe15f Introduce RequestUtil to encapsulate getting/setting actor on requests(#2449) 2021-04-07 23:33:05 -04:00
Alexander Skvortsov
da598db376 Allow configuring default enabled extensions as part of installation (#2757)
This is needed for the testing library
2021-04-07 22:47:54 -04:00
Alexander Skvortsov
d31e0573f8 Don't fail silently on cache clear (#2756) 2021-04-07 22:13:08 -04:00
Sami Mazouz
2968341f77 Fix a missed getRouteData() (#2774) 2021-04-07 20:08:21 -04:00
flarum-bot
9839370701 Bundled output for commit 40dc6d0feb [skip ci] 2021-04-07 22:26:04 +00:00
Alexander Skvortsov
40dc6d0feb Preloaded API document Improvements (#2754)
* Invalidate preloadedApiDocument if URL has changed
* Revert to using `getRouteData()[0]`
2021-04-07 23:25:01 +01:00
flarum-bot
945f6478b5 Bundled output for commit 69a10c97be [skip ci] 2021-04-07 18:31:38 +00:00
David Wheatley
69a10c97be Merge "Remove unneeded vendor prefixes" (#2766) 2021-04-07 19:30:15 +01:00
Daniël Klabbers
0074f0c984 Removes duplication of cache clearing (#2738) 2021-04-07 17:29:32 +01:00
David Wheatley
19465fb522 Fix missing vendor prefix on post scrubber; move styles to Less 2021-04-05 23:19:52 +01:00
David Wheatley
0fe7723a7f Remove unneeded vendor prefixes 2021-04-05 20:27:47 +00:00
flarum-bot
fbe2813378 Bundled output for commit 4b69a35260 [skip ci] 2021-04-05 15:28:37 +00:00
David Wheatley
4b69a35260 Replace classList with clsx library (#2760) 2021-04-05 16:27:16 +01:00
Alexander Skvortsov
5e8155e1cc Remove unnecessary and imperceptible fade (#2685)
This concern was raised in https://discuss.flarum.org/d/26422-idearequest-make-header-background-color-match-exact-value-from-config.
2021-04-04 01:49:31 +01:00
flarum-bot
0f0f2b6d4e Bundled output for commit 3dae397c65 [skip ci] 2021-04-03 02:16:32 +00:00
David Wheatley
3dae397c65 Merge "Small Admin Patches" (#2739) from flarum/ck/adminux-patch2 into master
- Fixes #2736
- Fixes #2728
2021-04-03 03:14:41 +01:00
David Wheatley
7025a7f5e0 Pin GitHub Actions at specific tags and commits (#2748)
* Pin 3rd party action

* Pin GitHub-maintained actions to tag

* Bump Bundlewatch Node.js to v14 LTS

I have no clue what my thought process was when creating this workflow
initially. Thrown this in here as it's a minor change and it's silly to
make a PR just to update this number, in my opinion.
2021-04-03 01:00:26 +01:00
flarum-bot
12f6b1b375 Bundled output for commit 2de57af7c8 [skip ci] 2021-03-30 00:20:26 +00:00
David Sevilla Martin
2de57af7c8 Move forum & admin app declarations to separate files 2021-03-29 20:19:15 -04:00
Sami Mazouz
1c4817a0b3 Eager loading extender (#2724)
* Eager loading extender
* Add tests for the eager loading extender
2021-03-25 15:36:39 +01:00
KyrneDev
0eefbf0374 Help on redraw 2021-03-24 17:30:13 -10:00
KyrneDev
90c0bc410e Null name/desc breaks search fix 2021-03-24 17:29:54 -10:00
Sami Mazouz
d642fb531c Improve ApiSerializer tests (#2733)
The ApiSerializerTest was added before the ApiController extender, so I used a workaround at the time to check for the existence of the relationships on the serializer.
2021-03-23 17:33:51 -04:00
Alexander Skvortsov
706eaeda41 Use anonymous class for FakeApp (#2725)
It's a better implementation than declaring a second class in the same file, which can confuse IDEs. Furthermore, FakeApp shouldn't be used outside this file.
2021-03-22 19:00:36 +01:00
Sami Mazouz
3cc18c1da2 Eager load ListPostsController needed relations (#2717)
* Eager load ListPostsController needed relations
* Add comment explaining the reason for eagerloading
2021-03-22 09:54:18 +01:00
Alexander Skvortsov
8dd57ffed2 Include task scheduler in core 2021-03-19 18:01:38 -04:00
Alexander Skvortsov
d29495203b Move laravel helpers back in, deprecate perpetually 2021-03-19 18:01:38 -04:00
flarum-bot
783c563305 Bundled output for commit 908d087e00 [skip ci] 2021-03-19 18:14:58 +00:00
Alexander Skvortsov
908d087e00 Remove deprecated code from beta 16 (#2705) 2021-03-19 19:13:50 +01:00
sl-kr
374189d48e Refactor AccountActivationMailer and SendConfirmationEmailController (#2493)
* Add AccountActivationMailerTrait and use in AccountActivationMailer and SendConfirmationEmailController
* Remove prefix

Co-authored-by: Alexander Skvortsov <38059171+askvortsov1@users.noreply.github.com>
2021-03-19 18:06:41 +01:00
flarum-bot
fe8dda6fd0 Bundled output for commit cd9ee48af6 [skip ci] 2021-03-18 22:04:58 +00:00
David Wheatley
cd9ee48af6 [A11Y] Add aria-label and landmark role to search input (#2669)
* Adds role="search" to Search container
* Add aria-label to search input

See this page for more info:
https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Search_role
2021-03-18 23:03:01 +01:00
flarum-bot
2e9078a7cf Bundled output for commit 0cc12aed95 [skip ci] 2021-03-18 21:39:56 +00:00
David Wheatley
0cc12aed95 [A11Y] Fix nav drawer being focusable when off-screen on small viewports (#2666)
* Fix nav drawer being focusable when off-screen on small viewports

Fixes #2565

* Implement review suggestions

* Format
2021-03-18 22:38:32 +01:00
David Wheatley
59fdd7628a Speed up JS linting (#2709)
* Install Prettier only, instead of all deps

* Allow running on workflow dispatch

Allows manually triggered CI runs by org members

* Update Node to latest LTS; update step descriptions
2021-03-18 21:14:10 +00:00
David Wheatley
298f6c39f2 Add bundlewatch to track bundle size changes in PRs (#2695)
(Below steps already performed, but kept for future reference.)

Head here to get auth ID: https://service.bundlewatch.io/setup-github
Create repo secret called `BUNDLEWATCH_GITHUB_TOKEN` with the token inside
2021-03-17 14:54:42 +00:00
Alexander Skvortsov
233b97329c Drop the generate:migration command (#2686)
Core source code should contain things necessary for core to run. Development tooling like this belongs in external packages, like the upcoming Flarum CLI.
2021-03-16 12:41:07 -04:00
flarum-bot
1b5b143930 Bundled output for commit 0d139e6133 [skip ci] 2021-03-16 14:52:59 +00:00
David Wheatley
0d139e6133 [A11Y] Add aria-label to dropdown toggles (#2668)
Implement custom accessible dropdown toggle labels for forum components

Making the a11y label more specific to the specific action it performs is critical for good UX with assistive technologies.
2021-03-16 10:50:36 -04:00
Ian Morland
0e6a60bd5b Canonical URL: use UrlGenerator in place of extracting the url from request (#2674) 2021-03-15 21:43:59 -04:00
flarum-bot
6e4c75eba6 Bundled output for commit 386f3d3db1 [skip ci] 2021-03-16 01:43:29 +00:00
David Sevilla Martín
386f3d3db1 Fix Stream function code being shown when renaming discussion (#2693) 2021-03-15 21:42:22 -04:00
Alexander Skvortsov
9fffb8ec1a L8 requires constructor arguments to PhpEngine 2021-03-15 12:48:47 -04:00
Daniel Klabbers
92e590f1ab Release v0.1.0-beta.16 constant updated 2021-03-15 16:21:21 +01:00
Daniel Klabbers
098908cb4a Release v0.1.0-beta.16 2021-03-15 16:09:23 +01:00
Sami Mazouz
901846d0cf Beta 16 Changelog (#2687)
* Beta 16 Changelog

* Review tweaks

* Consistent letter casing

* IOS -> iOS

* Removed accidentally added F

* Csrf -> CSRF

Co-authored-by: David Wheatley <hi@davwheat.dev>
2021-03-15 14:55:47 +01:00
Daniel Klabbers
5a3aefb76c npm audit fix 2021-03-15 13:25:12 +01:00
Alexander Skvortsov
cf2a636e81 Apply GetModelIsPrivate BC mode to CommentPost, not Post 2021-03-13 17:16:18 -05:00
Alexander Skvortsov
a8ba510655 Fix ModelPrivate docblocks 2021-03-13 17:15:50 -05:00
Alexander Skvortsov
9c3b6c596f Merge pull request #2684 from flarum/as/filter-mutator-consistency
Make filter mutator API consistent with search mutator API.
2021-03-13 17:01:33 -05:00
Alexander Skvortsov
2310d782a3 Fix Index content, only use search when applicable. 2021-03-12 15:30:36 -05:00
Alexander Skvortsov
e9642250ae Provide active filters to filter state 2021-03-12 15:30:14 -05:00
flarum-bot
a6dd545dbc Bundled output for commit a64c39835a [skip ci] 2021-03-12 05:35:57 +00:00
Alexander Skvortsov
a64c39835a Fix shaky composer on safari mobile
When the composer is opened while scrolled to the absolute bottom of the page (via hitting the "reply" button, `window.scrollTop` has a value of ~600px greater than it should. This doesn't seem to be the composer element's height (which appears to be 0 at the time). This incorrect scrollTop positions the composer off screen, which causes Safari to freak out and shake the element violently as it tries to scroll to the cursor (which is now off screen).

We can get around this by calculating scrollTop ourselves.

Fixes https://github.com/flarum/core/issues/2683
2021-03-12 00:23:37 -05:00
Alexander Skvortsov
db0d8e89c7 Make filter mutator API consistent with search mutator API.
This is inline with the docblock for the Filter extender, and is much more sensible.
2021-03-11 23:12:49 -05:00
flarum-bot
4e126708e9 Bundled output for commit b88a7cb33b [skip ci] 2021-03-09 03:46:55 +00:00
Alexander Skvortsov
b88a7cb33b Search: dont adjust height if not rendered 2021-03-08 22:45:39 -05:00
flarum-bot
a2f52c09fd Bundled output for commit 30017eef09 [skip ci] 2021-03-08 21:31:49 +00:00
Alexander Skvortsov
30017eef09 Send username as author filter value instead of id.
For consistency with the Discussion AuthorFilterGambit, this should be sent usernames, not numerical ids.
2021-03-08 16:29:48 -05:00
flarum-bot
d0ffa26b0b Bundled output for commit 612a57c466 [skip ci] 2021-03-08 21:25:06 +00:00
Alexander Skvortsov
612a57c466 Use new author key for filtering posts
Fixes https://github.com/flarum/core/issues/2671
2021-03-08 16:21:36 -05:00
Alexander Skvortsov
91e8b56961 Add deprecated "user" filter for posts
In the filterer refactor for ListPostsController, the filter key was changed to `author` for consistency with the AuthorFilterGambit used in discussions. This commit adds a deprecated `user` filter back in for a release to allow for a graceful transition
2021-03-08 16:20:26 -05:00
flarum-bot
ba9665e9db Bundled output for commit 8eea0985a4 [skip ci] 2021-03-07 22:37:00 +00:00
Alexander Skvortsov
8eea0985a4 Split JSDoc directives to separate lines. 2021-03-07 17:35:58 -05:00
flarum-bot
1bcb9d3ea1 Bundled output for commit 2c3e1f9923 [skip ci] 2021-03-07 21:33:50 +00:00
Alexander Skvortsov
2c3e1f9923 Use flarum/testing for test infrastructure (#2545) 2021-03-07 16:32:41 -05:00
Sami Mazouz
bc607e089e Eagerload some needed relations in ListDiscussionsController (#2639) 2021-03-07 16:32:23 -05:00
Sami Mazouz
91d5d9c176 Use absolute positioning for the Composer on Safari (#2660) 2021-03-07 16:31:46 -05:00
Alexander Skvortsov
3aa118ab94 Fix search box out of screen (#2650)
Programatically set search results max height
2021-03-07 16:31:23 -05:00
Daniël Klabbers
4b0ad6972d added optional powered-by header (#2618) 2021-03-05 10:05:13 -05:00
Daniël Klabbers
84ded0ce50 Laravel components v8 (#2576)
- update actions ci
- include json for 4 spaces tab
- provide output int for process code exit
- adhere to parent type hint of builder
- mailer instance now needs a name, multiple can be instantiated
- getOriginal now uses mutators in the model
- Temporarily loosen MailableInterface requirements. This avoids an immediate BC break for classes in extensions that implement this interface.
- Temporarily provide (and autoload) old symfony translator interface
- make queue exception handler compatible with the contract of L8
- Update phpunit schema for newer version
- Update phpunit assert calls for newer version
2021-03-05 09:43:35 -05:00
Sami Mazouz
725863a6e2 Move TextEditor styles to common (#2661)
Now that TextEditor js component is shared, it only makes sense to also 
have its styles shared
2021-03-05 08:14:19 -05:00
Alexander Skvortsov
c81f629b0b Rename app to container (#2609)
* Rename `app` helper to `resolve`, deprecate old version
* Rename $this->app to $this->container in service providers

We no longer couple Flarum\Foundation\Application to the Laravel container; instead, we use the container separately. Changing our naming to reflect that will make things clearer.
2021-03-04 22:14:48 -05:00
flarum-bot
15cbe4daaa Bundled output for commit ddac07d991 [skip ci] 2021-03-04 21:52:50 +00:00
Alexander Skvortsov
ddac07d991 Move TextEditor to common (#2649) 2021-03-04 16:51:34 -05:00
Clark Winkelmann
08ba2599d7 Refactor Access Tokens (#2651)
- Make session token-based instead of user-based
- Clear current session access tokens on logout
- Introduce increment ID so we can show tokens to moderators in the future without exposing secrets
- Switch to type classes to manage the different token types. New implementation fixes #2075
- Drop ability to customize lifetime per-token
- Add developer access keys that don't expire. These must be created from the database for now
- Add title in preparation for the developer token UI
- Add IP and user agent logging
- Delete all non-remember tokens in migration
2021-03-04 16:50:38 -05:00
Blake Payne
8eef7230e9 Updated GroupFilterGambit to prevent hidden groups being visible wher… (#2657)
Updated GroupFilterGambit to prevent hidden groups being visible where they shouldn't be and to ensure that only the selected groups are returned on a search. Fixes #2559
2021-03-04 10:08:12 -05:00
flarum-bot
a61f9e7328 Bundled output for commit a65e1de641 [skip ci] 2021-03-03 23:52:04 +00:00
daniellesniak
a65e1de641 Convert common helpers to Typescript (#2541) 2021-03-03 18:50:54 -05:00
396 changed files with 10346 additions and 6080 deletions

View File

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

View File

@@ -7,10 +7,24 @@ on:
jobs:
build:
name: JS / Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: flarum/action-build@master
- name: Check out code
uses: actions/checkout@v2
- name: Restore npm cache
uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('js/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
# Our action will install npm, cd into `./js`, run `npm run build`,
# then commit and upload any changes
- name: Build production JS
uses: flarum/action-build@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

76
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,76 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
# Run on:
# - pushes to master, or
# - PRs with a base of `master`
# - which do not **only** consist of changes to .md or .less files
on:
push:
branches: [ master ]
paths-ignore:
- '**/*.md'
- '**/*.less'
pull_request:
branches: [ master ]
paths-ignore:
- '**/*.md'
- '**/*.less'
schedule:
- cron: '0 0 * * 1,3,5'
jobs:
analyze:
name: Analyze / ${{ matrix.language }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -1,6 +1,7 @@
name: Lint
on:
workflow_dispatch:
push:
paths:
- 'js/src/**'
@@ -10,22 +11,18 @@ on:
jobs:
prettier:
name: JS / Prettier
runs-on: ubuntu-latest
name: JS / Prettier
steps:
- uses: actions/checkout@master
- name: Check out code
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v1
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: "12"
node-version: "14"
- name: Install JS dependencies
run: npm ci
working-directory: ./js
- name: Check JS code for formatting
run: node_modules/.bin/prettier --check src
- name: Check JS formatting
run: npx prettier --check src
working-directory: ./js

41
.github/workflows/pr_size_change.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Bundle size checker
on:
workflow_dispatch:
push:
paths:
- "js/**"
pull_request:
paths:
- "js/**"
jobs:
bundlewatch:
runs-on: ubuntu-latest
name: Bundlewatch
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: "14"
- name: Install JS dependencies
run: npm ci
working-directory: ./js
- name: Build production assets
run: npm run build
working-directory: ./js
- name: Check bundle size change
run: node_modules/.bin/bundlewatch --config .bundlewatch.config.json
working-directory: ./js
env:
BUNDLEWATCH_GITHUB_TOKEN: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}

View File

@@ -8,7 +8,7 @@ jobs:
strategy:
matrix:
php: ['7.2', '7.3', '7.4', '8.0']
php: [7.3, 7.4, '8.0']
service: ['mysql:5.7', mariadb]
prefix: ['', flarum_]
@@ -21,12 +21,6 @@ jobs:
prefixStr: (prefix)
exclude:
- php: 7.2
service: 'mysql:5.7'
prefix: flarum_
- php: 7.2
service: mariadb
prefix: flarum_
- php: 7.3
service: 'mysql:5.7'
prefix: flarum_
@@ -49,10 +43,11 @@ jobs:
name: 'PHP ${{ matrix.php }} / ${{ matrix.db }} ${{ matrix.prefixStr }}'
steps:
- uses: actions/checkout@master
- name: Check out code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@0b9d33cd0782337377999751fc10ea079fdd7104 # pin@v2
with:
php-version: ${{ matrix.php }}
coverage: xdebug
@@ -80,3 +75,5 @@ jobs:
- name: Run Composer tests
run: composer test
env:
COMPOSER_PROCESS_TIMEOUT: 600

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@ composer.phar
node_modules
.DS_Store
Thumbs.db
tests/.phpunit.result.cache
/tests/integration/tmp
.vagrant
.idea/*

View File

@@ -12,7 +12,3 @@ disabled:
- phpdoc_order
- phpdoc_separation
- phpdoc_types
finder:
exclude:
- "stubs"

View File

@@ -1,5 +1,96 @@
# Changelog
## [0.1.0-beta.16](https://github.com/flarum/core/compare/v0.1.0-beta.15...v0.1.0-beta.16)
### Added
- Allow event subscribers (https://github.com/flarum/core/pull/2535)
- Allow Settings extender to have a default value (https://github.com/flarum/core/pull/2495)
- Allow hooking into the sending of notifications before being send (https://github.com/flarum/core/pull/2533)
- PHP 8 support (https://github.com/flarum/core/pull/2507)
- Search extender (https://github.com/flarum/core/pull/2483)
- User badges to post preview (https://github.com/flarum/core/pull/2555)
- Optional extension dependencies allow a booting order (https://github.com/flarum/core/pull/2579)
- Auth extender (https://github.com/flarum/core/pull/2176)
- `X-Powered-By` header added to allow indexers easier data aggregation of Flarum adoption (https://github.com/flarum/core/pull/2618)
### Changed
- Run integration tests in transaction (https://github.com/flarum/core/pull/2304)
- Allow policies to return a boolean for simplified allow/deny (https://github.com/flarum/core/pull/2534)
- Converted highlight helper to typescript (https://github.com/flarum/core/pull/2532)
- Add accessibility attributes to Mark as Read button (https://github.com/flarum/core/pull/2564)
- Dismiss errors on change email modal upon a new request ([00913d5](https://github.com/flarum/core/commit/00913d5b0be2172cfce1f16aaf64a24f3d2e6d4b))
- Disabled extensions now are marked with a red circle instead of a red dot (https://github.com/flarum/core/pull/2562)
- Extension dependency errors now show the extension title instead of the ID (https://github.com/flarum/core/pull/2563)
- Change `mutate` method on ApiSerializer extender to `attributes` (https://github.com/flarum/core/pull/2578)
- Moved locale files to the core from the language pack (https://github.com/flarum/core/pull/2408)
- AdminPage extensibility and generic improvements (https://github.com/flarum/core/pull/2593)
- Remove entry of authors, link to https://flarum.org/team (https://github.com/flarum/core/pull/2625)
- Search and filtering are split (https://github.com/flarum/core/pull/2454)
- Move IP identification into a middleware (https://github.com/flarum/core/pull/2624)
- Editor Driver abstraction introduced (https://github.com/flarum/core/pull/2594)
- Allow overriding routes (https://github.com/flarum/core/pull/2577)
- Split user edit permissions into permissions for editing of user credentials, username, groups and suspending (https://github.com/flarum/core/pull/2620)
- Reduced number of admin extension categories (https://github.com/flarum/core/pull/2604)
- Move search related classes to a dedicated Query namespace (https://github.com/flarum/core/pull/2645)
- Rewrite common helpers into typescript (https://github.com/flarum/core/pull/2541)
- `TextEditor` is moved to the common namespace for use in the admin frontend (https://github.com/flarum/core/pull/2649)
- Update Laravel/Illuminate components to 8 (https://github.com/flarum/core/pull/2576)
- Eager load relations in discussion listing to improve performance (https://github.com/flarum/core/pull/2639)
- Adopt flarum/testing package (https://github.com/flarum/core/pull/2545)
- Replace `user` gambit with `author` gambit ([612a57c](https://github.com/flarum/core/commit/612a57c4664415a3ea120103483645c32acc6f12))
- Posts page of on user profile loads posts using username instead of id ([30017ee](https://github.com/flarum/core/commit/30017eef09ae9e78640c4e2cacd4909fffa8d775))
### Fixed
- Transform css breaks iOS scroll functionality (https://github.com/flarum/core/pull/2527)
- Composer header is hidden on mobile devices (https://github.com/flarum/core/pull/2279)
- Cannot delete a post or discussion of a deleted user (https://github.com/flarum/core/pull/2521)
- DiscussionListPane jumps around not keeping the scroll position (https://github.com/flarum/core/pull/2402)
- Infinite scroll on notifications dropdown broken (https://github.com/flarum/core/pull/2524)
- The show language selector switch remains toggled on ([9347b12](https://github.com/flarum/core/commit/9347b12b47bf4ab97ffb7ca92673604b237c1012))
- Model Visibility extender throws exception on extensions that aren't installed or enabled (https://github.com/flarum/core/pull/2580)
- Extensions are marked as enabled when enabling fails to unmet extension dependencies (https://github.com/flarum/core/pull/2558)
- Routes to admin extension pages without a valid ID break the admin page (https://github.com/flarum/core/pull/2584)
- Disabled fieldset use an incorrect CSS property `disallowed` (https://github.com/flarum/core/pull/2585)
- Scrolling to a post that is already loaded the Load More button shows and does not trigger (https://github.com/flarum/core/pull/2388)
- Opening discussions on some mobile devices require a double tap (https://github.com/flarum/core/pull/2607)
- iOS devices show erratic behavior in the post stream while updating (https://github.com/flarum/core/pull/2548)
- Small mobile screens partially hides the composer when the keyboard is open (https://github.com/flarum/core/pull/2631)
- Clearing cache does not clear the template cache in storage/views (https://github.com/flarum/core/pull/2648)
- Boot errors show critical information (https://github.com/flarum/core/pull/2633)
- List user endpoint discloses last online even if user choose against it (https://github.com/flarum/core/pull/2634)
- Group gambit disclosed hidden groups (https://github.com/flarum/core/pull/2657)
- Search results on small windows not fully visible (https://github.com/flarum/core/pull/2650)
- Composer goes off screen on Safari when starting to type (https://github.com/flarum/core/pull/2660)
- A search that has no results shows the search results dropdown ([b88a7cb](https://github.com/flarum/core/commit/b88a7cb33b56e318f11670e9e2d563aef94db039))
- The composer modal moves around when typing on Safari ([a64c398](https://github.com/flarum/core/commit/a64c39835aba43e831209609f4a9638ae589aa41))
### Removed
- Deprecated CSRF wildcard path match
- Deprecated policy and visibility scoping events
- Deprecated post types event
- Deprecated validation events
- Deprecated notification events
- Deprecated floodgate
- Deprecated user preferences event
- Deprecated formatting events
- Deprecated api events
- Deprecated bootstrap.php support
- PHP 7.2 support (https://github.com/flarum/core/pull/2507)
- Bidi attribute in the rendered HTML (https://github.com/flarum/core/pull/2602)
- `AccessToken::find`, use `AccessToken::findValid` instead (https://github.com/flarum/core/pull/2651)
### Deprecated
- `GetModelIsPrivate` event (https://github.com/flarum/core/pull/2587)
- `CheckingPassword` event (https://github.com/flarum/core/pull/2176)
- `event()` helper (https://github.com/flarum/core/pull/2608)
- `AccessToken::generate` argument `$lifetime` (https://github.com/flarum/core/pull/2651)
- `Rememberer::remember` argument `$token` should receive an instance of `RememberAccessToken` with `AccessToken` being deprecated (https://github.com/flarum/core/pull/2651)
- `Rememberer::rememberUser` (https://github.com/flarum/core/pull/2651)
- `SessionAuthenticator::logIn` argument `$userId`, should be replaced with `AccessToken` (https://github.com/flarum/core/pull/2651)
- `TextEditor` has been moved to `common` (https://github.com/flarum/core/pull/2649)
- `UserFilter` ([91e8b56](https://github.com/flarum/core/commit/91e8b569618957c86757ef89bac666e9102db5ae))
## [0.1.0-beta.15](https://github.com/flarum/core/compare/v0.1.0-beta.14.1...v0.1.0-beta.15)
### Added
@@ -210,7 +301,7 @@
- SES mail support (#2011)
- Backward compatibility layer for `Flarum\Mail\DriverInterface`, new methods from beta.12 are now required
- `Flarum\Util\Str` helper class
- `Flarum\Event\ConfigureMiddleware` event
- `Flarum\Event\ConfigureMiddleware` event
### Deprecated
- `Flarum\Event\AbstractConfigureRoutes` event class

View File

@@ -1,7 +1,10 @@
{
"name": "flarum/core",
"description": "Delightfully simple forum software.",
"keywords": ["forum", "discussion"],
"keywords": [
"forum",
"discussion"
],
"homepage": "https://flarum.org/",
"license": "MIT",
"authors": [
@@ -17,27 +20,29 @@
"docs": "https://flarum.org/docs/"
},
"require": {
"php": ">=7.2",
"php": ">=7.3",
"axy/sourcemap": "^0.1.4",
"components/font-awesome": "^5.14.0",
"dflydev/fig-cookies": "^3.0.0",
"doctrine/dbal": "^2.7",
"dragonmantank/cron-expression": "^3.1.0",
"franzl/whoops-middleware": "^2.0.0",
"illuminate/bus": "^6.0",
"illuminate/cache": "^6.0",
"illuminate/config": "^6.0",
"illuminate/container": "^6.0",
"illuminate/contracts": "^6.0",
"illuminate/database": "^6.0",
"illuminate/events": "^6.0",
"illuminate/filesystem": "^6.0",
"illuminate/hashing": "^6.0",
"illuminate/mail": "^6.0",
"illuminate/queue": "^6.0",
"illuminate/session": "^6.0",
"illuminate/support": "^6.0",
"illuminate/validation": "^6.0",
"illuminate/view": "^6.0",
"illuminate/bus": "^8.0",
"illuminate/cache": "^8.0",
"illuminate/config": "^8.0",
"illuminate/console": "^8.0",
"illuminate/container": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/database": "^8.0",
"illuminate/events": "^8.0",
"illuminate/filesystem": "^8.0",
"illuminate/hashing": "^8.0",
"illuminate/mail": "^8.0",
"illuminate/queue": "^8.0",
"illuminate/session": "^8.0",
"illuminate/support": "^8.0",
"illuminate/validation": "^8.0",
"illuminate/view": "^8.0",
"intervention/image": "^2.5.0",
"laminas/laminas-diactoros": "^2.4.1",
"laminas/laminas-httphandlerrunner": "^1.2.0",
@@ -54,18 +59,17 @@
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0",
"s9e/text-formatter": "^2.3.6",
"symfony/config": "^4.3.4",
"symfony/console": "^4.3.4",
"symfony/event-dispatcher": "^4.3.4",
"symfony/config": "^5.2.2",
"symfony/console": "^5.2.2",
"symfony/event-dispatcher": "^5.2.2",
"symfony/mime": "^5.2.0",
"symfony/translation": "^4.3.4",
"symfony/yaml": "^4.3.4",
"symfony/translation": "^5.1.5",
"symfony/yaml": "^5.2.2",
"tobscure/json-api": "^0.3.0",
"wikimedia/less.php": "^3.0"
},
"require-dev": {
"mockery/mockery": "^1.3.3",
"phpunit/phpunit": "^8.0"
"flarum/testing": "^0.1.0-beta.16"
},
"autoload": {
"psr-4": {

View File

@@ -0,0 +1,8 @@
{
"files": [
{
"path": "./dist/*.js"
}
],
"defaultCompression": "gzip"
}

40
js/CustomLoader.js Normal file
View File

@@ -0,0 +1,40 @@
// Hi early reviewer! I'm a temporary file and
// will be moved to the Flarum webpack config soon!
const loaderUtils = require('loader-utils');
// Custom loader logic
module.exports = function (source) {
// Get the type of the module to be exported
const location = loaderUtils.interpolateName(this, '[folder]/', {
context: this.rootContext || this.context,
});
// Get the name of module to be exported
const moduleName = loaderUtils.interpolateName(this, '[name]', {
context: this.rootContext || this.context,
});
// Don't export low level files
if (/.*\/(admin|forum)$/.test(location) || /(index|app|compat|FlarumRegistry)$/.test(moduleName)) {
return source;
}
let addition = "";
// Find the export names
const matches = [...source.matchAll(/export\s+?(?:default\s?|function|abstract\s?|class)+?\s([^(\s<;]*)/gm)];
matches.map(match => {
let name = match[1]
if (!name || name === 'interface') {
return;
}
// Add code at the end of the file to add the file to registry
addition += `\nwindow.flreg.add('${location}${name}', ${name})`
});
return source + addition;
}

View File

@@ -8,4 +8,4 @@
*/
export * from './src/common';
export * from './src/admin';
export * from './src/admin';

26
js/dist/admin.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
js/dist/admin/flarum-core.js vendored Normal file

File diff suppressed because one or more lines are too long

1
js/dist/admin/flarum-core.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
js/dist/admin/runtime.js vendored Normal file
View File

@@ -0,0 +1,2 @@
(()=>{var e,r={},o={};function t(e){var n=o[e];if(void 0!==n)return n.exports;var l=o[e]={exports:{}};return r[e].call(l.exports,l,l.exports,t),l.exports}t.m=r,e=[],t.O=(r,o,n,l)=>{if(!o){var a=1/0;for(f=0;f<e.length;f++){for(var[o,n,l]=e[f],i=!0,u=0;u<o.length;u++)(!1&l||a>=l)&&Object.keys(t.O).every((e=>t.O[e](o[u])))?o.splice(u--,1):(i=!1,l<a&&(a=l));i&&(e.splice(f--,1),r=n())}return r}l=l||0;for(var f=e.length;f>0&&e[f-1][2]>l;f--)e[f]=e[f-1];e[f]=[o,n,l]},t.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return t.d(r,{a:r}),r},t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),t.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e={93:0};t.O.j=r=>0===e[r];var r=(r,o)=>{var n,l,[a,i,u]=o,f=0;for(n in i)t.o(i,n)&&(t.m[n]=i[n]);for(u&&u(t),r&&r(o);f<a.length;f++)l=a[f],t.o(e,l)&&e[l]&&e[l][0](),e[a[f]]=0;t.O()},o=self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[];o.forEach(r.bind(null,0)),o.push=r.bind(null,o.push.bind(o))})(),t.O()})();
//# sourceMappingURL=runtime.js.map

1
js/dist/admin/runtime.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
js/dist/common/common.js vendored Normal file

File diff suppressed because one or more lines are too long

1
js/dist/common/common.js.map vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

53
js/dist/forum.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[372],{4146:(a,s,t)=>{t.r(s),t.d(s,{default:()=>n});var e=t(1788),o=t(5556),r=t(2587),i=t(1024),n=function(a){function s(){return a.apply(this,arguments)||this}(0,e.Z)(s,a);var t=s.prototype;return t.oninit=function(s){a.prototype.oninit.call(this,s),this.success=!1,this.email=(0,i.Z)(app.session.user.email()),this.password=(0,i.Z)("")},t.className=function(){return"ChangeEmailModal Modal--small"},t.title=function(){return app.translator.trans("core.forum.change_email.title")},t.content=function(){return this.success?m("div",{className:"Modal-body"},m("div",{className:"Form Form--centered"},m("p",{className:"helpText"},app.translator.trans("core.forum.change_email.confirmation_message",{email:m("strong",null,this.email())})),m("div",{className:"Form-group"},m(r.Z,{className:"Button Button--primary Button--block",onclick:this.hide.bind(this)},app.translator.trans("core.forum.change_email.dismiss_button"))))):m("div",{className:"Modal-body"},m("div",{className:"Form Form--centered"},m("div",{className:"Form-group"},m("input",{type:"email",name:"email",className:"FormControl",placeholder:app.session.user.email(),bidi:this.email,disabled:this.loading})),m("div",{className:"Form-group"},m("input",{type:"password",name:"password",className:"FormControl",placeholder:app.translator.trans("core.forum.change_email.confirm_password_placeholder"),bidi:this.password,disabled:this.loading})),m("div",{className:"Form-group"},r.Z.component({className:"Button Button--primary Button--block",type:"submit",loading:this.loading},app.translator.trans("core.forum.change_email.submit_button")))))},t.onsubmit=function(a){var s=this;a.preventDefault(),this.email()!==app.session.user.email()?(this.loading=!0,this.alertAttrs=null,app.session.user.save({email:this.email()},{errorHandler:this.onerror.bind(this),meta:{password:this.password()}}).then((function(){s.success=!0})).catch((function(){})).then(this.loaded.bind(this))):this.hide()},t.onerror=function(s){401===s.status&&(s.alert.content=app.translator.trans("core.forum.change_email.incorrect_password_message")),a.prototype.onerror.call(this,s)},s}(o.Z);window.flreg.add("components/ChangeEmailModal",n)}}]);
//# sourceMappingURL=ChangeEmailModal.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[503],{22:(t,a,e)=>{e.r(a),e.d(a,{default:()=>s});var o=e(1788),r=e(5556),n=e(2587),s=function(t){function a(){return t.apply(this,arguments)||this}(0,o.Z)(a,t);var e=a.prototype;return e.className=function(){return"ChangePasswordModal Modal--small"},e.title=function(){return app.translator.trans("core.forum.change_password.title")},e.content=function(){return m("div",{className:"Modal-body"},m("div",{className:"Form Form--centered"},m("p",{className:"helpText"},app.translator.trans("core.forum.change_password.text")),m("div",{className:"Form-group"},n.Z.component({className:"Button Button--primary Button--block",type:"submit",loading:this.loading},app.translator.trans("core.forum.change_password.send_button")))))},e.onsubmit=function(t){t.preventDefault(),this.loading=!0,app.request({method:"POST",url:app.forum.attribute("apiUrl")+"/forgot",body:{email:app.session.user.email()}}).then(this.hide.bind(this),this.loaded.bind(this))},a}(r.Z);window.flreg.add("components/ChangePasswordModal",s)}}]);
//# sourceMappingURL=ChangePasswordModal.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack://@flarum/core/./src/forum/components/ChangePasswordModal.js"],"names":["ChangePasswordModal","className","title","app","translator","trans","content","Button","type","loading","this","onsubmit","e","preventDefault","request","method","url","forum","attribute","body","email","session","user","then","hide","bind","loaded","Modal","window","flreg","add"],"mappings":"4JAOqBA,E,sGACnBC,UAAA,WACE,MAAO,oC,EAGTC,MAAA,WACE,OAAOC,IAAIC,WAAWC,MAAM,qC,EAG9BC,QAAA,WACE,OACE,SAAKL,UAAU,cACb,SAAKA,UAAU,uBACb,OAAGA,UAAU,YAAYE,IAAIC,WAAWC,MAAM,oCAC9C,SAAKJ,UAAU,cACZM,cACC,CACEN,UAAW,uCACXO,KAAM,SACNC,QAASC,KAAKD,SAEhBN,IAAIC,WAAWC,MAAM,+C,EAQjCM,SAAA,SAASC,GACPA,EAAEC,iBAEFH,KAAKD,SAAU,EAEfN,IACGW,QAAQ,CACPC,OAAQ,OACRC,IAAKb,IAAIc,MAAMC,UAAU,UAAY,UACrCC,KAAM,CAAEC,MAAOjB,IAAIkB,QAAQC,KAAKF,WAEjCG,KAAKb,KAAKc,KAAKC,KAAKf,MAAOA,KAAKgB,OAAOD,KAAKf,Q,GAxCFiB,KA4CjDC,OAAOC,MAAMC,IAAI,iCAAkC9B","file":"forum/components/ChangePasswordModal.js","sourcesContent":["import Modal from '../../common/components/Modal';\nimport Button from '../../common/components/Button';\n\n/**\n * The `ChangePasswordModal` component shows a modal dialog which allows the\n * user to send themself a password reset email.\n */\nexport default class ChangePasswordModal extends Modal {\n className() {\n return 'ChangePasswordModal Modal--small';\n }\n\n title() {\n return app.translator.trans('core.forum.change_password.title');\n }\n\n content() {\n return (\n <div className=\"Modal-body\">\n <div className=\"Form Form--centered\">\n <p className=\"helpText\">{app.translator.trans('core.forum.change_password.text')}</p>\n <div className=\"Form-group\">\n {Button.component(\n {\n className: 'Button Button--primary Button--block',\n type: 'submit',\n loading: this.loading,\n },\n app.translator.trans('core.forum.change_password.send_button')\n )}\n </div>\n </div>\n </div>\n );\n }\n\n onsubmit(e) {\n e.preventDefault();\n\n this.loading = true;\n\n app\n .request({\n method: 'POST',\n url: app.forum.attribute('apiUrl') + '/forgot',\n body: { email: app.session.user.email() },\n })\n .then(this.hide.bind(this), this.loaded.bind(this));\n }\n}\n\nwindow.flreg.add('components/ChangePasswordModal', ChangePasswordModal)"],"sourceRoot":""}

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[437],{3406:(t,s,o)=>{o.r(s),o.d(s,{default:()=>a});var e=o(1788),i=o(4810),r=o(5731),n=o(1024),a=function(t){function s(){return t.apply(this,arguments)||this}(0,e.Z)(s,t),s.initAttrs=function(s){t.initAttrs.call(this,s),s.placeholder=s.placeholder||(0,r.Z)(app.translator.trans("core.forum.composer_discussion.body_placeholder")),s.submitLabel=s.submitLabel||app.translator.trans("core.forum.composer_discussion.submit_button"),s.confirmExit=s.confirmExit||(0,r.Z)(app.translator.trans("core.forum.composer_discussion.discard_confirmation")),s.titlePlaceholder=s.titlePlaceholder||(0,r.Z)(app.translator.trans("core.forum.composer_discussion.title_placeholder")),s.className="ComposerBody--discussion"};var o=s.prototype;return o.oninit=function(s){t.prototype.oninit.call(this,s),this.composer.fields.title=this.composer.fields.title||(0,n.Z)(""),this.title=this.composer.fields.title},o.headerItems=function(){var s=t.prototype.headerItems.call(this);return s.add("title",m("h3",null,app.translator.trans("core.forum.composer_discussion.title")),100),s.add("discussionTitle",m("h3",null,m("input",{className:"FormControl",bidi:this.title,placeholder:this.attrs.titlePlaceholder,disabled:!!this.attrs.disabled,onkeydown:this.onkeydown.bind(this)}))),s},o.onkeydown=function(t){13===t.which&&(t.preventDefault(),this.composer.editor.moveCursorTo(0)),t.redraw=!1},o.hasChanges=function(){return this.title()||this.composer.fields.content()},o.data=function(){return{title:this.title(),content:this.composer.fields.content()}},o.onsubmit=function(){var t=this;this.loading=!0;var s=this.data();app.store.createRecord("discussions").save(s).then((function(s){t.composer.hide(),app.discussions.refresh({deferClear:!0}),m.route.set(app.route.discussion(s))}),this.loaded.bind(this))},s}(i.Z);window.flreg.add("components/DiscussionComposer",a)}}]);
//# sourceMappingURL=DiscussionComposer.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[799],{5813:(t,e,s)=>{s.a(t,(async t=>{s.r(e),s.d(e,{default:()=>r});var n=s(1788),a=s(486),o=s(2060),r=function(t){function e(){return t.apply(this,arguments)||this}(0,n.Z)(e,t);var s=e.prototype;return s.oninit=function(e){t.prototype.oninit.call(this,e),this.loadUser(m.route.param("username"))},s.show=function(e){t.prototype.show.call(this,e),this.state=new o.Z({q:"author:"+e.username(),sort:"newest"}),this.state.refresh()},s.content=function(){return m("div",{className:"DiscussionsUserPage"},a.Z.component({state:this.state}))},e}((await s.e(251).then(s.bind(s,6068))).default);window.flreg.add("components/DiscussionsUserPage",r),t()}),1)}}]);
//# sourceMappingURL=DiscussionsUserPage.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack://@flarum/core/./src/forum/components/DiscussionsUserPage.js"],"names":["DiscussionsUserPage","oninit","vnode","this","loadUser","m","route","param","show","user","state","DiscussionListState","q","username","sort","refresh","content","className","DiscussionList","window","flreg","add"],"mappings":"8KASqBA,E,sGACnBC,OAAA,SAAOC,GACL,YAAMD,OAAN,UAAaC,GAEbC,KAAKC,SAASC,EAAEC,MAAMC,MAAM,c,EAG9BC,KAAA,SAAKC,GACH,YAAMD,KAAN,UAAWC,GAEXN,KAAKO,MAAQ,IAAIC,IAAoB,CACnCC,EAAG,UAAYH,EAAKI,WACpBC,KAAM,WAGRX,KAAKO,MAAMK,W,EAGbC,QAAA,WACE,OAAO,SAAKC,UAAU,uBAAuBC,cAAyB,CAAER,MAAOP,KAAKO,U,UAzBhE,+BAAP,SA6BjBS,OAAOC,MAAMC,IAAI,iCAAkCrB,G","file":"forum/components/DiscussionsUserPage.js","sourcesContent":["import DiscussionList from './DiscussionList';\nimport DiscussionListState from '../states/DiscussionListState';\n\nconst UserPage = (await import(/* webpackChunkName: \"forum/components/UserPage\" */ './UserPage')).default;\n\n/**\n * The `DiscussionsUserPage` component shows a discussion list inside of a user\n * page.\n */\nexport default class DiscussionsUserPage extends UserPage {\n oninit(vnode) {\n super.oninit(vnode);\n\n this.loadUser(m.route.param('username'));\n }\n\n show(user) {\n super.show(user);\n\n this.state = new DiscussionListState({\n q: 'author:' + user.username(),\n sort: 'newest',\n });\n\n this.state.refresh();\n }\n\n content() {\n return <div className=\"DiscussionsUserPage\">{DiscussionList.component({ state: this.state })}</div>;\n }\n}\n\nwindow.flreg.add('components/DiscussionsUserPage', DiscussionsUserPage)"],"sourceRoot":""}

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[293],{763:(t,o,s)=>{s.r(o),s.d(o,{default:()=>u});var e=s(1788),r=s(4810),n=s(2587),i=s(8046),a=s(9100);function p(t){app.composer.isFullScreen()&&(app.composer.minimize(),t.stopPropagation())}var u=function(t){function o(){return t.apply(this,arguments)||this}(0,e.Z)(o,t),o.initAttrs=function(o){t.initAttrs.call(this,o),o.submitLabel=o.submitLabel||app.translator.trans("core.forum.composer_edit.submit_button"),o.confirmExit=o.confirmExit||app.translator.trans("core.forum.composer_edit.discard_confirmation"),o.originalContent=o.originalContent||o.post.content(),o.user=o.user||o.post.user(),o.post.editedContent=o.originalContent};var s=o.prototype;return s.headerItems=function(){var o=t.prototype.headerItems.call(this),s=this.attrs.post;return o.add("title",m("h3",null,(0,a.Z)("fas fa-pencil-alt")," ",m(i.Z,{href:app.route.discussion(s.discussion(),s.number()),onclick:p},app.translator.trans("core.forum.composer_edit.post_link",{number:s.number(),discussion:s.discussion().title()})))),o},s.jumpToPreview=function(t){p(t),m.route.set(app.route.post(this.attrs.post))},s.data=function(){return{content:this.composer.fields.content()}},s.onsubmit=function(){var t=this,o=this.attrs.post.discussion();this.loading=!0;var s=this.data();this.attrs.post.save(s).then((function(s){if(app.viewingDiscussion(o))app.current.get("stream").goToNumber(s.number());else{var e,r=n.Z.component({className:"Button Button--link",onclick:function(){m.route.set(app.route.post(s)),app.alerts.dismiss(e)}},app.translator.trans("core.forum.composer_edit.view_button"));e=app.alerts.show({type:"success",controls:[r]},app.translator.trans("core.forum.composer_edit.edited_message"))}t.composer.hide()}),this.loaded.bind(this))},o}(r.Z);window.flreg.add("components/EditPostComposer",u)}}]);
//# sourceMappingURL=EditPostComposer.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[352],{3089:(s,r,t)=>{t.r(r),t.d(r,{default:()=>p});var e=t(1788),a=t(5556),i=t(2587),n=t(7880),o=t(4032),d=t(5731),u=t(4594),l=t(1024),p=function(s){function r(){return s.apply(this,arguments)||this}(0,e.Z)(r,s);var t=r.prototype;return t.oninit=function(r){var t=this;s.prototype.oninit.call(this,r);var e=this.attrs.user;this.username=(0,l.Z)(e.username()||""),this.email=(0,l.Z)(e.email()||""),this.isEmailConfirmed=(0,l.Z)(e.isEmailConfirmed()||!1),this.setPassword=(0,l.Z)(!1),this.password=(0,l.Z)(e.password()||""),this.groups={},app.store.all("groups").filter((function(s){return-1===[o.Z.GUEST_ID,o.Z.MEMBER_ID].indexOf(s.id())})).forEach((function(s){return t.groups[s.id()]=(0,l.Z)(-1!==e.groups().indexOf(s))}))},t.className=function(){return"EditUserModal Modal--small"},t.title=function(){return app.translator.trans("core.forum.edit_user.title")},t.content=function(){var s=this.fields().toArray();return m("div",{className:"Modal-body"},s.length>1?m("div",{className:"Form"},this.fields().toArray()):app.translator.trans("core.forum.edit_user.nothing_available"))},t.fields=function(){var s=this,r=new u.Z;return app.session.user.canEditCredentials()&&(r.add("username",m("div",{className:"Form-group"},m("label",null,app.translator.trans("core.forum.edit_user.username_heading")),m("input",{className:"FormControl",placeholder:(0,d.Z)(app.translator.trans("core.forum.edit_user.username_label")),bidi:this.username,disabled:this.nonAdminEditingAdmin()})),40),app.session.user!==this.attrs.user&&(r.add("email",m("div",{className:"Form-group"},m("label",null,app.translator.trans("core.forum.edit_user.email_heading")),m("div",null,m("input",{className:"FormControl",placeholder:(0,d.Z)(app.translator.trans("core.forum.edit_user.email_label")),bidi:this.email,disabled:this.nonAdminEditingAdmin()})),!this.isEmailConfirmed()&&this.userIsAdmin(app.session.user)?m("div",null,i.Z.component({className:"Button Button--block",loading:this.loading,onclick:this.activate.bind(this)},app.translator.trans("core.forum.edit_user.activate_button"))):""),30),r.add("password",m("div",{className:"Form-group"},m("label",null,app.translator.trans("core.forum.edit_user.password_heading")),m("div",null,m("label",{className:"checkbox"},m("input",{type:"checkbox",onchange:function(r){s.setPassword(r.target.checked),m.redraw.sync(),r.target.checked&&s.$("[name=password]").select(),r.redraw=!1},disabled:this.nonAdminEditingAdmin()}),app.translator.trans("core.forum.edit_user.set_password_label")),this.setPassword()?m("input",{className:"FormControl",type:"password",name:"password",placeholder:(0,d.Z)(app.translator.trans("core.forum.edit_user.password_label")),bidi:this.password,disabled:this.nonAdminEditingAdmin()}):"")),20))),app.session.user.canEditGroups()&&r.add("groups",m("div",{className:"Form-group EditUserModal-groups"},m("label",null,app.translator.trans("core.forum.edit_user.groups_heading")),m("div",null,Object.keys(this.groups).map((function(s){return app.store.getById("groups",s)})).map((function(r){return m("label",{className:"checkbox"},m("input",{type:"checkbox",bidi:s.groups[r.id()],disabled:r.id()===o.Z.ADMINISTRATOR_ID&&(s.attrs.user===app.session.user||!s.userIsAdmin(app.session.user))}),n.Z.component({group:r,label:""})," ",r.nameSingular())})))),10),r.add("submit",m("div",{className:"Form-group"},i.Z.component({className:"Button Button--primary",type:"submit",loading:this.loading},app.translator.trans("core.forum.edit_user.submit_button"))),-10),r},t.activate=function(){var s=this;this.loading=!0;var r={username:this.username(),isEmailConfirmed:!0};this.attrs.user.save(r,{errorHandler:this.onerror.bind(this)}).then((function(){s.isEmailConfirmed(!0),s.loading=!1,m.redraw()})).catch((function(){s.loading=!1,m.redraw()}))},t.data=function(){var s=this,r={relationships:{}};return this.attrs.user.canEditCredentials()&&!this.nonAdminEditingAdmin()&&(r.username=this.username(),app.session.user!==this.attrs.user&&(r.email=this.email()),this.setPassword()&&(r.password=this.password())),this.attrs.user.canEditGroups()&&(r.relationships.groups=Object.keys(this.groups).filter((function(r){return s.groups[r]()})).map((function(s){return app.store.getById("groups",s)}))),r},t.onsubmit=function(s){var r=this;s.preventDefault(),this.loading=!0,this.attrs.user.save(this.data(),{errorHandler:this.onerror.bind(this)}).then(this.hide.bind(this)).catch((function(){r.loading=!1,m.redraw()}))},t.nonAdminEditingAdmin=function(){return this.userIsAdmin(this.attrs.user)&&!this.userIsAdmin(app.session.user)},t.userIsAdmin=function(s){return s.groups().some((function(s){return s.id()===o.Z.ADMINISTRATOR_ID}))},r}(a.Z);window.flreg.add("components/EditUserModal",p)}}]);
//# sourceMappingURL=EditUserModal.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[502],{5833:(t,o,r)=>{r.r(o),r.d(o,{default:()=>l});var a=r(1788),s=r(5556),e=r(2587),n=r(5731),i=r(1024),l=function(t){function o(){return t.apply(this,arguments)||this}(0,a.Z)(o,t);var r=o.prototype;return r.oninit=function(o){t.prototype.oninit.call(this,o),this.email=(0,i.Z)(this.attrs.email||""),this.success=!1},r.className=function(){return"ForgotPasswordModal Modal--small"},r.title=function(){return app.translator.trans("core.forum.forgot_password.title")},r.content=function(){return this.success?m("div",{className:"Modal-body"},m("div",{className:"Form Form--centered"},m("p",{className:"helpText"},app.translator.trans("core.forum.forgot_password.email_sent_message")),m("div",{className:"Form-group"},m(e.Z,{className:"Button Button--primary Button--block",onclick:this.hide.bind(this)},app.translator.trans("core.forum.forgot_password.dismiss_button"))))):m("div",{className:"Modal-body"},m("div",{className:"Form Form--centered"},m("p",{className:"helpText"},app.translator.trans("core.forum.forgot_password.text")),m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"email",type:"email",placeholder:(0,n.Z)(app.translator.trans("core.forum.forgot_password.email_placeholder")),bidi:this.email,disabled:this.loading})),m("div",{className:"Form-group"},e.Z.component({className:"Button Button--primary Button--block",type:"submit",loading:this.loading},app.translator.trans("core.forum.forgot_password.submit_button")))))},r.onsubmit=function(t){var o=this;t.preventDefault(),this.loading=!0,app.request({method:"POST",url:app.forum.attribute("apiUrl")+"/forgot",body:{email:this.email()},errorHandler:this.onerror.bind(this)}).then((function(){o.success=!0,o.alert=null})).catch((function(){})).then(this.loaded.bind(this))},r.onerror=function(o){404===o.status&&(o.alert.content=app.translator.trans("core.forum.forgot_password.not_found_message")),t.prototype.onerror.call(this,o)},o}(s.Z);window.flreg.add("components/ForgotPasswordModal",l)}}]);
//# sourceMappingURL=ForgotPasswordModal.js.map

File diff suppressed because one or more lines are too long

2
js/dist/forum/components/IndexPage.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[460],{7527:(t,o,i)=>{i.d(o,{Z:()=>e});var n=i(1788),r=i(8931),a=i(4594),e=function(t){function o(){return t.apply(this,arguments)||this}(0,n.Z)(o,t);var i=o.prototype;return i.view=function(){return m("div",{className:"LogInButtons"},this.items().toArray())},i.items=function(){return new a.Z},o}(r.Z);window.flreg.add("components/LogInButtons",e)},1498:(t,o,i)=>{i.r(o),i.d(o,{default:()=>c});var n=i(1788),r=i(5556),a=i(2587),e=i(7527),s=i(5731),l=i(4594),d=i(1024),c=function(t){function o(){return t.apply(this,arguments)||this}(0,n.Z)(o,t);var r=o.prototype;return r.oninit=function(o){t.prototype.oninit.call(this,o),this.identification=(0,d.Z)(this.attrs.identification||""),this.password=(0,d.Z)(this.attrs.password||""),this.remember=(0,d.Z)(!!this.attrs.remember)},r.className=function(){return"LogInModal Modal--small"},r.title=function(){return app.translator.trans("core.forum.log_in.title")},r.content=function(){return[m("div",{className:"Modal-body"},this.body()),m("div",{className:"Modal-footer"},this.footer())]},r.body=function(){return[m(e.Z,null),m("div",{className:"Form Form--centered"},this.fields().toArray())]},r.fields=function(){var t=new l.Z;return t.add("identification",m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"identification",type:"text",placeholder:(0,s.Z)(app.translator.trans("core.forum.log_in.username_or_email_placeholder")),bidi:this.identification,disabled:this.loading})),30),t.add("password",m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"password",type:"password",placeholder:(0,s.Z)(app.translator.trans("core.forum.log_in.password_placeholder")),bidi:this.password,disabled:this.loading})),20),t.add("remember",m("div",{className:"Form-group"},m("div",null,m("label",{className:"checkbox"},m("input",{type:"checkbox",bidi:this.remember,disabled:this.loading}),app.translator.trans("core.forum.log_in.remember_me_label")))),10),t.add("submit",m("div",{className:"Form-group"},a.Z.component({className:"Button Button--primary Button--block",type:"submit",loading:this.loading},app.translator.trans("core.forum.log_in.submit_button"))),-10),t},r.footer=function(){return[m("p",{className:"LogInModal-forgotPassword"},m("a",{onclick:this.forgotPassword.bind(this)},app.translator.trans("core.forum.log_in.forgot_password_link"))),app.forum.attribute("allowSignUp")?m("p",{className:"LogInModal-signUp"},app.translator.trans("core.forum.log_in.sign_up_text",{a:m("a",{onclick:this.signUp.bind(this)})})):""]},r.forgotPassword=function(){var t=this.identification(),o=-1!==t.indexOf("@")?{email:t}:void 0;app.modal.show((function(){return i.e(502).then(i.bind(i,5833))}),o)},r.signUp=function(){var t={password:this.password()},o=this.identification();t[-1!==o.indexOf("@")?"email":"username"]=o,app.modal.show((function(){return i.e(395).then(i.bind(i,3235))}),t)},r.onready=function(){this.$("[name="+(this.identification()?"password":"identification")+"]").select()},r.onsubmit=function(t){t.preventDefault(),this.loading=!0;var o=this.identification(),i=this.password(),n=this.remember();app.session.login({identification:o,password:i,remember:n},{errorHandler:this.onerror.bind(this)}).then((function(){return window.location.reload()}),this.loaded.bind(this))},r.onerror=function(o){401===o.status&&(o.alert.content=app.translator.trans("core.forum.log_in.invalid_login_message")),t.prototype.onerror.call(this,o)},o}(r.Z);window.flreg.add("components/LogInModal",c)}}]);
//# sourceMappingURL=LogInModal.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[77],{3490:(t,i,n)=>{n.r(i),n.d(i,{default:()=>N});var o=n(1788),a=n(8931),s=n(7473),e=n(2587),c=n(8046),r=n(8726),l=n(8197),u=n(9908),f=n(9100),p=n(6961),d=function(t){function i(){return t.apply(this,arguments)||this}(0,o.Z)(i,t);var n=i.prototype;return n.view=function(){var t=this,i=this.attrs.notification,n=this.href();return m(c.Z,{className:"Notification Notification--"+i.contentType()+" "+(i.isRead()?"":"unread"),href:n,external:n.includes("://"),onclick:this.markAsRead.bind(this)},!i.isRead()&&e.Z.component({className:"Notification-action Button Button--icon Button--link",icon:"fas fa-check",title:app.translator.trans("core.forum.notifications.mark_as_read_tooltip"),onclick:function(i){i.preventDefault(),i.stopPropagation(),t.markAsRead()}}),(0,u.Z)(i.fromUser()),(0,f.Z)(this.icon(),{className:"Notification-icon"}),m("span",{className:"Notification-content"},this.content()),(0,p.Z)(i.createdAt()),m("div",{className:"Notification-excerpt"},this.excerpt()))},n.icon=function(){},n.href=function(){},n.content=function(){},n.excerpt=function(){},n.markAsRead=function(){this.attrs.notification.isRead()||(app.session.user.pushAttributes({unreadNotificationCount:app.session.user.unreadNotificationCount()-1}),this.attrs.notification.save({isRead:!0}))},i}(a.Z);window.flreg.add("components/Notification",d);var h=function(t){function i(){return t.apply(this,arguments)||this}(0,o.Z)(i,t);var n=i.prototype;return n.icon=function(){return"fas fa-pencil-alt"},n.href=function(){var t=this.attrs.notification;return app.route.discussion(t.subject(),t.content().postNumber)},n.content=function(){return app.translator.trans("core.forum.notifications.discussion_renamed_text",{user:this.attrs.notification.fromUser()})},i}(d);window.flreg.add("components/DiscussionRenamedNotification",h);var N=function(t){function i(){return t.apply(this,arguments)||this}(0,o.Z)(i,t);var n=i.prototype;return n.view=function(){var t=this,i=this.attrs.state,n=i.getNotificationPages();return m("div",{className:"NotificationList"},m("div",{className:"NotificationList-header"},m("div",{className:"App-primaryControl"},e.Z.component({className:"Button Button--icon Button--link",icon:"fas fa-check",title:app.translator.trans("core.forum.notifications.mark_all_as_read_tooltip"),onclick:i.markAllAsRead.bind(i)})),m("h4",{className:"App-titleControl App-titleControl--text"},app.translator.trans("core.forum.notifications.title"))),m("div",{className:"NotificationList-content"},n.length?n.map((function(i){var n=[],o={};return i.forEach((function(t){var i=t.subject();if(void 0!==i){var a=!1;i instanceof l.Z?a=i:i&&i.discussion&&(a=i.discussion());var s=a?a.id():0;o[s]=o[s]||{discussion:a,notifications:[]},o[s].notifications.push(t),-1===n.indexOf(o[s])&&n.push(o[s])}})),n.map((function(i){var n=i.discussion&&i.discussion.badges().toArray();return m("div",{className:"NotificationGroup"},i.discussion?m(c.Z,{className:"NotificationGroup-header",href:app.route.discussion(i.discussion)},n&&n.length?m("ul",{className:"NotificationGroup-badges badges"},(0,s.Z)(n)):"",i.discussion.title()):m("div",{className:"NotificationGroup-header"},app.forum.attribute("title")),m("ul",{className:"NotificationGroup-content"},i.notifications.map((function(i){var n=t.notificationComponents()[i.contentType()];return n?m("li",null,n.component({notification:i})):""}))))}))})):"",i.isLoading()?m(r.Z,{className:"LoadingIndicator--block"}):n.length?"":m("div",{className:"NotificationList-empty"},app.translator.trans("core.forum.notifications.empty_text"))))},n.notificationComponents=function(){return{discussionRenamed:h}},n.oncreate=function(i){t.prototype.oncreate.call(this,i),this.$notifications=this.$(".NotificationList-content"),this.$scrollParent=this.inPanel()?this.$notifications:$(window),this.boundScrollHandler=this.scrollHandler.bind(this),this.$scrollParent.on("scroll",this.boundScrollHandler)},n.onremove=function(){this.$scrollParent.off("scroll",this.boundScrollHandler)},n.scrollHandler=function(){var t=this.attrs.state,i=this.inPanel()?this.$scrollParent[0]:document.documentElement,n=Math.abs(i.scrollHeight-i.scrollTop-i.clientHeight)<=1;t.hasMoreResults()&&!t.isLoading()&&n&&t.loadMore()},n.inPanel=function(){return"auto"===this.$notifications.css("overflow")},i}(a.Z);window.flreg.add("components/NotificationList",N)}}]);
//# sourceMappingURL=NotificationList.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[765],{9440:(t,n,o)=>{o.r(n),o.d(n,{default:()=>s});var a=o(1788),e=o(9657),i=o(9100),s=function(t){function n(){return t.apply(this,arguments)||this}(0,a.Z)(n,t),n.initAttrs=function(n){n.className=n.className||"NotificationsDropdown",n.buttonClassName=n.buttonClassName||"Button Button--flat",n.menuClassName=n.menuClassName||"Dropdown-menu--right",n.label=n.label||app.translator.trans("core.forum.notifications.tooltip"),n.icon=n.icon||"fas fa-bell",n.accessibleToggleLabel=n.accessibleToggleLabel||app.translator.trans("core.forum.notifications.toggle_dropdown_accessible_label"),t.initAttrs.call(this,n)};var e=n.prototype;return e.getButton=function(){var n=this.getNewCount(),o=t.prototype.getButton.call(this);return o.attrs.title=this.attrs.label,o.attrs.className+=n?" new":"",o.attrs.onclick=this.onclick.bind(this),o},e.getButtonContent=function(){var t=this.getUnreadCount();return[(0,i.Z)(this.attrs.icon,{className:"Button-icon"}),t?m("span",{className:"NotificationsDropdown-unread"},t):"",m("span",{className:"Button-label"},this.attrs.label)]},e.getMenu=function(){var t=this.NotificationList;return m("div",{className:"Dropdown-menu "+this.attrs.menuClassName,onclick:this.menuClick.bind(this)},this.showing&&t?m(t,{state:this.attrs.state}):"")},e.onclick=function(){var t=this;o.e(77).then(o.bind(o,3490)).then((function(n){t.NotificationList=n.default,m.redraw()})),app.drawer.isOpen()?this.goToRoute():this.attrs.state.load()},e.goToRoute=function(){m.route.set(app.route("notifications"))},e.getUnreadCount=function(){return app.session.user.unreadNotificationCount()},e.getNewCount=function(){return app.session.user.newNotificationCount()},e.menuClick=function(t){(t.shiftKey||t.metaKey||t.ctrlKey||2===t.which)&&t.stopPropagation()},n}(e.Z);window.flreg.add("components/NotificationsDropdown",s)}}]);
//# sourceMappingURL=NotificationsDropdown.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack://@flarum/core/./src/forum/components/NotificationsDropdown.js"],"names":["NotificationsDropdown","initAttrs","attrs","className","buttonClassName","menuClassName","label","app","translator","trans","icon","accessibleToggleLabel","getButton","newNotifications","this","getNewCount","vdom","title","onclick","bind","getButtonContent","unread","getUnreadCount","getMenu","NotificationList","menuClick","showing","state","then","m","redraw","drawer","isOpen","goToRoute","load","route","set","session","user","unreadNotificationCount","newNotificationCount","e","shiftKey","metaKey","ctrlKey","which","stopPropagation","Dropdown","window","flreg","add"],"mappings":"8JAGqBA,E,6EACZC,UAAP,SAAiBC,GACfA,EAAMC,UAAYD,EAAMC,WAAa,wBACrCD,EAAME,gBAAkBF,EAAME,iBAAmB,sBACjDF,EAAMG,cAAgBH,EAAMG,eAAiB,uBAC7CH,EAAMI,MAAQJ,EAAMI,OAASC,IAAIC,WAAWC,MAAM,oCAClDP,EAAMQ,KAAOR,EAAMQ,MAAQ,cAE3BR,EAAMS,sBAAwBT,EAAMS,uBAAyBJ,IAAIC,WAAWC,MAAM,6DAElF,EAAMR,UAAN,UAAgBC,I,2BAGlBU,UAAA,WACE,IAAMC,EAAmBC,KAAKC,cACxBC,EAAO,EAAH,UAASJ,UAAT,WAOV,OALAI,EAAKd,MAAMe,MAAQH,KAAKZ,MAAMI,MAE9BU,EAAKd,MAAMC,WAAaU,EAAmB,OAAS,GACpDG,EAAKd,MAAMgB,QAAUJ,KAAKI,QAAQC,KAAKL,MAEhCE,G,EAGTI,iBAAA,WACE,IAAMC,EAASP,KAAKQ,iBAEpB,MAAO,EACLZ,OAAKI,KAAKZ,MAAMQ,KAAM,CAAEP,UAAW,gBACnCkB,EAAS,UAAMlB,UAAU,gCAAgCkB,GAAiB,GAC1E,UAAMlB,UAAU,gBAAgBW,KAAKZ,MAAMI,S,EAI/CiB,QAAA,WACE,IAAMC,EAAmBV,KAAKU,iBAE9B,OACE,SAAKrB,UAAW,iBAAmBW,KAAKZ,MAAMG,cAAea,QAASJ,KAAKW,UAAUN,KAAKL,OACvFA,KAAKY,SAAWF,EAAmB,EAACA,EAAD,CAAkBG,MAAOb,KAAKZ,MAAMyB,QAAY,K,EAK1FT,QAAA,WAAU,WACR,6BAAyFU,MAAK,SAACJ,GAC7F,EAAKA,iBAAmBA,EAAgB,QACxCK,EAAEC,YAGAvB,IAAIwB,OAAOC,SACblB,KAAKmB,YAELnB,KAAKZ,MAAMyB,MAAMO,Q,EAIrBD,UAAA,WACEJ,EAAEM,MAAMC,IAAI7B,IAAI4B,MAAM,mB,EAGxBb,eAAA,WACE,OAAOf,IAAI8B,QAAQC,KAAKC,2B,EAG1BxB,YAAA,WACE,OAAOR,IAAI8B,QAAQC,KAAKE,wB,EAG1Bf,UAAA,SAAUgB,IAGJA,EAAEC,UAAYD,EAAEE,SAAWF,EAAEG,SAAuB,IAAZH,EAAEI,QAAaJ,EAAEK,mB,GAzEdC,KA6EnDC,OAAOC,MAAMC,IAAI,mCAAoClD","file":"forum/components/NotificationsDropdown.js","sourcesContent":["import Dropdown from '../../common/components/Dropdown';\nimport icon from '../../common/helpers/icon';\n\nexport default class NotificationsDropdown extends Dropdown {\n static initAttrs(attrs) {\n attrs.className = attrs.className || 'NotificationsDropdown';\n attrs.buttonClassName = attrs.buttonClassName || 'Button Button--flat';\n attrs.menuClassName = attrs.menuClassName || 'Dropdown-menu--right';\n attrs.label = attrs.label || app.translator.trans('core.forum.notifications.tooltip');\n attrs.icon = attrs.icon || 'fas fa-bell';\n // For best a11y support, both `title` and `aria-label` should be used\n attrs.accessibleToggleLabel = attrs.accessibleToggleLabel || app.translator.trans('core.forum.notifications.toggle_dropdown_accessible_label');\n\n super.initAttrs(attrs);\n }\n\n getButton() {\n const newNotifications = this.getNewCount();\n const vdom = super.getButton();\n\n vdom.attrs.title = this.attrs.label;\n\n vdom.attrs.className += newNotifications ? ' new' : '';\n vdom.attrs.onclick = this.onclick.bind(this);\n\n return vdom;\n }\n\n getButtonContent() {\n const unread = this.getUnreadCount();\n\n return [\n icon(this.attrs.icon, { className: 'Button-icon' }),\n unread ? <span className=\"NotificationsDropdown-unread\">{unread}</span> : '',\n <span className=\"Button-label\">{this.attrs.label}</span>,\n ];\n }\n\n getMenu() {\n const NotificationList = this.NotificationList;\n\n return (\n <div className={'Dropdown-menu ' + this.attrs.menuClassName} onclick={this.menuClick.bind(this)}>\n {this.showing && NotificationList ? <NotificationList state={this.attrs.state} /> : ''}\n </div>\n );\n }\n\n onclick() {\n import(/* webpackChunkName: \"forum/components/NotificationList\" */ './NotificationList').then((NotificationList) => {\n this.NotificationList = NotificationList.default;\n m.redraw();\n });\n\n if (app.drawer.isOpen()) {\n this.goToRoute();\n } else {\n this.attrs.state.load();\n }\n }\n\n goToRoute() {\n m.route.set(app.route('notifications'));\n }\n\n getUnreadCount() {\n return app.session.user.unreadNotificationCount();\n }\n\n getNewCount() {\n return app.session.user.newNotificationCount();\n }\n\n menuClick(e) {\n // Don't close the notifications dropdown if the user is opening a link in a\n // new tab or window.\n if (e.shiftKey || e.metaKey || e.ctrlKey || e.which === 2) e.stopPropagation();\n }\n}\n\nwindow.flreg.add('components/NotificationsDropdown', NotificationsDropdown)"],"sourceRoot":""}

2
js/dist/forum/components/Post.js vendored Normal file

File diff suppressed because one or more lines are too long

1
js/dist/forum/components/Post.js.map vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
js/dist/forum/components/PostUser.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[564],{7214:(t,i,n)=>{n.r(i),n.d(i,{default:()=>a});var s=n(1788),e=n(5556),r=n(2587),o=n(1024),a=function(t){function i(){return t.apply(this,arguments)||this}(0,s.Z)(i,t);var n=i.prototype;return n.oninit=function(i){t.prototype.oninit.call(this,i),this.discussion=this.attrs.discussion,this.currentTitle=this.attrs.currentTitle,this.newTitle=(0,o.Z)(this.currentTitle)},n.className=function(){return"RenameDiscussionModal Modal--small"},n.title=function(){return app.translator.trans("core.forum.rename_discussion.title")},n.content=function(){return m("div",{className:"Modal-body"},m("div",{className:"Form Form--centered"},m("div",{className:"Form-group"},m("input",{className:"FormControl",bidi:this.newTitle,type:"text"})),m("div",{className:"Form-group"},r.Z.component({className:"Button Button--primary Button--block",type:"submit",loading:this.loading},app.translator.trans("core.forum.rename_discussion.submit_button")))))},n.onsubmit=function(t){var i=this;t.preventDefault(),this.loading=!0;var n=this.newTitle(),s=this.currentTitle;if(n&&n!==s)return this.discussion.save({title:n}).then((function(){app.viewingDiscussion(i.discussion)&&app.current.get("stream").update(),m.redraw(),i.hide()})).catch((function(){i.loading=!1,m.redraw()}));this.hide()},i}(e.Z);window.flreg.add("components/RenameDiscussionModal",a)}}]);
//# sourceMappingURL=RenameDiscussionModal.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack://@flarum/core/./src/forum/components/RenameDiscussionModal.js"],"names":["RenameDiscussionModal","oninit","vnode","this","discussion","attrs","currentTitle","newTitle","Stream","className","title","app","translator","trans","content","bidi","type","Button","loading","onsubmit","e","preventDefault","save","then","viewingDiscussion","current","get","update","m","redraw","hide","Modal","window","flreg","add"],"mappings":"wKAOqBA,E,sGACnBC,OAAA,SAAOC,GACL,YAAMD,OAAN,UAAaC,GAEbC,KAAKC,WAAaD,KAAKE,MAAMD,WAC7BD,KAAKG,aAAeH,KAAKE,MAAMC,aAC/BH,KAAKI,UAAWC,OAAOL,KAAKG,e,EAG9BG,UAAA,WACE,MAAO,sC,EAGTC,MAAA,WACE,OAAOC,IAAIC,WAAWC,MAAM,uC,EAG9BC,QAAA,WACE,OACE,SAAKL,UAAU,cACb,SAAKA,UAAU,uBACb,SAAKA,UAAU,cACb,WAAOA,UAAU,cAAcM,KAAMZ,KAAKI,SAAUS,KAAK,UAE3D,SAAKP,UAAU,cACZQ,cACC,CACER,UAAW,uCACXO,KAAM,SACNE,QAASf,KAAKe,SAEhBP,IAAIC,WAAWC,MAAM,mD,EAQjCM,SAAA,SAASC,GAAG,WACVA,EAAEC,iBAEFlB,KAAKe,SAAU,EAEf,IAAMR,EAAQP,KAAKI,WACbD,EAAeH,KAAKG,aAK1B,GAAII,GAASA,IAAUJ,EACrB,OAAOH,KAAKC,WACTkB,KAAK,CAAEZ,UACPa,MAAK,WACAZ,IAAIa,kBAAkB,EAAKpB,aAC7BO,IAAIc,QAAQC,IAAI,UAAUC,SAE5BC,EAAEC,SACF,EAAKC,UAPF,OASE,WACL,EAAKZ,SAAU,EACfU,EAAEC,YAGN1B,KAAK2B,Q,GAjEwCC,KAsEnDC,OAAOC,MAAMC,IAAI,mCAAoClC","file":"forum/components/RenameDiscussionModal.js","sourcesContent":["import Modal from '../../common/components/Modal';\nimport Button from '../../common/components/Button';\nimport Stream from '../../common/utils/Stream';\n\n/**\n * The 'RenameDiscussionModal' displays a modal dialog with an input to rename a discussion\n */\nexport default class RenameDiscussionModal extends Modal {\n oninit(vnode) {\n super.oninit(vnode);\n\n this.discussion = this.attrs.discussion;\n this.currentTitle = this.attrs.currentTitle;\n this.newTitle = Stream(this.currentTitle);\n }\n\n className() {\n return 'RenameDiscussionModal Modal--small';\n }\n\n title() {\n return app.translator.trans('core.forum.rename_discussion.title');\n }\n\n content() {\n return (\n <div className=\"Modal-body\">\n <div className=\"Form Form--centered\">\n <div className=\"Form-group\">\n <input className=\"FormControl\" bidi={this.newTitle} type=\"text\" />\n </div>\n <div className=\"Form-group\">\n {Button.component(\n {\n className: 'Button Button--primary Button--block',\n type: 'submit',\n loading: this.loading,\n },\n app.translator.trans('core.forum.rename_discussion.submit_button')\n )}\n </div>\n </div>\n </div>\n );\n }\n\n onsubmit(e) {\n e.preventDefault();\n\n this.loading = true;\n\n const title = this.newTitle();\n const currentTitle = this.currentTitle;\n\n // If the title is different to what it was before, then save it. After the\n // save has completed, update the post stream as there will be a new post\n // indicating that the discussion was renamed.\n if (title && title !== currentTitle) {\n return this.discussion\n .save({ title })\n .then(() => {\n if (app.viewingDiscussion(this.discussion)) {\n app.current.get('stream').update();\n }\n m.redraw();\n this.hide();\n })\n .catch(() => {\n this.loading = false;\n m.redraw();\n });\n } else {\n this.hide();\n }\n }\n}\n\nwindow.flreg.add('components/RenameDiscussionModal', RenameDiscussionModal)"],"sourceRoot":""}

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[557],{2304:(t,n,o)=>{o.r(n),o.d(n,{default:()=>f});var a=o(2122),e=o(1788),r=o(9908),s=o(507),i=o(9657),p=o(2558),u=o(2587),l=o(4594),c=o(5128),f=function(t){function n(){return t.apply(this,arguments)||this}(0,e.Z)(n,t),n.initAttrs=function(n){t.initAttrs.call(this,n),n.className="SessionDropdown",n.buttonClassName="Button Button--user Button--flat",n.menuClassName="Dropdown-menu--right",n.accessibleToggleLabel=app.translator.trans("core.forum.header.session_dropdown_accessible_label")};var o=n.prototype;return o.view=function(n){return t.prototype.view.call(this,(0,a.Z)({},n,{children:this.items().toArray()}))},o.getButtonContent=function(){var t=app.session.user;return[(0,r.Z)(t)," ",m("span",{className:"Button-label"},(0,s.Z)(t))]},o.items=function(){var t=new l.Z,n=app.session.user;return t.add("profile",p.Z.component({icon:"fas fa-user",href:app.route.user(n)},app.translator.trans("core.forum.header.profile_button")),100),t.add("settings",p.Z.component({icon:"fas fa-cog",href:app.route("settings")},app.translator.trans("core.forum.header.settings_button")),50),app.forum.attribute("adminUrl")&&t.add("administration",p.Z.component({icon:"fas fa-wrench",href:app.forum.attribute("adminUrl"),target:"_blank"},app.translator.trans("core.forum.header.admin_button")),0),t.add("separator",c.Z.component(),-90),t.add("logOut",u.Z.component({icon:"fas fa-sign-out-alt",onclick:app.session.logout.bind(app.session)},app.translator.trans("core.forum.header.log_out_button")),-100),t},n}(i.Z);window.flreg.add("components/SessionDropdown",f)}}]);
//# sourceMappingURL=SessionDropdown.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack://@flarum/core/./src/forum/components/SessionDropdown.js"],"names":["SessionDropdown","initAttrs","attrs","className","buttonClassName","menuClassName","accessibleToggleLabel","app","translator","trans","view","vnode","children","this","items","toArray","getButtonContent","user","session","avatar","username","ItemList","add","LinkButton","icon","href","route","forum","attribute","target","Separator","Button","onclick","logout","bind","Dropdown","window","flreg"],"mappings":"yNAYqBA,E,6EACZC,UAAP,SAAiBC,GACf,EAAMD,UAAN,UAAgBC,GAEhBA,EAAMC,UAAY,kBAClBD,EAAME,gBAAkB,mCACxBF,EAAMG,cAAgB,uBAEtBH,EAAMI,sBAAwBC,IAAIC,WAAWC,MAAM,wD,2BAGrDC,KAAA,SAAKC,GACH,mBAAaD,KAAb,qBAAuBC,EAAvB,CAA8BC,SAAUC,KAAKC,QAAQC,c,EAGvDC,iBAAA,WACE,IAAMC,EAAOV,IAAIW,QAAQD,KAEzB,MAAO,EAACE,OAAOF,GAAO,IAAK,UAAMd,UAAU,iBAAgBiB,OAASH,M,EAQtEH,MAAA,WACE,IAAMA,EAAQ,IAAIO,IACZJ,EAAOV,IAAIW,QAAQD,KAuDzB,OArDAH,EAAMQ,IACJ,UACAC,cACE,CACEC,KAAM,cACNC,KAAMlB,IAAImB,MAAMT,KAAKA,IAEvBV,IAAIC,WAAWC,MAAM,qCAEvB,KAGFK,EAAMQ,IACJ,WACAC,cACE,CACEC,KAAM,aACNC,KAAMlB,IAAImB,MAAM,aAElBnB,IAAIC,WAAWC,MAAM,sCAEvB,IAGEF,IAAIoB,MAAMC,UAAU,aACtBd,EAAMQ,IACJ,iBACAC,cACE,CACEC,KAAM,gBACNC,KAAMlB,IAAIoB,MAAMC,UAAU,YAC1BC,OAAQ,UAEVtB,IAAIC,WAAWC,MAAM,mCAEvB,GAIJK,EAAMQ,IAAI,YAAaQ,iBAAwB,IAE/ChB,EAAMQ,IACJ,SACAS,cACE,CACEP,KAAM,sBACNQ,QAASzB,IAAIW,QAAQe,OAAOC,KAAK3B,IAAIW,UAEvCX,IAAIC,WAAWC,MAAM,sCAEtB,KAGIK,G,GAnFkCqB,KAuF7CC,OAAOC,MAAMf,IAAI,6BAA8BtB","file":"forum/components/SessionDropdown.js","sourcesContent":["import avatar from '../../common/helpers/avatar';\nimport username from '../../common/helpers/username';\nimport Dropdown from '../../common/components/Dropdown';\nimport LinkButton from '../../common/components/LinkButton';\nimport Button from '../../common/components/Button';\nimport ItemList from '../../common/utils/ItemList';\nimport Separator from '../../common/components/Separator';\n\n/**\n * The `SessionDropdown` component shows a button with the current user's\n * avatar/name, with a dropdown of session controls.\n */\nexport default class SessionDropdown extends Dropdown {\n static initAttrs(attrs) {\n super.initAttrs(attrs);\n\n attrs.className = 'SessionDropdown';\n attrs.buttonClassName = 'Button Button--user Button--flat';\n attrs.menuClassName = 'Dropdown-menu--right';\n\n attrs.accessibleToggleLabel = app.translator.trans('core.forum.header.session_dropdown_accessible_label');\n }\n\n view(vnode) {\n return super.view({ ...vnode, children: this.items().toArray() });\n }\n\n getButtonContent() {\n const user = app.session.user;\n\n return [avatar(user), ' ', <span className=\"Button-label\">{username(user)}</span>];\n }\n\n /**\n * Build an item list for the contents of the dropdown menu.\n *\n * @return {ItemList}\n */\n items() {\n const items = new ItemList();\n const user = app.session.user;\n\n items.add(\n 'profile',\n LinkButton.component(\n {\n icon: 'fas fa-user',\n href: app.route.user(user),\n },\n app.translator.trans('core.forum.header.profile_button')\n ),\n 100\n );\n\n items.add(\n 'settings',\n LinkButton.component(\n {\n icon: 'fas fa-cog',\n href: app.route('settings'),\n },\n app.translator.trans('core.forum.header.settings_button')\n ),\n 50\n );\n\n if (app.forum.attribute('adminUrl')) {\n items.add(\n 'administration',\n LinkButton.component(\n {\n icon: 'fas fa-wrench',\n href: app.forum.attribute('adminUrl'),\n target: '_blank',\n },\n app.translator.trans('core.forum.header.admin_button')\n ),\n 0\n );\n }\n\n items.add('separator', Separator.component(), -90);\n\n items.add(\n 'logOut',\n Button.component(\n {\n icon: 'fas fa-sign-out-alt',\n onclick: app.session.logout.bind(app.session),\n },\n app.translator.trans('core.forum.header.log_out_button')\n ),\n -100\n );\n\n return items;\n }\n}\n\nwindow.flreg.add('components/SessionDropdown', SessionDropdown)"],"sourceRoot":""}

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[826],{6991:(t,n,e)=>{e.d(n,{Z:()=>c});var i=e(1788),a=e(8931),o=e(5971),r=e(9100),s=e(4594),c=function(t){function n(){return t.apply(this,arguments)||this}(0,i.Z)(n,t);var e=n.prototype;return e.oninit=function(n){t.prototype.oninit.call(this,n),this.methods=this.notificationMethods().toArray(),this.loading={},this.types=this.notificationTypes().toArray()},e.view=function(){var t=this,n=this.attrs.user.preferences();return m("table",{className:"NotificationGrid"},m("thead",null,m("tr",null,m("td",null),this.methods.map((function(n){return m("th",{className:"NotificationGrid-groupToggle",onclick:t.toggleMethod.bind(t,n.name)},(0,r.Z)(n.icon)," ",n.label)})))),m("tbody",null,this.types.map((function(e){return m("tr",null,m("td",{className:"NotificationGrid-groupToggle",onclick:t.toggleType.bind(t,e.name)},(0,r.Z)(e.icon)," ",e.label),t.methods.map((function(i){var a=t.preferenceKey(e.name,i.name);return m("td",{className:"NotificationGrid-checkbox"},m(o.Z,{state:!!n[a],loading:t.loading[a],disabled:!(a in n),onchange:t.toggle.bind(t,[a])}))})))}))))},e.oncreate=function(n){t.prototype.oncreate.call(this,n),this.$("thead .NotificationGrid-groupToggle").bind("mouseenter mouseleave",(function(t){var n=parseInt($(this).index(),10)+1;$(this).parents("table").find("td:nth-child("+n+")").toggleClass("highlighted","mouseenter"===t.type)})),this.$("tbody .NotificationGrid-groupToggle").bind("mouseenter mouseleave",(function(t){$(this).parent().find("td").toggleClass("highlighted","mouseenter"===t.type)}))},e.toggle=function(t){var n=this,e=this.attrs.user,i=e.preferences(),a=!i[t[0]];t.forEach((function(t){n.loading[t]=!0,i[t]=a})),m.redraw(),e.save({preferences:i}).then((function(){t.forEach((function(t){return n.loading[t]=!1})),m.redraw()}))},e.toggleMethod=function(t){var n=this,e=this.types.map((function(e){return n.preferenceKey(e.name,t)})).filter((function(t){return t in n.attrs.user.preferences()}));this.toggle(e)},e.toggleType=function(t){var n=this,e=this.methods.map((function(e){return n.preferenceKey(t,e.name)})).filter((function(t){return t in n.attrs.user.preferences()}));this.toggle(e)},e.preferenceKey=function(t,n){return"notify_"+t+"_"+n},e.notificationMethods=function(){var t=new s.Z;return t.add("alert",{name:"alert",icon:"fas fa-bell",label:app.translator.trans("core.forum.settings.notify_by_web_heading")}),t.add("email",{name:"email",icon:"far fa-envelope",label:app.translator.trans("core.forum.settings.notify_by_email_heading")}),t},e.notificationTypes=function(){var t=new s.Z;return t.add("discussionRenamed",{name:"discussionRenamed",icon:"fas fa-pencil-alt",label:app.translator.trans("core.forum.settings.notify_discussion_renamed_label")}),t},n}(a.Z);window.flreg.add("components/NotificationGrid",c)},5792:(t,n,e)=>{e.a(t,(async t=>{e.r(n),e.d(n,{default:()=>u});var i=e(1788),a=e(4594),o=e(833),r=e(2587),s=e(4926),c=e(6991),l=e(7473),u=function(t){function n(){return t.apply(this,arguments)||this}(0,i.Z)(n,t);var u=n.prototype;return u.oninit=function(n){t.prototype.oninit.call(this,n),this.show(app.session.user),app.setTitle(app.translator.trans("core.forum.settings.title"))},u.content=function(){return m("div",{className:"SettingsPage"},m("ul",null,(0,l.Z)(this.settingsItems().toArray())))},u.settingsItems=function(){var t=this,n=new a.Z;return["account","notifications","privacy"].forEach((function(e){n.add(e,m(s.Z,{className:"Settings-"+e,label:app.translator.trans("core.forum.settings."+e+"_heading")},t[e+"Items"]().toArray()))})),n},u.accountItems=function(){var t=new a.Z,n=function(){return e.e(372).then(e.bind(e,4146))},i=function(){return e.e(503).then(e.bind(e,22))};return t.add("changePassword",m(r.Z,{className:"Button",onclick:function(){return app.modal.show(i)}},app.translator.trans("core.forum.settings.change_password_button"))),t.add("changeEmail",m(r.Z,{className:"Button",onclick:function(){return app.modal.show(n)}},app.translator.trans("core.forum.settings.change_email_button"))),t},u.notificationsItems=function(){var t=new a.Z;return t.add("notificationGrid",m(c.Z,{user:this.user})),t},u.privacyItems=function(){var t=this,n=new a.Z;return n.add("discloseOnline",m(o.Z,{state:this.user.preferences().discloseOnline,onchange:function(n){t.discloseOnlineLoading=!0,t.user.savePreferences({discloseOnline:n}).then((function(){t.discloseOnlineLoading=!1,m.redraw()}))},loading:this.discloseOnlineLoading},app.translator.trans("core.forum.settings.privacy_disclose_online_label"))),n},n}((await e.e(251).then(e.bind(e,6068))).default);window.flreg.add("components/SettingsPage",u),t()}),1)}}]);
//# sourceMappingURL=SettingsPage.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[]).push([[395],{7527:(t,a,s)=>{s.d(a,{Z:()=>n});var r=s(1788),e=s(8931),i=s(4594),n=function(t){function a(){return t.apply(this,arguments)||this}(0,r.Z)(a,t);var s=a.prototype;return s.view=function(){return m("div",{className:"LogInButtons"},this.items().toArray())},s.items=function(){return new i.Z},a}(e.Z);window.flreg.add("components/LogInButtons",n)},3235:(t,a,s)=>{s.r(a),s.d(a,{default:()=>u});var r=s(1788),e=s(5556),i=s(2587),n=s(7527),o=s(5731),l=s(4594),d=s(1024),u=function(t){function a(){return t.apply(this,arguments)||this}(0,r.Z)(a,t);var e=a.prototype;return e.oninit=function(a){t.prototype.oninit.call(this,a),this.username=(0,d.Z)(this.attrs.username||""),this.email=(0,d.Z)(this.attrs.email||""),this.password=(0,d.Z)(this.attrs.password||"")},e.className=function(){return"Modal--small SignUpModal"},e.title=function(){return app.translator.trans("core.forum.sign_up.title")},e.content=function(){return[m("div",{className:"Modal-body"},this.body()),m("div",{className:"Modal-footer"},this.footer())]},e.isProvided=function(t){return this.attrs.provided&&-1!==this.attrs.provided.indexOf(t)},e.body=function(){return[this.attrs.token?"":m(n.Z,null),m("div",{className:"Form Form--centered"},this.fields().toArray())]},e.fields=function(){var t=new l.Z;return t.add("username",m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"username",type:"text",placeholder:(0,o.Z)(app.translator.trans("core.forum.sign_up.username_placeholder")),bidi:this.username,disabled:this.loading||this.isProvided("username")})),30),t.add("email",m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"email",type:"email",placeholder:(0,o.Z)(app.translator.trans("core.forum.sign_up.email_placeholder")),bidi:this.email,disabled:this.loading||this.isProvided("email")})),20),this.attrs.token||t.add("password",m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"password",type:"password",placeholder:(0,o.Z)(app.translator.trans("core.forum.sign_up.password_placeholder")),bidi:this.password,disabled:this.loading})),10),t.add("submit",m("div",{className:"Form-group"},m(i.Z,{className:"Button Button--primary Button--block",type:"submit",loading:this.loading},app.translator.trans("core.forum.sign_up.submit_button"))),-10),t},e.footer=function(){return[m("p",{className:"SignUpModal-logIn"},app.translator.trans("core.forum.sign_up.log_in_text",{a:m("a",{onclick:this.logIn.bind(this)})}))]},e.logIn=function(){var t={identification:this.email()||this.username(),password:this.password()};app.modal.show((function(){return s.e(460).then(s.bind(s,1498))}),t)},e.onready=function(){this.attrs.username&&!this.attrs.email?this.$("[name=email]").select():this.$("[name=username]").select()},e.onsubmit=function(t){t.preventDefault(),this.loading=!0;var a=this.submitData();app.request({url:app.forum.attribute("baseUrl")+"/register",method:"POST",body:a,errorHandler:this.onerror.bind(this)}).then((function(){return window.location.reload()}),this.loaded.bind(this))},e.submitData=function(){var t={username:this.username(),email:this.email()};return this.attrs.token?t.token=this.attrs.token:t.password=this.password(),t},a}(e.Z);window.flreg.add("components/SignUpModal",u)}}]);
//# sourceMappingURL=SignUpModal.js.map

File diff suppressed because one or more lines are too long

2
js/dist/forum/components/UserPage.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

3
js/dist/forum/flarum-core.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
/*!
* Block below copied from Protovis: http://mbostock.github.com/protovis/
* Copyright 2010 Stanford Visualization Group
* Licensed under the BSD License: http://www.opensource.org/licenses/bsd-license.php
*/
/*!
* Color Thief v2.0
* by Lokesh Dhakar - http://www.lokeshdhakar.com
*
* Thanks
* ------
* Nick Rabinowitz - For creating quantize.js.
* John Schulz - For clean up and optimization. @JFSIII
* Nathan Spady - For adding drag and drop support to the demo page.
*
* License
* -------
* Copyright 2011, 2015 Lokesh Dhakar
* Released under the MIT license
* https://raw.githubusercontent.com/lokesh/color-thief/master/LICENSE
*
*/
/*!
* quantize.js Copyright 2008 Nick Rabinowitz.
* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
*/

1
js/dist/forum/flarum-core.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
js/dist/forum/runtime.js vendored Normal file
View File

@@ -0,0 +1,2 @@
(()=>{var e,o,r,t,n,a,s,i,u={},c={};function m(e){var o=c[e];if(void 0!==o)return o.exports;var r=c[e]={exports:{}};return u[e].call(r.exports,r,r.exports,m),r.exports}m.m=u,e="function"==typeof Symbol?Symbol("webpack then"):"__webpack_then__",o="function"==typeof Symbol?Symbol("webpack exports"):"__webpack_exports__",r=e=>{e&&(e.forEach((e=>e.r--)),e.forEach((e=>e.r--?e.r++:e())))},t=e=>!--e.r&&e(),n=(e,o)=>e?e.push(o):t(o),m.a=(a,s,i)=>{var u,c,m,p=i&&[],f=a.exports,l=!0,d=!1,h=(o,r,t)=>{d||(d=!0,r.r+=o.length,o.map(((o,n)=>o[e](r,t))),d=!1)},b=new Promise(((e,o)=>{m=o,c=()=>(e(f),r(p),p=0)}));b[o]=f,b[e]=(e,o)=>{if(l)return t(e);u&&h(u,e,o),n(p,e),b.catch(o)},a.exports=b,s((a=>{if(!a)return c();var s,i;u=(a=>a.map((a=>{if(null!==a&&"object"==typeof a){if(a[e])return a;if(a.then){var s=[];a.then((e=>{i[o]=e,r(s),s=0}));var i={[e]:(e,o)=>(n(s,e),a.catch(o))};return i}}return{[e]:e=>t(e),[o]:a}})))(a);var m=new Promise(((e,r)=>{(s=()=>e(i=u.map((e=>e[o])))).r=0,h(u,s,r)}));return s.r?m:i})).then(c,m),l=!1},a=[],m.O=(e,o,r,t)=>{if(!o){var n=1/0;for(u=0;u<a.length;u++){for(var[o,r,t]=a[u],s=!0,i=0;i<o.length;i++)(!1&t||n>=t)&&Object.keys(m.O).every((e=>m.O[e](o[i])))?o.splice(i--,1):(s=!1,t<n&&(n=t));s&&(a.splice(u--,1),e=r())}return e}t=t||0;for(var u=a.length;u>0&&a[u-1][2]>t;u--)a[u]=a[u-1];a[u]=[o,r,t]},m.n=e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return m.d(o,{a:o}),o},m.d=(e,o)=>{for(var r in o)m.o(o,r)&&!m.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},m.f={},m.e=e=>Promise.all(Object.keys(m.f).reduce(((o,r)=>(m.f[r](e,o),o)),[])),m.u=e=>({28:"forum/components/PostsUserPage",77:"forum/components/NotificationList",192:"forum/components/Post",247:"common/components/TextEditor",251:"forum/components/UserPage",293:"forum/components/EditPostComposer",352:"forum/components/EditUserModal",372:"forum/components/ChangeEmailModal",395:"forum/components/SignUpModal",437:"forum/components/DiscussionComposer",460:"forum/components/LogInModal",502:"forum/components/ForgotPasswordModal",503:"forum/components/ChangePasswordModal",557:"forum/components/SessionDropdown",563:"forum/components/PostStream",564:"forum/components/RenameDiscussionModal",765:"forum/components/NotificationsDropdown",779:"forum/components/PostUser",799:"forum/components/DiscussionsUserPage",826:"forum/components/SettingsPage",847:"forum/components/IndexPage"}[e]+".js"),m.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),m.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),s={},i="@flarum/core:",m.l=(e,o,r,t)=>{if(s[e])s[e].push(o);else{var n,a;if(void 0!==r)for(var u=document.getElementsByTagName("script"),c=0;c<u.length;c++){var p=u[c];if(p.getAttribute("src")==e||p.getAttribute("data-webpack")==i+r){n=p;break}}n||(a=!0,(n=document.createElement("script")).charset="utf-8",n.timeout=120,m.nc&&n.setAttribute("nonce",m.nc),n.setAttribute("data-webpack",i+r),n.src=e),s[e]=[o];var f=(o,r)=>{n.onerror=n.onload=null,clearTimeout(l);var t=s[e];if(delete s[e],n.parentNode&&n.parentNode.removeChild(n),t&&t.forEach((e=>e(r))),o)return o(r)},l=setTimeout(f.bind(null,void 0,{type:"timeout",target:n}),12e4);n.onerror=f.bind(null,n.onerror),n.onload=f.bind(null,n.onload),a&&document.head.appendChild(n)}},m.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},m.p="/assets/",(()=>{var e={406:0};m.f.j=(o,r)=>{var t=m.o(e,o)?e[o]:void 0;if(0!==t)if(t)r.push(t[2]);else if(406!=o){var n=new Promise(((r,n)=>t=e[o]=[r,n]));r.push(t[2]=n);var a=m.p+m.u(o),s=new Error;m.l(a,(r=>{if(m.o(e,o)&&(0!==(t=e[o])&&(e[o]=void 0),t)){var n=r&&("load"===r.type?"missing":r.type),a=r&&r.target&&r.target.src;s.message="Loading chunk "+o+" failed.\n("+n+": "+a+")",s.name="ChunkLoadError",s.type=n,s.request=a,t[1](s)}}),"chunk-"+o,o)}else e[o]=0},m.O.j=o=>0===e[o];var o=(o,r)=>{var t,n,[a,s,i]=r,u=0;for(t in s)m.o(s,t)&&(m.m[t]=s[t]);for(i&&i(m),o&&o(r);u<a.length;u++)n=a[u],m.o(e,n)&&e[n]&&e[n][0](),e[a[u]]=0;m.O()},r=self.webpackChunk_flarum_core=self.webpackChunk_flarum_core||[];r.forEach(o.bind(null,0)),r.push=o.bind(null,r.push.bind(r))})(),m.O()})();
//# sourceMappingURL=runtime.js.map

1
js/dist/forum/runtime.js.map vendored Normal file

File diff suppressed because one or more lines are too long

3
js/dist/forum/vendor.js vendored Normal file

File diff suppressed because one or more lines are too long

24
js/dist/forum/vendor.js.LICENSE.txt vendored Normal file
View File

@@ -0,0 +1,24 @@
/*!
* Sizzle CSS Selector Engine v2.3.6
* https://sizzlejs.com/
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https://js.foundation/
*
* Date: 2021-02-16
*/
/*!
* jQuery JavaScript Library v3.6.0
* https://jquery.com/
*
* Includes Sizzle.js
* https://sizzlejs.com/
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2021-03-02T17:08Z
*/

1
js/dist/forum/vendor.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -8,4 +8,4 @@
*/
export * from './src/common';
export * from './src/forum';
export * from './src/forum';

8917
js/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,28 +2,41 @@
"private": true,
"name": "@flarum/core",
"dependencies": {
"@babel/preset-typescript": "^7.10.1",
"@types/mithril": "^2.0.3",
"bootstrap": "^3.4.1",
"classnames": "^2.2.5",
"clsx": "^1.1.1",
"color-thief-browser": "^2.0.2",
"dayjs": "^1.8.28",
"expose-loader": "^0.7.5",
"flarum-webpack-config": "0.1.0-beta.10",
"jquery": "^3.5.1",
"dayjs": "^1.10.4",
"jquery": "^3.6.0",
"jquery.hotkeys": "^0.1.0",
"lodash-es": "^4.17.14",
"lodash-es": "^4.17.21",
"mithril": "^2.0.4",
"punycode": "^2.1.1",
"spin.js": "^3.1.0",
"textarea-caret": "^3.1.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"webpack-merge": "^4.1.4"
"webpack-visualizer-plugin": "^0.1.11",
"zepto": "^1.2.0"
},
"devDependencies": {
"husky": "^4.2.5",
"prettier": "2.0.2"
"@babel/plugin-proposal-export-default-from": "^7.12.13",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-syntax-top-level-await": "^7.12.13",
"@babel/preset-typescript": "^7.13.0",
"@types/jquery": "^3.5.5",
"@types/lodash-es": "^4.17.4",
"@types/mithril": "^2.0.7",
"@types/punycode": "^2.1.0",
"@types/textarea-caret": "^3.0.0",
"babel-plugin-add-module-exports": "^1.0.4",
"bundlewatch": "^0.3.2",
"expose-loader": "^2.0.0",
"flarum-webpack-config": "0.1.0-beta.10",
"husky": "^4.3.8",
"loader-utils": "^1.4.0",
"prettier": "^2.2.1",
"webpack": "~5.33.2",
"webpack-bundle-analyzer": "^4.4.1",
"webpack-cli": "~4.6.0",
"webpack-merge": "~5.7.3"
},
"scripts": {
"dev": "webpack --mode development --watch",

17
js/shims.d.ts vendored
View File

@@ -8,6 +8,8 @@ import * as _$ from 'jquery';
// Globals from flarum/core
import Application from './src/common/Application';
import FlarumRegistry from './src/common/FlarumRegistry';
/**
* flarum/core exposes several extensions globally:
*
@@ -19,9 +21,21 @@ import Application from './src/common/Application';
* to (and should not) bundle these themselves.
*/
declare global {
const $: typeof _$;
// $ is already defined by `@types/jquery`
const m: Mithril.Static;
const dayjs: typeof _dayjs;
// Extend JQuery with our custom functions, defined with $.fn
interface JQuery {
/**
* Creates a tooltip on a jQuery element reference.
*
* Optionally accepts placement and delay options.
*
* Returns the same reference to allow for method chaining.
*/
tooltip: (tooltipOptions?: { placement?: 'top' | 'bottom' | 'left' | 'right'; delay?: number }) => JQuery;
}
}
/**
@@ -29,4 +43,5 @@ declare global {
*/
declare global {
const app: Application;
const flreg: FlarumRegistry;
}

8
js/src/admin/app.ts Normal file
View File

@@ -0,0 +1,8 @@
import Admin from './AdminApplication';
const app = new Admin();
// @ts-ignore
window.app = app;
export default app;

View File

@@ -126,16 +126,17 @@ export default class AdminNav extends Component {
categorizedExtensions[category].map((extension) => {
const query = this.query().toUpperCase();
const title = extension.extra['flarum-extension'].title;
const title = extension.extra['flarum-extension'].title || '';
const description = extension.description || '';
if (!query || title.toUpperCase().includes(query) || extension.description.toUpperCase().includes(query)) {
if (!query || title.toUpperCase().includes(query) || description.toUpperCase().includes(query)) {
items.add(
`extension-${extension.id}`,
<ExtensionLinkButton
href={app.route('extension', { id: extension.id })}
extensionId={extension.id}
className="ExtensionNavButton"
title={extension.description}
title={description}
>
{title}
</ExtensionLinkButton>,

View File

@@ -98,35 +98,41 @@ export default class AdminPage extends Page {
return entry.call(this);
}
const setting = entry.setting;
const help = entry.help;
delete entry.help;
const { setting, help, ...componentAttrs } = entry;
delete componentAttrs.help;
const value = this.setting([setting])();
if (['bool', 'checkbox', 'switch', 'boolean'].includes(entry.type)) {
if (['bool', 'checkbox', 'switch', 'boolean'].includes(componentAttrs.type)) {
return (
<div className="Form-group">
<Switch state={!!value && value !== '0'} onchange={this.settings[setting]} {...entry}>
{entry.label}
<Switch state={!!value && value !== '0'} onchange={this.settings[setting]} {...componentAttrs}>
{componentAttrs.label}
</Switch>
<div className="helpText">{help}</div>
</div>
);
} else if (['select', 'dropdown', 'selectdropdown'].includes(entry.type)) {
} else if (['select', 'dropdown', 'selectdropdown'].includes(componentAttrs.type)) {
return (
<div className="Form-group">
<label>{entry.label}</label>
<label>{componentAttrs.label}</label>
<div className="helpText">{help}</div>
<Select value={value || entry.default} options={entry.options} buttonClassName="Button" onchange={this.settings[setting]} {...entry} />
<Select
value={value || componentAttrs.default}
options={componentAttrs.options}
buttonClassName="Button"
onchange={this.settings[setting]}
{...componentAttrs}
/>
</div>
);
} else {
entry.className = classList(['FormControl', entry.className]);
componentAttrs.className = classList(['FormControl', componentAttrs.className]);
return (
<div className="Form-group">
{entry.label ? <label>{entry.label}</label> : ''}
{componentAttrs.label ? <label>{componentAttrs.label}</label> : ''}
<div className="helpText">{help}</div>
<input type={entry.type} bidi={this.setting(setting)} {...entry} />
<input type={componentAttrs.type} bidi={this.setting(setting)} {...componentAttrs} />
</div>
);
}

View File

@@ -36,7 +36,7 @@ export default class UploadImageButton extends Button {
$input
.appendTo('body')
.hide()
.click()
.trigger('click')
.on('change', (e) => {
const body = new FormData();
body.append(this.attrs.name, $(e.target)[0].files[0]);

View File

@@ -1,18 +1,5 @@
import AdminApplication from './AdminApplication';
const app = new AdminApplication();
// Backwards compatibility
window.app = app;
import app from './app';
export { app };
// Export public API
// Export compat API
import compatObj from './compat';
import proxifyCompat from '../common/utils/proxifyCompat';
compatObj.app = app;
export const compat = proxifyCompat(compatObj, 'admin');

View File

@@ -159,6 +159,8 @@ export default class Application {
title = '';
titleCount = 0;
initialRoute;
load(payload) {
this.data = payload;
this.translator.locale = payload.locale;
@@ -174,6 +176,8 @@ export default class Application {
this.session = new Session(this.store.getById('users', this.data.session.userId), this.data.session.csrfToken);
this.mount();
this.initialRoute = window.location.href;
}
bootExtensions(extensions) {
@@ -226,7 +230,8 @@ export default class Application {
* @public
*/
preloadedApiDocument() {
if (this.data.apiDocument) {
// If the URL has changed, the preloaded Api document is invalid.
if (this.data.apiDocument && window.location.href === this.initialRoute) {
const results = this.store.pushPayload(this.data.apiDocument);
this.data.apiDocument = null;

View File

@@ -77,12 +77,12 @@ export default abstract class Component<T extends ComponentAttrs = ComponentAttr
* containing all of the `li` elements inside the DOM element of this
* component.
*
* @param {String} [selector] a jQuery-compatible selector string
* @returns {jQuery} the jQuery object for the DOM node
* @param [selector] a jQuery-compatible selector string
* @returns the jQuery object for the DOM node
* @final
*/
protected $(selector) {
const $element = $(this.element);
protected $(selector: string): JQuery {
const $element = $(this.element) as JQuery<HTMLElement>;
return selector ? $element.find(selector) : $element;
}
@@ -94,7 +94,7 @@ export default abstract class Component<T extends ComponentAttrs = ComponentAttr
* @see https://mithril.js.org/hyperscript.html#mselector,-attributes,-children
*/
static component(attrs = {}, children = null): Mithril.Vnode {
const componentAttrs = Object.assign({}, attrs);
const componentAttrs = Object.assign({}, attrs) as Record<string, unknown>;
return m(this as any, componentAttrs, children);
}

View File

@@ -0,0 +1,55 @@
interface ExportRegistry {
moduleExports: object;
onLoads: object;
/**
* Add an instance to the registry.
* This serves as the equivalent of `flarum.core.compat[id] = object`
*/
add(id: string, object: any);
/**
* Add a function to run when object of id "id" is added (or overriden).
* If such an object is already registered, the handler will be applied immediately.
*/
onLoad(id: string, handler: Function);
/**
* Retrieve an object of type `id` from the registry.
*/
get(id: string): any;
}
export default class FlarumRegistry implements ExportRegistry {
moduleExports = {};
onLoads = {};
add(id: string, object: any) {
const onLoads = this.onLoads[id];
if (onLoads) {
onLoads.map((onLoad) => {
object = onLoad(object);
});
}
this.moduleExports[id] = object;
}
onLoad(id: string, handler: Function) {
const loadedObject = this.moduleExports[id];
if (loadedObject) {
this.moduleExports[id] = handler(loadedObject);
} else {
this.onLoads[id] = this.onLoads[id] || [];
this.onLoads[id].push(handler);
}
}
get(id: string): any {
if (this.moduleExports[id]) {
return this.moduleExports[id];
}
}
}

View File

@@ -1,145 +0,0 @@
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 Stream from './utils/Stream';
import SubtreeRetainer from './utils/SubtreeRetainer';
import setRouteWithForcedRefresh from './utils/setRouteWithForcedRefresh';
import extract from './utils/extract';
import ScrollListener from './utils/ScrollListener';
import stringToColor from './utils/stringToColor';
import subclassOf from './utils/subclassOf';
import patchMithril from './utils/patchMithril';
import proxifyCompat from './utils/proxifyCompat';
import classList from './utils/classList';
import extractText from './utils/extractText';
import formatNumber from './utils/formatNumber';
import mapRoutes from './utils/mapRoutes';
import withAttr from './utils/withAttr';
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 Page from './components/Page';
import Switch from './components/Switch';
import Badge from './components/Badge';
import LoadingIndicator from './components/LoadingIndicator';
import Placeholder from './components/Placeholder';
import Separator from './components/Separator';
import Dropdown from './components/Dropdown';
import SplitDropdown from './components/SplitDropdown';
import RequestErrorModal from './components/RequestErrorModal';
import FieldSet from './components/FieldSet';
import Select from './components/Select';
import Navigation from './components/Navigation';
import Alert from './components/Alert';
import Link from './components/Link';
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';
import Fragment from './Fragment';
import DefaultResolver from './resolvers/DefaultResolver';
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/Stream': Stream,
'utils/subclassOf': subclassOf,
'utils/setRouteWithForcedRefresh': setRouteWithForcedRefresh,
'utils/patchMithril': patchMithril,
'utils/proxifyCompat': proxifyCompat,
'utils/classList': classList,
'utils/extractText': extractText,
'utils/formatNumber': formatNumber,
'utils/mapRoutes': mapRoutes,
'utils/withAttr': withAttr,
'models/Notification': Notification,
'models/User': User,
'models/Post': Post,
'models/Discussion': Discussion,
'models/Group': Group,
'models/Forum': Forum,
Component: Component,
Fragment: Fragment,
Translator: Translator,
'components/AlertManager': AlertManager,
'components/Page': Page,
'components/Switch': Switch,
'components/Badge': Badge,
'components/LoadingIndicator': LoadingIndicator,
'components/Placeholder': Placeholder,
'components/Separator': Separator,
'components/Dropdown': Dropdown,
'components/SplitDropdown': SplitDropdown,
'components/RequestErrorModal': RequestErrorModal,
'components/FieldSet': FieldSet,
'components/Select': Select,
'components/Navigation': Navigation,
'components/Alert': Alert,
'components/Link': Link,
'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,
'resolvers/DefaultResolver': DefaultResolver,
};

View File

@@ -13,6 +13,7 @@ import listItems from '../helpers/listItems';
* - `icon` The name of an icon to show in the dropdown toggle button.
* - `caretIcon` The name of an icon to show on the right of the button.
* - `label` The label of the dropdown toggle button. Defaults to 'Controls'.
* - `accessibleToggleLabel` The label used to describe the dropdown toggle button to assistive readers. Defaults to 'Toggle dropdown menu'.
* - `onhide`
* - `onshow`
*
@@ -25,6 +26,7 @@ export default class Dropdown extends Component {
attrs.menuClassName = attrs.menuClassName || '';
attrs.label = attrs.label || '';
attrs.caretIcon = typeof attrs.caretIcon !== 'undefined' ? attrs.caretIcon : 'fas fa-caret-down';
attrs.accessibleToggleLabel = attrs.accessibleToggleLabel || app.translator.trans('core.lib.dropdown.toggle_dropdown_accessible_label');
}
oninit(vnode) {
@@ -92,7 +94,13 @@ export default class Dropdown extends Component {
*/
getButton(children) {
return (
<button className={'Dropdown-toggle ' + this.attrs.buttonClassName} data-toggle="dropdown" onclick={this.attrs.onclick}>
<button
className={'Dropdown-toggle ' + this.attrs.buttonClassName}
aria-haspopup="menu"
aria-label={this.attrs.accessibleToggleLabel}
data-toggle="dropdown"
onclick={this.attrs.onclick}
>
{this.getButtonContent(children)}
</button>
);

View File

@@ -24,7 +24,12 @@ export default class SplitDropdown extends Dropdown {
return [
Button.component(buttonAttrs, firstChild.children),
<button className={'Dropdown-toggle Button Button--icon ' + this.attrs.buttonClassName} data-toggle="dropdown">
<button
className={'Dropdown-toggle Button Button--icon ' + this.attrs.buttonClassName}
aria-haspopup="menu"
aria-label={this.attrs.accessibleToggleLabel}
data-toggle="dropdown"
>
{icon(this.attrs.icon, { className: 'Button-icon' })}
{icon('fas fa-caret-down', { className: 'Button-caret' })}
</button>,

View File

@@ -1,7 +1,7 @@
import Component from '../../common/Component';
import ItemList from '../../common/utils/ItemList';
import listItems from '../../common/helpers/listItems';
import Button from '../../common/components/Button';
import Component from '../Component';
import ItemList from '../utils/ItemList';
import listItems from '../helpers/listItems';
import Button from './Button';
import BasicEditorDriver from '../utils/BasicEditorDriver';

View File

@@ -1,4 +1,4 @@
import Button from '../../common/components/Button';
import Button from './Button';
/**
* The `TextEditorButton` component displays a button suitable for the text

View File

@@ -1,26 +1,28 @@
import * as Mithril from 'mithril';
import User from '../models/User';
/**
* The `avatar` helper displays a user's avatar.
*
* @param {User} user
* @param {Object} attrs Attributes to apply to the avatar element
* @return {Object}
* @param user
* @param attrs Attributes to apply to the avatar element
*/
export default function avatar(user, attrs = {}) {
export default function avatar(user: User, attrs: Object = {}): Mithril.Vnode {
attrs.className = 'Avatar ' + (attrs.className || '');
let content = '';
let content: string = '';
// If the `title` attribute is set to null or false, we don't want to give the
// avatar a title. On the other hand, if it hasn't been given at all, we can
// safely default it to the user's username.
const hasTitle = attrs.title === 'undefined' || attrs.title;
const hasTitle: boolean | string = attrs.title === 'undefined' || attrs.title;
if (!hasTitle) delete attrs.title;
// If a user has been passed, then we will set up an avatar using their
// uploaded image, or the first letter of their username if they haven't
// uploaded one.
if (user) {
const username = user.displayName() || '?';
const avatarUrl = user.avatarUrl();
const username: string = user.displayName() || '?';
const avatarUrl: string = user.avatarUrl();
if (hasTitle) attrs.title = attrs.title || username;

View File

@@ -1,15 +1,16 @@
import * as Mithril from 'mithril';
import Separator from '../components/Separator';
import classList from '../utils/classList';
function isSeparator(item) {
function isSeparator(item): boolean {
return item.tag === Separator;
}
function withoutUnnecessarySeparators(items) {
function withoutUnnecessarySeparators(items: Array<Mithril.Vnode>): Array<Mithril.Vnode> {
const newItems = [];
let prevItem;
items.filter(Boolean).forEach((item, i) => {
items.filter(Boolean).forEach((item: Mithril.Vnode, i: number) => {
if (!isSeparator(item) || (prevItem && !isSeparator(prevItem) && i !== items.length - 1)) {
prevItem = item;
newItems.push(item);
@@ -22,14 +23,11 @@ function withoutUnnecessarySeparators(items) {
/**
* The `listItems` helper wraps a collection of components in <li> tags,
* stripping out any unnecessary `Separator` components.
*
* @param {*} items
* @return {Array}
*/
export default function listItems(items) {
export default function listItems(items: Mithril.Vnode | Array<Mithril.Vnode>): Array<Mithril.Vnode> {
if (!(items instanceof Array)) items = [items];
return withoutUnnecessarySeparators(items).map((item) => {
return withoutUnnecessarySeparators(items).map((item: Mithril.Vnode) => {
const isListItem = item.tag && item.tag.isListItem;
const active = item.tag && item.tag.isActive && item.tag.isActive(item.attrs);
const className = (item.attrs && item.attrs.itemClassName) || item.itemClassName;
@@ -40,7 +38,7 @@ export default function listItems(items) {
item.key = item.attrs.key;
}
const node = isListItem ? (
const node: Mithril.Vnode = isListItem ? (
item
) : (
<li

View File

@@ -1,12 +1,11 @@
import * as Mithril from 'mithril';
import User from '../models/User';
import icon from './icon';
/**
* The `useronline` helper displays a green circle if the user is online
*
* @param {User} user
* @return {Object}
*/
export default function userOnline(user) {
export default function userOnline(user: User): Mithril.Vnode {
if (user.lastSeenAt() && user.isOnline()) {
return <span className="UserOnline">{icon('fas fa-circle')}</span>;
}

View File

@@ -1,11 +1,11 @@
import * as Mithril from 'mithril';
import User from '../models/User';
/**
* The `username` helper displays a user's username in a <span class="username">
* tag. If the user doesn't exist, the username will be displayed as [deleted].
*
* @param {User} user
* @return {Object}
*/
export default function username(user) {
export default function username(user: User): Mithril.Vnode {
const name = (user && user.displayName()) || app.translator.trans('core.lib.username.deleted_text');
return <span className="username">{name}</span>;

View File

@@ -1,6 +1,8 @@
import 'expose-loader?$!expose-loader?jQuery!jquery';
import 'expose-loader?m!mithril';
import 'expose-loader?dayjs!dayjs';
// Expose jQuery, mithril and dayjs to the window browser object
import 'expose-loader?exposes=$,jQuery!jquery';
import 'expose-loader?exposes=m!mithril';
import 'expose-loader?exposes=dayjs!dayjs';
import 'bootstrap/js/affix';
import 'bootstrap/js/dropdown';
import 'bootstrap/js/modal';

View File

@@ -1,4 +1,4 @@
import Mithril from 'mithril';
import Component from '../Component';
/**
* Generates a route resolver for a given component.
@@ -7,7 +7,7 @@ import Mithril from 'mithril';
* - It sets a key on the component so a rerender will be triggered on route change.
*/
export default class DefaultResolver {
component: Mithril.Component;
component: Component | Function;
routeName: string;
constructor(component, routeName) {
@@ -31,8 +31,13 @@ export default class DefaultResolver {
};
}
onmatch(args, requestedPath, route) {
return this.component;
async onmatch(args, requestedPath, route) {
if (typeof this.component.component === 'function') {
return this.component;
} else {
const component = await this.component();
return component.default;
}
}
render(vnode) {

View File

@@ -10,12 +10,17 @@ export default class ModalManagerState {
*
* @public
*/
show(componentClass, attrs) {
async show(componentClass, attrs) {
// Breaking Change Compliance Warning, Remove in Beta 15.
if (!(componentClass.prototype instanceof Modal)) {
// This is duplicated so that if the error is caught, an error message still shows up in the debug console.
console.error('The ModalManager can only show Modals');
throw new Error('The ModalManager can only show Modals');
if (typeof componentClass === 'function') {
const componentResolver = await componentClass();
componentClass = componentResolver.default;
} else {
// This is duplicated so that if the error is caught, an error message still shows up in the debug console.
console.error('The ModalManager can only show Modals');
throw new Error('The ModalManager can only show Modals');
}
}
if (componentClass.init) {
// This is duplicated so that if the error is caught, an error message still shows up in the debug console.

View File

@@ -7,7 +7,7 @@ export default class Drawer {
constructor() {
// Set up an event handler so that whenever the content area is tapped,
// the drawer will close.
$('#content').click((e) => {
$('#content').on('click tap', e => {
if (this.isOpen()) {
e.preventDefault();
this.hide();
@@ -31,7 +31,24 @@ export default class Drawer {
* @public
*/
hide() {
$('#app').removeClass('drawerOpen');
/**
* As part of hiding the drawer, this function also ensures that the drawer
* correctly animates out, while ensuring it is not part of the navigation
* tree while off-screen.
*
* More info: https://github.com/flarum/core/pull/2666#discussion_r595381014
*/
const $app = $('#app');
if (!$app.hasClass('drawerOpen')) return;
const $drawer = $('#drawer');
// Used to prevent `visibility: hidden` from breaking the exit animation
$drawer.css('visibility', 'visible').one('transitionend', () => $drawer.css('visibility', ''));
$app.removeClass('drawerOpen');
if (this.$backdrop) this.$backdrop.remove();
}

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