mirror of
https://github.com/flarum/core.git
synced 2025-08-13 11:54:32 +02:00
Compare commits
195 Commits
cw/conditi
...
v1.8.2
Author | SHA1 | Date | |
---|---|---|---|
|
82e08e3fa5 | ||
|
2c4a2b8d9e | ||
|
00866fbba9 | ||
|
0d1d4d46d1 | ||
|
b1383a955f | ||
|
daeab48ae8 | ||
|
e03ca4406d | ||
|
7894c6a69b | ||
|
102e31754a | ||
|
8538f9c8f6 | ||
|
5a4bb7ccf2 | ||
|
d2a6329689 | ||
|
2bc2899a1d | ||
|
5437bf5c23 | ||
|
717af13bb1 | ||
|
e72541e35d | ||
|
577890d89c | ||
|
253a3d281d | ||
|
d27f952584 | ||
|
e5abffc75b | ||
|
d1059c1cc7 | ||
|
777c304ab7 | ||
|
789246b621 | ||
|
980cfd6c28 | ||
|
65390a4fc0 | ||
|
c7c86a77e9 | ||
|
f1f6051deb | ||
|
bded3da42d | ||
|
231cee1f78 | ||
|
f6c9bbb427 | ||
|
feb968780a | ||
|
5b89d3e91a | ||
|
ba7599e6fe | ||
|
80b34d1164 | ||
|
3accdc322c | ||
|
4247e54c64 | ||
|
ef35faaded | ||
|
715b8c39ae | ||
|
232618aba6 | ||
|
96e1411b7d | ||
|
21b483625e | ||
|
9363682e1c | ||
|
c766881e1f | ||
|
e63e161be6 | ||
|
3264455068 | ||
|
d7fcd8a9e5 | ||
|
b4f3f0558e | ||
|
919c3bb770 | ||
|
7298ccb301 | ||
|
cfdd6910eb | ||
|
7ebeb9c0a5 | ||
|
af3f91ca5b | ||
|
4784307e26 | ||
|
105b22976e | ||
|
fea31a8290 | ||
|
accdfde6e1 | ||
|
7684a1086a | ||
|
f8577c8078 | ||
|
e55844f3db | ||
|
1d20f4d4aa | ||
|
803f0cd0f4 | ||
|
8576df1a43 | ||
|
1792e22639 | ||
|
5e281136f6 | ||
|
b868c3d763 | ||
|
297a2d8c5c | ||
|
c0af41c305 | ||
|
d0669b08aa | ||
|
6b8e9ce1db | ||
|
fbbece4bda | ||
|
13e655aca5 | ||
|
c00e8706e1 | ||
|
1b5da13e8a | ||
|
ecfbcd1c30 | ||
|
818a100625 | ||
|
176b5540d8 | ||
|
2e76a8ecb5 | ||
|
11aa7bbb35 | ||
|
3a26c29935 | ||
|
94e92cf24e | ||
|
aa33cfd1f8 | ||
|
4901c586ce | ||
|
7a6d477550 | ||
|
b89a01c010 | ||
|
8b11fef3ee | ||
|
8a114cd826 | ||
|
62c93b4a05 | ||
|
fab71f2d01 | ||
|
e8c867dcac | ||
|
1247a7f1dd | ||
|
b0aad1a2d6 | ||
|
bddc9d96f2 | ||
|
d684248492 | ||
|
85b63681ae | ||
|
8372363cc2 | ||
|
a6a067ad48 | ||
|
241eba4d0c | ||
|
a6b12826c3 | ||
|
dd868ab44e | ||
|
5f3e0d6a09 | ||
|
661b9d7d9a | ||
|
b7498d6cb1 | ||
|
e7c55532a0 | ||
|
cce6b74fce | ||
|
da651c722b | ||
|
abc9670659 | ||
|
b66fe5dd5f | ||
|
7d79895ae0 | ||
|
3ab4529232 | ||
|
360a2ba1d8 | ||
|
eaa4063fef | ||
|
72d277bd45 | ||
|
28e3ccfde6 | ||
|
3f864bafc8 | ||
|
3af0481f30 | ||
|
1761660c98 | ||
|
8ddb0feb09 | ||
|
fa30f4f250 | ||
|
79a9b23096 | ||
|
33e2bd1a77 | ||
|
a3a39caa44 | ||
|
bbf873442a | ||
|
d35bb873a8 | ||
|
598ff21d7d | ||
|
9342903d68 | ||
|
ea7b270f47 | ||
|
906b0fb633 | ||
|
408a92b4ea | ||
|
0da069ba9f | ||
|
d8fa791d9c | ||
|
fee6ffe396 | ||
|
7a60a529da | ||
|
37fd218723 | ||
|
1ee5cf6ba9 | ||
|
ced1c2d94f | ||
|
f8d856028d | ||
|
748cca6d12 | ||
|
f4f8369dc0 | ||
|
aa0b3288d5 | ||
|
153bb1a53c | ||
|
ee1e04cdc2 | ||
|
77a0b11bc8 | ||
|
7e6458a125 | ||
|
675cdab658 | ||
|
e7fc29a59f | ||
|
08dead81ce | ||
|
47b670aa29 | ||
|
f9a5d485c3 | ||
|
5717a74fcc | ||
|
2e0f026dde | ||
|
bf52743510 | ||
|
da1bf8da21 | ||
|
ccf9442d79 | ||
|
4bb3b2235d | ||
|
03d2d7eabb | ||
|
4d292263b5 | ||
|
6adae00f72 | ||
|
d7f4975330 | ||
|
5fe3cfd837 | ||
|
2d2bf5c504 | ||
|
a4f4ee8e71 | ||
|
4a38047bfb | ||
|
d5e6f6db5f | ||
|
20e7d245da | ||
|
243bc139b0 | ||
|
adf78bbd95 | ||
|
c8d9f1111e | ||
|
e5f05166a0 | ||
|
02556c6ca6 | ||
|
666223fa8c | ||
|
12dfcc5c79 | ||
|
248a71d9b5 | ||
|
a131e87911 | ||
|
be63b28437 | ||
|
132fdea659 | ||
|
fe8480c8f7 | ||
|
1e8a0f930d | ||
|
d7b9a03f31 | ||
|
78189f29d2 | ||
|
07f8b6161a | ||
|
0eff1f6b2d | ||
|
a53a0db2b7 | ||
|
a129999132 | ||
|
8f80cde5b7 | ||
|
4de3cd4d9c | ||
|
3dd2cadb9b | ||
|
605225c851 | ||
|
f33fbdd0b5 | ||
|
5bc47c0278 | ||
|
0e238a9c82 | ||
|
64fa35f2f3 | ||
|
c99d04fce2 | ||
|
67c0d75ebc | ||
|
6f4f964ce8 | ||
|
67dd2c21b6 |
@@ -18,7 +18,7 @@ trim_trailing_whitespace = false
|
|||||||
[*.{php,xml,json}]
|
[*.{php,xml,json}]
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
|
||||||
[tsconfig.json]
|
[{tsconfig.json,prettierrc.json}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
[*.neon]
|
[*.neon]
|
||||||
|
19
.github/workflows/REUSABLE_backend.yml
vendored
19
.github/workflows/REUSABLE_backend.yml
vendored
@@ -25,7 +25,7 @@ on:
|
|||||||
description: Versions of PHP to test with. Should be array of strings encoded as JSON array
|
description: Versions of PHP to test with. Should be array of strings encoded as JSON array
|
||||||
type: string
|
type: string
|
||||||
required: false
|
required: false
|
||||||
default: '["7.3", "7.4", "8.0", "8.1"]'
|
default: '["7.3", "7.4", "8.0", "8.1", "8.2"]'
|
||||||
|
|
||||||
php_extensions:
|
php_extensions:
|
||||||
description: PHP extensions to install.
|
description: PHP extensions to install.
|
||||||
@@ -58,6 +58,7 @@ jobs:
|
|||||||
php: ${{ fromJSON(inputs.php_versions) }}
|
php: ${{ fromJSON(inputs.php_versions) }}
|
||||||
service: ${{ fromJSON(inputs.db_versions) }}
|
service: ${{ fromJSON(inputs.db_versions) }}
|
||||||
prefix: ['']
|
prefix: ['']
|
||||||
|
php_ini_values: [inputs.php_ini_values]
|
||||||
|
|
||||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude
|
||||||
include:
|
include:
|
||||||
@@ -86,12 +87,24 @@ jobs:
|
|||||||
prefix: flarum_
|
prefix: flarum_
|
||||||
prefixStr: (prefix)
|
prefixStr: (prefix)
|
||||||
|
|
||||||
|
# @TODO: remove in 2.0
|
||||||
|
# Include testing PHP 8.2 with deprecation warnings disabled.
|
||||||
|
- php: 8.2
|
||||||
|
php_ini_values: error_reporting=E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED
|
||||||
|
|
||||||
# To reduce number of actions, we exclude some PHP versions from running with some DB versions.
|
# To reduce number of actions, we exclude some PHP versions from running with some DB versions.
|
||||||
exclude:
|
exclude:
|
||||||
- php: ${{ fromJSON(inputs.php_versions)[1] }}
|
- php: ${{ fromJSON(inputs.php_versions)[1] }}
|
||||||
service: 'mysql:8.0.30'
|
service: 'mysql:8.0.30'
|
||||||
- php: ${{ fromJSON(inputs.php_versions)[2] }}
|
- php: ${{ fromJSON(inputs.php_versions)[2] }}
|
||||||
service: 'mysql:8.0.30'
|
service: 'mysql:8.0.30'
|
||||||
|
- php: ${{ fromJSON(inputs.php_versions)[3] }}
|
||||||
|
service: 'mysql:8.0.30'
|
||||||
|
|
||||||
|
# @TODO: remove in 2.0
|
||||||
|
# Exclude testing PHP 8.2 with deprecation warnings enabled.
|
||||||
|
- php: 8.2
|
||||||
|
php_ini_values: error_reporting=E_ALL
|
||||||
|
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
@@ -115,7 +128,7 @@ jobs:
|
|||||||
coverage: xdebug
|
coverage: xdebug
|
||||||
extensions: ${{ inputs.php_extensions }}
|
extensions: ${{ inputs.php_extensions }}
|
||||||
tools: phpunit, composer:v2
|
tools: phpunit, composer:v2
|
||||||
ini-values: ${{ inputs.php_ini_values }}
|
ini-values: ${{ matrix.php_ini_values }}
|
||||||
|
|
||||||
# The authentication alter is necessary because newer mysql versions use the `caching_sha2_password` driver,
|
# The authentication alter is necessary because newer mysql versions use the `caching_sha2_password` driver,
|
||||||
# which isn't supported prior to PHP7.4
|
# which isn't supported prior to PHP7.4
|
||||||
@@ -167,7 +180,7 @@ jobs:
|
|||||||
coverage: xdebug
|
coverage: xdebug
|
||||||
extensions: ${{ inputs.php_extensions }}
|
extensions: ${{ inputs.php_extensions }}
|
||||||
tools: phpunit, composer:v2
|
tools: phpunit, composer:v2
|
||||||
ini-values: ${{ inputs.php_ini_values }}
|
ini-values: ${{ matrix.php_ini_values }}
|
||||||
|
|
||||||
- name: Install Composer dependencies
|
- name: Install Composer dependencies
|
||||||
run: composer install
|
run: composer install
|
||||||
|
19
.github/workflows/REUSABLE_frontend.yml
vendored
19
.github/workflows/REUSABLE_frontend.yml
vendored
@@ -28,6 +28,11 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
required: false
|
required: false
|
||||||
default: check-typings-coverage
|
default: check-typings-coverage
|
||||||
|
test_script:
|
||||||
|
description: "Script to run for tests. Empty value to disable."
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
default: test
|
||||||
|
|
||||||
enable_bundlewatch:
|
enable_bundlewatch:
|
||||||
description: "Enable Bundlewatch?"
|
description: "Enable Bundlewatch?"
|
||||||
@@ -44,6 +49,11 @@ on:
|
|||||||
type: boolean
|
type: boolean
|
||||||
default: true
|
default: true
|
||||||
required: false
|
required: false
|
||||||
|
enable_tests:
|
||||||
|
description: "Enable Tests?"
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
required: false
|
||||||
|
|
||||||
backend_directory:
|
backend_directory:
|
||||||
description: The directory of the project where backend code is located. This should contain a `composer.json` file, and is generally the root directory of the repo.
|
description: The directory of the project where backend code is located. This should contain a `composer.json` file, and is generally the root directory of the repo.
|
||||||
@@ -96,10 +106,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: ${{ inputs.node_version }}
|
node-version: ${{ inputs.node_version }}
|
||||||
cache: ${{ inputs.js_package_manager }}
|
cache: ${{ inputs.js_package_manager }}
|
||||||
@@ -108,7 +118,7 @@ jobs:
|
|||||||
- name: Setup PHP
|
- name: Setup PHP
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
php-version: '8.0'
|
php-version: '8.2'
|
||||||
extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip
|
extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip
|
||||||
tools: composer:v2
|
tools: composer:v2
|
||||||
|
|
||||||
@@ -122,7 +132,7 @@ jobs:
|
|||||||
working-directory: ${{ inputs.frontend_directory }}
|
working-directory: ${{ inputs.frontend_directory }}
|
||||||
|
|
||||||
- name: JS Checks & Production Build
|
- name: JS Checks & Production Build
|
||||||
uses: flarum/action-build@3
|
uses: flarum/action-build@v3
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
build_script: ${{ inputs.build_script }}
|
build_script: ${{ inputs.build_script }}
|
||||||
@@ -130,6 +140,7 @@ jobs:
|
|||||||
format_script: ${{ inputs.enable_prettier == true && inputs.format_script || '' }}
|
format_script: ${{ inputs.enable_prettier == true && inputs.format_script || '' }}
|
||||||
check_typings_script: ${{ inputs.enable_typescript == true && inputs.check_typings_script || '' }}
|
check_typings_script: ${{ inputs.enable_typescript == true && inputs.check_typings_script || '' }}
|
||||||
type_coverage_script: ${{ inputs.enable_typescript == true && inputs.type_coverage_script || '' }}
|
type_coverage_script: ${{ inputs.enable_typescript == true && inputs.type_coverage_script || '' }}
|
||||||
|
test_script: ${{ inputs.enable_tests == true && inputs.test_script || '' }}
|
||||||
package_manager: ${{ inputs.js_package_manager }}
|
package_manager: ${{ inputs.js_package_manager }}
|
||||||
js_path: ${{ inputs.frontend_directory }}
|
js_path: ${{ inputs.frontend_directory }}
|
||||||
do_not_commit: ${{ github.ref != format('refs/heads/{0}', inputs.main_git_branch) || github.event_name != 'push' }}
|
do_not_commit: ${{ github.ref != format('refs/heads/{0}', inputs.main_git_branch) || github.event_name != 'push' }}
|
||||||
|
@@ -6,6 +6,6 @@ jobs:
|
|||||||
run:
|
run:
|
||||||
uses: ./.github/workflows/REUSABLE_backend.yml
|
uses: ./.github/workflows/REUSABLE_backend.yml
|
||||||
with:
|
with:
|
||||||
enable_backend_testing: true
|
enable_backend_testing: false
|
||||||
|
|
||||||
backend_directory: ./extensions/package-manager
|
backend_directory: ./extensions/package-manager
|
||||||
|
5
.github/workflows/frontend.yml
vendored
5
.github/workflows/frontend.yml
vendored
@@ -10,7 +10,10 @@ jobs:
|
|||||||
backend_directory: ./
|
backend_directory: ./
|
||||||
js_package_manager: yarn
|
js_package_manager: yarn
|
||||||
cache_dependency_path: ./yarn.lock
|
cache_dependency_path: ./yarn.lock
|
||||||
main_git_branch: main
|
main_git_branch: 1.x
|
||||||
|
enable_tests: true
|
||||||
|
# @TODO: fix bundlewatch
|
||||||
|
enable_bundlewatch: false
|
||||||
|
|
||||||
secrets:
|
secrets:
|
||||||
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
|
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
|
||||||
|
8
.github/workflows/prepare-release.yml
vendored
8
.github/workflows/prepare-release.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Prepare release
|
- name: Prepare release
|
||||||
uses: flarum/action-release@master
|
uses: flarum/action-release@master
|
||||||
env:
|
with:
|
||||||
NEXT_TAG: ${{ inputs.version }}
|
next_tag: ${{ inputs.version }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
OPEN_COLLECTIVE_TOKEN: ${{ secrets.OPEN_COLLECTIVE_TOKEN }}
|
open_collective_token: ${{ secrets.OPEN_COLLECTIVE_TOKEN }}
|
||||||
|
130
CHANGELOG.md
130
CHANGELOG.md
@@ -1,5 +1,135 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [v1.8.2](https://github.com/flarum/framework/compare/v1.8.1...v1.8.2)
|
||||||
|
### Fixed
|
||||||
|
* suspended users can abuse avatar upload [#3890]
|
||||||
|
* missing compat exports [#3888]
|
||||||
|
|
||||||
|
## [v1.8.1](https://github.com/flarum/framework/compare/v1.8.0...v1.8.1)
|
||||||
|
### Fixed
|
||||||
|
* recover temporary solution for html entities in browser title (e72541e35de4f71f9d870bbd9bb46ddf586bdf1d)
|
||||||
|
* custom contrast color affected by parents (577890d89c593ae5b6cb96083fab69e2f1ae600c)
|
||||||
|
* reply placeholder wrong positioning (253a3d281dbf5ce3fa712b629b80587cf67e7dbe)
|
||||||
|
* (mentions) missed post mentions UI changes with lazy loading [#3832]
|
||||||
|
* (mentions) cannot use newly introduced mentionables extender [#3849]
|
||||||
|
* (mentions) missing slug from post mention links ([5a4bb7c](5a4bb7ccf226f66dd44816cb69b3d7cfe4ad7f7c))
|
||||||
|
|
||||||
|
## [v1.8.0](https://github.com/flarum/framework/compare/v1.7.1...v1.8.0)
|
||||||
|
### Fixed
|
||||||
|
- (a11y) reply placeholder not accessible [#3793]
|
||||||
|
- (bbcode) highlight.js does not work after changing post content [#3817]
|
||||||
|
- (bbcode) localize quote `wrote` string [#3809]
|
||||||
|
- (mentions) mentions XHR fired even after mentioning is done [#3806]
|
||||||
|
- (package-manager) available core updates cause an error in the dashboard ([fab71f2](fab71f2d01fa20ce9b3002833339dc5ea3ea6301))
|
||||||
|
- (tags) not all tags are loaded in the permission grid [#3804]
|
||||||
|
- (tags) tag discussion modal filters with exact matches only after first index [#3786]
|
||||||
|
- (testing) always clear cache in integration test's tearDown [#3818]
|
||||||
|
- `UserSecurityPage` not exported ([232618a](232618aba604ab003425df38b895208c863d3260))
|
||||||
|
- `isDark()` utility can receive null value [#3774]
|
||||||
|
- approving a post does not bump user `comment_count` [#3790]
|
||||||
|
- circular dependencies disable all involved extensions [#3785]
|
||||||
|
- color input overflowing the input box [#3796]
|
||||||
|
- deleting a discussion from the profile does not visually remove it [#3799]
|
||||||
|
- discussion page showing horizontal scroll on iOS [#3821]
|
||||||
|
- empty string displayed as SelectDropdown title [#3773]
|
||||||
|
- filter values are not validated [#3795]
|
||||||
|
- infinite scroll not initialized for notifications on big screens [#3733]
|
||||||
|
- notification subject discussion eager loading fails [#3788]
|
||||||
|
- null as 2nd param in `preg_match` is deprecated [#3801]
|
||||||
|
- unread count in post stream not visible [#3791]
|
||||||
|
- unreadable badge icon on certain colors [#3810]
|
||||||
|
- integrity constraint violation [#3772]
|
||||||
|
### Changed
|
||||||
|
- (core,mentions) limit `mentionedBy` post relation results [#3780]
|
||||||
|
- (likes) limit `likes` relationship results [#3781]
|
||||||
|
- Change some methods from private to protected, to be able to extend the affected classes [#3802]
|
||||||
|
- Do not catch exceptions when testing Console commands [#3813]
|
||||||
|
- drop usage of jquery in `install` and `update` interfaces [#3797]
|
||||||
|
- extensibility improvements [#3729]
|
||||||
|
- major frontend JS cleanup [#3609]
|
||||||
|
- revert ineffective code for encoding of page title [#3768]
|
||||||
|
- speed up post creation time [#3808]
|
||||||
|
### Added
|
||||||
|
- (mentions,tags) tag mentions [#3769]
|
||||||
|
- add delete own posts permission [#3784]
|
||||||
|
- add a trait to flush the formatter cache in tests [#3811]
|
||||||
|
- add user creation to users list page [#3744]
|
||||||
|
- cli command for enabling or disabling an extension [#3816]
|
||||||
|
- conditional extenders [#3759]
|
||||||
|
- provide old content to `Revised` event [#3789]
|
||||||
|
|
||||||
|
## [v1.7.1](https://github.com/flarum/framework/compare/v1.7.0...v1.7.1)
|
||||||
|
### Fixed
|
||||||
|
- (tags) composer tag selection modal using wrong primary max & min numbers (abc9670659426b765274376945b818b70d84848c)
|
||||||
|
- missing parameter names in token title translation. (#3752)
|
||||||
|
- hardcoded language strings in StatusWidget (#3754)
|
||||||
|
- hide developer tokens section in if there is nothing to display or create (#3753)
|
||||||
|
- improve sessions user UI on mobile (dd868ab44e11e892d020e3b9412553c6a789e68d)
|
||||||
|
|
||||||
|
## [v1.7.0](https://github.com/flarum/framework/compare/v1.6.3...v1.7.0)
|
||||||
|
### Added
|
||||||
|
- (actions) allow running JS tests in GH actions [#3730]
|
||||||
|
- (core) PHP 8.2 Support [#3709]
|
||||||
|
- (jest) create jest config package for unit testing [#3678]
|
||||||
|
- (jest) mithril component testing [#3679]
|
||||||
|
- (phpstan) foundation for usage in extensions [#3666]
|
||||||
|
- (seo) Do not use h3 header for poster author in posts stream [#3732]
|
||||||
|
- (seo) Use h2 header for discussions on discussions list [#3731]
|
||||||
|
- (seo) shift h1 tag from logo to discussion title [#3724]
|
||||||
|
- (tags) admin tag selection component (reusable tag selection modal) [#3686]
|
||||||
|
- Admin User Search [#3712]
|
||||||
|
- access tokens user management UI [#3587]
|
||||||
|
- add display name column to admin users list [#3740]
|
||||||
|
- allow push additional items to the end of the poststream [#3691]
|
||||||
|
- allow using utf8 characters in tag slugs [#3588]
|
||||||
|
- expose queue driver, schedule status [#3593]
|
||||||
|
- expose {time} to eventPost data, fix renamed tooltip [#3698]
|
||||||
|
- frontend `Model` extender [#3646]
|
||||||
|
- global logout to clear all sessions, access tokens, email tokens and password tokens [#3605]
|
||||||
|
- improved page navigation for users list [#3741]
|
||||||
|
- introduce frontend extenders [#3645]
|
||||||
|
### Fixed
|
||||||
|
- (mentions) correctly convert a 3 char. hex color to a 6 char. one [#3694]
|
||||||
|
- (mentions) post reply mention missing notification on approval [#3738]
|
||||||
|
- (phpstan) adapt phpstan package for extension use [#3727]
|
||||||
|
- (tags) clickable tag labels have underline [#3737]
|
||||||
|
- (tags) tag text color contrast [#3653]
|
||||||
|
- 3 digit hex color value in color input not supported [#3706]
|
||||||
|
- column `id` can be ambiguous in group filter with extensions [#3696]
|
||||||
|
- disallow certain dangerous LESS features ([1761660](1761660c98ea5a3e9665fb8e6041d1f2ee62a444))
|
||||||
|
- evaluated page title content [#3684]
|
||||||
|
- invalid translation key for scheduler dashboard [#3736]
|
||||||
|
- load actor.groups on showforumcontroller [#3716]
|
||||||
|
- make go-to-page input number-like [#3743]
|
||||||
|
- normal logout affects all sessions [#3571]
|
||||||
|
- permissions table on mobile is unusable [#3722]
|
||||||
|
- post dropdown opens all dropdowns in `.Post-actions` [#3675]
|
||||||
|
- typo in Formatter extender docblock [#3676]
|
||||||
|
- undefined showing in dropdown active title [#3700]
|
||||||
|
### Changed
|
||||||
|
- (phpstan) enable phpstan in bundled extensions [#3667]
|
||||||
|
- Add missing states exports to `compat.ts` [#3683]
|
||||||
|
- Indicate cross-origin request in generic error message [#3669]
|
||||||
|
- Merge branch 'release/v1.6.2' ([e0b9dcf](e0b9dcfbcd7db175368dbc98255f9223da8df17d))
|
||||||
|
- The negate field doesn't get used, which means you cant exclude tags [#3713]
|
||||||
|
- Update forum.less to fix the misalignment of the choose tags button [#3726]
|
||||||
|
- `yarn audit-fix` ([8ddb0fe](8ddb0feb097dad06c5763107d7a7f7b5a55562c4))
|
||||||
|
- `yarn` ([ee1e04c](ee1e04cdc26b3e63057a58899f32f482901a95fd))
|
||||||
|
- convert `Dropdown` components to TS [#3608]
|
||||||
|
- fix php 8.1 on preg_match 2nd argument being null, which also optimizes slightly ([d7b9a03](d7b9a03f31847c39631ba495df8f515509774610))
|
||||||
|
- improve group mentions parsing [#3723]
|
||||||
|
- prepare `@flarum/jest-config` for release ([748cca6](748cca6d12f8b1744a6017c09395725bdbb4a118))
|
||||||
|
- remove use of deprecated phpunit assertion ([3af0481](3af0481f304277f5380fac9c9b169a7fa651f53b))
|
||||||
|
- set flarum version to 1.7.0 for dev ([2517bc0](2517bc0f70b0f0e3d3ea3f6ae06af8604d89b25d))
|
||||||
|
- update JS dependencies [#3695]
|
||||||
|
|
||||||
|
## [v1.6.3](https://github.com/flarum/framework/compare/v1.6.2...v1.6.3)
|
||||||
|
### Fixed
|
||||||
|
* Post mentions can be used to read any post on the forum without access control (ab1c868b978e8b0d09a5d682c54665dae17d0985).
|
||||||
|
* Notifications can leak restricted content (d0a2b95dca57d3dae9a0d77b610b1cb1d0b1766a).
|
||||||
|
* Any user including unactivated can reply in public discussions whose first post was permanently deleted (12f14112a0ecd1484d97330b82beb2a145919015).
|
||||||
|
* (subscriptions) Post notifications not getting access checked (https://github.com/flarum/framework/commit/e5f05166a062a9a6eb7c12e28728bfd5db7270e3).
|
||||||
|
|
||||||
## [v1.6.2](https://github.com/flarum/framework/compare/v1.6.1...v1.6.2)
|
## [v1.6.2](https://github.com/flarum/framework/compare/v1.6.1...v1.6.2)
|
||||||
### Fixed
|
### Fixed
|
||||||
* XSS Vulnerability in core (https://github.com/flarum/framework/pull/3684).
|
* XSS Vulnerability in core (https://github.com/flarum/framework/pull/3684).
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
"Flarum\\": "framework/core/src",
|
"Flarum\\": "framework/core/src",
|
||||||
"Flarum\\Akismet\\": "extensions/akismet/src",
|
"Flarum\\Akismet\\": "extensions/akismet/src",
|
||||||
"Flarum\\Approval\\": "extensions/approval/src",
|
"Flarum\\Approval\\": "extensions/approval/src",
|
||||||
|
"Flarum\\BBCode\\": "extensions/bbcode/src",
|
||||||
"Flarum\\Flags\\": "extensions/flags/src",
|
"Flarum\\Flags\\": "extensions/flags/src",
|
||||||
"Flarum\\Likes\\": "extensions/likes/src",
|
"Flarum\\Likes\\": "extensions/likes/src",
|
||||||
"Flarum\\Lock\\": "extensions/lock/src",
|
"Flarum\\Lock\\": "extensions/lock/src",
|
||||||
@@ -84,8 +85,8 @@
|
|||||||
"flarum/testing": "self.version"
|
"flarum/testing": "self.version"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-json": "*",
|
|
||||||
"php": ">=7.3",
|
"php": ">=7.3",
|
||||||
|
"ext-json": "*",
|
||||||
"components/font-awesome": "^5.14.0",
|
"components/font-awesome": "^5.14.0",
|
||||||
"composer/composer": "^2.0",
|
"composer/composer": "^2.0",
|
||||||
"dflydev/fig-cookies": "^3.0.0",
|
"dflydev/fig-cookies": "^3.0.0",
|
||||||
@@ -110,8 +111,9 @@
|
|||||||
"illuminate/validation": "^8.0",
|
"illuminate/validation": "^8.0",
|
||||||
"illuminate/view": "^8.0",
|
"illuminate/view": "^8.0",
|
||||||
"intervention/image": "2.5.* || ^2.6.1",
|
"intervention/image": "2.5.* || ^2.6.1",
|
||||||
|
"jenssegers/agent": "^2.6",
|
||||||
"laminas/laminas-diactoros": "^2.4.1",
|
"laminas/laminas-diactoros": "^2.4.1",
|
||||||
"laminas/laminas-httphandlerrunner": "^1.2.0",
|
"laminas/laminas-httphandlerrunner": "^1.2.0 || ^2.3.0",
|
||||||
"laminas/laminas-stratigility": "^3.2.2",
|
"laminas/laminas-stratigility": "^3.2.2",
|
||||||
"league/flysystem": "^1.0.11",
|
"league/flysystem": "^1.0.11",
|
||||||
"matthiasmullie/minify": "^1.3",
|
"matthiasmullie/minify": "^1.3",
|
||||||
@@ -126,6 +128,7 @@
|
|||||||
"psr/http-server-middleware": "^1.0",
|
"psr/http-server-middleware": "^1.0",
|
||||||
"pusher/pusher-php-server": "^2.2",
|
"pusher/pusher-php-server": "^2.2",
|
||||||
"s9e/text-formatter": "^2.3.6",
|
"s9e/text-formatter": "^2.3.6",
|
||||||
|
"staudenmeir/eloquent-eager-limit": "^1.0",
|
||||||
"sycho/json-api": "^0.5.0",
|
"sycho/json-api": "^0.5.0",
|
||||||
"sycho/sourcemap": "^2.0.0",
|
"sycho/sourcemap": "^2.0.0",
|
||||||
"symfony/config": "^5.2.2",
|
"symfony/config": "^5.2.2",
|
||||||
@@ -180,7 +183,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"analyse:phpstan": "phpstan analyse"
|
"analyse:phpstan": "phpstan analyse",
|
||||||
|
"clear-cache:phpstan": "phpstan clear-result-cache"
|
||||||
},
|
},
|
||||||
"scripts-descriptions": {
|
"scripts-descriptions": {
|
||||||
"analyse:phpstan": "Run static analysis"
|
"analyse:phpstan": "Run static analysis"
|
||||||
|
@@ -19,8 +19,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^1.6",
|
"flarum/core": "^1.8",
|
||||||
"flarum/approval": "^1.2"
|
"flarum/approval": "^1.7"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
@@ -13,6 +13,7 @@ use Flarum\Approval\Event\PostWasApproved;
|
|||||||
use Flarum\Extend;
|
use Flarum\Extend;
|
||||||
use Flarum\Post\Event\Hidden;
|
use Flarum\Post\Event\Hidden;
|
||||||
use Flarum\Post\Event\Saving;
|
use Flarum\Post\Event\Saving;
|
||||||
|
use Flarum\Post\Post;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
(new Extend\Frontend('forum'))
|
(new Extend\Frontend('forum'))
|
||||||
@@ -30,4 +31,7 @@ return [
|
|||||||
|
|
||||||
(new Extend\ServiceProvider())
|
(new Extend\ServiceProvider())
|
||||||
->register(AkismetProvider::class),
|
->register(AkismetProvider::class),
|
||||||
|
|
||||||
|
(new Extend\Model(Post::class))
|
||||||
|
->cast('is_spam', 'bool'),
|
||||||
];
|
];
|
||||||
|
2
extensions/akismet/js/dist/admin.js.map
generated
vendored
2
extensions/akismet/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,IACzBH,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,kBAAkB,WACrCA,IAAAA,cAAAA,IACO,kBACJC,gBAAgB,CACfC,QAAS,yBACTC,KAAM,OACNC,MAAOJ,IAAAA,WAAAA,MAAqB,yDAE7BC,gBAAgB,CAEfC,QAAS,qCACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,mEAC5BK,KAAML,IAAAA,WAAAA,MAAqB,oEAE5BM,mBACC,CACEC,KAAM,kBACNH,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BQ,WAAY,iBAEd,QAEL,G","sources":["webpack://@flarum/akismet/webpack/bootstrap","webpack://@flarum/akismet/webpack/runtime/compat get default export","webpack://@flarum/akismet/webpack/runtime/define property getters","webpack://@flarum/akismet/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/akismet/webpack/runtime/make namespace object","webpack://@flarum/akismet/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/akismet/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-akismet', () => {\n app.extensionData\n .for('flarum-akismet')\n .registerSetting({\n setting: 'flarum-akismet.api_key',\n type: 'text',\n label: app.translator.trans('flarum-akismet.admin.akismet_settings.api_key_label'),\n })\n .registerSetting({\n //https://blog.akismet.com/2014/04/23/theres-a-ninja-in-your-akismet/\n setting: 'flarum-akismet.delete_blatant_spam',\n type: 'boolean',\n label: app.translator.trans('flarum-akismet.admin.akismet_settings.delete_blatant_spam_label'),\n help: app.translator.trans('flarum-akismet.admin.akismet_settings.delete_blatant_spam_help'),\n })\n .registerPermission(\n {\n icon: 'fas fa-vote-yea',\n label: app.translator.trans('flarum-akismet.admin.permissions.bypass_akismet'),\n permission: 'bypassAkismet',\n },\n 'start'\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","help","registerPermission","icon","permission"],"sourceRoot":""}
|
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,IACzBH,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,kBAAkB,WACrCA,IAAAA,cAAAA,IACO,kBACJC,gBAAgB,CACfC,QAAS,yBACTC,KAAM,OACNC,MAAOJ,IAAAA,WAAAA,MAAqB,yDAE7BC,gBAAgB,CAEfC,QAAS,qCACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,mEAC5BK,KAAML,IAAAA,WAAAA,MAAqB,oEAE5BM,mBACC,CACEC,KAAM,kBACNH,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BQ,WAAY,iBAEd,QAEN,G","sources":["webpack://@flarum/akismet/webpack/bootstrap","webpack://@flarum/akismet/webpack/runtime/compat get default export","webpack://@flarum/akismet/webpack/runtime/define property getters","webpack://@flarum/akismet/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/akismet/webpack/runtime/make namespace object","webpack://@flarum/akismet/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/akismet/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-akismet', () => {\n app.extensionData\n .for('flarum-akismet')\n .registerSetting({\n setting: 'flarum-akismet.api_key',\n type: 'text',\n label: app.translator.trans('flarum-akismet.admin.akismet_settings.api_key_label'),\n })\n .registerSetting({\n //https://blog.akismet.com/2014/04/23/theres-a-ninja-in-your-akismet/\n setting: 'flarum-akismet.delete_blatant_spam',\n type: 'boolean',\n label: app.translator.trans('flarum-akismet.admin.akismet_settings.delete_blatant_spam_label'),\n help: app.translator.trans('flarum-akismet.admin.akismet_settings.delete_blatant_spam_help'),\n })\n .registerPermission(\n {\n icon: 'fas fa-vote-yea',\n label: app.translator.trans('flarum-akismet.admin.permissions.bypass_akismet'),\n permission: 'bypassAkismet',\n },\n 'start'\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","help","registerPermission","icon","permission"],"sourceRoot":""}
|
2
extensions/akismet/js/dist/forum.js
generated
vendored
2
extensions/akismet/js/dist/forum.js
generated
vendored
@@ -1,2 +1,2 @@
|
|||||||
(()=>{var t={n:e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return t.d(o,{a:o}),o},d:(e,o)=>{for(var r in o)t.o(o,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};(()=>{"use strict";t.r(e);const o=flarum.core.compat["common/extend"],r=flarum.core.compat["forum/app"];var a=t.n(r);const n=flarum.core.compat["forum/utils/PostControls"];var m=t.n(n);const s=flarum.core.compat["forum/components/CommentPost"];var l=t.n(s);a().initializers.add("flarum-akismet",(function(){(0,o.extend)(m(),"destructiveControls",(function(t,e){if(t.has("approve")){var o=e.flags();if(o&&o.some((function(t){return"akismet"===(null==t?void 0:t.type())}))){var r=t.get("approve");r&&"object"==typeof r&&"children"in r&&(r.children=a().translator.trans("flarum-akismet.forum.post.not_spam_button"))}}})),(0,o.override)(l().prototype,"flagReason",(function(t,e){return"akismet"===e.type()?a().translator.trans("flarum-akismet.forum.post.akismet_flagged_text"):t(e)}))}))})(),module.exports=e})();
|
(()=>{var t={n:e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return t.d(o,{a:o}),o},d:(e,o)=>{for(var r in o)t.o(o,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};(()=>{"use strict";t.r(e);const o=flarum.core.compat["common/extend"],r=flarum.core.compat["forum/app"];var a=t.n(r);const n=flarum.core.compat["forum/utils/PostControls"];var s=t.n(n);const l=flarum.core.compat["forum/components/Post"];var u=t.n(l);a().initializers.add("flarum-akismet",(function(){(0,o.extend)(s(),"destructiveControls",(function(t,e){if(t.has("approve")){var o=e.flags();if(o&&o.some((function(t){return"akismet"===(null==t?void 0:t.type())}))){var r=t.get("approve");r&&"object"==typeof r&&"children"in r&&(r.children=a().translator.trans("flarum-akismet.forum.post.not_spam_button"))}}})),(0,o.override)(u().prototype,"flagReason",(function(t,e){return"akismet"===e.type()?a().translator.trans("flarum-akismet.forum.post.akismet_flagged_text"):t(e)}))}))})(),module.exports=e})();
|
||||||
//# sourceMappingURL=forum.js.map
|
//# sourceMappingURL=forum.js.map
|
2
extensions/akismet/js/dist/forum.js.map
generated
vendored
2
extensions/akismet/js/dist/forum.js.map
generated
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"forum.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,4B,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,gC,aCSxDC,IAAAA,aAAAA,IAAqB,kBAAkB,YACrCC,EAAAA,EAAAA,QAAOC,IAAc,uBAAuB,SAAUC,EAAmCC,GACvF,GAAID,EAAME,IAAI,WAAY,CACxB,IAAMC,EAAQF,EAAKE,QAEnB,GAAIA,GAASA,EAAMC,MAAK,SAACC,GAAD,MAA2B,aAAb,MAAJA,OAAA,EAAAA,EAAMC,OAAhB,IAAuC,CAC7D,IAAMC,EAAcP,EAAMf,IAAI,WAC1BsB,GAAsC,iBAAhBA,GAA4B,aAAcA,IAClEA,EAAYC,SAAWX,IAAAA,WAAAA,MAAqB,6CAE/C,CACF,CACF,KAEDY,EAAAA,EAAAA,UAASC,IAAAA,UAAuB,cAAc,SAAUC,EAAUN,GAChE,MAAoB,YAAhBA,EAAKC,OACAT,IAAAA,WAAAA,MAAqB,kDAGvBc,EAASN,EACjB,GACF,G","sources":["webpack://@flarum/akismet/webpack/bootstrap","webpack://@flarum/akismet/webpack/runtime/compat get default export","webpack://@flarum/akismet/webpack/runtime/define property getters","webpack://@flarum/akismet/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/akismet/webpack/runtime/make namespace object","webpack://@flarum/akismet/external root \"flarum.core.compat['common/extend']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/app']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/utils/PostControls']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/components/CommentPost']\"","webpack://@flarum/akismet/./src/forum/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/app'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/utils/PostControls'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/components/CommentPost'];","import { extend, override } from 'flarum/common/extend';\nimport app from 'flarum/forum/app';\nimport type Post from 'flarum/common/models/Post';\nimport type ItemList from 'flarum/common/utils/ItemList';\n\nimport PostControls from 'flarum/forum/utils/PostControls';\nimport CommentPost from 'flarum/forum/components/CommentPost';\nimport type Mithril from 'mithril';\n\napp.initializers.add('flarum-akismet', () => {\n extend(PostControls, 'destructiveControls', function (items: ItemList<Mithril.Children>, post: Post) {\n if (items.has('approve')) {\n const flags = post.flags();\n\n if (flags && flags.some((flag) => flag?.type() === 'akismet')) {\n const approveItem = items.get('approve');\n if (approveItem && typeof approveItem === 'object' && 'children' in approveItem) {\n approveItem.children = app.translator.trans('flarum-akismet.forum.post.not_spam_button');\n }\n }\n }\n });\n\n override(CommentPost.prototype, 'flagReason', function (original, flag) {\n if (flag.type() === 'akismet') {\n return app.translator.trans('flarum-akismet.forum.post.akismet_flagged_text');\n }\n\n return original(flag);\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","extend","PostControls","items","post","has","flags","some","flag","type","approveItem","children","override","CommentPost","original"],"sourceRoot":""}
|
{"version":3,"file":"forum.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,4B,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,yB,aCSxDC,IAAAA,aAAAA,IAAqB,kBAAkB,YACrCC,EAAAA,EAAAA,QAAOC,IAAc,uBAAuB,SAAUC,EAAmCC,GACvF,GAAID,EAAME,IAAI,WAAY,CACxB,IAAMC,EAAQF,EAAKE,QAEnB,GAAIA,GAASA,EAAMC,MAAK,SAACC,GAAI,MAAsB,aAAb,MAAJA,OAAI,EAAJA,EAAMC,OAAoB,IAAG,CAC7D,IAAMC,EAAcP,EAAMf,IAAI,WAC1BsB,GAAsC,iBAAhBA,GAA4B,aAAcA,IAClEA,EAAYC,SAAWX,IAAAA,WAAAA,MAAqB,6CAEhD,CACF,CACF,KAEAY,EAAAA,EAAAA,UAASC,IAAAA,UAAyB,cAAc,SAAUC,EAAUN,GAClE,MAAoB,YAAhBA,EAAKC,OACAT,IAAAA,WAAAA,MAAqB,kDAGvBc,EAASN,EAClB,GACF,G","sources":["webpack://@flarum/akismet/webpack/bootstrap","webpack://@flarum/akismet/webpack/runtime/compat get default export","webpack://@flarum/akismet/webpack/runtime/define property getters","webpack://@flarum/akismet/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/akismet/webpack/runtime/make namespace object","webpack://@flarum/akismet/external root \"flarum.core.compat['common/extend']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/app']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/utils/PostControls']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/components/Post']\"","webpack://@flarum/akismet/./src/forum/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/app'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/utils/PostControls'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/components/Post'];","import { extend, override } from 'flarum/common/extend';\nimport app from 'flarum/forum/app';\nimport type Post from 'flarum/common/models/Post';\nimport type ItemList from 'flarum/common/utils/ItemList';\n\nimport PostControls from 'flarum/forum/utils/PostControls';\nimport PostComponent from 'flarum/forum/components/Post';\nimport type Mithril from 'mithril';\n\napp.initializers.add('flarum-akismet', () => {\n extend(PostControls, 'destructiveControls', function (items: ItemList<Mithril.Children>, post: Post) {\n if (items.has('approve')) {\n const flags = post.flags();\n\n if (flags && flags.some((flag) => flag?.type() === 'akismet')) {\n const approveItem = items.get('approve');\n if (approveItem && typeof approveItem === 'object' && 'children' in approveItem) {\n approveItem.children = app.translator.trans('flarum-akismet.forum.post.not_spam_button');\n }\n }\n }\n });\n\n override(PostComponent.prototype, 'flagReason', function (original, flag) {\n if (flag.type() === 'akismet') {\n return app.translator.trans('flarum-akismet.forum.post.akismet_flagged_text');\n }\n\n return original(flag);\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","extend","PostControls","items","post","has","flags","some","flag","type","approveItem","children","override","PostComponent","original"],"sourceRoot":""}
|
@@ -20,7 +20,7 @@
|
|||||||
"flarum-tsconfig": "^1.0.2",
|
"flarum-tsconfig": "^1.0.2",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"flarum-webpack-config": "^2.0.0",
|
"flarum-webpack-config": "^2.0.0",
|
||||||
"webpack": "^5.65.0",
|
"webpack": "^5.76.0",
|
||||||
"webpack-cli": "^4.9.1",
|
"webpack-cli": "^4.9.1",
|
||||||
"typescript": "^4.5.4",
|
"typescript": "^4.5.4",
|
||||||
"typescript-coverage-report": "^0.6.1"
|
"typescript-coverage-report": "^0.6.1"
|
||||||
|
@@ -4,7 +4,7 @@ import type Post from 'flarum/common/models/Post';
|
|||||||
import type ItemList from 'flarum/common/utils/ItemList';
|
import type ItemList from 'flarum/common/utils/ItemList';
|
||||||
|
|
||||||
import PostControls from 'flarum/forum/utils/PostControls';
|
import PostControls from 'flarum/forum/utils/PostControls';
|
||||||
import CommentPost from 'flarum/forum/components/CommentPost';
|
import PostComponent from 'flarum/forum/components/Post';
|
||||||
import type Mithril from 'mithril';
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
app.initializers.add('flarum-akismet', () => {
|
app.initializers.add('flarum-akismet', () => {
|
||||||
@@ -21,7 +21,7 @@ app.initializers.add('flarum-akismet', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
override(CommentPost.prototype, 'flagReason', function (original, flag) {
|
override(PostComponent.prototype, 'flagReason', function (original, flag) {
|
||||||
if (flag.type() === 'akismet') {
|
if (flag.type() === 'akismet') {
|
||||||
return app.translator.trans('flarum-akismet.forum.post.akismet_flagged_text');
|
return app.translator.trans('flarum-akismet.forum.post.akismet_flagged_text');
|
||||||
}
|
}
|
||||||
|
@@ -50,7 +50,7 @@ class ValidatePost
|
|||||||
->withContent($post->content)
|
->withContent($post->content)
|
||||||
->withAuthorName($post->user->username)
|
->withAuthorName($post->user->username)
|
||||||
->withAuthorEmail($post->user->email)
|
->withAuthorEmail($post->user->email)
|
||||||
->withType($post->number == 1 ? 'forum-post' : 'reply')
|
->withType($post->number === 1 ? 'forum-post' : 'reply')
|
||||||
->withIp($post->ip_address)
|
->withIp($post->ip_address)
|
||||||
->withUserAgent($_SERVER['HTTP_USER_AGENT'])
|
->withUserAgent($_SERVER['HTTP_USER_AGENT'])
|
||||||
->checkSpam();
|
->checkSpam();
|
||||||
|
@@ -19,8 +19,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^1.6",
|
"flarum/core": "^1.8",
|
||||||
"flarum/flags": "^1.2"
|
"flarum/flags": "^1.7"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
@@ -28,15 +28,17 @@ return [
|
|||||||
|
|
||||||
// Discussions should be approved by default
|
// Discussions should be approved by default
|
||||||
(new Extend\Model(Discussion::class))
|
(new Extend\Model(Discussion::class))
|
||||||
->default('is_approved', true),
|
->default('is_approved', true)
|
||||||
|
->cast('is_approved', 'bool'),
|
||||||
|
|
||||||
// Posts should be approved by default
|
// Posts should be approved by default
|
||||||
(new Extend\Model(Post::class))
|
(new Extend\Model(Post::class))
|
||||||
->default('is_approved', true),
|
->default('is_approved', true)
|
||||||
|
->cast('is_approved', 'bool'),
|
||||||
|
|
||||||
(new Extend\ApiSerializer(BasicDiscussionSerializer::class))
|
(new Extend\ApiSerializer(BasicDiscussionSerializer::class))
|
||||||
->attribute('isApproved', function ($serializer, Discussion $discussion) {
|
->attribute('isApproved', function ($serializer, Discussion $discussion) {
|
||||||
return (bool) $discussion->is_approved;
|
return $discussion->is_approved;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
(new Extend\ApiSerializer(PostSerializer::class))
|
(new Extend\ApiSerializer(PostSerializer::class))
|
||||||
|
2
extensions/approval/js/dist/admin.js.map
generated
vendored
2
extensions/approval/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCGxDC,IAAAA,aAAAA,IAAqB,mBAAmB,YACtCC,EAAAA,EAAAA,QAAOD,IAAK,0BAA0B,SAAUE,EAAUC,GACrC,oCAAfA,GACFD,EAASE,KAAK,mBAEG,oCAAfD,GACFD,EAASE,KAAK,mBAEjB,IAEDJ,IAAAA,cAAAA,IACO,mBACJK,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,8EAC5BG,WAAY,mCAEd,QACA,IAEDE,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,kEAC5BG,WAAY,mCAEd,QACA,IAEDE,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,yDAC5BG,WAAY,2BAEd,WACA,GAEL,G","sources":["webpack://@flarum/approval/webpack/bootstrap","webpack://@flarum/approval/webpack/runtime/compat get default export","webpack://@flarum/approval/webpack/runtime/define property getters","webpack://@flarum/approval/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/approval/webpack/runtime/make namespace object","webpack://@flarum/approval/external root \"flarum.core.compat['common/extend']\"","webpack://@flarum/approval/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/approval/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import { extend } from 'flarum/common/extend';\nimport app from 'flarum/admin/app';\n\napp.initializers.add('flarum-approval', () => {\n extend(app, 'getRequiredPermissions', function (required, permission) {\n if (permission === 'discussion.startWithoutApproval') {\n required.push('startDiscussion');\n }\n if (permission === 'discussion.replyWithoutApproval') {\n required.push('discussion.reply');\n }\n });\n\n app.extensionData\n .for('flarum-approval')\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.start_discussions_without_approval_label'),\n permission: 'discussion.startWithoutApproval',\n },\n 'start',\n 95\n )\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.reply_without_approval_label'),\n permission: 'discussion.replyWithoutApproval',\n },\n 'reply',\n 95\n )\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.approve_posts_label'),\n permission: 'discussion.approvePosts',\n },\n 'moderate',\n 65\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","extend","required","permission","push","registerPermission","icon","label"],"sourceRoot":""}
|
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCGxDC,IAAAA,aAAAA,IAAqB,mBAAmB,YACtCC,EAAAA,EAAAA,QAAOD,IAAK,0BAA0B,SAAUE,EAAUC,GACrC,oCAAfA,GACFD,EAASE,KAAK,mBAEG,oCAAfD,GACFD,EAASE,KAAK,mBAElB,IAEAJ,IAAAA,cAAAA,IACO,mBACJK,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,8EAC5BG,WAAY,mCAEd,QACA,IAEDE,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,kEAC5BG,WAAY,mCAEd,QACA,IAEDE,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,yDAC5BG,WAAY,2BAEd,WACA,GAEN,G","sources":["webpack://@flarum/approval/webpack/bootstrap","webpack://@flarum/approval/webpack/runtime/compat get default export","webpack://@flarum/approval/webpack/runtime/define property getters","webpack://@flarum/approval/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/approval/webpack/runtime/make namespace object","webpack://@flarum/approval/external root \"flarum.core.compat['common/extend']\"","webpack://@flarum/approval/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/approval/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import { extend } from 'flarum/common/extend';\nimport app from 'flarum/admin/app';\n\napp.initializers.add('flarum-approval', () => {\n extend(app, 'getRequiredPermissions', function (required, permission) {\n if (permission === 'discussion.startWithoutApproval') {\n required.push('startDiscussion');\n }\n if (permission === 'discussion.replyWithoutApproval') {\n required.push('discussion.reply');\n }\n });\n\n app.extensionData\n .for('flarum-approval')\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.start_discussions_without_approval_label'),\n permission: 'discussion.startWithoutApproval',\n },\n 'start',\n 95\n )\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.reply_without_approval_label'),\n permission: 'discussion.replyWithoutApproval',\n },\n 'reply',\n 95\n )\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.approve_posts_label'),\n permission: 'discussion.approvePosts',\n },\n 'moderate',\n 65\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","extend","required","permission","push","registerPermission","icon","label"],"sourceRoot":""}
|
2
extensions/approval/js/dist/forum.js.map
generated
vendored
2
extensions/approval/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"flarum-webpack-config": "^2.0.0",
|
"flarum-webpack-config": "^2.0.0",
|
||||||
"webpack": "^5.65.0",
|
"webpack": "^5.76.0",
|
||||||
"webpack-cli": "^4.9.1",
|
"webpack-cli": "^4.9.1",
|
||||||
"@flarum/prettier-config": "^1.0.0"
|
"@flarum/prettier-config": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
namespace Flarum\Approval\Listener;
|
namespace Flarum\Approval\Listener;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use Flarum\Discussion\Discussion;
|
use Flarum\Discussion\Discussion;
|
||||||
use Flarum\Flags\Flag;
|
use Flarum\Flags\Flag;
|
||||||
use Flarum\Post\CommentPost;
|
use Flarum\Post\CommentPost;
|
||||||
@@ -55,7 +56,7 @@ class UnapproveNewContent
|
|||||||
|
|
||||||
$flag->post_id = $post->id;
|
$flag->post_id = $post->id;
|
||||||
$flag->type = 'approval';
|
$flag->type = 'approval';
|
||||||
$flag->created_at = time();
|
$flag->created_at = Carbon::now();
|
||||||
|
|
||||||
$flag->save();
|
$flag->save();
|
||||||
});
|
});
|
||||||
|
@@ -22,7 +22,7 @@ class UpdateDiscussionAfterPostApproval
|
|||||||
$discussion->refreshCommentCount();
|
$discussion->refreshCommentCount();
|
||||||
$discussion->refreshLastPost();
|
$discussion->refreshLastPost();
|
||||||
|
|
||||||
if ($post->number == 1) {
|
if ($post->number === 1) {
|
||||||
$discussion->is_approved = true;
|
$discussion->is_approved = true;
|
||||||
|
|
||||||
$discussion->afterSave(function () use ($user) {
|
$discussion->afterSave(function () use ($user) {
|
||||||
@@ -36,5 +36,10 @@ class UpdateDiscussionAfterPostApproval
|
|||||||
$user->refreshCommentCount();
|
$user->refreshCommentCount();
|
||||||
$user->save();
|
$user->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($post->user) {
|
||||||
|
$post->user->refreshCommentCount();
|
||||||
|
$post->user->save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^1.6"
|
"flarum/core": "^1.8"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Flarum\\BBCode\\": "src"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
|
@@ -7,24 +7,14 @@
|
|||||||
* LICENSE file that was distributed with this source code.
|
* LICENSE file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Flarum\Extend;
|
namespace Flarum\BBCode;
|
||||||
use s9e\TextFormatter\Configurator;
|
|
||||||
|
|
||||||
return (new Extend\Formatter)
|
use Flarum\Extend;
|
||||||
->configure(function (Configurator $config) {
|
|
||||||
$config->BBCodes->addFromRepository('B');
|
return [
|
||||||
$config->BBCodes->addFromRepository('I');
|
new Extend\Locales(__DIR__.'/locale'),
|
||||||
$config->BBCodes->addFromRepository('U');
|
|
||||||
$config->BBCodes->addFromRepository('S');
|
(new Extend\Formatter)
|
||||||
$config->BBCodes->addFromRepository('URL');
|
->render(Render::class)
|
||||||
$config->BBCodes->addFromRepository('IMG');
|
->configure(Configure::class),
|
||||||
$config->BBCodes->addFromRepository('EMAIL');
|
];
|
||||||
$config->BBCodes->addFromRepository('CODE');
|
|
||||||
$config->BBCodes->addFromRepository('QUOTE');
|
|
||||||
$config->BBCodes->addFromRepository('LIST');
|
|
||||||
$config->BBCodes->addFromRepository('DEL');
|
|
||||||
$config->BBCodes->addFromRepository('COLOR');
|
|
||||||
$config->BBCodes->addFromRepository('CENTER');
|
|
||||||
$config->BBCodes->addFromRepository('SIZE');
|
|
||||||
$config->BBCodes->addFromRepository('*');
|
|
||||||
});
|
|
||||||
|
10
extensions/bbcode/locale/en.yml
Normal file
10
extensions/bbcode/locale/en.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
flarum-bbcode:
|
||||||
|
|
||||||
|
##
|
||||||
|
# UNIQUE KEYS - The following keys are used in only one location each.
|
||||||
|
##
|
||||||
|
|
||||||
|
# Translations in this namespace are used by the forum user interface.
|
||||||
|
forum:
|
||||||
|
quote:
|
||||||
|
wrote: wrote
|
59
extensions/bbcode/src/Configure.php
Normal file
59
extensions/bbcode/src/Configure.php
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\BBCode;
|
||||||
|
|
||||||
|
use s9e\TextFormatter\Configurator;
|
||||||
|
|
||||||
|
class Configure
|
||||||
|
{
|
||||||
|
public function __invoke(Configurator $config)
|
||||||
|
{
|
||||||
|
$this->addTagsFromRepositories($config);
|
||||||
|
$this->adaptHighlightJs($config);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addTagsFromRepositories(Configurator $config): void
|
||||||
|
{
|
||||||
|
$config->BBCodes->addFromRepository('B');
|
||||||
|
$config->BBCodes->addFromRepository('I');
|
||||||
|
$config->BBCodes->addFromRepository('U');
|
||||||
|
$config->BBCodes->addFromRepository('S');
|
||||||
|
$config->BBCodes->addFromRepository('URL');
|
||||||
|
$config->BBCodes->addFromRepository('IMG');
|
||||||
|
$config->BBCodes->addFromRepository('EMAIL');
|
||||||
|
$config->BBCodes->addFromRepository('CODE');
|
||||||
|
$config->BBCodes->addFromRepository('QUOTE', 'default', [
|
||||||
|
'authorStr' => '<xsl:value-of select="@author"/> <xsl:value-of select="$L_WROTE"/>'
|
||||||
|
]);
|
||||||
|
$config->BBCodes->addFromRepository('LIST');
|
||||||
|
$config->BBCodes->addFromRepository('DEL');
|
||||||
|
$config->BBCodes->addFromRepository('COLOR');
|
||||||
|
$config->BBCodes->addFromRepository('CENTER');
|
||||||
|
$config->BBCodes->addFromRepository('SIZE');
|
||||||
|
$config->BBCodes->addFromRepository('*');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix for highlight JS not working after changing post content.
|
||||||
|
*
|
||||||
|
* @link https://github.com/flarum/framework/issues/3794
|
||||||
|
*/
|
||||||
|
protected function adaptHighlightJs(Configurator $config): void
|
||||||
|
{
|
||||||
|
$codeTag = $config->tags->get('CODE');
|
||||||
|
$script = '
|
||||||
|
<script>
|
||||||
|
if(window.hljsLoader && !document.currentScript.parentNode.hasAttribute(\'data-s9e-livepreview-onupdate\')) {
|
||||||
|
window.hljsLoader.highlightBlocks(document.currentScript.parentNode);
|
||||||
|
}
|
||||||
|
</script>';
|
||||||
|
$codeTag->template = str_replace('</pre>', $script.'</pre>', $codeTag->template);
|
||||||
|
}
|
||||||
|
}
|
33
extensions/bbcode/src/Render.php
Normal file
33
extensions/bbcode/src/Render.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\BBCode;
|
||||||
|
|
||||||
|
use s9e\TextFormatter\Renderer;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
|
class Render
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var TranslatorInterface
|
||||||
|
*/
|
||||||
|
protected $translator;
|
||||||
|
|
||||||
|
public function __construct(TranslatorInterface $translator)
|
||||||
|
{
|
||||||
|
$this->translator = $translator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(Renderer $renderer, $context, string $xml): string
|
||||||
|
{
|
||||||
|
$renderer->setParameter('L_WROTE', $this->translator->trans('flarum-bbcode.forum.quote.wrote'));
|
||||||
|
|
||||||
|
return $xml;
|
||||||
|
}
|
||||||
|
}
|
@@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^1.6"
|
"flarum/core": "^1.8"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
2
extensions/embed/js/dist/forum.js.map
generated
vendored
2
extensions/embed/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -9,7 +9,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"flarum-webpack-config": "^2.0.0",
|
"flarum-webpack-config": "^2.0.0",
|
||||||
"webpack": "^5.65.0",
|
"webpack": "^5.76.0",
|
||||||
"webpack-cli": "^4.9.1",
|
"webpack-cli": "^4.9.1",
|
||||||
"@flarum/prettier-config": "^1.0.0"
|
"@flarum/prettier-config": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^1.6"
|
"flarum/core": "^1.8"
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
|
2
extensions/emoji/js/dist/forum.js
generated
vendored
2
extensions/emoji/js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/emoji/js/dist/forum.js.map
generated
vendored
2
extensions/emoji/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -14,7 +14,7 @@
|
|||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"typescript": "^4.5.4",
|
"typescript": "^4.5.4",
|
||||||
"typescript-coverage-report": "^0.6.1",
|
"typescript-coverage-report": "^0.6.1",
|
||||||
"webpack": "^5.65.0",
|
"webpack": "^5.76.0",
|
||||||
"webpack-cli": "^4.9.1"
|
"webpack-cli": "^4.9.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@@ -3,7 +3,7 @@ import emojiMap from 'simple-emoji-map';
|
|||||||
import { extend } from 'flarum/common/extend';
|
import { extend } from 'flarum/common/extend';
|
||||||
import TextEditor from 'flarum/common/components/TextEditor';
|
import TextEditor from 'flarum/common/components/TextEditor';
|
||||||
import TextEditorButton from 'flarum/common/components/TextEditorButton';
|
import TextEditorButton from 'flarum/common/components/TextEditorButton';
|
||||||
import KeyboardNavigatable from 'flarum/forum/utils/KeyboardNavigatable';
|
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
|
||||||
|
|
||||||
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
|
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
|
||||||
import getEmojiIconCode from './helpers/getEmojiIconCode';
|
import getEmojiIconCode from './helpers/getEmojiIconCode';
|
||||||
@@ -80,7 +80,7 @@ export default function addComposerAutocomplete() {
|
|||||||
dropdown.setIndex($(this).parent().index() - 1);
|
dropdown.setIndex($(this).parent().index() - 1);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img alt={emoji} class="emoji" draggable="false" loading="lazy" src={`${cdn}72x72/${code}.png`} />
|
<img alt={emoji} className="emoji" draggable="false" loading="lazy" src={`${cdn}72x72/${code}.png`} />
|
||||||
{name}
|
{name}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^1.6"
|
"flarum/core": "^1.8"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
@@ -46,7 +46,7 @@ return [
|
|||||||
->delete('/posts/{id}/flags', 'flags.delete', DeleteFlagsController::class),
|
->delete('/posts/{id}/flags', 'flags.delete', DeleteFlagsController::class),
|
||||||
|
|
||||||
(new Extend\Model(User::class))
|
(new Extend\Model(User::class))
|
||||||
->dateAttribute('read_flags_at'),
|
->cast('read_flags_at', 'datetime'),
|
||||||
|
|
||||||
(new Extend\Model(Post::class))
|
(new Extend\Model(Post::class))
|
||||||
->hasMany('flags', Flag::class, 'post_id'),
|
->hasMany('flags', Flag::class, 'post_id'),
|
||||||
|
2
extensions/flags/js/dist-typings/forum/compat.d.ts
generated
vendored
2
extensions/flags/js/dist-typings/forum/compat.d.ts
generated
vendored
@@ -1,4 +1,4 @@
|
|||||||
declare var _default: {
|
declare const _default: {
|
||||||
'flags/addFlagsToPosts': typeof addFlagsToPosts;
|
'flags/addFlagsToPosts': typeof addFlagsToPosts;
|
||||||
'flags/addFlagControl': typeof addFlagControl;
|
'flags/addFlagControl': typeof addFlagControl;
|
||||||
'flags/addFlagsDropdown': typeof addFlagsDropdown;
|
'flags/addFlagsDropdown': typeof addFlagsDropdown;
|
||||||
|
2
extensions/flags/js/dist-typings/forum/components/FlagPostModal.d.ts
generated
vendored
2
extensions/flags/js/dist-typings/forum/components/FlagPostModal.d.ts
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/// <reference types="flarum/@types/translator-icu-rich" />
|
/// <reference types="flarum/@types/translator-icu-rich" />
|
||||||
export default class FlagPostModal extends Modal<import("flarum/common/components/Modal").IInternalModalAttrs> {
|
export default class FlagPostModal extends Modal<import("flarum/common/components/Modal").IInternalModalAttrs, undefined> {
|
||||||
constructor();
|
constructor();
|
||||||
oninit(vnode: any): void;
|
oninit(vnode: any): void;
|
||||||
success: boolean | undefined;
|
success: boolean | undefined;
|
||||||
|
6
extensions/flags/js/dist-typings/forum/components/FlagsDropdown.d.ts
generated
vendored
6
extensions/flags/js/dist-typings/forum/components/FlagsDropdown.d.ts
generated
vendored
@@ -1,7 +1,7 @@
|
|||||||
export default class FlagsDropdown {
|
export default class FlagsDropdown extends NotificationsDropdown<import("flarum/common/components/Dropdown").IDropdownAttrs> {
|
||||||
static initAttrs(attrs: any): void;
|
static initAttrs(attrs: any): void;
|
||||||
getMenu(): JSX.Element;
|
constructor();
|
||||||
goToRoute(): void;
|
|
||||||
getUnreadCount(): any;
|
getUnreadCount(): any;
|
||||||
getNewCount(): unknown;
|
getNewCount(): unknown;
|
||||||
}
|
}
|
||||||
|
import NotificationsDropdown from "flarum/forum/components/NotificationsDropdown";
|
||||||
|
2
extensions/flags/js/dist-typings/forum/extend.d.ts
generated
vendored
Normal file
2
extensions/flags/js/dist-typings/forum/extend.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
declare const _default: (import("flarum/common/extenders/Model").default | import("flarum/common/extenders/Routes").default | import("flarum/common/extenders/Store").default)[];
|
||||||
|
export default _default;
|
2
extensions/flags/js/dist-typings/forum/index.d.ts
generated
vendored
2
extensions/flags/js/dist-typings/forum/index.d.ts
generated
vendored
@@ -1 +1 @@
|
|||||||
export {};
|
export { default as extend } from './extend';
|
||||||
|
2
extensions/flags/js/dist/admin.js.map
generated
vendored
2
extensions/flags/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,gBAAgB,WACnCA,IAAAA,cAAAA,IACO,gBACJC,gBACC,CACEC,QAAS,8BACTC,KAAM,OACNC,MAAOJ,IAAAA,WAAAA,MAAqB,qDAE9B,IAEDC,gBAAgB,CACfC,QAAS,4BACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,sDAE7BK,mBACC,CACEC,KAAM,cACNF,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BO,WAAY,wBAEd,WACA,IAGDF,mBACC,CACEC,KAAM,cACNF,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BO,WAAY,wBAEd,QACA,GAEL,G","sources":["webpack://@flarum/flags/webpack/bootstrap","webpack://@flarum/flags/webpack/runtime/compat get default export","webpack://@flarum/flags/webpack/runtime/define property getters","webpack://@flarum/flags/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/flags/webpack/runtime/make namespace object","webpack://@flarum/flags/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/flags/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-flags', () => {\n app.extensionData\n .for('flarum-flags')\n .registerSetting(\n {\n setting: 'flarum-flags.guidelines_url',\n type: 'text',\n label: app.translator.trans('flarum-flags.admin.settings.guidelines_url_label'),\n },\n 15\n )\n .registerSetting({\n setting: 'flarum-flags.can_flag_own',\n type: 'boolean',\n label: app.translator.trans('flarum-flags.admin.settings.flag_own_posts_label'),\n })\n .registerPermission(\n {\n icon: 'fas fa-flag',\n label: app.translator.trans('flarum-flags.admin.permissions.view_flags_label'),\n permission: 'discussion.viewFlags',\n },\n 'moderate',\n 65\n )\n\n .registerPermission(\n {\n icon: 'fas fa-flag',\n label: app.translator.trans('flarum-flags.admin.permissions.flag_posts_label'),\n permission: 'discussion.flagPosts',\n },\n 'reply',\n 65\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","registerPermission","icon","permission"],"sourceRoot":""}
|
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,gBAAgB,WACnCA,IAAAA,cAAAA,IACO,gBACJC,gBACC,CACEC,QAAS,8BACTC,KAAM,OACNC,MAAOJ,IAAAA,WAAAA,MAAqB,qDAE9B,IAEDC,gBAAgB,CACfC,QAAS,4BACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,sDAE7BK,mBACC,CACEC,KAAM,cACNF,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BO,WAAY,wBAEd,WACA,IAGDF,mBACC,CACEC,KAAM,cACNF,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BO,WAAY,wBAEd,QACA,GAEN,G","sources":["webpack://@flarum/flags/webpack/bootstrap","webpack://@flarum/flags/webpack/runtime/compat get default export","webpack://@flarum/flags/webpack/runtime/define property getters","webpack://@flarum/flags/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/flags/webpack/runtime/make namespace object","webpack://@flarum/flags/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/flags/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-flags', () => {\n app.extensionData\n .for('flarum-flags')\n .registerSetting(\n {\n setting: 'flarum-flags.guidelines_url',\n type: 'text',\n label: app.translator.trans('flarum-flags.admin.settings.guidelines_url_label'),\n },\n 15\n )\n .registerSetting({\n setting: 'flarum-flags.can_flag_own',\n type: 'boolean',\n label: app.translator.trans('flarum-flags.admin.settings.flag_own_posts_label'),\n })\n .registerPermission(\n {\n icon: 'fas fa-flag',\n label: app.translator.trans('flarum-flags.admin.permissions.view_flags_label'),\n permission: 'discussion.viewFlags',\n },\n 'moderate',\n 65\n )\n\n .registerPermission(\n {\n icon: 'fas fa-flag',\n label: app.translator.trans('flarum-flags.admin.permissions.flag_posts_label'),\n permission: 'discussion.flagPosts',\n },\n 'reply',\n 65\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","registerPermission","icon","permission"],"sourceRoot":""}
|
2
extensions/flags/js/dist/forum.js
generated
vendored
2
extensions/flags/js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/flags/js/dist/forum.js.map
generated
vendored
2
extensions/flags/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -7,7 +7,7 @@
|
|||||||
"@types/mithril": "^2.0.8",
|
"@types/mithril": "^2.0.8",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"flarum-webpack-config": "^2.0.0",
|
"flarum-webpack-config": "^2.0.0",
|
||||||
"webpack": "^5.65.0",
|
"webpack": "^5.76.0",
|
||||||
"webpack-cli": "^4.9.1",
|
"webpack-cli": "^4.9.1",
|
||||||
"@flarum/prettier-config": "^1.0.0",
|
"@flarum/prettier-config": "^1.0.0",
|
||||||
"flarum-tsconfig": "^1.0.2",
|
"flarum-tsconfig": "^1.0.2",
|
||||||
|
@@ -108,7 +108,7 @@ export default function () {
|
|||||||
user,
|
user,
|
||||||
reason,
|
reason,
|
||||||
}),
|
}),
|
||||||
detail ? <span className="Post-flagged-detail">{detail}</span> : '',
|
!!detail && <span className="Post-flagged-detail">{detail}</span>,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -55,7 +55,7 @@ export default class FlagList extends Component {
|
|||||||
) : !this.state.loading ? (
|
) : !this.state.loading ? (
|
||||||
<div className="NotificationList-empty">{app.translator.trans('flarum-flags.forum.flagged_posts.empty_text')}</div>
|
<div className="NotificationList-empty">{app.translator.trans('flarum-flags.forum.flagged_posts.empty_text')}</div>
|
||||||
) : (
|
) : (
|
||||||
LoadingIndicator.component({ className: 'LoadingIndicator--block' })
|
<LoadingIndicator className="LoadingIndicator--block" />
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -67,15 +67,13 @@ export default class FlagPostModal extends Modal {
|
|||||||
<input type="radio" name="reason" checked={this.reason() === 'off_topic'} value="off_topic" onclick={withAttr('value', this.reason)} />
|
<input type="radio" name="reason" checked={this.reason() === 'off_topic'} value="off_topic" onclick={withAttr('value', this.reason)} />
|
||||||
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_off_topic_label')}</strong>
|
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_off_topic_label')}</strong>
|
||||||
{app.translator.trans('flarum-flags.forum.flag_post.reason_off_topic_text')}
|
{app.translator.trans('flarum-flags.forum.flag_post.reason_off_topic_text')}
|
||||||
{this.reason() === 'off_topic' ? (
|
{this.reason() === 'off_topic' && (
|
||||||
<textarea
|
<textarea
|
||||||
className="FormControl"
|
className="FormControl"
|
||||||
placeholder={app.translator.trans('flarum-flags.forum.flag_post.reason_details_placeholder')}
|
placeholder={app.translator.trans('flarum-flags.forum.flag_post.reason_details_placeholder')}
|
||||||
value={this.reasonDetail()}
|
value={this.reasonDetail()}
|
||||||
oninput={withAttr('value', this.reasonDetail)}
|
oninput={withAttr('value', this.reasonDetail)}
|
||||||
></textarea>
|
></textarea>
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)}
|
)}
|
||||||
</label>,
|
</label>,
|
||||||
70
|
70
|
||||||
@@ -95,15 +93,13 @@ export default class FlagPostModal extends Modal {
|
|||||||
{app.translator.trans('flarum-flags.forum.flag_post.reason_inappropriate_text', {
|
{app.translator.trans('flarum-flags.forum.flag_post.reason_inappropriate_text', {
|
||||||
a: guidelinesUrl ? <a href={guidelinesUrl} target="_blank" /> : undefined,
|
a: guidelinesUrl ? <a href={guidelinesUrl} target="_blank" /> : undefined,
|
||||||
})}
|
})}
|
||||||
{this.reason() === 'inappropriate' ? (
|
{this.reason() === 'inappropriate' && (
|
||||||
<textarea
|
<textarea
|
||||||
className="FormControl"
|
className="FormControl"
|
||||||
placeholder={app.translator.trans('flarum-flags.forum.flag_post.reason_details_placeholder')}
|
placeholder={app.translator.trans('flarum-flags.forum.flag_post.reason_details_placeholder')}
|
||||||
value={this.reasonDetail()}
|
value={this.reasonDetail()}
|
||||||
oninput={withAttr('value', this.reasonDetail)}
|
oninput={withAttr('value', this.reasonDetail)}
|
||||||
></textarea>
|
></textarea>
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)}
|
)}
|
||||||
</label>,
|
</label>,
|
||||||
60
|
60
|
||||||
@@ -115,15 +111,13 @@ export default class FlagPostModal extends Modal {
|
|||||||
<input type="radio" name="reason" checked={this.reason() === 'spam'} value="spam" onclick={withAttr('value', this.reason)} />
|
<input type="radio" name="reason" checked={this.reason() === 'spam'} value="spam" onclick={withAttr('value', this.reason)} />
|
||||||
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_spam_label')}</strong>
|
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_spam_label')}</strong>
|
||||||
{app.translator.trans('flarum-flags.forum.flag_post.reason_spam_text')}
|
{app.translator.trans('flarum-flags.forum.flag_post.reason_spam_text')}
|
||||||
{this.reason() === 'spam' ? (
|
{this.reason() === 'spam' && (
|
||||||
<textarea
|
<textarea
|
||||||
className="FormControl"
|
className="FormControl"
|
||||||
placeholder={app.translator.trans('flarum-flags.forum.flag_post.reason_details_placeholder')}
|
placeholder={app.translator.trans('flarum-flags.forum.flag_post.reason_details_placeholder')}
|
||||||
value={this.reasonDetail()}
|
value={this.reasonDetail()}
|
||||||
oninput={withAttr('value', this.reasonDetail)}
|
oninput={withAttr('value', this.reasonDetail)}
|
||||||
></textarea>
|
></textarea>
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)}
|
)}
|
||||||
</label>,
|
</label>,
|
||||||
50
|
50
|
||||||
@@ -134,10 +128,8 @@ export default class FlagPostModal extends Modal {
|
|||||||
<label className="checkbox">
|
<label className="checkbox">
|
||||||
<input type="radio" name="reason" checked={this.reason() === 'other'} value="other" onclick={withAttr('value', this.reason)} />
|
<input type="radio" name="reason" checked={this.reason() === 'other'} value="other" onclick={withAttr('value', this.reason)} />
|
||||||
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_other_label')}</strong>
|
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_other_label')}</strong>
|
||||||
{this.reason() === 'other' ? (
|
{this.reason() === 'other' && (
|
||||||
<textarea className="FormControl" value={this.reasonDetail()} oninput={withAttr('value', this.reasonDetail)}></textarea>
|
<textarea className="FormControl" value={this.reasonDetail()} oninput={withAttr('value', this.reasonDetail)}></textarea>
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)}
|
)}
|
||||||
</label>,
|
</label>,
|
||||||
10
|
10
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import NotificationsDropdown from 'flarum/components/NotificationsDropdown';
|
import NotificationsDropdown from 'flarum/forum/components/NotificationsDropdown';
|
||||||
|
|
||||||
import FlagList from './FlagList';
|
import FlagList from './FlagList';
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ export default class FlagsDropdown extends NotificationsDropdown {
|
|||||||
getMenu() {
|
getMenu() {
|
||||||
return (
|
return (
|
||||||
<div className={'Dropdown-menu ' + this.attrs.menuClassName} onclick={this.menuClick.bind(this)}>
|
<div className={'Dropdown-menu ' + this.attrs.menuClassName} onclick={this.menuClick.bind(this)}>
|
||||||
{this.showing ? FlagList.component({ state: this.attrs.state }) : ''}
|
{this.showing && <FlagList state={this.attrs.state} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
16
extensions/flags/js/src/forum/extend.ts
Normal file
16
extensions/flags/js/src/forum/extend.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import Extend from 'flarum/common/extenders';
|
||||||
|
import Post from 'flarum/common/models/Post';
|
||||||
|
import FlagsPage from './components/FlagsPage';
|
||||||
|
import Flag from './models/Flag';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
new Extend.Routes() //
|
||||||
|
.add('flags', '/flags', FlagsPage),
|
||||||
|
|
||||||
|
new Extend.Store() //
|
||||||
|
.add('flags', Flag),
|
||||||
|
|
||||||
|
new Extend.Model(Post) //
|
||||||
|
.hasMany<Flag>('flags')
|
||||||
|
.attribute<boolean>('canFlag'),
|
||||||
|
];
|
@@ -1,21 +1,13 @@
|
|||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import Model from 'flarum/common/Model';
|
|
||||||
|
|
||||||
import Flag from './models/Flag';
|
|
||||||
import FlagsPage from './components/FlagsPage';
|
|
||||||
import FlagListState from './states/FlagListState';
|
import FlagListState from './states/FlagListState';
|
||||||
import addFlagControl from './addFlagControl';
|
import addFlagControl from './addFlagControl';
|
||||||
import addFlagsDropdown from './addFlagsDropdown';
|
import addFlagsDropdown from './addFlagsDropdown';
|
||||||
import addFlagsToPosts from './addFlagsToPosts';
|
import addFlagsToPosts from './addFlagsToPosts';
|
||||||
|
|
||||||
|
export { default as extend } from './extend';
|
||||||
|
|
||||||
app.initializers.add('flarum-flags', () => {
|
app.initializers.add('flarum-flags', () => {
|
||||||
Post.prototype.flags = Model.hasMany<Flag>('flags');
|
|
||||||
Post.prototype.canFlag = Model.attribute<boolean>('canFlag');
|
|
||||||
|
|
||||||
app.store.models.flags = Flag;
|
|
||||||
|
|
||||||
app.routes.flags = { path: '/flags', component: FlagsPage };
|
|
||||||
|
|
||||||
app.flags = new FlagListState(app);
|
app.flags = new FlagListState(app);
|
||||||
|
|
||||||
addFlagControl();
|
addFlagControl();
|
||||||
@@ -26,6 +18,5 @@ app.initializers.add('flarum-flags', () => {
|
|||||||
// Expose compat API
|
// Expose compat API
|
||||||
import flagsCompat from './compat';
|
import flagsCompat from './compat';
|
||||||
import { compat } from '@flarum/core/forum';
|
import { compat } from '@flarum/core/forum';
|
||||||
import Post from 'flarum/common/models/Post';
|
|
||||||
|
|
||||||
Object.assign(compat, flagsCompat);
|
Object.assign(compat, flagsCompat);
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
namespace Flarum\Flags\Api\Controller;
|
namespace Flarum\Flags\Api\Controller;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use Flarum\Api\Controller\AbstractListController;
|
use Flarum\Api\Controller\AbstractListController;
|
||||||
use Flarum\Flags\Api\Serializer\FlagSerializer;
|
use Flarum\Flags\Api\Serializer\FlagSerializer;
|
||||||
use Flarum\Flags\Flag;
|
use Flarum\Flags\Flag;
|
||||||
@@ -43,7 +44,7 @@ class ListFlagsController extends AbstractListController
|
|||||||
|
|
||||||
$actor->assertRegistered();
|
$actor->assertRegistered();
|
||||||
|
|
||||||
$actor->read_flags_at = time();
|
$actor->read_flags_at = Carbon::now();
|
||||||
$actor->save();
|
$actor->save();
|
||||||
|
|
||||||
$flags = Flag::whereVisibleTo($actor)
|
$flags = Flag::whereVisibleTo($actor)
|
||||||
|
@@ -12,6 +12,8 @@ namespace Flarum\Flags\Api\Serializer;
|
|||||||
use Flarum\Api\Serializer\AbstractSerializer;
|
use Flarum\Api\Serializer\AbstractSerializer;
|
||||||
use Flarum\Api\Serializer\BasicUserSerializer;
|
use Flarum\Api\Serializer\BasicUserSerializer;
|
||||||
use Flarum\Api\Serializer\PostSerializer;
|
use Flarum\Api\Serializer\PostSerializer;
|
||||||
|
use Flarum\Flags\Flag;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
class FlagSerializer extends AbstractSerializer
|
class FlagSerializer extends AbstractSerializer
|
||||||
{
|
{
|
||||||
@@ -20,11 +22,14 @@ class FlagSerializer extends AbstractSerializer
|
|||||||
*/
|
*/
|
||||||
protected $type = 'flags';
|
protected $type = 'flags';
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
protected function getDefaultAttributes($flag)
|
protected function getDefaultAttributes($flag)
|
||||||
{
|
{
|
||||||
|
if (! ($flag instanceof Flag)) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
get_class($this).' can only serialize instances of '.Flag::class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'type' => $flag->type,
|
'type' => $flag->type,
|
||||||
'reason' => $flag->reason,
|
'reason' => $flag->reason,
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
namespace Flarum\Flags\Command;
|
namespace Flarum\Flags\Command;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use Flarum\Flags\Event\Created;
|
use Flarum\Flags\Event\Created;
|
||||||
use Flarum\Flags\Flag;
|
use Flarum\Flags\Flag;
|
||||||
use Flarum\Foundation\ValidationException;
|
use Flarum\Foundation\ValidationException;
|
||||||
@@ -99,7 +100,7 @@ class CreateFlagHandler
|
|||||||
$flag->type = 'user';
|
$flag->type = 'user';
|
||||||
$flag->reason = Arr::get($data, 'attributes.reason');
|
$flag->reason = Arr::get($data, 'attributes.reason');
|
||||||
$flag->reason_detail = Arr::get($data, 'attributes.reasonDetail');
|
$flag->reason_detail = Arr::get($data, 'attributes.reasonDetail');
|
||||||
$flag->created_at = time();
|
$flag->created_at = Carbon::now();
|
||||||
|
|
||||||
$flag->save();
|
$flag->save();
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@ namespace Flarum\Flags\Command;
|
|||||||
|
|
||||||
use Flarum\Flags\Event\Deleting;
|
use Flarum\Flags\Event\Deleting;
|
||||||
use Flarum\Flags\Event\FlagsWillBeDeleted;
|
use Flarum\Flags\Event\FlagsWillBeDeleted;
|
||||||
use Flarum\Flags\Flag;
|
use Flarum\Post\Post;
|
||||||
use Flarum\Post\PostRepository;
|
use Flarum\Post\PostRepository;
|
||||||
use Illuminate\Events\Dispatcher;
|
use Illuminate\Events\Dispatcher;
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ class DeleteFlagsHandler
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param DeleteFlags $command
|
* @param DeleteFlags $command
|
||||||
* @return Flag
|
* @return Post
|
||||||
*/
|
*/
|
||||||
public function handle(DeleteFlags $command)
|
public function handle(DeleteFlags $command)
|
||||||
{
|
{
|
||||||
|
@@ -9,11 +9,23 @@
|
|||||||
|
|
||||||
namespace Flarum\Flags;
|
namespace Flarum\Flags;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use Flarum\Database\AbstractModel;
|
use Flarum\Database\AbstractModel;
|
||||||
use Flarum\Database\ScopeVisibilityTrait;
|
use Flarum\Database\ScopeVisibilityTrait;
|
||||||
use Flarum\Post\Post;
|
use Flarum\Post\Post;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $post_id
|
||||||
|
* @property int $user_id
|
||||||
|
* @property string $type
|
||||||
|
* @property string $reason
|
||||||
|
* @property string $reason_detail
|
||||||
|
* @property Carbon $created_at
|
||||||
|
*
|
||||||
|
* @property-read Post $post
|
||||||
|
* @property-read User $user
|
||||||
|
*/
|
||||||
class Flag extends AbstractModel
|
class Flag extends AbstractModel
|
||||||
{
|
{
|
||||||
use ScopeVisibilityTrait;
|
use ScopeVisibilityTrait;
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^1.6"
|
"flarum/core": "^1.8"
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^1.6"
|
"flarum/core": "^1.8"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
@@ -13,12 +13,15 @@ use Flarum\Api\Controller;
|
|||||||
use Flarum\Api\Serializer\BasicUserSerializer;
|
use Flarum\Api\Serializer\BasicUserSerializer;
|
||||||
use Flarum\Api\Serializer\PostSerializer;
|
use Flarum\Api\Serializer\PostSerializer;
|
||||||
use Flarum\Extend;
|
use Flarum\Extend;
|
||||||
|
use Flarum\Likes\Api\LoadLikesRelationship;
|
||||||
use Flarum\Likes\Event\PostWasLiked;
|
use Flarum\Likes\Event\PostWasLiked;
|
||||||
use Flarum\Likes\Event\PostWasUnliked;
|
use Flarum\Likes\Event\PostWasUnliked;
|
||||||
use Flarum\Likes\Notification\PostLikedBlueprint;
|
use Flarum\Likes\Notification\PostLikedBlueprint;
|
||||||
use Flarum\Likes\Query\LikedByFilter;
|
use Flarum\Likes\Query\LikedByFilter;
|
||||||
|
use Flarum\Likes\Query\LikedFilter;
|
||||||
use Flarum\Post\Filter\PostFilterer;
|
use Flarum\Post\Filter\PostFilterer;
|
||||||
use Flarum\Post\Post;
|
use Flarum\Post\Post;
|
||||||
|
use Flarum\User\Filter\UserFilterer;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -41,19 +44,32 @@ return [
|
|||||||
->hasMany('likes', BasicUserSerializer::class)
|
->hasMany('likes', BasicUserSerializer::class)
|
||||||
->attribute('canLike', function (PostSerializer $serializer, $model) {
|
->attribute('canLike', function (PostSerializer $serializer, $model) {
|
||||||
return (bool) $serializer->getActor()->can('like', $model);
|
return (bool) $serializer->getActor()->can('like', $model);
|
||||||
|
})
|
||||||
|
->attribute('likesCount', function (PostSerializer $serializer, $model) {
|
||||||
|
return $model->getAttribute('likes_count') ?: 0;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
(new Extend\ApiController(Controller\ShowDiscussionController::class))
|
(new Extend\ApiController(Controller\ShowDiscussionController::class))
|
||||||
->addInclude('posts.likes'),
|
->addInclude('posts.likes')
|
||||||
|
->loadWhere('posts.likes', [LoadLikesRelationship::class, 'mutateRelation'])
|
||||||
|
->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']),
|
||||||
|
|
||||||
(new Extend\ApiController(Controller\ListPostsController::class))
|
(new Extend\ApiController(Controller\ListPostsController::class))
|
||||||
->addInclude('likes'),
|
->addInclude('likes')
|
||||||
|
->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation'])
|
||||||
|
->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']),
|
||||||
(new Extend\ApiController(Controller\ShowPostController::class))
|
(new Extend\ApiController(Controller\ShowPostController::class))
|
||||||
->addInclude('likes'),
|
->addInclude('likes')
|
||||||
|
->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation'])
|
||||||
|
->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']),
|
||||||
(new Extend\ApiController(Controller\CreatePostController::class))
|
(new Extend\ApiController(Controller\CreatePostController::class))
|
||||||
->addInclude('likes'),
|
->addInclude('likes')
|
||||||
|
->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation'])
|
||||||
|
->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']),
|
||||||
(new Extend\ApiController(Controller\UpdatePostController::class))
|
(new Extend\ApiController(Controller\UpdatePostController::class))
|
||||||
->addInclude('likes'),
|
->addInclude('likes')
|
||||||
|
->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation'])
|
||||||
|
->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']),
|
||||||
|
|
||||||
(new Extend\Event())
|
(new Extend\Event())
|
||||||
->listen(PostWasLiked::class, Listener\SendNotificationWhenPostIsLiked::class)
|
->listen(PostWasLiked::class, Listener\SendNotificationWhenPostIsLiked::class)
|
||||||
@@ -63,6 +79,9 @@ return [
|
|||||||
(new Extend\Filter(PostFilterer::class))
|
(new Extend\Filter(PostFilterer::class))
|
||||||
->addFilter(LikedByFilter::class),
|
->addFilter(LikedByFilter::class),
|
||||||
|
|
||||||
|
(new Extend\Filter(UserFilterer::class))
|
||||||
|
->addFilter(LikedFilter::class),
|
||||||
|
|
||||||
(new Extend\Settings())
|
(new Extend\Settings())
|
||||||
->default('flarum-likes.like_own_post', true),
|
->default('flarum-likes.like_own_post', true),
|
||||||
|
|
||||||
|
2
extensions/likes/js/dist/admin.js.map
generated
vendored
2
extensions/likes/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,gBAAgB,WACnCA,IAAAA,cAAAA,IACO,gBACJC,mBACC,CACEC,KAAM,mBACNC,MAAOH,IAAAA,WAAAA,MAAqB,mDAC5BI,WAAY,wBAEd,SAEDC,gBAAgB,CACfC,QAAS,6BACTC,KAAM,OACNJ,MAAOH,IAAAA,WAAAA,MAAqB,oDAC5BQ,KAAMR,IAAAA,WAAAA,MAAqB,oDAEhC,G","sources":["webpack://@flarum/likes/webpack/bootstrap","webpack://@flarum/likes/webpack/runtime/compat get default export","webpack://@flarum/likes/webpack/runtime/define property getters","webpack://@flarum/likes/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/likes/webpack/runtime/make namespace object","webpack://@flarum/likes/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/likes/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-likes', () => {\n app.extensionData\n .for('flarum-likes')\n .registerPermission(\n {\n icon: 'far fa-thumbs-up',\n label: app.translator.trans('flarum-likes.admin.permissions.like_posts_label'),\n permission: 'discussion.likePosts',\n },\n 'reply'\n )\n .registerSetting({\n setting: 'flarum-likes.like_own_post',\n type: 'bool',\n label: app.translator.trans('flarum-likes.admin.settings.like_own_posts_label'),\n help: app.translator.trans('flarum-likes.admin.settings.like_own_posts_help'),\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerPermission","icon","label","permission","registerSetting","setting","type","help"],"sourceRoot":""}
|
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,gBAAgB,WACnCA,IAAAA,cAAAA,IACO,gBACJC,mBACC,CACEC,KAAM,mBACNC,MAAOH,IAAAA,WAAAA,MAAqB,mDAC5BI,WAAY,wBAEd,SAEDC,gBAAgB,CACfC,QAAS,6BACTC,KAAM,OACNJ,MAAOH,IAAAA,WAAAA,MAAqB,oDAC5BQ,KAAMR,IAAAA,WAAAA,MAAqB,oDAEjC,G","sources":["webpack://@flarum/likes/webpack/bootstrap","webpack://@flarum/likes/webpack/runtime/compat get default export","webpack://@flarum/likes/webpack/runtime/define property getters","webpack://@flarum/likes/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/likes/webpack/runtime/make namespace object","webpack://@flarum/likes/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/likes/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-likes', () => {\n app.extensionData\n .for('flarum-likes')\n .registerPermission(\n {\n icon: 'far fa-thumbs-up',\n label: app.translator.trans('flarum-likes.admin.permissions.like_posts_label'),\n permission: 'discussion.likePosts',\n },\n 'reply'\n )\n .registerSetting({\n setting: 'flarum-likes.like_own_post',\n type: 'bool',\n label: app.translator.trans('flarum-likes.admin.settings.like_own_posts_label'),\n help: app.translator.trans('flarum-likes.admin.settings.like_own_posts_help'),\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerPermission","icon","label","permission","registerSetting","setting","type","help"],"sourceRoot":""}
|
2
extensions/likes/js/dist/forum.js
generated
vendored
2
extensions/likes/js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/likes/js/dist/forum.js.map
generated
vendored
2
extensions/likes/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"flarum-webpack-config": "^2.0.0",
|
"flarum-webpack-config": "^2.0.0",
|
||||||
"webpack": "^5.65.0",
|
"webpack": "^5.76.0",
|
||||||
"webpack-cli": "^4.9.1",
|
"webpack-cli": "^4.9.1",
|
||||||
"@flarum/prettier-config": "^1.0.0"
|
"@flarum/prettier-config": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
9
extensions/likes/js/src/@types/shims.d.ts
vendored
Normal file
9
extensions/likes/js/src/@types/shims.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import Post from 'flarum/common/models/Post';
|
||||||
|
import User from 'flarum/common/models/User';
|
||||||
|
|
||||||
|
declare module 'flarum/common/models/Post' {
|
||||||
|
export default interface Post {
|
||||||
|
likes(): User[];
|
||||||
|
likesCount(): number;
|
||||||
|
}
|
||||||
|
}
|
@@ -15,32 +15,31 @@ export default function () {
|
|||||||
|
|
||||||
items.add(
|
items.add(
|
||||||
'like',
|
'like',
|
||||||
Button.component(
|
<Button
|
||||||
{
|
className="Button Button--link"
|
||||||
className: 'Button Button--link',
|
onclick={() => {
|
||||||
onclick: () => {
|
isLiked = !isLiked;
|
||||||
isLiked = !isLiked;
|
|
||||||
|
|
||||||
post.save({ isLiked });
|
post.save({ isLiked });
|
||||||
|
|
||||||
// We've saved the fact that we do or don't like the post, but in order
|
// We've saved the fact that we do or don't like the post, but in order
|
||||||
// to provide instantaneous feedback to the user, we'll need to add or
|
// to provide instantaneous feedback to the user, we'll need to add or
|
||||||
// remove the like from the relationship data manually.
|
// remove the like from the relationship data manually.
|
||||||
const data = post.data.relationships.likes.data;
|
const data = post.data.relationships.likes.data;
|
||||||
data.some((like, i) => {
|
data.some((like, i) => {
|
||||||
if (like.id === app.session.user.id()) {
|
if (like.id === app.session.user.id()) {
|
||||||
data.splice(i, 1);
|
data.splice(i, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isLiked) {
|
|
||||||
data.unshift({ type: 'users', id: app.session.user.id() });
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
},
|
|
||||||
app.translator.trans(isLiked ? 'flarum-likes.forum.post.unlike_link' : 'flarum-likes.forum.post.like_link')
|
if (isLiked) {
|
||||||
)
|
data.unshift({ type: 'users', id: app.session.user.id() });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{app.translator.trans(isLiked ? 'flarum-likes.forum.post.unlike_link' : 'flarum-likes.forum.post.like_link')}
|
||||||
|
</Button>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ import Link from 'flarum/common/components/Link';
|
|||||||
import punctuateSeries from 'flarum/common/helpers/punctuateSeries';
|
import punctuateSeries from 'flarum/common/helpers/punctuateSeries';
|
||||||
import username from 'flarum/common/helpers/username';
|
import username from 'flarum/common/helpers/username';
|
||||||
import icon from 'flarum/common/helpers/icon';
|
import icon from 'flarum/common/helpers/icon';
|
||||||
|
import Button from 'flarum/common/components/Button';
|
||||||
|
|
||||||
import PostLikesModal from './components/PostLikesModal';
|
import PostLikesModal from './components/PostLikesModal';
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ export default function () {
|
|||||||
|
|
||||||
if (likes && likes.length) {
|
if (likes && likes.length) {
|
||||||
const limit = 4;
|
const limit = 4;
|
||||||
const overLimit = likes.length > limit;
|
const overLimit = post.likesCount() > limit;
|
||||||
|
|
||||||
// Construct a list of names of users who have liked this post. Make sure the
|
// Construct a list of names of users who have liked this post. Make sure the
|
||||||
// current user is first in the list, and cap a maximum of 4 items.
|
// current user is first in the list, and cap a maximum of 4 items.
|
||||||
@@ -34,26 +35,31 @@ export default function () {
|
|||||||
// others" name to the end of the list. Clicking on it will display a modal
|
// others" name to the end of the list. Clicking on it will display a modal
|
||||||
// with a full list of names.
|
// with a full list of names.
|
||||||
if (overLimit) {
|
if (overLimit) {
|
||||||
const count = likes.length - names.length;
|
const count = post.likesCount() - names.length;
|
||||||
|
const label = app.translator.trans('flarum-likes.forum.post.others_link', { count });
|
||||||
|
|
||||||
names.push(
|
if (app.forum.attribute('canSearchUsers')) {
|
||||||
<a
|
names.push(
|
||||||
href="#"
|
<Button
|
||||||
onclick={(e) => {
|
className="Button Button--ua-reset Button--text"
|
||||||
e.preventDefault();
|
onclick={(e) => {
|
||||||
app.modal.show(PostLikesModal, { post });
|
e.preventDefault();
|
||||||
}}
|
app.modal.show(PostLikesModal, { post });
|
||||||
>
|
}}
|
||||||
{app.translator.trans('flarum-likes.forum.post.others_link', { count })}
|
>
|
||||||
</a>
|
{label}
|
||||||
);
|
</Button>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
names.push(<span>{label}</span>);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
items.add(
|
items.add(
|
||||||
'liked',
|
'liked',
|
||||||
<div className="Post-likedBy">
|
<div className="Post-likedBy">
|
||||||
{icon('far fa-thumbs-up')}
|
{icon('far fa-thumbs-up')}
|
||||||
{app.translator.trans('flarum-likes.forum.post.liked_by' + (likes[0] === app.session.user ? '_self' : '') + '_text', {
|
{app.translator.trans(`flarum-likes.forum.post.liked_by${likes[0] === app.session.user ? '_self' : ''}_text`, {
|
||||||
count: names.length,
|
count: names.length,
|
||||||
users: punctuateSeries(names),
|
users: punctuateSeries(names),
|
||||||
})}
|
})}
|
||||||
|
@@ -2,17 +2,15 @@ import { extend } from 'flarum/common/extend';
|
|||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import UserPage from 'flarum/forum/components/UserPage';
|
import UserPage from 'flarum/forum/components/UserPage';
|
||||||
import LinkButton from 'flarum/common/components/LinkButton';
|
import LinkButton from 'flarum/common/components/LinkButton';
|
||||||
import LikesUserPage from './components/LikesUserPage';
|
|
||||||
import ItemList from 'flarum/common/utils/ItemList';
|
import ItemList from 'flarum/common/utils/ItemList';
|
||||||
import type Mithril from 'mithril';
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
export default function addLikesTabToUserProfile() {
|
export default function addLikesTabToUserProfile() {
|
||||||
app.routes['user.likes'] = { path: '/u/:username/likes', component: LikesUserPage };
|
|
||||||
extend(UserPage.prototype, 'navItems', function (items: ItemList<Mithril.Children>) {
|
extend(UserPage.prototype, 'navItems', function (items: ItemList<Mithril.Children>) {
|
||||||
const user = this.user;
|
const user = this.user;
|
||||||
items.add(
|
items.add(
|
||||||
'likes',
|
'likes',
|
||||||
<LinkButton href={app.route('user.likes', { username: user.slug() })} icon="far fa-thumbs-up">
|
<LinkButton href={app.route('user.likes', { username: user?.slug() })} icon="far fa-thumbs-up">
|
||||||
{app.translator.trans('flarum-likes.forum.user.likes_link')}
|
{app.translator.trans('flarum-likes.forum.user.likes_link')}
|
||||||
</LinkButton>,
|
</LinkButton>,
|
||||||
88
|
88
|
||||||
|
@@ -1,31 +0,0 @@
|
|||||||
import app from 'flarum/forum/app';
|
|
||||||
import Modal from 'flarum/common/components/Modal';
|
|
||||||
import Link from 'flarum/common/components/Link';
|
|
||||||
import avatar from 'flarum/common/helpers/avatar';
|
|
||||||
import username from 'flarum/common/helpers/username';
|
|
||||||
|
|
||||||
export default class PostLikesModal extends Modal {
|
|
||||||
className() {
|
|
||||||
return 'PostLikesModal Modal--small';
|
|
||||||
}
|
|
||||||
|
|
||||||
title() {
|
|
||||||
return app.translator.trans('flarum-likes.forum.post_likes.title');
|
|
||||||
}
|
|
||||||
|
|
||||||
content() {
|
|
||||||
return (
|
|
||||||
<div className="Modal-body">
|
|
||||||
<ul className="PostLikesModal-list">
|
|
||||||
{this.attrs.post.likes().map((user) => (
|
|
||||||
<li>
|
|
||||||
<Link href={app.route.user(user)}>
|
|
||||||
{avatar(user)} {username(user)}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
72
extensions/likes/js/src/forum/components/PostLikesModal.tsx
Normal file
72
extensions/likes/js/src/forum/components/PostLikesModal.tsx
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import app from 'flarum/forum/app';
|
||||||
|
import Modal from 'flarum/common/components/Modal';
|
||||||
|
import Link from 'flarum/common/components/Link';
|
||||||
|
import avatar from 'flarum/common/helpers/avatar';
|
||||||
|
import username from 'flarum/common/helpers/username';
|
||||||
|
import type { IInternalModalAttrs } from 'flarum/common/components/Modal';
|
||||||
|
import type Post from 'flarum/common/models/Post';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
import PostLikesModalState from '../states/PostLikesModalState';
|
||||||
|
import Button from 'flarum/common/components/Button';
|
||||||
|
import LoadingIndicator from 'flarum/common/components/LoadingIndicator';
|
||||||
|
|
||||||
|
export interface IPostLikesModalAttrs extends IInternalModalAttrs {
|
||||||
|
post: Post;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class PostLikesModal<CustomAttrs extends IPostLikesModalAttrs = IPostLikesModalAttrs> extends Modal<CustomAttrs, PostLikesModalState> {
|
||||||
|
oninit(vnode: Mithril.VnodeDOM<CustomAttrs, this>) {
|
||||||
|
super.oninit(vnode);
|
||||||
|
|
||||||
|
this.state = new PostLikesModalState({
|
||||||
|
filter: {
|
||||||
|
liked: this.attrs.post.id()!,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
this.state.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
className() {
|
||||||
|
return 'PostLikesModal Modal--small';
|
||||||
|
}
|
||||||
|
|
||||||
|
title() {
|
||||||
|
return app.translator.trans('flarum-likes.forum.post_likes.title');
|
||||||
|
}
|
||||||
|
|
||||||
|
content() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="Modal-body">
|
||||||
|
{this.state.isInitialLoading() ? (
|
||||||
|
<LoadingIndicator />
|
||||||
|
) : (
|
||||||
|
<ul className="PostLikesModal-list">
|
||||||
|
{this.state.getPages().map((page) =>
|
||||||
|
page.items.map((user) => (
|
||||||
|
<li>
|
||||||
|
<Link href={app.route.user(user)}>
|
||||||
|
{avatar(user)} {username(user)}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{this.state.hasNext() ? (
|
||||||
|
<div className="Modal-footer">
|
||||||
|
<div className="Form Form--centered">
|
||||||
|
<div className="Form-group">
|
||||||
|
<Button className="Button Button--block" onclick={() => this.state.loadNext()} loading={this.state.isLoadingNext()}>
|
||||||
|
{app.translator.trans('flarum-likes.forum.post_likes.load_more_button')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
14
extensions/likes/js/src/forum/extend.ts
Normal file
14
extensions/likes/js/src/forum/extend.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import Extend from 'flarum/common/extenders';
|
||||||
|
import Post from 'flarum/common/models/Post';
|
||||||
|
import User from 'flarum/common/models/User';
|
||||||
|
import LikesUserPage from './components/LikesUserPage';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
new Extend.Routes() //
|
||||||
|
.add('user.likes', '/u/:username/likes', LikesUserPage),
|
||||||
|
|
||||||
|
new Extend.Model(Post) //
|
||||||
|
.hasMany<User>('likes')
|
||||||
|
.attribute<number>('likesCount')
|
||||||
|
.attribute<boolean>('canLike'),
|
||||||
|
];
|
@@ -1,7 +1,5 @@
|
|||||||
import { extend } from 'flarum/common/extend';
|
import { extend } from 'flarum/common/extend';
|
||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import Post from 'flarum/common/models/Post';
|
|
||||||
import Model from 'flarum/common/Model';
|
|
||||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||||
|
|
||||||
import addLikeAction from './addLikeAction';
|
import addLikeAction from './addLikeAction';
|
||||||
@@ -9,12 +7,11 @@ import addLikesList from './addLikesList';
|
|||||||
import PostLikedNotification from './components/PostLikedNotification';
|
import PostLikedNotification from './components/PostLikedNotification';
|
||||||
import addLikesTabToUserProfile from './addLikesTabToUserProfile';
|
import addLikesTabToUserProfile from './addLikesTabToUserProfile';
|
||||||
|
|
||||||
|
export { default as extend } from './extend';
|
||||||
|
|
||||||
app.initializers.add('flarum-likes', () => {
|
app.initializers.add('flarum-likes', () => {
|
||||||
app.notificationComponents.postLiked = PostLikedNotification;
|
app.notificationComponents.postLiked = PostLikedNotification;
|
||||||
|
|
||||||
Post.prototype.canLike = Model.attribute('canLike');
|
|
||||||
Post.prototype.likes = Model.hasMany('likes');
|
|
||||||
|
|
||||||
addLikeAction();
|
addLikeAction();
|
||||||
addLikesList();
|
addLikesList();
|
||||||
addLikesTabToUserProfile();
|
addLikesTabToUserProfile();
|
||||||
|
26
extensions/likes/js/src/forum/states/PostLikesModalState.ts
Normal file
26
extensions/likes/js/src/forum/states/PostLikesModalState.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import PaginatedListState, { PaginatedListParams } from 'flarum/common/states/PaginatedListState';
|
||||||
|
import User from 'flarum/common/models/User';
|
||||||
|
|
||||||
|
export interface PostLikesModalListParams extends PaginatedListParams {
|
||||||
|
filter: {
|
||||||
|
liked: string;
|
||||||
|
};
|
||||||
|
page?: {
|
||||||
|
offset?: number;
|
||||||
|
limit: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class PostLikesModalState<P extends PostLikesModalListParams = PostLikesModalListParams> extends PaginatedListState<User, P> {
|
||||||
|
constructor(params: P, page: number = 1) {
|
||||||
|
const limit = 10;
|
||||||
|
|
||||||
|
params.page = { ...(params.page || {}), limit };
|
||||||
|
|
||||||
|
super(params, page, limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
get type(): string {
|
||||||
|
return 'users';
|
||||||
|
}
|
||||||
|
}
|
20
extensions/likes/js/tsconfig.json
Normal file
20
extensions/likes/js/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// Use Flarum's tsconfig as a starting point
|
||||||
|
"extends": "flarum-tsconfig",
|
||||||
|
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||||
|
// and also tells your Typescript server to read core's global typings for
|
||||||
|
// access to `dayjs` and `$` in the global namespace.
|
||||||
|
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
// This will output typings to `dist-typings`
|
||||||
|
"declarationDir": "./dist-typings",
|
||||||
|
"paths": {
|
||||||
|
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
// TODO: remove after export registry system implemented
|
||||||
|
// Without this, the old-style `@flarum/core` import is resolved to
|
||||||
|
// source code in flarum/core instead of the dist typings.
|
||||||
|
// This causes an inaccurate "duplicate export" error.
|
||||||
|
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -35,6 +35,7 @@ flarum-likes:
|
|||||||
# These translations are used by the Users Who Like This modal dialog.
|
# These translations are used by the Users Who Like This modal dialog.
|
||||||
post_likes:
|
post_likes:
|
||||||
title: Users Who Like This
|
title: Users Who Like This
|
||||||
|
load_more_button: => core.ref.load_more
|
||||||
|
|
||||||
# These translations are used in the Settings page.
|
# These translations are used in the Settings page.
|
||||||
settings:
|
settings:
|
||||||
|
60
extensions/likes/src/Api/LoadLikesRelationship.php
Normal file
60
extensions/likes/src/Api/LoadLikesRelationship.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Likes\Api;
|
||||||
|
|
||||||
|
use Flarum\Discussion\Discussion;
|
||||||
|
use Flarum\Http\RequestUtil;
|
||||||
|
use Flarum\Post\Post;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
use Illuminate\Database\Query\Expression;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
|
class LoadLikesRelationship
|
||||||
|
{
|
||||||
|
public static $maxLikes = 4;
|
||||||
|
|
||||||
|
public static function mutateRelation(BelongsToMany $query, ServerRequestInterface $request): BelongsToMany
|
||||||
|
{
|
||||||
|
$actor = RequestUtil::getActor($request);
|
||||||
|
|
||||||
|
$grammar = $query->getQuery()->getGrammar();
|
||||||
|
|
||||||
|
return $query
|
||||||
|
// So that we can tell if the current user has liked the post.
|
||||||
|
->orderBy(new Expression($grammar->wrap('user_id').' = '.$actor->id), 'desc')
|
||||||
|
// Limiting a relationship results is only possible because
|
||||||
|
// the Post model uses the \Staudenmeir\EloquentEagerLimit\HasEagerLimit
|
||||||
|
// trait.
|
||||||
|
->limit(self::$maxLikes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called using the @see ApiController::prepareDataForSerialization extender.
|
||||||
|
*/
|
||||||
|
public static function countRelation($controller, $data): void
|
||||||
|
{
|
||||||
|
$loadable = null;
|
||||||
|
|
||||||
|
if ($data instanceof Discussion) {
|
||||||
|
$loadable = $data->newCollection($data->posts)->filter(function ($post) {
|
||||||
|
return $post instanceof Post;
|
||||||
|
});
|
||||||
|
} elseif ($data instanceof Collection) {
|
||||||
|
$loadable = $data;
|
||||||
|
} elseif ($data instanceof Post) {
|
||||||
|
$loadable = $data->newCollection([$data]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($loadable) {
|
||||||
|
$loadable->loadCount('likes');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -11,17 +11,20 @@ namespace Flarum\Likes\Query;
|
|||||||
|
|
||||||
use Flarum\Filter\FilterInterface;
|
use Flarum\Filter\FilterInterface;
|
||||||
use Flarum\Filter\FilterState;
|
use Flarum\Filter\FilterState;
|
||||||
|
use Flarum\Filter\ValidateFilterTrait;
|
||||||
|
|
||||||
class LikedByFilter implements FilterInterface
|
class LikedByFilter implements FilterInterface
|
||||||
{
|
{
|
||||||
|
use ValidateFilterTrait;
|
||||||
|
|
||||||
public function getFilterKey(): string
|
public function getFilterKey(): string
|
||||||
{
|
{
|
||||||
return 'likedBy';
|
return 'likedBy';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function filter(FilterState $filterState, string $filterValue, bool $negate)
|
public function filter(FilterState $filterState, $filterValue, bool $negate)
|
||||||
{
|
{
|
||||||
$likedId = trim($filterValue, '"');
|
$likedId = $this->asInt($filterValue);
|
||||||
|
|
||||||
$filterState
|
$filterState
|
||||||
->getQuery()
|
->getQuery()
|
||||||
|
34
extensions/likes/src/Query/LikedFilter.php
Normal file
34
extensions/likes/src/Query/LikedFilter.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Likes\Query;
|
||||||
|
|
||||||
|
use Flarum\Filter\FilterInterface;
|
||||||
|
use Flarum\Filter\FilterState;
|
||||||
|
|
||||||
|
class LikedFilter implements FilterInterface
|
||||||
|
{
|
||||||
|
public function getFilterKey(): string
|
||||||
|
{
|
||||||
|
return 'liked';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filter(FilterState $filterState, string $filterValue, bool $negate)
|
||||||
|
{
|
||||||
|
$likedId = trim($filterValue, '"');
|
||||||
|
|
||||||
|
$filterState
|
||||||
|
->getQuery()
|
||||||
|
->whereIn('id', function ($query) use ($likedId) {
|
||||||
|
$query->select('user_id')
|
||||||
|
->from('post_likes')
|
||||||
|
->where('post_id', $likedId);
|
||||||
|
}, 'and', $negate);
|
||||||
|
}
|
||||||
|
}
|
210
extensions/likes/tests/integration/api/ListPostsTest.php
Normal file
210
extensions/likes/tests/integration/api/ListPostsTest.php
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed copyright and license information, please view the
|
||||||
|
* LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Likes\Tests\integration\api\discussions;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Flarum\Group\Group;
|
||||||
|
use Flarum\Likes\Api\LoadLikesRelationship;
|
||||||
|
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
|
||||||
|
use Flarum\Testing\integration\TestCase;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
|
class ListPostsTest extends TestCase
|
||||||
|
{
|
||||||
|
use RetrievesAuthorizedUsers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->extension('flarum-likes');
|
||||||
|
|
||||||
|
$this->prepareDatabase([
|
||||||
|
'discussions' => [
|
||||||
|
['id' => 100, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'user_id' => 1, 'first_post_id' => 101, 'comment_count' => 1],
|
||||||
|
],
|
||||||
|
'posts' => [
|
||||||
|
['id' => 101, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
|
||||||
|
],
|
||||||
|
'users' => [
|
||||||
|
$this->normalUser(),
|
||||||
|
['id' => 102, 'username' => 'user102', 'email' => '102@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
['id' => 103, 'username' => 'user103', 'email' => '103@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
['id' => 104, 'username' => 'user104', 'email' => '104@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
['id' => 105, 'username' => 'user105', 'email' => '105@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
['id' => 106, 'username' => 'user106', 'email' => '106@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
['id' => 107, 'username' => 'user107', 'email' => '107@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
['id' => 108, 'username' => 'user108', 'email' => '108@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
['id' => 109, 'username' => 'user109', 'email' => '109@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
['id' => 110, 'username' => 'user110', 'email' => '110@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
['id' => 111, 'username' => 'user111', 'email' => '111@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
['id' => 112, 'username' => 'user112', 'email' => '112@machine.local', 'is_email_confirmed' => 1],
|
||||||
|
],
|
||||||
|
'post_likes' => [
|
||||||
|
['user_id' => 102, 'post_id' => 101],
|
||||||
|
['user_id' => 104, 'post_id' => 101],
|
||||||
|
['user_id' => 105, 'post_id' => 101],
|
||||||
|
['user_id' => 106, 'post_id' => 101],
|
||||||
|
['user_id' => 107, 'post_id' => 101],
|
||||||
|
['user_id' => 108, 'post_id' => 101],
|
||||||
|
['user_id' => 109, 'post_id' => 101],
|
||||||
|
['user_id' => 110, 'post_id' => 101],
|
||||||
|
['user_id' => 2, 'post_id' => 101],
|
||||||
|
['user_id' => 111, 'post_id' => 101],
|
||||||
|
['user_id' => 112, 'post_id' => 101],
|
||||||
|
],
|
||||||
|
'group_permission' => [
|
||||||
|
['group_id' => Group::GUEST_ID, 'permission' => 'searchUsers'],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function liked_filter_works()
|
||||||
|
{
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/api/users')
|
||||||
|
->withQueryParams([
|
||||||
|
'filter' => ['liked' => 101],
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true)['data'];
|
||||||
|
|
||||||
|
// Order-independent comparison
|
||||||
|
$ids = Arr::pluck($data, 'id');
|
||||||
|
$this->assertEqualsCanonicalizing([
|
||||||
|
102, 104, 105, 106, 107, 108, 109, 110, 2, 111, 112
|
||||||
|
], $ids, 'IDs do not match');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function liked_filter_works_negated()
|
||||||
|
{
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/api/users')
|
||||||
|
->withQueryParams([
|
||||||
|
'filter' => ['-liked' => 101],
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true)['data'];
|
||||||
|
|
||||||
|
// Order-independent comparison
|
||||||
|
$ids = Arr::pluck($data, 'id');
|
||||||
|
$this->assertEqualsCanonicalizing([1, 103], $ids, 'IDs do not match');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function likes_relation_returns_limited_results_and_shows_only_visible_posts_in_show_post_endpoint()
|
||||||
|
{
|
||||||
|
// List posts endpoint
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/api/posts/101', [
|
||||||
|
'authenticatedAs' => 2,
|
||||||
|
])->withQueryParams([
|
||||||
|
'include' => 'likes',
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true)['data'];
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
|
$likes = $data['relationships']['likes']['data'];
|
||||||
|
|
||||||
|
// Only displays a limited amount of likes
|
||||||
|
$this->assertCount(LoadLikesRelationship::$maxLikes, $likes);
|
||||||
|
// Displays the correct count of likes
|
||||||
|
$this->assertEquals(11, $data['attributes']['likesCount']);
|
||||||
|
// Of the limited amount of likes, the actor always appears
|
||||||
|
$this->assertEquals([2, 102, 104, 105], Arr::pluck($likes, 'id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function likes_relation_returns_limited_results_and_shows_only_visible_posts_in_list_posts_endpoint()
|
||||||
|
{
|
||||||
|
// List posts endpoint
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/api/posts', [
|
||||||
|
'authenticatedAs' => 2,
|
||||||
|
])->withQueryParams([
|
||||||
|
'filter' => ['discussion' => 100],
|
||||||
|
'include' => 'likes',
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true)['data'];
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
|
$likes = $data[0]['relationships']['likes']['data'];
|
||||||
|
|
||||||
|
// Only displays a limited amount of likes
|
||||||
|
$this->assertCount(LoadLikesRelationship::$maxLikes, $likes);
|
||||||
|
// Displays the correct count of likes
|
||||||
|
$this->assertEquals(11, $data[0]['attributes']['likesCount']);
|
||||||
|
// Of the limited amount of likes, the actor always appears
|
||||||
|
$this->assertEquals([2, 102, 104, 105], Arr::pluck($likes, 'id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider likesIncludeProvider
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function likes_relation_returns_limited_results_and_shows_only_visible_posts_in_show_discussion_endpoint(string $include)
|
||||||
|
{
|
||||||
|
// Show discussion endpoint
|
||||||
|
$response = $this->send(
|
||||||
|
$this->request('GET', '/api/discussions/100', [
|
||||||
|
'authenticatedAs' => 2,
|
||||||
|
])->withQueryParams([
|
||||||
|
'include' => $include,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
$included = json_decode($response->getBody()->getContents(), true)['included'];
|
||||||
|
|
||||||
|
$likes = collect($included)
|
||||||
|
->where('type', 'posts')
|
||||||
|
->where('id', 101)
|
||||||
|
->first()['relationships']['likes']['data'];
|
||||||
|
|
||||||
|
// Only displays a limited amount of likes
|
||||||
|
$this->assertCount(LoadLikesRelationship::$maxLikes, $likes);
|
||||||
|
// Displays the correct count of likes
|
||||||
|
$this->assertEquals(11, collect($included)
|
||||||
|
->where('type', 'posts')
|
||||||
|
->where('id', 101)
|
||||||
|
->first()['attributes']['likesCount']);
|
||||||
|
// Of the limited amount of likes, the actor always appears
|
||||||
|
$this->assertEquals([2, 102, 104, 105], Arr::pluck($likes, 'id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function likesIncludeProvider(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['posts,posts.likes'],
|
||||||
|
['posts.likes'],
|
||||||
|
[''],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^1.6"
|
"flarum/core": "^1.8"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
@@ -35,12 +35,15 @@ return [
|
|||||||
(new Extend\Notification())
|
(new Extend\Notification())
|
||||||
->type(DiscussionLockedBlueprint::class, BasicDiscussionSerializer::class, ['alert']),
|
->type(DiscussionLockedBlueprint::class, BasicDiscussionSerializer::class, ['alert']),
|
||||||
|
|
||||||
|
(new Extend\Model(Discussion::class))
|
||||||
|
->cast('is_locked', 'bool'),
|
||||||
|
|
||||||
(new Extend\ApiSerializer(DiscussionSerializer::class))
|
(new Extend\ApiSerializer(DiscussionSerializer::class))
|
||||||
->attribute('isLocked', function (DiscussionSerializer $serializer, Discussion $discussion) {
|
->attribute('isLocked', function (DiscussionSerializer $serializer, Discussion $discussion) {
|
||||||
return (bool) $discussion->is_locked;
|
return $discussion->is_locked;
|
||||||
})
|
})
|
||||||
->attribute('canLock', function (DiscussionSerializer $serializer, Discussion $discussion) {
|
->attribute('canLock', function (DiscussionSerializer $serializer, Discussion $discussion) {
|
||||||
return (bool) $serializer->getActor()->can('lock', $discussion);
|
return $serializer->getActor()->can('lock', $discussion);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
(new Extend\Post())
|
(new Extend\Post())
|
||||||
|
2
extensions/lock/js/dist/admin.js.map
generated
vendored
2
extensions/lock/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,QAAQ,WAC3BA,IAAAA,cAAAA,IAAsB,eAAeC,mBACnC,CACEC,KAAM,cACNC,MAAOH,IAAAA,WAAAA,MAAqB,wDAC5BI,WAAY,mBAEd,WACA,GAEH,G","sources":["webpack://@flarum/lock/webpack/bootstrap","webpack://@flarum/lock/webpack/runtime/compat get default export","webpack://@flarum/lock/webpack/runtime/define property getters","webpack://@flarum/lock/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/lock/webpack/runtime/make namespace object","webpack://@flarum/lock/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/lock/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('lock', () => {\n app.extensionData.for('flarum-lock').registerPermission(\n {\n icon: 'fas fa-lock',\n label: app.translator.trans('flarum-lock.admin.permissions.lock_discussions_label'),\n permission: 'discussion.lock',\n },\n 'moderate',\n 95\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerPermission","icon","label","permission"],"sourceRoot":""}
|
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,QAAQ,WAC3BA,IAAAA,cAAAA,IAAsB,eAAeC,mBACnC,CACEC,KAAM,cACNC,MAAOH,IAAAA,WAAAA,MAAqB,wDAC5BI,WAAY,mBAEd,WACA,GAEJ,G","sources":["webpack://@flarum/lock/webpack/bootstrap","webpack://@flarum/lock/webpack/runtime/compat get default export","webpack://@flarum/lock/webpack/runtime/define property getters","webpack://@flarum/lock/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/lock/webpack/runtime/make namespace object","webpack://@flarum/lock/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/lock/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('lock', () => {\n app.extensionData.for('flarum-lock').registerPermission(\n {\n icon: 'fas fa-lock',\n label: app.translator.trans('flarum-lock.admin.permissions.lock_discussions_label'),\n permission: 'discussion.lock',\n },\n 'moderate',\n 95\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerPermission","icon","label","permission"],"sourceRoot":""}
|
2
extensions/lock/js/dist/forum.js
generated
vendored
2
extensions/lock/js/dist/forum.js
generated
vendored
@@ -1,2 +1,2 @@
|
|||||||
(()=>{var o={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return o.d(n,{a:n}),n},d:(t,n)=>{for(var c in n)o.o(n,c)&&!o.o(t,c)&&Object.defineProperty(t,c,{enumerable:!0,get:n[c]})},o:(o,t)=>Object.prototype.hasOwnProperty.call(o,t),r:o=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(o,"__esModule",{value:!0})}},t={};(()=>{"use strict";o.r(t);const n=flarum.core.compat["common/extend"],c=flarum.core.compat["forum/app"];var r=o.n(c);const e=flarum.core.compat["common/Model"];var s=o.n(e);const a=flarum.core.compat["common/models/Discussion"];var i=o.n(a);const u=flarum.core.compat["forum/components/NotificationGrid"];var l=o.n(u);function f(o,t){return f=Object.setPrototypeOf||function(o,t){return o.__proto__=t,o},f(o,t)}function p(o,t){o.prototype=Object.create(t.prototype),o.prototype.constructor=o,f(o,t)}const d=flarum.core.compat["forum/components/EventPost"];var k=function(o){function t(){return o.apply(this,arguments)||this}p(t,o);var n=t.prototype;return n.icon=function(){return this.attrs.post.content().locked?"fas fa-lock":"fas fa-unlock"},n.descriptionKey=function(){return this.attrs.post.content().locked?"flarum-lock.forum.post_stream.discussion_locked_text":"flarum-lock.forum.post_stream.discussion_unlocked_text"},t}(o.n(d)());const y=flarum.core.compat["forum/components/Notification"];var _=function(o){function t(){return o.apply(this,arguments)||this}p(t,o);var n=t.prototype;return n.icon=function(){return"fas fa-lock"},n.href=function(){var o=this.attrs.notification;return r().route.discussion(o.subject(),o.content().postNumber)},n.content=function(){return r().translator.trans("flarum-lock.forum.notifications.discussion_locked_text",{user:this.attrs.notification.fromUser()})},t}(o.n(y)());const b=flarum.core.compat["common/components/Badge"];var v=o.n(b);const h=flarum.core.compat["forum/utils/DiscussionControls"];var L=o.n(h);const g=flarum.core.compat["forum/components/DiscussionPage"];var x=o.n(g);const O=flarum.core.compat["common/components/Button"];var j=o.n(O);r().initializers.add("flarum-lock",(function(){r().postComponents.discussionLocked=k,r().notificationComponents.discussionLocked=_,i().prototype.isLocked=s().attribute("isLocked"),i().prototype.canLock=s().attribute("canLock"),(0,n.extend)(i().prototype,"badges",(function(o){this.isLocked()&&o.add("locked",v().component({type:"locked",label:r().translator.trans("flarum-lock.forum.badge.locked_tooltip"),icon:"fas fa-lock"}))})),(0,n.extend)(L(),"moderationControls",(function(o,t){t.canLock()&&o.add("lock",j().component({icon:"fas fa-lock",onclick:this.lockAction.bind(t)},r().translator.trans(t.isLocked()?"flarum-lock.forum.discussion_controls.unlock_button":"flarum-lock.forum.discussion_controls.lock_button")))})),L().lockAction=function(){this.save({isLocked:!this.isLocked()}).then((function(){r().current.matches(x())&&r().current.get("stream").update(),m.redraw()}))},(0,n.extend)(l().prototype,"notificationTypes",(function(o){o.add("discussionLocked",{name:"discussionLocked",icon:"fas fa-lock",label:r().translator.trans("flarum-lock.forum.settings.notify_discussion_locked_label")})}))}))})(),module.exports=t})();
|
(()=>{var o={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return o.d(n,{a:n}),n},d:(t,n)=>{for(var e in n)o.o(n,e)&&!o.o(t,e)&&Object.defineProperty(t,e,{enumerable:!0,get:n[e]})},o:(o,t)=>Object.prototype.hasOwnProperty.call(o,t),r:o=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(o,"__esModule",{value:!0})}},t={};(()=>{"use strict";o.r(t),o.d(t,{extend:()=>j});const n=flarum.core.compat["common/extend"],e=flarum.core.compat["forum/app"];var c=o.n(e);const r=flarum.core.compat["forum/components/NotificationGrid"];var s=o.n(r);function a(o,t){return a=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(o,t){return o.__proto__=t,o},a(o,t)}function i(o,t){o.prototype=Object.create(t.prototype),o.prototype.constructor=o,a(o,t)}const u=flarum.core.compat["forum/components/Notification"];var f=function(o){function t(){return o.apply(this,arguments)||this}i(t,o);var n=t.prototype;return n.icon=function(){return"fas fa-lock"},n.href=function(){var o=this.attrs.notification;return c().route.discussion(o.subject(),o.content().postNumber)},n.content=function(){return c().translator.trans("flarum-lock.forum.notifications.discussion_locked_text",{user:this.attrs.notification.fromUser()})},t}(o.n(u)());const l=flarum.core.compat["common/models/Discussion"];var d=o.n(l);const p=flarum.core.compat["common/components/Badge"];var k=o.n(p);const y=flarum.core.compat["forum/utils/DiscussionControls"];var b=o.n(y);const _=flarum.core.compat["forum/components/DiscussionPage"];var v=o.n(_);const h=flarum.core.compat["common/components/Button"];var g=o.n(h);const L=flarum.core.compat["common/extenders"];var x=o.n(L);const O=flarum.core.compat["forum/components/EventPost"];var P=function(o){function t(){return o.apply(this,arguments)||this}i(t,o);var n=t.prototype;return n.icon=function(){return this.attrs.post.content().locked?"fas fa-lock":"fas fa-unlock"},n.descriptionKey=function(){return this.attrs.post.content().locked?"flarum-lock.forum.post_stream.discussion_locked_text":"flarum-lock.forum.post_stream.discussion_unlocked_text"},t}(o.n(O)());const j=[(new(x().PostTypes)).add("discussionLocked",P),new(x().Model)(d()).attribute("isLocked").attribute("canLock")];c().initializers.add("flarum-lock",(function(){c().notificationComponents.discussionLocked=f,(0,n.extend)(d().prototype,"badges",(function(o){this.isLocked()&&o.add("locked",m(k(),{type:"locked",label:c().translator.trans("flarum-lock.forum.badge.locked_tooltip"),icon:"fas fa-lock"}))})),(0,n.extend)(b(),"moderationControls",(function(o,t){t.canLock()&&o.add("lock",m(g(),{icon:"fas fa-lock",onclick:this.lockAction.bind(t)},c().translator.trans("flarum-lock.forum.discussion_controls."+(t.isLocked()?"unlock":"lock")+"_button")))})),b().lockAction=function(){this.save({isLocked:!this.isLocked()}).then((function(){c().current.matches(v())&&c().current.get("stream").update(),m.redraw()}))},(0,n.extend)(s().prototype,"notificationTypes",(function(o){o.add("discussionLocked",{name:"discussionLocked",icon:"fas fa-lock",label:c().translator.trans("flarum-lock.forum.settings.notify_discussion_locked_label")})}))}))})(),module.exports=t})();
|
||||||
//# sourceMappingURL=forum.js.map
|
//# sourceMappingURL=forum.js.map
|
2
extensions/lock/js/dist/forum.js.map
generated
vendored
2
extensions/lock/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"flarum-webpack-config": "^2.0.0",
|
"flarum-webpack-config": "^2.0.0",
|
||||||
"webpack": "^5.65.0",
|
"webpack": "^5.76.0",
|
||||||
"webpack-cli": "^4.9.1",
|
"webpack-cli": "^4.9.1",
|
||||||
"@flarum/prettier-config": "^1.0.0",
|
"@flarum/prettier-config": "^1.0.0",
|
||||||
"flarum-tsconfig": "^1.0.2",
|
"flarum-tsconfig": "^1.0.2",
|
||||||
|
@@ -6,14 +6,7 @@ import Badge from 'flarum/common/components/Badge';
|
|||||||
export default function addLockBadge() {
|
export default function addLockBadge() {
|
||||||
extend(Discussion.prototype, 'badges', function (badges) {
|
extend(Discussion.prototype, 'badges', function (badges) {
|
||||||
if (this.isLocked()) {
|
if (this.isLocked()) {
|
||||||
badges.add(
|
badges.add('locked', <Badge type="locked" label={app.translator.trans('flarum-lock.forum.badge.locked_tooltip')} icon="fas fa-lock" />);
|
||||||
'locked',
|
|
||||||
Badge.component({
|
|
||||||
type: 'locked',
|
|
||||||
label: app.translator.trans('flarum-lock.forum.badge.locked_tooltip'),
|
|
||||||
icon: 'fas fa-lock',
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -9,15 +9,9 @@ export default function addLockControl() {
|
|||||||
if (discussion.canLock()) {
|
if (discussion.canLock()) {
|
||||||
items.add(
|
items.add(
|
||||||
'lock',
|
'lock',
|
||||||
Button.component(
|
<Button icon="fas fa-lock" onclick={this.lockAction.bind(discussion)}>
|
||||||
{
|
{app.translator.trans(`flarum-lock.forum.discussion_controls.${discussion.isLocked() ? 'unlock' : 'lock'}_button`)}
|
||||||
icon: 'fas fa-lock',
|
</Button>
|
||||||
onclick: this.lockAction.bind(discussion),
|
|
||||||
},
|
|
||||||
app.translator.trans(
|
|
||||||
discussion.isLocked() ? 'flarum-lock.forum.discussion_controls.unlock_button' : 'flarum-lock.forum.discussion_controls.lock_button'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
12
extensions/lock/js/src/forum/extend.ts
Normal file
12
extensions/lock/js/src/forum/extend.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import Extend from 'flarum/common/extenders';
|
||||||
|
import Discussion from 'flarum/common/models/Discussion';
|
||||||
|
import DiscussionLockedPost from './components/DiscussionLockedPost';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
new Extend.PostTypes() //
|
||||||
|
.add('discussionLocked', DiscussionLockedPost),
|
||||||
|
|
||||||
|
new Extend.Model(Discussion) //
|
||||||
|
.attribute<boolean>('isLocked')
|
||||||
|
.attribute<boolean>('canLock'),
|
||||||
|
];
|
@@ -1,20 +1,15 @@
|
|||||||
import { extend } from 'flarum/common/extend';
|
import { extend } from 'flarum/common/extend';
|
||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import Model from 'flarum/common/Model';
|
|
||||||
import Discussion from 'flarum/common/models/Discussion';
|
|
||||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||||
|
|
||||||
import DiscussionLockedPost from './components/DiscussionLockedPost';
|
|
||||||
import DiscussionLockedNotification from './components/DiscussionLockedNotification';
|
import DiscussionLockedNotification from './components/DiscussionLockedNotification';
|
||||||
import addLockBadge from './addLockBadge';
|
import addLockBadge from './addLockBadge';
|
||||||
import addLockControl from './addLockControl';
|
import addLockControl from './addLockControl';
|
||||||
|
|
||||||
app.initializers.add('flarum-lock', () => {
|
export { default as extend } from './extend';
|
||||||
app.postComponents.discussionLocked = DiscussionLockedPost;
|
|
||||||
app.notificationComponents.discussionLocked = DiscussionLockedNotification;
|
|
||||||
|
|
||||||
Discussion.prototype.isLocked = Model.attribute('isLocked');
|
app.initializers.add('flarum-lock', () => {
|
||||||
Discussion.prototype.canLock = Model.attribute('canLock');
|
app.notificationComponents.discussionLocked = DiscussionLockedNotification;
|
||||||
|
|
||||||
addLockBadge();
|
addLockBadge();
|
||||||
addLockControl();
|
addLockControl();
|
||||||
|
20
extensions/lock/js/tsconfig.json
Normal file
20
extensions/lock/js/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// Use Flarum's tsconfig as a starting point
|
||||||
|
"extends": "flarum-tsconfig",
|
||||||
|
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||||
|
// and also tells your Typescript server to read core's global typings for
|
||||||
|
// access to `dayjs` and `$` in the global namespace.
|
||||||
|
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
// This will output typings to `dist-typings`
|
||||||
|
"declarationDir": "./dist-typings",
|
||||||
|
"paths": {
|
||||||
|
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
// TODO: remove after export registry system implemented
|
||||||
|
// Without this, the old-style `@flarum/core` import is resolved to
|
||||||
|
// source code in flarum/core instead of the dist typings.
|
||||||
|
// This causes an inaccurate "duplicate export" error.
|
||||||
|
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -29,8 +29,8 @@ flarum-lock:
|
|||||||
|
|
||||||
# These translations are displayed between posts in the post stream.
|
# These translations are displayed between posts in the post stream.
|
||||||
post_stream:
|
post_stream:
|
||||||
discussion_locked_text: "{username} locked the discussion."
|
discussion_locked_text: "{username} locked the discussion {time}."
|
||||||
discussion_unlocked_text: "{username} unlocked the discussion."
|
discussion_unlocked_text: "{username} unlocked the discussion {time}."
|
||||||
|
|
||||||
# These translations are used in the Settings page.
|
# These translations are used in the Settings page.
|
||||||
settings:
|
settings:
|
||||||
|
@@ -18,7 +18,7 @@ class DiscussionPolicy extends AbstractPolicy
|
|||||||
/**
|
/**
|
||||||
* @param User $actor
|
* @param User $actor
|
||||||
* @param Discussion $discussion
|
* @param Discussion $discussion
|
||||||
* @return bool
|
* @return string|void
|
||||||
*/
|
*/
|
||||||
public function reply(User $actor, Discussion $discussion)
|
public function reply(User $actor, Discussion $discussion)
|
||||||
{
|
{
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
namespace Flarum\Lock\Post;
|
namespace Flarum\Lock\Post;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use Flarum\Post\AbstractEventPost;
|
use Flarum\Post\AbstractEventPost;
|
||||||
use Flarum\Post\MergeableInterface;
|
use Flarum\Post\MergeableInterface;
|
||||||
use Flarum\Post\Post;
|
use Flarum\Post\Post;
|
||||||
@@ -59,7 +60,7 @@ class DiscussionLockedPost extends AbstractEventPost implements MergeableInterfa
|
|||||||
$post = new static;
|
$post = new static;
|
||||||
|
|
||||||
$post->content = static::buildContent($isLocked);
|
$post->content = static::buildContent($isLocked);
|
||||||
$post->created_at = time();
|
$post->created_at = Carbon::now();
|
||||||
$post->discussion_id = $discussionId;
|
$post->discussion_id = $discussionId;
|
||||||
$post->user_id = $userId;
|
$post->user_id = $userId;
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ class LockedFilterGambit extends AbstractRegexGambit implements FilterInterface
|
|||||||
return 'locked';
|
return 'locked';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function filter(FilterState $filterState, string $filterValue, bool $negate)
|
public function filter(FilterState $filterState, $filterValue, bool $negate)
|
||||||
{
|
{
|
||||||
$this->constrain($filterState->getQuery(), $negate);
|
$this->constrain($filterState->getQuery(), $negate);
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"flarum/core": "^1.6"
|
"flarum/core": "^1.8"
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
|
2
extensions/markdown/js/dist/admin.js
generated
vendored
2
extensions/markdown/js/dist/admin.js
generated
vendored
@@ -1,2 +1,2 @@
|
|||||||
(()=>{var t={n:o=>{var e=o&&o.__esModule?()=>o.default:()=>o;return t.d(e,{a:e}),e},d:(o,e)=>{for(var r in e)t.o(e,r)&&!t.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:e[r]})},o:(t,o)=>Object.prototype.hasOwnProperty.call(t,o),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},o={};(()=>{"use strict";t.r(o);const e=flarum.core.compat["admin/app"];var r=t.n(e);const i=flarum.core.compat["common/app"];var n=t.n(i);const a=flarum.core.compat["common/extend"],c=flarum.core.compat["common/components/TextEditor"];var l=t.n(c);const s=flarum.core.compat["common/utils/BasicEditorDriver"];var d=t.n(s);const u=flarum.core.compat["common/utils/styleSelectedText"];var f=t.n(u);function p(t,o){return p=Object.setPrototypeOf||function(t,o){return t.__proto__=o,t},p(t,o)}function h(t,o){t.prototype=Object.create(o.prototype),t.prototype.constructor=t,p(t,o)}const k=flarum.core.compat["common/Component"];var y=t.n(k),b=function(t){function o(){return t.apply(this,arguments)||this}return h(o,t),o.prototype.view=function(t){return m("div",{class:"MarkdownToolbar"},t.children)},o}(y());const x=flarum.core.compat["common/helpers/icon"];var v=t.n(x);const g=flarum.core.compat["common/components/Tooltip"];var _=t.n(g),w=function(t){function o(){return t.apply(this,arguments)||this}h(o,t);var e=o.prototype;return e.oncreate=function(o){t.prototype.oncreate.call(this,o)},e.view=function(){var t=m("button",{className:"Button Button--icon Button--link",type:"button","data-hotkey":this.attrs.hotkey,onkeydown:this.keydown.bind(this),onclick:this.attrs.onclick},v()(this.attrs.icon));return this.attrs.title?m(_(),{text:this.attrs.title},t):t},e.keydown=function(t){" "!==t.key&&"Enter"!==t.key||(t.preventDefault(),this.element.click())},o}(y());const T=flarum.core.compat["common/utils/ItemList"];var O=t.n(T),S=navigator.userAgent.match(/Macintosh/)?"⌘":"ctrl",I={header:{prefix:"### "},bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},strikethrough:{prefix:"~~",suffix:"~~",trimFirst:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](https://)",replaceNext:"https://",scanFor:"https?://"},image:{prefix:"",replaceNext:"https://",scanFor:"https?://"},unordered_list:{prefix:"- ",multiline:!0,surroundWithNewlines:!0},ordered_list:{prefix:"1. ",multiline:!0,orderedList:!0},spoiler:{prefix:">!",suffix:"!<",blockPrefix:">! ",multiline:!0,trimFirst:!0}},P=function(t,o){f()(o.el,I[t])};function j(t,o,e){return function(r){r.key===o&&(r.metaKey&&"⌘"===S||r.ctrlKey&&"ctrl"===S)&&(r.preventDefault(),P(t,e))}}function F(t){var o=this,e="function"==typeof t?t():new(O());function r(t,o){return n().translator.trans("flarum-markdown.lib.composer."+t+"_tooltip")+(o?" <"+S+"-"+o+">":"")}var i=function(t){return function(){return P(t,o.attrs.composer.editor)}};return e.add("header",m(w,{title:r("header"),icon:"fas fa-heading",onclick:i("header")}),1e3),e.add("bold",m(w,{title:r("bold","b"),icon:"fas fa-bold",onclick:i("bold")}),900),e.add("italic",m(w,{title:r("italic","i"),icon:"fas fa-italic",onclick:i("italic")}),800),e.add("strikethrough",m(w,{title:r("strikethrough"),icon:"fas fa-strikethrough",onclick:i("strikethrough")}),700),e.add("quote",m(w,{title:r("quote"),icon:"fas fa-quote-left",onclick:i("quote")}),600),e.add("spoiler",m(w,{title:r("spoiler"),icon:"fas fa-exclamation-triangle",onclick:i("spoiler")}),500),e.add("code",m(w,{title:r("code"),icon:"fas fa-code",onclick:i("code")}),400),e.add("link",m(w,{title:r("link"),icon:"fas fa-link",onclick:i("link")}),300),e.add("image",m(w,{title:r("image"),icon:"fas fa-image",onclick:i("image")}),200),e.add("unordered_list",m(w,{title:r("unordered_list"),icon:"fas fa-list-ul",onclick:i("unordered_list")}),100),e.add("ordered_list",m(w,{title:r("ordered_list"),icon:"fas fa-list-ol",onclick:i("ordered_list")}),0),e}r().initializers.add("flarum-markdown",(function(t){(0,a.extend)(d().prototype,"keyHandlers",(function(t){t.add("bold",j("bold","b",this)),t.add("italic",j("italic","i",this))})),l().prototype.markdownToolbarItems?(0,a.override)(l().prototype,"markdownToolbarItems",F):l().prototype.markdownToolbarItems=F,(0,a.extend)(l().prototype,"toolbarItems",(function(t){t.add("markdown",m(b,{for:this.textareaId,setShortcutHandler:function(t){return shortcutHandler=t}},this.markdownToolbarItems().toArray()),100)}))}))})(),module.exports=o})();
|
(()=>{var t={n:o=>{var e=o&&o.__esModule?()=>o.default:()=>o;return t.d(e,{a:e}),e},d:(o,e)=>{for(var r in e)t.o(e,r)&&!t.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:e[r]})},o:(t,o)=>Object.prototype.hasOwnProperty.call(t,o),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},o={};(()=>{"use strict";t.r(o);const e=flarum.core.compat["admin/app"];var r=t.n(e);const i=flarum.core.compat["common/app"];var n=t.n(i);const a=flarum.core.compat["common/extend"],c=flarum.core.compat["common/components/TextEditor"];var l=t.n(c);const s=flarum.core.compat["common/utils/BasicEditorDriver"];var d=t.n(s);const u=flarum.core.compat["common/utils/styleSelectedText"];var f=t.n(u);function p(t,o){return p=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,o){return t.__proto__=o,t},p(t,o)}function h(t,o){t.prototype=Object.create(o.prototype),t.prototype.constructor=t,p(t,o)}const k=flarum.core.compat["common/Component"];var y=t.n(k),b=function(t){function o(){return t.apply(this,arguments)||this}return h(o,t),o.prototype.view=function(t){return m("div",{className:"MarkdownToolbar"},t.children)},o}(y());const x=flarum.core.compat["common/helpers/icon"];var v=t.n(x);const g=flarum.core.compat["common/components/Tooltip"];var _=t.n(g),w=function(t){function o(){return t.apply(this,arguments)||this}h(o,t);var e=o.prototype;return e.oncreate=function(o){t.prototype.oncreate.call(this,o)},e.view=function(){var t=m("button",{className:"Button Button--icon Button--link",type:"button","data-hotkey":this.attrs.hotkey,onkeydown:this.keydown.bind(this),onclick:this.attrs.onclick},v()(this.attrs.icon));return this.attrs.title?m(_(),{text:this.attrs.title},t):t},e.keydown=function(t){" "!==t.key&&"Enter"!==t.key||(t.preventDefault(),this.element.click())},o}(y());const O=flarum.core.compat["common/utils/ItemList"];var T=t.n(O),P=navigator.userAgent.match(/Macintosh/)?"⌘":"ctrl",S={header:{prefix:"### "},bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},strikethrough:{prefix:"~~",suffix:"~~",trimFirst:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](https://)",replaceNext:"https://",scanFor:"https?://"},image:{prefix:"",replaceNext:"https://",scanFor:"https?://"},unordered_list:{prefix:"- ",multiline:!0,surroundWithNewlines:!0},ordered_list:{prefix:"1. ",multiline:!0,orderedList:!0},spoiler:{prefix:">!",suffix:"!<",blockPrefix:">! ",multiline:!0,trimFirst:!0}},j=function(t,o){f()(o.el,S[t])};function I(t,o,e){return function(r){r.key===o&&(r.metaKey&&"⌘"===P||r.ctrlKey&&"ctrl"===P)&&(r.preventDefault(),j(t,e))}}function F(t){var o=this,e="function"==typeof t?t():new(T());function r(t,o){return n().translator.trans("flarum-markdown.lib.composer."+t+"_tooltip")+(o?" <"+P+"-"+o+">":"")}var i=function(t){return function(){return j(t,o.attrs.composer.editor)}};return e.add("header",m(w,{title:r("header"),icon:"fas fa-heading",onclick:i("header")}),1e3),e.add("bold",m(w,{title:r("bold","b"),icon:"fas fa-bold",onclick:i("bold")}),900),e.add("italic",m(w,{title:r("italic","i"),icon:"fas fa-italic",onclick:i("italic")}),800),e.add("strikethrough",m(w,{title:r("strikethrough"),icon:"fas fa-strikethrough",onclick:i("strikethrough")}),700),e.add("quote",m(w,{title:r("quote"),icon:"fas fa-quote-left",onclick:i("quote")}),600),e.add("spoiler",m(w,{title:r("spoiler"),icon:"fas fa-exclamation-triangle",onclick:i("spoiler")}),500),e.add("code",m(w,{title:r("code"),icon:"fas fa-code",onclick:i("code")}),400),e.add("link",m(w,{title:r("link"),icon:"fas fa-link",onclick:i("link")}),300),e.add("image",m(w,{title:r("image"),icon:"fas fa-image",onclick:i("image")}),200),e.add("unordered_list",m(w,{title:r("unordered_list"),icon:"fas fa-list-ul",onclick:i("unordered_list")}),100),e.add("ordered_list",m(w,{title:r("ordered_list"),icon:"fas fa-list-ol",onclick:i("ordered_list")}),0),e}r().initializers.add("flarum-markdown",(function(t){(0,a.extend)(d().prototype,"keyHandlers",(function(t){t.add("bold",I("bold","b",this)),t.add("italic",I("italic","i",this))})),l().prototype.markdownToolbarItems?(0,a.override)(l().prototype,"markdownToolbarItems",F):l().prototype.markdownToolbarItems=F,(0,a.extend)(l().prototype,"toolbarItems",(function(t){t.add("markdown",m(b,{for:this.textareaId,setShortcutHandler:function(t){return shortcutHandler=t}},this.markdownToolbarItems().toArray()),100)}))}))})(),module.exports=o})();
|
||||||
//# sourceMappingURL=admin.js.map
|
//# sourceMappingURL=admin.js.map
|
2
extensions/markdown/js/dist/admin.js.map
generated
vendored
2
extensions/markdown/js/dist/admin.js.map
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/markdown/js/dist/forum.js
generated
vendored
2
extensions/markdown/js/dist/forum.js
generated
vendored
@@ -1,2 +1,2 @@
|
|||||||
(()=>{var t={n:o=>{var e=o&&o.__esModule?()=>o.default:()=>o;return t.d(e,{a:e}),e},d:(o,e)=>{for(var r in e)t.o(e,r)&&!t.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:e[r]})},o:(t,o)=>Object.prototype.hasOwnProperty.call(t,o),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},o={};(()=>{"use strict";t.r(o);const e=flarum.core.compat["forum/app"];var r=t.n(e);const i=flarum.core.compat["common/app"];var n=t.n(i);const a=flarum.core.compat["common/extend"],c=flarum.core.compat["common/components/TextEditor"];var l=t.n(c);const s=flarum.core.compat["common/utils/BasicEditorDriver"];var d=t.n(s);const u=flarum.core.compat["common/utils/styleSelectedText"];var f=t.n(u);function p(t,o){return p=Object.setPrototypeOf||function(t,o){return t.__proto__=o,t},p(t,o)}function h(t,o){t.prototype=Object.create(o.prototype),t.prototype.constructor=t,p(t,o)}const k=flarum.core.compat["common/Component"];var y=t.n(k),b=function(t){function o(){return t.apply(this,arguments)||this}return h(o,t),o.prototype.view=function(t){return m("div",{class:"MarkdownToolbar"},t.children)},o}(y());const x=flarum.core.compat["common/helpers/icon"];var v=t.n(x);const g=flarum.core.compat["common/components/Tooltip"];var _=t.n(g),w=function(t){function o(){return t.apply(this,arguments)||this}h(o,t);var e=o.prototype;return e.oncreate=function(o){t.prototype.oncreate.call(this,o)},e.view=function(){var t=m("button",{className:"Button Button--icon Button--link",type:"button","data-hotkey":this.attrs.hotkey,onkeydown:this.keydown.bind(this),onclick:this.attrs.onclick},v()(this.attrs.icon));return this.attrs.title?m(_(),{text:this.attrs.title},t):t},e.keydown=function(t){" "!==t.key&&"Enter"!==t.key||(t.preventDefault(),this.element.click())},o}(y());const T=flarum.core.compat["common/utils/ItemList"];var O=t.n(T),S=navigator.userAgent.match(/Macintosh/)?"⌘":"ctrl",I={header:{prefix:"### "},bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},strikethrough:{prefix:"~~",suffix:"~~",trimFirst:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](https://)",replaceNext:"https://",scanFor:"https?://"},image:{prefix:"",replaceNext:"https://",scanFor:"https?://"},unordered_list:{prefix:"- ",multiline:!0,surroundWithNewlines:!0},ordered_list:{prefix:"1. ",multiline:!0,orderedList:!0},spoiler:{prefix:">!",suffix:"!<",blockPrefix:">! ",multiline:!0,trimFirst:!0}},P=function(t,o){f()(o.el,I[t])};function j(t,o,e){return function(r){r.key===o&&(r.metaKey&&"⌘"===S||r.ctrlKey&&"ctrl"===S)&&(r.preventDefault(),P(t,e))}}function F(t){var o=this,e="function"==typeof t?t():new(O());function r(t,o){return n().translator.trans("flarum-markdown.lib.composer."+t+"_tooltip")+(o?" <"+S+"-"+o+">":"")}var i=function(t){return function(){return P(t,o.attrs.composer.editor)}};return e.add("header",m(w,{title:r("header"),icon:"fas fa-heading",onclick:i("header")}),1e3),e.add("bold",m(w,{title:r("bold","b"),icon:"fas fa-bold",onclick:i("bold")}),900),e.add("italic",m(w,{title:r("italic","i"),icon:"fas fa-italic",onclick:i("italic")}),800),e.add("strikethrough",m(w,{title:r("strikethrough"),icon:"fas fa-strikethrough",onclick:i("strikethrough")}),700),e.add("quote",m(w,{title:r("quote"),icon:"fas fa-quote-left",onclick:i("quote")}),600),e.add("spoiler",m(w,{title:r("spoiler"),icon:"fas fa-exclamation-triangle",onclick:i("spoiler")}),500),e.add("code",m(w,{title:r("code"),icon:"fas fa-code",onclick:i("code")}),400),e.add("link",m(w,{title:r("link"),icon:"fas fa-link",onclick:i("link")}),300),e.add("image",m(w,{title:r("image"),icon:"fas fa-image",onclick:i("image")}),200),e.add("unordered_list",m(w,{title:r("unordered_list"),icon:"fas fa-list-ul",onclick:i("unordered_list")}),100),e.add("ordered_list",m(w,{title:r("ordered_list"),icon:"fas fa-list-ol",onclick:i("ordered_list")}),0),e}r().initializers.add("flarum-markdown",(function(t){(0,a.extend)(d().prototype,"keyHandlers",(function(t){t.add("bold",j("bold","b",this)),t.add("italic",j("italic","i",this))})),l().prototype.markdownToolbarItems?(0,a.override)(l().prototype,"markdownToolbarItems",F):l().prototype.markdownToolbarItems=F,(0,a.extend)(l().prototype,"toolbarItems",(function(t){t.add("markdown",m(b,{for:this.textareaId,setShortcutHandler:function(t){return shortcutHandler=t}},this.markdownToolbarItems().toArray()),100)}))}))})(),module.exports=o})();
|
(()=>{var t={n:o=>{var e=o&&o.__esModule?()=>o.default:()=>o;return t.d(e,{a:e}),e},d:(o,e)=>{for(var r in e)t.o(e,r)&&!t.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:e[r]})},o:(t,o)=>Object.prototype.hasOwnProperty.call(t,o),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},o={};(()=>{"use strict";t.r(o);const e=flarum.core.compat["forum/app"];var r=t.n(e);const i=flarum.core.compat["common/app"];var n=t.n(i);const a=flarum.core.compat["common/extend"],c=flarum.core.compat["common/components/TextEditor"];var l=t.n(c);const s=flarum.core.compat["common/utils/BasicEditorDriver"];var d=t.n(s);const u=flarum.core.compat["common/utils/styleSelectedText"];var f=t.n(u);function p(t,o){return p=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,o){return t.__proto__=o,t},p(t,o)}function h(t,o){t.prototype=Object.create(o.prototype),t.prototype.constructor=t,p(t,o)}const k=flarum.core.compat["common/Component"];var y=t.n(k),b=function(t){function o(){return t.apply(this,arguments)||this}return h(o,t),o.prototype.view=function(t){return m("div",{className:"MarkdownToolbar"},t.children)},o}(y());const x=flarum.core.compat["common/helpers/icon"];var v=t.n(x);const g=flarum.core.compat["common/components/Tooltip"];var _=t.n(g),w=function(t){function o(){return t.apply(this,arguments)||this}h(o,t);var e=o.prototype;return e.oncreate=function(o){t.prototype.oncreate.call(this,o)},e.view=function(){var t=m("button",{className:"Button Button--icon Button--link",type:"button","data-hotkey":this.attrs.hotkey,onkeydown:this.keydown.bind(this),onclick:this.attrs.onclick},v()(this.attrs.icon));return this.attrs.title?m(_(),{text:this.attrs.title},t):t},e.keydown=function(t){" "!==t.key&&"Enter"!==t.key||(t.preventDefault(),this.element.click())},o}(y());const O=flarum.core.compat["common/utils/ItemList"];var T=t.n(O),P=navigator.userAgent.match(/Macintosh/)?"⌘":"ctrl",S={header:{prefix:"### "},bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},strikethrough:{prefix:"~~",suffix:"~~",trimFirst:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](https://)",replaceNext:"https://",scanFor:"https?://"},image:{prefix:"",replaceNext:"https://",scanFor:"https?://"},unordered_list:{prefix:"- ",multiline:!0,surroundWithNewlines:!0},ordered_list:{prefix:"1. ",multiline:!0,orderedList:!0},spoiler:{prefix:">!",suffix:"!<",blockPrefix:">! ",multiline:!0,trimFirst:!0}},j=function(t,o){f()(o.el,S[t])};function I(t,o,e){return function(r){r.key===o&&(r.metaKey&&"⌘"===P||r.ctrlKey&&"ctrl"===P)&&(r.preventDefault(),j(t,e))}}function F(t){var o=this,e="function"==typeof t?t():new(T());function r(t,o){return n().translator.trans("flarum-markdown.lib.composer."+t+"_tooltip")+(o?" <"+P+"-"+o+">":"")}var i=function(t){return function(){return j(t,o.attrs.composer.editor)}};return e.add("header",m(w,{title:r("header"),icon:"fas fa-heading",onclick:i("header")}),1e3),e.add("bold",m(w,{title:r("bold","b"),icon:"fas fa-bold",onclick:i("bold")}),900),e.add("italic",m(w,{title:r("italic","i"),icon:"fas fa-italic",onclick:i("italic")}),800),e.add("strikethrough",m(w,{title:r("strikethrough"),icon:"fas fa-strikethrough",onclick:i("strikethrough")}),700),e.add("quote",m(w,{title:r("quote"),icon:"fas fa-quote-left",onclick:i("quote")}),600),e.add("spoiler",m(w,{title:r("spoiler"),icon:"fas fa-exclamation-triangle",onclick:i("spoiler")}),500),e.add("code",m(w,{title:r("code"),icon:"fas fa-code",onclick:i("code")}),400),e.add("link",m(w,{title:r("link"),icon:"fas fa-link",onclick:i("link")}),300),e.add("image",m(w,{title:r("image"),icon:"fas fa-image",onclick:i("image")}),200),e.add("unordered_list",m(w,{title:r("unordered_list"),icon:"fas fa-list-ul",onclick:i("unordered_list")}),100),e.add("ordered_list",m(w,{title:r("ordered_list"),icon:"fas fa-list-ol",onclick:i("ordered_list")}),0),e}r().initializers.add("flarum-markdown",(function(t){(0,a.extend)(d().prototype,"keyHandlers",(function(t){t.add("bold",I("bold","b",this)),t.add("italic",I("italic","i",this))})),l().prototype.markdownToolbarItems?(0,a.override)(l().prototype,"markdownToolbarItems",F):l().prototype.markdownToolbarItems=F,(0,a.extend)(l().prototype,"toolbarItems",(function(t){t.add("markdown",m(b,{for:this.textareaId,setShortcutHandler:function(t){return shortcutHandler=t}},this.markdownToolbarItems().toArray()),100)}))}))})(),module.exports=o})();
|
||||||
//# sourceMappingURL=forum.js.map
|
//# sourceMappingURL=forum.js.map
|
2
extensions/markdown/js/dist/forum.js.map
generated
vendored
2
extensions/markdown/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user