1
0
mirror of https://github.com/flarum/core.git synced 2025-09-01 04:11:56 +02:00

Compare commits

..

77 Commits

Author SHA1 Message Date
IanM
5bd7e5dfe3 chore: create changelog 2024-10-09 14:00:11 +01:00
IanM
956ac20c4c chore: bump appver 2024-10-09 10:45:06 +01:00
flarum-bot
b7e41ce82f Bundled output for commit c737d7b8f5
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-10-08 14:07:09 +00:00
IanM
c737d7b8f5 fix: basicspage broken when no displayname drivers enabled (#4062) 2024-10-08 15:00:43 +01:00
Davide Iadeluca
9295e7b96f chore(flags): require flarum/core ^1.8.6 (#4061) 2024-10-08 07:40:35 +01:00
Davide Iadeluca
9377256409 chore: 1.8.6 changelog (#4058)
* chore: `1.8.6` changelog

* chore: add recent fix

* chore: remove interim fixes
2024-10-08 07:13:56 +01:00
Davide Iadeluca
9c91c89326 [1.x] fix(core, mentions): return null if content left empty in formatter (#4059)
* test(core): implement test for creating discussion without content

* fix(core): handle `null` case in XML parser

* fix(mentions): change/remove typings in unparser

* fix(mentions): return early if xml null

* chore: fix PHPStan

* chore: move tests to mentions

* chore: remove unused import

* chore: remove unused imports

* test(mentions): implement test for post editing with content empty

* test(mentions): change post edit tests

* test(mentions): add test for creating discussion with empty string
2024-10-08 06:56:09 +01:00
flarum-bot
8169550f1c Bundled output for commit d5a1653d24
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-10-03 08:51:49 +00:00
Robert Korulczyk
d5a1653d24 [1.x] feat: allow to customize time formats through translations (#4053)
* Allow to customize time formats

* Fix CS
2024-10-03 09:47:48 +01:00
flarum-bot
db605bdbaa Bundled output for commit 1665d47adc
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-10-03 08:04:40 +00:00
IanM
1665d47adc fix: compat: still return controls view item, even if empty (#4057) 2024-10-03 09:01:17 +01:00
flarum-bot
1c71ee0968 Bundled output for commit 6846f4232c
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-10-03 06:29:46 +00:00
IanM
6846f4232c fix: js error as guest on DiscussionListItem (#4056) 2024-10-03 08:25:00 +02:00
Davide Iadeluca
88f182cc93 [1.x] [extensibility] Add (some) missing shims (#4027)
* chore: add some missing shims

* chore: remove unused import
2024-10-02 12:13:26 +01:00
flarum-bot
ed72aa0128 Bundled output for commit 12d21cdbfc
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-10-02 10:25:42 +00:00
Davide Iadeluca
12d21cdbfc [1.x] [extensibility] refactor(core): allow labels of PostStreamScrubber to be customized (#4049)
* refactor(core): allow labels to be customized

* chore: change type annotation

* chore: remove type annotations

Importing `NestedStringArray` did cause issues in the CI
2024-10-02 11:19:26 +01:00
flarum-bot
359681f3c6 Bundled output for commit 1a4c4a0275
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-10-02 09:25:35 +00:00
IanM
1a4c4a0275 feat: provide an 'actions' dropdown for extensions to add their additional buttons (#4054) 2024-10-02 10:18:00 +01:00
IanM
ea2fd2cade Revert "feat: provide an 'actions' dropdown for extensions to add their additional buttons"
This reverts commit 772852b3b3.
2024-10-02 09:53:12 +01:00
IanM
772852b3b3 feat: provide an 'actions' dropdown for extensions to add their additional buttons 2024-10-02 09:52:07 +01:00
flarum-bot
71717f9ebb Bundled output for commit 449ba48ba3
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-10-02 07:10:53 +00:00
Davide Iadeluca
449ba48ba3 [1.x] [extensibility] Export all missing modules in compat (#4044)
* chore(emoji): export missing modules in compat API

* chore(flags): export missing modules in compat API

* chore(likes): export missing modules in compat API

* chore(lock): export missing modules in compat API

* chore(markdown): export missing modules in compat API

* chore(mentions): export missing modules in compat API

* chore(nicknames): export missing modules in compat API

* chore(extension-manager): export missing modules in compat API

* chore(statistics): export missing modules in compat API

* chore(sticky): export missing modules in compat API

* chore(subscriptions): export missing modules in compat API

* chore(suspend): export missing modules in compat API

* chore(tags): export missing modules in compat API

* chore(core): export missing modules in compat API

* chore: fix tsconfig
2024-10-02 08:04:10 +01:00
flarum-bot
4d75da36b8 Bundled output for commit d4fe5f5a7a
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-10-02 06:54:38 +00:00
Davide Iadeluca
d4fe5f5a7a [1.x] [extensibility] refactor(core, flags): improve & use extensibility of CommentPost & Post (#4047)
* refactor(core): improve extensibility of `CommentPost`

* refactor(core): rename method to more appropriate name

* refactor(core): further improve extensibility of `CommentPost`

* refactor(core): improve extensibility of `Post`

* refactor(flags): use new extensibility for flagged posts
2024-10-02 07:47:05 +01:00
flarum-bot
256c1846b7 Bundled output for commit 1fee96aebe
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-30 14:45:34 +00:00
Davide Iadeluca
1fee96aebe fix(core): revert extensibility improvements for replyCountItem() (#4051)
This fixes a breaking change with third-party extensions calling `replyCountItem()` and not expecting it to be an array.
2024-09-30 15:38:30 +01:00
flarum-bot
b49b3104e4 Bundled output for commit 7d8cfdfaec
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-30 11:38:37 +00:00
Davide Iadeluca
7d8cfdfaec refactor(core): backport & improve extensibility of DiscussionListItem (#4048) 2024-09-30 12:32:23 +01:00
flarum-bot
845c38d6cb Bundled output for commit 4912a2e059
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-30 11:26:09 +00:00
Davide Iadeluca
4912a2e059 [1.x] [extensibility] refactor(core): improve extensibility of DiscussionPage (#4046)
* refactor(core): improve extensibility of `DiscussionPage`

* chore(core): improve type safety
2024-09-30 12:19:14 +01:00
flarum-bot
ca6d826f79 Bundled output for commit dce2549ff7
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-30 11:08:05 +00:00
Davide Iadeluca
dce2549ff7 [1.x] [extensibility] refactor(core): improve extensibility of IndexPage (#4045)
* refactor(core): improve extensibility of `IndexPage`

* refactor(core): refactor the extensibility refactor
2024-09-30 12:02:58 +01:00
flarum-bot
306d0bc124 Bundled output for commit e3d07cb8cc
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-30 10:46:59 +00:00
IanM
e3d07cb8cc feat: make it easier to add content after the first post (#4050) 2024-09-30 11:43:40 +01:00
flarum-bot
9bc8c7de99 Bundled output for commit 5076da9b38
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-29 19:16:08 +00:00
IanM
5076da9b38 feat: use common component for ip address display (#4042) 2024-09-29 20:12:53 +01:00
IanM
2c4d64cd20 [1.x] [extensibility] feat: allow classes that extends AbstractJob to be placed on a specified queue (#4026)
* feat: allow classes that extends AbstractJob to be placed on a specific queue

* Apply fixes from StyleCI

* php 7.3 compat

* Apply fixes from StyleCI

* change  to  to avoid conflicts with extensions that already do this

* chore: add docblock explaining that this solution only works for Redis queues

* Apply fixes from StyleCI

* chore: update docblock

* Apply fixes from StyleCI

---------

Co-authored-by: StyleCI Bot <bot@styleci.io>
2024-09-29 15:35:29 +01:00
flarum-bot
c9bd7dab1e Bundled output for commit df14216e1b
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-29 13:48:02 +00:00
IanM
df14216e1b chore: allow extending PostPreview content (#4043) 2024-09-29 14:44:51 +01:00
flarum-bot
de36551b45 Bundled output for commit 54fbcdedd5
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-29 11:30:04 +00:00
IanM
54fbcdedd5 chore: extensible TagHero (#4041) 2024-09-29 12:26:53 +01:00
flarum-bot
e9c8890686 Bundled output for commit 6dd0c0e915
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-29 11:12:28 +00:00
IanM
6dd0c0e915 [1.x] [extensibility] chore: make PostMeta extensible (#4040)
* chore: make PostMeta extensible

* add prio for ip item
2024-09-29 12:06:04 +01:00
flarum-bot
444df80caf Bundled output for commit 3ebd218588
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-29 09:03:25 +00:00
IanM
3ebd218588 chore: make WelcomeHero extensible (#4039) 2024-09-29 09:58:12 +01:00
IanM
9038ff64f8 [suspend][core] [1.x] fix: suspended users can remove avatar (#3998)
* fix: suspended users can remove avatar

* Apply fixes from StyleCI

---------

Co-authored-by: StyleCI Bot <bot@styleci.io>
2024-09-29 08:54:13 +01:00
flarum-bot
f8c30c96dc Bundled output for commit 3743bc0886
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-29 07:41:13 +00:00
IanM
3743bc0886 chore: point fontawesome links at v5 free (#4038) 2024-09-29 08:35:57 +01:00
flarum-bot
5855134b79 Bundled output for commit 7f657dac04
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-29 07:12:08 +00:00
IanM
7f657dac04 feat: make it easier to modify AppearancePage, BasicsPage, MailPage (#4037) 2024-09-29 08:07:10 +01:00
flarum-bot
84414c6699 Bundled output for commit bf0d895106
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-28 08:23:34 +00:00
IanM
bf0d895106 chore: fix Flarum logo url, remove huntr link 2024-09-28 09:17:05 +01:00
IanM
c942f3100d Revert "Export all missing modules in compat (#4006)" (#4032)
This reverts commit e0adf90453.
2024-09-28 09:11:37 +01:00
flarum-bot
d5882d9357 Bundled output for commit 7540ede897
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-28 07:59:41 +00:00
IanM
7540ede897 feat: allow modifying the discussion title on PostsUserPage (#4031) 2024-09-28 08:54:03 +01:00
flarum-bot
77d1a3d04b Bundled output for commit c79d2892de
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-28 06:44:31 +00:00
IanM
c79d2892de feat: [1.x] [extensibility] feat: allow to be extended (#4025) 2024-09-28 07:36:58 +01:00
IanM
46cdaf5d1a chore: bump version to 1.8.6 2024-09-28 07:31:05 +01:00
flarum-bot
4d59ec4600 Bundled output for commit e0adf90453
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-27 06:54:45 +00:00
Davide Iadeluca
e0adf90453 Export all missing modules in compat (#4006)
* chore(emoji): export missing modules in compat API

* chore(flags): export missing modules in compat API

* chore(likes): export missing modules in compat API

* chore(lock): export missing modules in compat API

* chore(markdown): export missing modules in compat API

* chore(mentions): export missing modules in compat API

* chore(nicknames): export missing modules in compat API

* chore(extension-manager): export missing modules in compat API

* chore(statistics): export missing modules in compat API

* chore(sticky): export missing modules in compat API

* chore(subscriptions): export missing modules in compat API

* chore(suspend): export missing modules in compat API

* chore(tags): export missing modules in compat API

* chore(core): export missing modules in compat API
2024-09-27 07:44:06 +01:00
flarum-bot
07a1781181 Bundled output for commit 80e70f4980
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-09-26 18:12:40 +00:00
80e70f4980 fix: reset admin page save button in catch (#3963) 2024-09-26 19:07:35 +01:00
StyleCI Bot
e43530e40a Apply fixes from StyleCI 2024-09-26 15:55:20 +00:00
IanM
24e88d12b8 chore: dummy commit to trigger style CI on 1.x 2024-09-26 16:38:56 +01:00
Rafał Całka
b3366e4c93 fix(tags): load correct user tag state and prevent N+1 queries in stateFor (#4008)
* fix: load tag state for correct user
* fix: prevent loading state if loaded previously
* fix(PHPStan): TagState can be null
2024-08-10 18:29:26 +01:00
Davide Iadeluca
8415d2233e ci: allow custom actions runner to be defined (#3989) 2024-05-16 17:30:30 +01:00
Daniël Klabbers
a52959ccf2 Patch vulnerability advisory (#3966)
Seems composer has a vulnerability, see https://github.com/advisories/GHSA-7c6p-848j-wh5h

Affected versions
>= 2.0.0-alpha1, < 2.2.23 -- patched in 2.2.23
>= 2.3.0-rc1, < 2.7.0 -- patched in 2.7.0

---

Let's raise the minimum to enforce the latest.

Thank you @peopleinside for reporting this.

(cherry picked from commit e771b908d5)
2024-02-22 11:43:31 +01:00
Sami Mazouz
b2044ff312 fix(em): breaks when composer deps get updated 2024-02-04 13:56:09 +01:00
IanM
50dd73b07c feat: support passing composer_auth values 2024-01-19 16:29:51 +00:00
Sami Mazouz
4f4977b7a5 fix(em): phpstan 2024-01-12 17:59:59 +01:00
Sami Mazouz
24b7dcb102 fix(em): composer.json schema issues 2024-01-12 17:57:08 +01:00
Sami Mazouz
25beb7919d fix: broken paths 2024-01-10 16:03:12 +01:00
Sami Mazouz
207032f6ff chore: rename package-manager to extension-manager 2024-01-10 15:56:32 +01:00
Davide Iadeluca
8205ae5bf5 [1.x] fix(Mentions): allow renderer to be used without context (#3953)
* fix(Mentions): allow renderer to be used without context

* test(Mentions): implement test for rendering post without context
2024-01-10 09:53:10 +00:00
flarum-bot
ac6f4d4d0c Bundled output for commit 56b2b3b2bc
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2024-01-06 17:07:40 +00:00
Sami Mazouz
56b2b3b2bc fix(package-manager): bugs 2024-01-06 18:00:09 +01:00
Sami Mazouz
7fb0e08c0a fix(package-manager): file not found exception 2024-01-06 13:07:02 +01:00
294 changed files with 2815 additions and 1073 deletions

View File

@@ -45,13 +45,25 @@ on:
required: false required: false
default: error_reporting=E_ALL default: error_reporting=E_ALL
runner_type:
description: The type of runner to use for the jobs. This should be one of the types supported by the `runs-on` keyword.
type: string
required: false
default: 'ubuntu-latest'
secrets:
composer_auth:
description: The Composer auth tokens to use for private packages.
required: false
env: env:
COMPOSER_ROOT_VERSION: dev-main COMPOSER_ROOT_VERSION: dev-main
FLARUM_TEST_TMP_DIR_LOCAL: tests/integration/tmp FLARUM_TEST_TMP_DIR_LOCAL: tests/integration/tmp
COMPOSER_AUTH: ${{ secrets.composer_auth }}
jobs: jobs:
test: test:
runs-on: ubuntu-latest runs-on: ${{ inputs.runner_type }}
strategy: strategy:
matrix: matrix:
@@ -160,7 +172,7 @@ jobs:
COMPOSER_PROCESS_TIMEOUT: 600 COMPOSER_PROCESS_TIMEOUT: 600
phpstan: phpstan:
runs-on: ubuntu-latest runs-on: ${{ inputs.runner_type }}
strategy: strategy:
matrix: matrix:

View File

@@ -86,20 +86,30 @@ on:
type: string type: string
required: false required: false
runner_type:
description: The type of runner to use for the jobs. This should be one of the types supported by the `runs-on` keyword.
type: string
required: false
default: 'ubuntu-latest'
secrets: secrets:
bundlewatch_github_token: bundlewatch_github_token:
description: The GitHub token to use for Bundlewatch. description: The GitHub token to use for Bundlewatch.
required: false required: false
composer_auth:
description: The Composer auth tokens to use for private packages.
required: false
env: env:
COMPOSER_ROOT_VERSION: dev-main COMPOSER_ROOT_VERSION: dev-main
ci_script: ${{ inputs.js_package_manager == 'yarn' && 'yarn install --immutable' || 'npm ci' }} ci_script: ${{ inputs.js_package_manager == 'yarn' && 'yarn install --immutable' || 'npm ci' }}
cache_dependency_path: ${{ inputs.cache_dependency_path || format(inputs.js_package_manager == 'yarn' && '{0}/yarn.lock' || '{0}/package-lock.json', inputs.frontend_directory) }} cache_dependency_path: ${{ inputs.cache_dependency_path || format(inputs.js_package_manager == 'yarn' && '{0}/yarn.lock' || '{0}/package-lock.json', inputs.frontend_directory) }}
COMPOSER_AUTH: ${{ secrets.composer_auth }}
jobs: jobs:
build: build:
name: Checks & Build name: Checks & Build
runs-on: ubuntu-latest runs-on: ${{ inputs.runner_type }}
if: >- if: >-
((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || github.event_name != 'pull_request') ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || github.event_name != 'pull_request')

View File

@@ -1,4 +1,4 @@
name: Package Manager PHP name: Extension Manager PHP
on: [workflow_dispatch, push, pull_request] on: [workflow_dispatch, push, pull_request]

View File

@@ -1,5 +1,37 @@
# Changelog # Changelog
## [v1.8.7](https://github.com/flarum/framework/compare/v1.8.6...v1.8.7)
### Fixed
* BasicsPage not viewable if only one language pack enabled, and/or `flarum/nicknames` not enabled (https://github.com/flarum/framework/pull/4062)
## [v1.8.6](https://github.com/flarum/framework/compare/v1.8.5...v1.8.6)
### Fixed
* reset admin page save button in catch handler (https://github.com/flarum/framework/pull/3963)
* suspended users can remove avatar (https://github.com/flarum/framework/pull/3998)
* return null if content left empty in formatter (https://github.com/flarum/framework/pull/4059)
### Changed
* allow DiscussionsSearchSource to be extended (https://github.com/flarum/framework/pull/4025)
* allow modifying the discussion title on PostsUserPage (https://github.com/flarum/framework/pull/4031)
* make it easier to modify AppearancePage, BasicsPage, MailPage (https://github.com/flarum/framework/pull/4037)
* point fontawesome links at v5 free (https://github.com/flarum/framework/pull/4038)
* make WelcomeHero extensible (https://github.com/flarum/framework/pull/4039)
* make PostMeta extensible (https://github.com/flarum/framework/pull/4040)
* extensible TagHero (https://github.com/flarum/framework/pull/4041)
* allow extending PostPreview content (https://github.com/flarum/framework/pull/4043)
* allow classes that extends AbstractJob to be placed on a specified queue (https://github.com/flarum/framework/pull/4026)
* use common component for ip address display (https://github.com/flarum/framework/pull/4042)
* make it easier to add content after the first post (https://github.com/flarum/framework/pull/4050)
* improve extensibility of IndexPage (https://github.com/flarum/framework/pull/4045)
* improve extensibility of DiscussionPage (https://github.com/flarum/framework/pull/4046)
* backport & improve extensibility of DiscussionListItem (https://github.com/flarum/framework/pull/4048)
* improve & use extensibility of CommentPost & Post (https://github.com/flarum/framework/pull/4047)
* allow labels of PostStreamScrubber to be customized (https://github.com/flarum/framework/pull/4049)
* allow to customize time formats through translations (https://github.com/flarum/framework/pull/4053)
### Added
* Export all missing modules in compat (https://github.com/flarum/framework/pull/4044)
* Add (some) missing shims (https://github.com/flarum/framework/pull/4027)
* provide an 'actions' dropdown for extensions to add their additional buttons to the admin UserListPage (https://github.com/flarum/framework/pull/4054)
## [v1.8.5](https://github.com/flarum/framework/compare/v1.8.4...v1.8.5) ## [v1.8.5](https://github.com/flarum/framework/compare/v1.8.4...v1.8.5)
### Fixed ### Fixed
* Logout controller allows open redirects [#3948] * Logout controller allows open redirects [#3948]

View File

@@ -1,5 +1,5 @@
<p align="center"> <p align="center">
<a href="https://flarum.org/"><img src="https://flarum.org/assets/img/logo.png"></a> <a href="https://flarum.org/"><img src="https://flarum.org/images/flarum.svg"></a>
</p> </p>
<p align="center"> <p align="center">
@@ -7,7 +7,6 @@
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/dt/flarum/core" alt="Total Downloads"></a> <a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/dt/flarum/core" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/github/v/release/flarum/core?sort=semver" alt="Latest Version"></a> <a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/github/v/release/flarum/core?sort=semver" alt="Latest Version"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/l/flarum/core" alt="License"></a> <a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/l/flarum/core" alt="License"></a>
<a href="https://huntr.dev/bounties/disclose/?target=https://github.com/flarum/core"><img src="https://cdn.huntr.dev/huntr_security_badge_mono.svg" alt="huntr"></a>
<a href="https://github.styleci.io/repos/28257573"><img src="https://github.styleci.io/repos/28257573/shield?style=flat" alt="StyleCI"></a> <a href="https://github.styleci.io/repos/28257573"><img src="https://github.styleci.io/repos/28257573/shield?style=flat" alt="StyleCI"></a>
</p> </p>
@@ -38,3 +37,4 @@ If you discover a security vulnerability within Flarum, please send an e-mail to
## License ## License
Flarum is open-source software licensed under the [MIT License](https://github.com/flarum/flarum/blob/master/LICENSE). Flarum is open-source software licensed under the [MIT License](https://github.com/flarum/flarum/blob/master/LICENSE).

View File

@@ -46,7 +46,7 @@
"Flarum\\Lock\\": "extensions/lock/src", "Flarum\\Lock\\": "extensions/lock/src",
"Flarum\\Mentions\\": "extensions/mentions/src", "Flarum\\Mentions\\": "extensions/mentions/src",
"Flarum\\Nicknames\\": "extensions/nicknames/src", "Flarum\\Nicknames\\": "extensions/nicknames/src",
"Flarum\\PackageManager\\": "extensions/package-manager/src", "Flarum\\ExtensionManager\\": "extensions/package-manager/src",
"Flarum\\Pusher\\": "extensions/pusher/src", "Flarum\\Pusher\\": "extensions/pusher/src",
"Flarum\\Statistics\\": "extensions/statistics/src", "Flarum\\Statistics\\": "extensions/statistics/src",
"Flarum\\Sticky\\": "extensions/sticky/src", "Flarum\\Sticky\\": "extensions/sticky/src",
@@ -74,7 +74,7 @@
"flarum/markdown": "self.version", "flarum/markdown": "self.version",
"flarum/mentions": "self.version", "flarum/mentions": "self.version",
"flarum/nicknames": "self.version", "flarum/nicknames": "self.version",
"flarum/package-manager": "self.version", "flarum/extension-manager": "self.version",
"flarum/pusher": "self.version", "flarum/pusher": "self.version",
"flarum/statistics": "self.version", "flarum/statistics": "self.version",
"flarum/sticky": "self.version", "flarum/sticky": "self.version",

View File

@@ -15,6 +15,7 @@
"declarationDir": "./dist-typings", "declarationDir": "./dist-typings",
"paths": { "paths": {
"flarum/*": ["../../../framework/core/js/dist-typings/*"], "flarum/*": ["../../../framework/core/js/dist-typings/*"],
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
"flarum/flags/*": ["../../flags/js/dist-typings/*"] "flarum/flags/*": ["../../flags/js/dist-typings/*"]
} }
} }

View File

@@ -50,7 +50,7 @@ class Akismet
$client = new Client(); $client = new Client();
return $client->request('POST', "$this->apiUrl/$type", [ return $client->request('POST', "$this->apiUrl/$type", [
'headers' => [ 'headers' => [
'User-Agent' => "Flarum/$this->flarumVersion | Akismet/$this->extensionVersion", 'User-Agent' => "Flarum/$this->flarumVersion | Akismet/$this->extensionVersion",
], ],
'form_params' => $this->params, 'form_params' => $this->params,

View File

@@ -0,0 +1,12 @@
declare module 'flarum/common/models/Discussion' {
export default interface Discussion {
isApproved(): boolean;
}
}
declare module 'flarum/common/models/Post' {
export default interface Post {
isApproved(): boolean;
canApprove(): boolean;
}
}

2
extensions/emoji/js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
import getEmojiIconCode from './helpers/getEmojiIconCode';
export default {
'emoji/fragments/AutocompleteDropdown': AutocompleteDropdown,
'emoji/helpers/getEmojiIconCode': getEmojiIconCode,
};

View File

@@ -11,3 +11,9 @@ app.initializers.add('flarum-emoji', () => {
// render emoji as image in Posts content and title. // render emoji as image in Posts content and title.
renderEmoji(); renderEmoji();
}); });
// Expose compat API
import emojiCompat from './compat';
import { compat } from '@flarum/core/forum';
Object.assign(compat, emojiCompat);

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.8" "flarum/core": "^1.8.6"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@@ -7,6 +7,7 @@ declare const _default: {
'flags/components/FlagPostModal': typeof FlagPostModal; 'flags/components/FlagPostModal': typeof FlagPostModal;
'flags/components/FlagsPage': typeof FlagsPage; 'flags/components/FlagsPage': typeof FlagsPage;
'flags/components/FlagsDropdown': typeof FlagsDropdown; 'flags/components/FlagsDropdown': typeof FlagsDropdown;
'flags/states/FlagListState': typeof FlagListState;
}; };
export default _default; export default _default;
import addFlagsToPosts from "./addFlagsToPosts"; import addFlagsToPosts from "./addFlagsToPosts";
@@ -17,3 +18,4 @@ import FlagList from "./components/FlagList";
import FlagPostModal from "./components/FlagPostModal"; import FlagPostModal from "./components/FlagPostModal";
import FlagsPage from "./components/FlagsPage"; import FlagsPage from "./components/FlagsPage";
import FlagsDropdown from "./components/FlagsDropdown"; import FlagsDropdown from "./components/FlagsDropdown";
import FlagListState from "./states/FlagListState";

2
extensions/flags/js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -75,7 +75,7 @@ export default function () {
return items; return items;
}; };
extend(Post.prototype, 'content', function (vdom) { extend(Post.prototype, 'viewItems', function (items) {
const post = this.attrs.post; const post = this.attrs.post;
const flags = post.flags(); const flags = post.flags();
@@ -83,7 +83,8 @@ export default function () {
if (post.isHidden()) this.revealContent = true; if (post.isHidden()) this.revealContent = true;
vdom.unshift( items.add(
'flagged',
<div className="Post-flagged"> <div className="Post-flagged">
<div className="Post-flagged-flags"> <div className="Post-flagged-flags">
{flags.map((flag) => ( {flags.map((flag) => (
@@ -91,7 +92,8 @@ export default function () {
))} ))}
</div> </div>
<div className="Post-flagged-actions">{this.flagActionItems().toArray()}</div> <div className="Post-flagged-actions">{this.flagActionItems().toArray()}</div>
</div> </div>,
110
); );
}); });

View File

@@ -6,6 +6,7 @@ import FlagList from './components/FlagList';
import FlagPostModal from './components/FlagPostModal'; import FlagPostModal from './components/FlagPostModal';
import FlagsPage from './components/FlagsPage'; import FlagsPage from './components/FlagsPage';
import FlagsDropdown from './components/FlagsDropdown'; import FlagsDropdown from './components/FlagsDropdown';
import FlagListState from './states/FlagListState';
export default { export default {
'flags/addFlagsToPosts': addFlagsToPosts, 'flags/addFlagsToPosts': addFlagsToPosts,
@@ -16,4 +17,5 @@ export default {
'flags/components/FlagPostModal': FlagPostModal, 'flags/components/FlagPostModal': FlagPostModal,
'flags/components/FlagsPage': FlagsPage, 'flags/components/FlagsPage': FlagsPage,
'flags/components/FlagsDropdown': FlagsDropdown, 'flags/components/FlagsDropdown': FlagsDropdown,
'flags/states/FlagListState': FlagListState,
}; };

View File

@@ -40,6 +40,7 @@ class AddCanFlagAttribute
// If $actor is the post author, check to see if the setting is enabled // If $actor is the post author, check to see if the setting is enabled
return (bool) $this->settings->get('flarum-flags.can_flag_own'); return (bool) $this->settings->get('flarum-flags.can_flag_own');
} }
// $actor is not the post author // $actor is not the post author
return true; return true;
} }

View File

@@ -31,10 +31,10 @@ class FlagSerializer extends AbstractSerializer
} }
return [ return [
'type' => $flag->type, 'type' => $flag->type,
'reason' => $flag->reason, 'reason' => $flag->reason,
'reasonDetail' => $flag->reason_detail, 'reasonDetail' => $flag->reason_detail,
'createdAt' => $this->formatDate($flag->created_at), 'createdAt' => $this->formatDate($flag->created_at),
]; ];
} }

2
extensions/likes/js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,9 @@
import Post from 'flarum/common/models/Post';
import User from 'flarum/common/models/User'; import User from 'flarum/common/models/User';
declare module 'flarum/common/models/Post' { declare module 'flarum/common/models/Post' {
export default interface Post { export default interface Post {
likes(): User[]; likes(): User[];
likesCount(): number; likesCount(): number;
canLike(): boolean;
} }
} }

View File

@@ -0,0 +1,11 @@
import LikesUserPage from './components/LikesUserPage';
import PostLikedNotification from './components/PostLikedNotification';
import PostLikesModal from './components/PostLikesModal';
import PostLikesModalState from './states/PostLikesModalState';
export default {
'likes/components/LikesUserPage': LikesUserPage,
'likes/components/PostLikedNotification': PostLikedNotification,
'likes/components/PostLikesModal': PostLikesModal,
'likes/states/PostLikesModalState': PostLikesModalState,
};

View File

@@ -24,3 +24,9 @@ app.initializers.add('flarum-likes', () => {
}); });
}); });
}); });
// Expose compat API
import likesCompat from './compat';
import { compat } from '@flarum/core/forum';
Object.assign(compat, likesCompat);

2
extensions/lock/js/dist/forum.js generated vendored
View File

@@ -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 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})(); (()=>{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),o.d(t,{extend:()=>j});const n=flarum.core.compat["common/extend"],c=flarum.core.compat["forum/app"];var e=o.n(c);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 l=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 e().route.discussion(o.subject(),o.content().postNumber)},n.content=function(){return e().translator.trans("flarum-lock.forum.notifications.discussion_locked_text",{user:this.attrs.notification.fromUser()})},t}(o.n(u)());const f=flarum.core.compat["common/models/Discussion"];var d=o.n(f);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 L=o.n(h);const g=flarum.core.compat["common/extenders"];var O=o.n(g);const x=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(x)());const j=[(new(O().PostTypes)).add("discussionLocked",P),new(O().Model)(d()).attribute("isLocked").attribute("canLock")],D={"lock/components/DiscussionLockedNotification":l,"lock/components/DiscussionLockedPost":P},S=flarum.core;e().initializers.add("flarum-lock",(function(){e().notificationComponents.discussionLocked=l,(0,n.extend)(d().prototype,"badges",(function(o){this.isLocked()&&o.add("locked",m(k(),{type:"locked",label:e().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(L(),{icon:"fas fa-lock",onclick:this.lockAction.bind(t)},e().translator.trans("flarum-lock.forum.discussion_controls."+(t.isLocked()?"unlock":"lock")+"_button")))})),b().lockAction=function(){this.save({isLocked:!this.isLocked()}).then((function(){e().current.matches(v())&&e().current.get("stream").update(),m.redraw()}))},(0,n.extend)(s().prototype,"notificationTypes",(function(o){o.add("discussionLocked",{name:"discussionLocked",icon:"fas fa-lock",label:e().translator.trans("flarum-lock.forum.settings.notify_discussion_locked_label")})}))})),Object.assign(S.compat,D)})(),module.exports=t})();
//# sourceMappingURL=forum.js.map //# sourceMappingURL=forum.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,6 @@
declare module 'flarum/common/models/Discussion' {
export default interface Discussion {
isLocked(): boolean;
canLock(): boolean;
}
}

View File

@@ -0,0 +1,7 @@
import DiscussionLockedNotification from './components/DiscussionLockedNotification';
import DiscussionLockedPost from './components/DiscussionLockedPost';
export default {
'lock/components/DiscussionLockedNotification': DiscussionLockedNotification,
'lock/components/DiscussionLockedPost': DiscussionLockedPost,
};

View File

@@ -22,3 +22,9 @@ app.initializers.add('flarum-lock', () => {
}); });
}); });
}); });
// Expose compat API
import lockCompat from './compat';
import { compat } from '@flarum/core/forum';
Object.assign(compat, lockCompat);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
import commonCompat from '../common/compat';
export default {
...commonCompat,
};

View File

@@ -2,3 +2,9 @@ import app from 'flarum/admin/app';
import { initialize } from '../common/index'; import { initialize } from '../common/index';
app.initializers.add('flarum-markdown', initialize); app.initializers.add('flarum-markdown', initialize);
// Expose compat API
import markdownCompat from './compat';
import { compat } from '@flarum/core/admin';
Object.assign(compat, markdownCompat);

View File

@@ -0,0 +1,7 @@
import MarkdownButton from './components/MarkdownButton';
import MarkdownToolbar from './components/MarkdownToolbar';
export default {
'markdown/components/MarkdownButton': MarkdownButton,
'markdown/components/MarkdownToolbar': MarkdownToolbar,
};

View File

@@ -0,0 +1,5 @@
import commonCompat from '../common/compat';
export default {
...commonCompat,
};

View File

@@ -2,3 +2,9 @@ import app from 'flarum/forum/app';
import { initialize } from '../common/index'; import { initialize } from '../common/index';
app.initializers.add('flarum-markdown', initialize); app.initializers.add('flarum-markdown', initialize);
// Expose compat API
import markdownCompat from './compat';
import { compat } from '@flarum/core/forum';
Object.assign(compat, markdownCompat);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,6 @@
import GroupMentionedNotification from './components/GroupMentionedNotification'; import GroupMentionedNotification from './components/GroupMentionedNotification';
import MentionedByModal from './components/MentionedByModal';
import MentionsDropdownItem from './components/MentionsDropdownItem';
import MentionsUserPage from './components/MentionsUserPage'; import MentionsUserPage from './components/MentionsUserPage';
import PostMentionedNotification from './components/PostMentionedNotification'; import PostMentionedNotification from './components/PostMentionedNotification';
import UserMentionedNotification from './components/UserMentionedNotification'; import UserMentionedNotification from './components/UserMentionedNotification';
@@ -9,13 +11,24 @@ import getMentionText from './utils/getMentionText';
import * as reply from './utils/reply'; import * as reply from './utils/reply';
import selectedText from './utils/selectedText'; import selectedText from './utils/selectedText';
import * as textFormatter from './utils/textFormatter'; import * as textFormatter from './utils/textFormatter';
import GroupMention from './mentionables/GroupMention';
import MentionableModel from './mentionables/MentionableModel'; import MentionableModel from './mentionables/MentionableModel';
import MentionableModels from './mentionables/MentionableModels';
import PostMention from './mentionables/PostMention';
import TagMention from './mentionables/TagMention';
import UserMention from './mentionables/UserMention';
import AtMentionFormat from './mentionables/formats/AtMentionFormat';
import HashMentionFormat from './mentionables/formats/HashMentionFormat';
import MentionFormat from './mentionables/formats/MentionFormat'; import MentionFormat from './mentionables/formats/MentionFormat';
import MentionFormats from './mentionables/formats/MentionFormats';
import Mentionables from './extenders/Mentionables'; import Mentionables from './extenders/Mentionables';
import MentionedByModalState from './state/MentionedByModalState';
export default { export default {
'mentions/components/MentionsUserPage': MentionsUserPage, 'mentions/components/MentionsUserPage': MentionsUserPage,
'mentions/components/PostMentionedNotification': PostMentionedNotification, 'mentions/components/PostMentionedNotification': PostMentionedNotification,
'mentions/components/MentionedByModal': MentionedByModal,
'mentions/components/MentionsDropdownItem': MentionsDropdownItem,
'mentions/components/UserMentionedNotification': UserMentionedNotification, 'mentions/components/UserMentionedNotification': UserMentionedNotification,
'mentions/components/GroupMentionedNotification': GroupMentionedNotification, 'mentions/components/GroupMentionedNotification': GroupMentionedNotification,
'mentions/fragments/AutocompleteDropdown': AutocompleteDropdown, 'mentions/fragments/AutocompleteDropdown': AutocompleteDropdown,
@@ -25,7 +38,16 @@ export default {
'mentions/utils/reply': reply, 'mentions/utils/reply': reply,
'mentions/utils/selectedText': selectedText, 'mentions/utils/selectedText': selectedText,
'mentions/utils/textFormatter': textFormatter, 'mentions/utils/textFormatter': textFormatter,
'mentions/mentionables/GroupMention': GroupMention,
'mentions/mentionables/MentionableModel': MentionableModel, 'mentions/mentionables/MentionableModel': MentionableModel,
'mentions/mentionables/MentionableModels': MentionableModels,
'mentions/mentionables/PostMention': PostMention,
'mentions/mentionables/TagMention': TagMention,
'mentions/mentionables/UserMention': UserMention,
'mentions/mentionables/formats/AtMentionFormat': AtMentionFormat,
'mentions/mentionables/formats/HashMentionFormat': HashMentionFormat,
'mentions/mentionables/formats/MentionFormat': MentionFormat, 'mentions/mentionables/formats/MentionFormat': MentionFormat,
'mentions/mentionables/formats/MentionFormats': MentionFormats,
'mentions/extenders/Mentionables': Mentionables, 'mentions/extenders/Mentionables': Mentionables,
'mentions/state/MentionedByModalState': MentionedByModalState,
}; };

View File

@@ -11,6 +11,7 @@ namespace Flarum\Mentions\Formatter;
use Flarum\Discussion\Discussion; use Flarum\Discussion\Discussion;
use Flarum\Http\SlugManager; use Flarum\Http\SlugManager;
use Flarum\Post\Post;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use s9e\TextFormatter\Renderer; use s9e\TextFormatter\Renderer;
use s9e\TextFormatter\Utils; use s9e\TextFormatter\Utils;
@@ -39,16 +40,17 @@ class FormatPostMentions
* *
* @param \s9e\TextFormatter\Renderer $renderer * @param \s9e\TextFormatter\Renderer $renderer
* @param mixed $context * @param mixed $context
* @param string|null $xml * @param string $xml
* @param \Psr\Http\Message\ServerRequestInterface $request * @param \Psr\Http\Message\ServerRequestInterface|null $request
* @return string * @return string $xml to be rendered
*/ */
public function __invoke(Renderer $renderer, $context, $xml, Request $request = null) public function __invoke(Renderer $renderer, $context, $xml, Request $request = null)
{ {
$post = $context; return Utils::replaceAttributes($xml, 'POSTMENTION', function ($attributes) use ($context) {
$post = (($context && isset($context->getRelations()['mentionsPosts'])) || $context instanceof Post)
? $context->mentionsPosts->find($attributes['id'])
: Post::find($attributes['id']);
return Utils::replaceAttributes($xml, 'POSTMENTION', function ($attributes) use ($post) {
$post = $post->mentionsPosts->find($attributes['id']);
if ($post && $post->user) { if ($post && $post->user) {
$attributes['displayname'] = $post->user->display_name; $attributes['displayname'] = $post->user->display_name;
} }

View File

@@ -9,6 +9,7 @@
namespace Flarum\Mentions\Formatter; namespace Flarum\Mentions\Formatter;
use Flarum\Post\Post;
use s9e\TextFormatter\Utils; use s9e\TextFormatter\Utils;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
@@ -27,12 +28,16 @@ class UnparsePostMentions
/** /**
* Configure rendering for user mentions. * Configure rendering for user mentions.
* *
* @param string $xml * @param string|null $xml
* @param mixed $context * @param mixed $context
* @return string $xml to be unparsed * @return mixed $xml to be unparsed
*/ */
public function __invoke($context, string $xml) public function __invoke($context, $xml)
{ {
if ($xml === null) {
return $xml;
}
$xml = $this->updatePostMentionTags($context, $xml); $xml = $this->updatePostMentionTags($context, $xml);
$xml = $this->unparsePostMentionTags($xml); $xml = $this->unparsePostMentionTags($xml);
@@ -50,8 +55,11 @@ class UnparsePostMentions
{ {
$post = $context; $post = $context;
return Utils::replaceAttributes($xml, 'POSTMENTION', function ($attributes) use ($post) { return Utils::replaceAttributes($xml, 'POSTMENTION', function ($attributes) use ($context) {
$post = $post->mentionsPosts->find($attributes['id']); $post = (($context && isset($context->getRelations()['mentionsPosts'])) || $context instanceof Post)
? $context->mentionsPosts->find($attributes['id'])
: Post::find($attributes['id']);
if ($post && $post->user) { if ($post && $post->user) {
$attributes['displayname'] = $post->user->display_name; $attributes['displayname'] = $post->user->display_name;
} }

View File

@@ -18,12 +18,16 @@ class UnparseTagMentions
/** /**
* Configure rendering for user mentions. * Configure rendering for user mentions.
* *
* @param string $xml * @param string|null $xml
* @param mixed $context * @param mixed $context
* @return string $xml to be unparsed * @return mixed $xml to be unparsed
*/ */
public function __invoke($context, string $xml) public function __invoke($context, $xml)
{ {
if ($xml === null) {
return $xml;
}
$xml = $this->updateTagMentionTags($context, $xml); $xml = $this->updateTagMentionTags($context, $xml);
$xml = $this->unparseTagMentionTags($xml); $xml = $this->unparseTagMentionTags($xml);

View File

@@ -29,12 +29,16 @@ class UnparseUserMentions
/** /**
* Configure rendering for user mentions. * Configure rendering for user mentions.
* *
* @param string $xml * @param string|null $xml
* @param mixed $context * @param mixed $context
* @return string $xml to be unparsed * @return mixed $xml to be unparsed
*/ */
public function __invoke($context, string $xml) public function __invoke($context, $xml)
{ {
if ($xml === null) {
return $xml;
}
$xml = $this->updateUserMentionTags($context, $xml); $xml = $this->updateUserMentionTags($context, $xml);
$xml = $this->unparseUserMentionTags($xml); $xml = $this->unparseUserMentionTags($xml);

View File

@@ -47,6 +47,8 @@ class SendMentionsNotificationsJob extends AbstractJob
public function __construct(CommentPost $post, array $userMentions, array $postMentions, array $groupMentions) public function __construct(CommentPost $post, array $userMentions, array $postMentions, array $groupMentions)
{ {
parent::__construct();
$this->post = $post; $this->post = $post;
$this->userMentions = $userMentions; $this->userMentions = $userMentions;
$this->postMentions = $postMentions; $this->postMentions = $postMentions;

View File

@@ -0,0 +1,137 @@
<?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\Mentions\Tests\integration\api;
use Flarum\Extend;
use Flarum\Testing\integration\TestCase;
class CreateDiscussionTest extends TestCase
{
/**
* @inheritDoc
*/
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-mentions');
$this->extend(
(new Extend\Event())
->listen(\Flarum\Post\Event\Saving::class, function ($event) {
$event->post->content;
})
);
}
/**
* @test
*/
public function cannot_create_discussion_with_empty_string()
{
$response = $this->send(
$this->request('POST', '/api/discussions', [
'authenticatedAs' => 1,
'json' => [
'data' => [
'attributes' => [
'title' => 'Test post',
'content' => '',
],
],
],
])
);
$this->assertEquals(422, $response->getStatusCode());
$body = (string) $response->getBody();
$this->assertJson($body);
$this->assertEquals([
'errors' => [
[
'status' => '422',
'code' => 'validation_error',
'detail' => 'The content field is required.',
'source' => ['pointer' => '/data/attributes/content'],
],
],
], json_decode($body, true));
}
/**
* @test
*/
public function cannot_create_discussion_without_content_property()
{
$response = $this->send(
$this->request('POST', '/api/discussions', [
'authenticatedAs' => 1,
'json' => [
'data' => [
'attributes' => [
'title' => 'Test post',
],
],
],
])
);
$this->assertEquals(422, $response->getStatusCode());
$body = (string) $response->getBody();
$this->assertJson($body);
$this->assertEquals([
'errors' => [
[
'status' => '422',
'code' => 'validation_error',
'detail' => 'The content field is required.',
'source' => ['pointer' => '/data/attributes/content'],
],
],
], json_decode($body, true));
}
/**
* @test
*/
public function cannot_create_discussion_with_content_set_to_null()
{
$response = $this->send(
$this->request('POST', '/api/discussions', [
'authenticatedAs' => 1,
'json' => [
'data' => [
'attributes' => [
'title' => 'Test post',
'content' => null,
],
],
],
])
);
$this->assertEquals(422, $response->getStatusCode());
$body = (string) $response->getBody();
$this->assertJson($body);
$this->assertEquals([
'errors' => [
[
'status' => '422',
'code' => 'validation_error',
'detail' => 'The content field is required.',
'source' => ['pointer' => '/data/attributes/content'],
],
],
], json_decode($body, true));
}
}

View File

@@ -0,0 +1,110 @@
<?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\Mentions\Tests\integration\api;
use Flarum\Extend;
use Flarum\Testing\integration\TestCase;
class EditPostTest extends TestCase
{
/**
* @inheritDoc
*/
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-mentions');
$this->prepareDatabase([
'discussions' => [
['id' => 1, 'title' => 'Discussion with post', 'user_id' => 1, 'first_post_id' => 1, 'comment_count' => 1],
],
'posts' => [
['id' => 1, 'discussion_id' => 1, 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>Text</p></t>'],
]
]);
$this->extend(
(new Extend\Event())
->listen(\Flarum\Post\Event\Saving::class, function ($event) {
$event->post->content;
})
);
}
/**
* @test
*/
public function cannot_update_post_with_empty_string()
{
$response = $this->send(
$this->request('PATCH', '/api/posts/1', [
'authenticatedAs' => 1,
'json' => [
'data' => [
'attributes' => [
'content' => '',
],
],
],
])
);
$this->assertEquals(422, $response->getStatusCode());
$body = (string) $response->getBody();
$this->assertJson($body);
$this->assertEquals([
'errors' => [
[
'status' => '422',
'code' => 'validation_error',
'detail' => 'The content field is required.',
'source' => ['pointer' => '/data/attributes/content'],
],
],
], json_decode($body, true));
}
/**
* @test
*/
public function cannot_update_post_with_invalid_content_type()
{
$response = $this->send(
$this->request('PATCH', '/api/posts/1', [
'authenticatedAs' => 1,
'json' => [
'data' => [
'attributes' => [
'content' => [],
],
],
],
])
);
$this->assertEquals(422, $response->getStatusCode());
$body = (string) $response->getBody();
$this->assertJson($body);
$this->assertEquals([
'errors' => [
[
'status' => '422',
'code' => 'validation_error',
'detail' => 'The content field is required.',
'source' => ['pointer' => '/data/attributes/content'],
],
],
], json_decode($body, true));
}
}

View File

@@ -11,7 +11,9 @@ namespace Flarum\Mentions\Tests\integration\api;
use Carbon\Carbon; use Carbon\Carbon;
use Flarum\Extend; use Flarum\Extend;
use Flarum\Formatter\Formatter;
use Flarum\Post\CommentPost; use Flarum\Post\CommentPost;
use Flarum\Post\Post;
use Flarum\Testing\integration\RetrievesAuthorizedUsers; use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase; use Flarum\Testing\integration\TestCase;
use Flarum\User\DisplayName\DriverInterface; use Flarum\User\DisplayName\DriverInterface;
@@ -538,6 +540,40 @@ class PostMentionsTest extends TestCase
$this->assertStringContainsString('PostMention', $response['data']['attributes']['contentHtml']); $this->assertStringContainsString('PostMention', $response['data']['attributes']['contentHtml']);
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsPosts->find(11)); $this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsPosts->find(11));
} }
/**
* @test
*/
public function rendering_post_mention_with_a_post_context_works()
{
/** @var Formatter $formatter */
$formatter = $this->app()->getContainer()->make(Formatter::class);
$post = Post::find(4);
$user = User::find(1);
$xml = $formatter->parse($post->content, $post, $user);
$renderedHtml = $formatter->render($xml, $post);
$this->assertStringContainsString('TOBY$', $renderedHtml);
}
/**
* @test
*/
public function rendering_post_mention_without_a_context_works()
{
/** @var Formatter $formatter */
$formatter = $this->app()->getContainer()->make(Formatter::class);
$post = Post::find(4);
$user = User::find(1);
$xml = $formatter->parse($post->content, null, $user);
$renderedHtml = $formatter->render($xml);
$this->assertStringContainsString('TOBY$', $renderedHtml);
}
} }
class CustomOtherDisplayNameDriver implements DriverInterface class CustomOtherDisplayNameDriver implements DriverInterface

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
declare module 'flarum/common/models/User' {
export default interface User {
canEditNickname(): boolean;
}
}

View File

@@ -0,0 +1,5 @@
import NicknameModal from './components/NicknameModal';
export default {
'nicknames/components/NicknameModal': NicknameModal,
};

View File

@@ -110,3 +110,9 @@ app.initializers.add('flarum/nicknames', () => {
} }
}); });
}); });
// Expose compat API
import nicknamesCompat from './compat';
import { compat } from '@flarum/core/forum';
Object.assign(compat, nicknamesCompat);

View File

@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) Sami Mazouz Copyright (c) 2024 Stichting Flarum (Flarum Foundation)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,6 +1,6 @@
# Package Manager # Extension Manager
The package manager is a tool that allows you to easily install and manage extensions. It runs [composer](https://getcomposer.org/) under the hood. The extension manager is a tool that allows you to easily install and manage extensions. It runs [composer](https://getcomposer.org/) under the hood.
## Security ## Security
@@ -10,9 +10,9 @@ This extension is optional and can be removed for those who prefer to manually m
## Troubleshooting ## Troubleshooting
If you have many extensions installed, you may run into memory issues when using the package manager. If this happens, you can use an asynchronous queue that will run the package manager in the background. If you have many extensions installed, you may run into memory issues when using the extension manager. If this happens, you can use an asynchronous queue that will run the extension manager in the background.
* Simple database queue guide: https://discuss.flarum.org/d/28151-database-queue-the-simplest-queue-even-for-shared-hosting * Simple database queue guide: https://discuss.flarum.org/d/28151-database-queue-the-simplest-queue-even-for-shared-hosting
* (Advanced) Redis queue: https://discuss.flarum.org/d/21873-redis-sessions-cache-queues * (Advanced) Redis queue: https://discuss.flarum.org/d/21873-redis-sessions-cache-queues
You can find detailed logs on the package manager operations in the `storage/logs/composer` directory. Please include the latest log file when reporting issues in the [Flarum support forum](https://discuss.flarum.org/t/support). You can find detailed logs on the extension manager operations in the `storage/logs/composer` directory. Please include the latest log file when reporting issues in the [Flarum support forum](https://discuss.flarum.org/t/support).

View File

@@ -1,6 +1,6 @@
{ {
"name": "flarum/package-manager", "name": "flarum/extension-manager",
"description": "A Flarum Package Manager.", "description": "An extension manager to install, update and remove extension packages from the interface (Wrapper around composer).",
"keywords": [ "keywords": [
"extensions", "extensions",
"composer", "composer",
@@ -18,12 +18,12 @@
} }
], ],
"support": { "support": {
"issues": "https://github.com/flarum/package-manager/issues", "issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/package-manager" "source": "https://github.com/flarum/extension-manager"
}, },
"require": { "require": {
"flarum/core": "^1.8", "flarum/core": "^1.8",
"composer/composer": "^2.3" "composer/composer": "^2.7"
}, },
"require-dev": { "require-dev": {
"flarum/testing": "^1.0.0", "flarum/testing": "^1.0.0",
@@ -31,7 +31,7 @@
}, },
"extra": { "extra": {
"flarum-extension": { "flarum-extension": {
"title": "Package Manager", "title": "Extension Manager",
"icon": { "icon": {
"name": "fas fa-box-open", "name": "fas fa-box-open",
"backgroundColor": "#117187", "backgroundColor": "#117187",
@@ -69,12 +69,12 @@
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Flarum\\PackageManager\\": "src/" "Flarum\\ExtensionManager\\": "src/"
} }
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
"Flarum\\PackageManager\\Tests\\": "tests/" "Flarum\\ExtensionManager\\Tests\\": "tests/"
} }
}, },
"scripts": { "scripts": {

View File

@@ -7,7 +7,7 @@
* LICENSE file that was distributed with this source code. * LICENSE file that was distributed with this source code.
*/ */
namespace Flarum\PackageManager; namespace Flarum\ExtensionManager;
use Flarum\Extend; use Flarum\Extend;
use Flarum\Foundation\Paths; use Flarum\Foundation\Paths;
@@ -17,16 +17,16 @@ use Illuminate\Queue\SyncQueue;
return [ return [
(new Extend\Routes('api')) (new Extend\Routes('api'))
->post('/package-manager/extensions', 'package-manager.extensions.require', Api\Controller\RequireExtensionController::class) ->post('/extension-manager/extensions', 'extension-manager.extensions.require', Api\Controller\RequireExtensionController::class)
->patch('/package-manager/extensions/{id}', 'package-manager.extensions.update', Api\Controller\UpdateExtensionController::class) ->patch('/extension-manager/extensions/{id}', 'extension-manager.extensions.update', Api\Controller\UpdateExtensionController::class)
->delete('/package-manager/extensions/{id}', 'package-manager.extensions.remove', Api\Controller\RemoveExtensionController::class) ->delete('/extension-manager/extensions/{id}', 'extension-manager.extensions.remove', Api\Controller\RemoveExtensionController::class)
->post('/package-manager/check-for-updates', 'package-manager.check-for-updates', Api\Controller\CheckForUpdatesController::class) ->post('/extension-manager/check-for-updates', 'extension-manager.check-for-updates', Api\Controller\CheckForUpdatesController::class)
->post('/package-manager/why-not', 'package-manager.why-not', Api\Controller\WhyNotController::class) ->post('/extension-manager/why-not', 'extension-manager.why-not', Api\Controller\WhyNotController::class)
->post('/package-manager/minor-update', 'package-manager.minor-update', Api\Controller\MinorUpdateController::class) ->post('/extension-manager/minor-update', 'extension-manager.minor-update', Api\Controller\MinorUpdateController::class)
->post('/package-manager/major-update', 'package-manager.major-update', Api\Controller\MajorUpdateController::class) ->post('/extension-manager/major-update', 'extension-manager.major-update', Api\Controller\MajorUpdateController::class)
->post('/package-manager/global-update', 'package-manager.global-update', Api\Controller\GlobalUpdateController::class) ->post('/extension-manager/global-update', 'extension-manager.global-update', Api\Controller\GlobalUpdateController::class)
->get('/package-manager-tasks', 'package-manager.tasks.index', Api\Controller\ListTasksController::class) ->get('/extension-manager-tasks', 'extension-manager.tasks.index', Api\Controller\ListTasksController::class)
->post('/package-manager/composer', 'package-manager.composer', Api\Controller\ConfigureComposerController::class), ->post('/extension-manager/composer', 'extension-manager.composer', Api\Controller\ConfigureComposerController::class),
(new Extend\Frontend('admin')) (new Extend\Frontend('admin'))
->css(__DIR__.'/less/admin.less') ->css(__DIR__.'/less/admin.less')
@@ -34,13 +34,13 @@ return [
->content(function (Document $document) { ->content(function (Document $document) {
$paths = resolve(Paths::class); $paths = resolve(Paths::class);
$document->payload['flarum-package-manager.writable_dirs'] = is_writable($paths->vendor) $document->payload['flarum-extension-manager.writable_dirs'] = is_writable($paths->vendor)
&& is_writable($paths->storage) && is_writable($paths->storage)
&& (! file_exists($paths->storage.'/.composer') || is_writable($paths->storage.'/.composer')) && (! file_exists($paths->storage.'/.composer') || is_writable($paths->storage.'/.composer'))
&& is_writable($paths->base.'/composer.json') && is_writable($paths->base.'/composer.json')
&& is_writable($paths->base.'/composer.lock'); && is_writable($paths->base.'/composer.lock');
$document->payload['flarum-package-manager.using_sync_queue'] = resolve(Queue::class) instanceof SyncQueue; $document->payload['flarum-extension-manager.using_sync_queue'] = resolve(Queue::class) instanceof SyncQueue;
}), }),
new Extend\Locales(__DIR__.'/locale'), new Extend\Locales(__DIR__.'/locale'),
@@ -48,12 +48,12 @@ return [
(new Extend\Settings()) (new Extend\Settings())
->default(Settings\LastUpdateCheck::key(), json_encode(Settings\LastUpdateCheck::default())) ->default(Settings\LastUpdateCheck::key(), json_encode(Settings\LastUpdateCheck::default()))
->default(Settings\LastUpdateRun::key(), json_encode(Settings\LastUpdateRun::default())) ->default(Settings\LastUpdateRun::key(), json_encode(Settings\LastUpdateRun::default()))
->default('flarum-package-manager.queue_jobs', false) ->default('flarum-extension-manager.queue_jobs', '0')
->default('flarum-package-manager.minimum_stability', 'stable') ->default('flarum-extension-manager.minimum_stability', 'stable')
->default('flarum-package-manager.task_retention_days', 7), ->default('flarum-extension-manager.task_retention_days', 7),
(new Extend\ServiceProvider) (new Extend\ServiceProvider)
->register(PackageManagerServiceProvider::class), ->register(ExtensionManagerServiceProvider::class),
(new Extend\ErrorHandling) (new Extend\ErrorHandling)
->handler(Exception\ComposerCommandFailedException::class, Exception\ExceptionHandler::class) ->handler(Exception\ComposerCommandFailedException::class, Exception\ExceptionHandler::class)

49
extensions/package-manager/js/dist-typings/compat.d.ts generated vendored Normal file
View File

@@ -0,0 +1,49 @@
import AuthMethodModal from './components/AuthMethodModal';
import ConfigureAuth from './components/ConfigureAuth';
import ConfigureComposer from './components/ConfigureComposer';
import ConfigureJson from './components/ConfigureJson';
import ControlSection from './components/ControlSection';
import ExtensionItem from './components/ExtensionItem';
import Installer from './components/Installer';
import Label from './components/Label';
import MajorUpdater from './components/MajorUpdater';
import Pagination from './components/Pagination';
import QueueSection from './components/QueueSection';
import RepositoryModal from './components/RepositoryModal';
import SettingsPage from './components/SettingsPage';
import TaskOutputModal from './components/TaskOutputModal';
import Updater from './components/Updater';
import WhyNotModal from './components/WhyNotModal';
import Task from './models/Task';
import ControlSectionState from './states/ControlSectionState';
import ExtensionManagerState from './states/ExtensionManagerState';
import QueueState from './states/QueueState';
import errorHandler from './utils/errorHandler';
import humanDuration from './utils/humanDuration';
import jumpToQueue from './utils/jumpToQueue';
declare const _default: {
'extension-manager/components/AuthMethodModal': typeof AuthMethodModal;
'extension-manager/components/ConfigureAuth': typeof ConfigureAuth;
'extension-manager/components/ConfigureComposer': typeof ConfigureComposer;
'extension-manager/components/ConfigureJson': typeof ConfigureJson;
'extension-manager/components/ControlSection': typeof ControlSection;
'extension-manager/components/ExtensionItem': typeof ExtensionItem;
'extension-manager/components/Installer': typeof Installer;
'extension-manager/components/Label': typeof Label;
'extension-manager/components/MajorUpdater': typeof MajorUpdater;
'extension-manager/components/Pagination': typeof Pagination;
'extension-manager/components/QueueSection': typeof QueueSection;
'extension-manager/components/RepositoryModal': typeof RepositoryModal;
'extension-manager/components/SettingsPage': typeof SettingsPage;
'extension-manager/components/TaskOutputModal': typeof TaskOutputModal;
'extension-manager/components/Updater': typeof Updater;
'extension-manager/components/WhyNotModal': typeof WhyNotModal;
'extension-manager/models/Task': typeof Task;
'extension-manager/states/ControlSectionState': typeof ControlSectionState;
'extension-manager/states/ExtensionManagerState': typeof ExtensionManagerState;
'extension-manager/states/QueueState': typeof QueueState;
'extension-manager/utils/errorHandler': typeof errorHandler;
'extension-manager/utils/humanDuration': typeof humanDuration;
'extension-manager/utils/jumpToQueue': typeof jumpToQueue;
};
export default _default;

View File

@@ -6,5 +6,5 @@ export default class ConfigureAuth extends ConfigureJson<IConfigureJson> {
className(): string; className(): string;
content(): Mithril.Children; content(): Mithril.Children;
submitButton(): Mithril.Children[]; submitButton(): Mithril.Children[];
onchange(type: string, host: string, token: string): void; onchange(oldHost: string | null, type: string, host: string, token: string): void;
} }

View File

@@ -47,6 +47,7 @@ export default class ControlSectionState {
get lastUpdateRun(): LastUpdateRun; get lastUpdateRun(): LastUpdateRun;
constructor(); constructor();
isLoading(name?: LoadingTypes): boolean; isLoading(name?: LoadingTypes): boolean;
hasOperationRunning(): boolean;
setLoading(name: LoadingTypes): void; setLoading(name: LoadingTypes): void;
requirePackage(data: any): void; requirePackage(data: any): void;
checkForUpdates(): void; checkForUpdates(): void;

View File

@@ -1,6 +1,6 @@
import QueueState from './QueueState'; import QueueState from './QueueState';
import ControlSectionState from './ControlSectionState'; import ControlSectionState from './ControlSectionState';
export default class PackageManagerState { export default class ExtensionManagerState {
queue: QueueState; queue: QueueState;
control: ControlSectionState; control: ControlSectionState;
} }

View File

@@ -15,4 +15,5 @@ export default class QueueState {
prev(): void; prev(): void;
next(): void; next(): void;
pollQueue(actionTaken?: boolean): void; pollQueue(actionTaken?: boolean): void;
hasPending(): boolean;
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
{ {
"name": "@flarum/package-manager", "name": "@flarum/extension-manager",
"version": "0.0.0", "version": "0.0.0",
"private": true, "private": true,
"prettier": "@flarum/prettier-config", "prettier": "@flarum/prettier-config",

View File

@@ -0,0 +1,52 @@
import AuthMethodModal from './components/AuthMethodModal';
import ConfigureAuth from './components/ConfigureAuth';
import ConfigureComposer from './components/ConfigureComposer';
import ConfigureJson from './components/ConfigureJson';
import ControlSection from './components/ControlSection';
import ExtensionItem from './components/ExtensionItem';
import Installer from './components/Installer';
import Label from './components/Label';
import MajorUpdater from './components/MajorUpdater';
import Pagination from './components/Pagination';
import QueueSection from './components/QueueSection';
import RepositoryModal from './components/RepositoryModal';
import SettingsPage from './components/SettingsPage';
import TaskOutputModal from './components/TaskOutputModal';
import Updater from './components/Updater';
import WhyNotModal from './components/WhyNotModal';
import Task from './models/Task';
import ControlSectionState from './states/ControlSectionState';
import ExtensionManagerState from './states/ExtensionManagerState';
import QueueState from './states/QueueState';
import errorHandler from './utils/errorHandler';
import humanDuration from './utils/humanDuration';
import jumpToQueue from './utils/jumpToQueue';
export default {
'extension-manager/components/AuthMethodModal': AuthMethodModal,
'extension-manager/components/ConfigureAuth': ConfigureAuth,
'extension-manager/components/ConfigureComposer': ConfigureComposer,
'extension-manager/components/ConfigureJson': ConfigureJson,
'extension-manager/components/ControlSection': ControlSection,
'extension-manager/components/ExtensionItem': ExtensionItem,
'extension-manager/components/Installer': Installer,
'extension-manager/components/Label': Label,
'extension-manager/components/MajorUpdater': MajorUpdater,
'extension-manager/components/Pagination': Pagination,
'extension-manager/components/QueueSection': QueueSection,
'extension-manager/components/RepositoryModal': RepositoryModal,
'extension-manager/components/SettingsPage': SettingsPage,
'extension-manager/components/TaskOutputModal': TaskOutputModal,
'extension-manager/components/Updater': Updater,
'extension-manager/components/WhyNotModal': WhyNotModal,
'extension-manager/models/Task': Task,
'extension-manager/states/ControlSectionState': ControlSectionState,
'extension-manager/states/ExtensionManagerState': ExtensionManagerState,
'extension-manager/states/QueueState': QueueState,
'extension-manager/utils/errorHandler': errorHandler,
'extension-manager/utils/humanDuration': humanDuration,
'extension-manager/utils/jumpToQueue': jumpToQueue,
};

View File

@@ -32,49 +32,49 @@ export default class AuthMethodModal<CustomAttrs extends IAuthMethodModalAttrs =
title(): Mithril.Children { title(): Mithril.Children {
const context = this.attrs.host ? 'edit' : 'add'; const context = this.attrs.host ? 'edit' : 'add';
return app.translator.trans(`flarum-package-manager.admin.auth_config.${context}_label`); return app.translator.trans(`flarum-extension-manager.admin.auth_config.${context}_label`);
} }
content(): Mithril.Children { content(): Mithril.Children {
const types = { const types = {
'github-oauth': app.translator.trans('flarum-package-manager.admin.auth_config.types.github-oauth'), 'github-oauth': app.translator.trans('flarum-extension-manager.admin.auth_config.types.github-oauth'),
'gitlab-oauth': app.translator.trans('flarum-package-manager.admin.auth_config.types.gitlab-oauth'), 'gitlab-oauth': app.translator.trans('flarum-extension-manager.admin.auth_config.types.gitlab-oauth'),
'gitlab-token': app.translator.trans('flarum-package-manager.admin.auth_config.types.gitlab-token'), 'gitlab-token': app.translator.trans('flarum-extension-manager.admin.auth_config.types.gitlab-token'),
bearer: app.translator.trans('flarum-package-manager.admin.auth_config.types.bearer'), bearer: app.translator.trans('flarum-extension-manager.admin.auth_config.types.bearer'),
}; };
return ( return (
<div className="Modal-body"> <div className="Modal-body">
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.auth_config.add_modal.type_label')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.auth_config.add_modal.type_label')}</label>
<Select options={types} value={this.type()} onchange={this.type} /> <Select options={types} value={this.type()} onchange={this.type} />
</div> </div>
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.auth_config.add_modal.host_label')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.auth_config.add_modal.host_label')}</label>
<input <input
className="FormControl" className="FormControl"
bidi={this.host} bidi={this.host}
placeholder={app.translator.trans('flarum-package-manager.admin.auth_config.add_modal.host_placeholder')} placeholder={app.translator.trans('flarum-extension-manager.admin.auth_config.add_modal.host_placeholder')}
/> />
</div> </div>
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.auth_config.add_modal.token_label')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.auth_config.add_modal.token_label')}</label>
<textarea <textarea
className="FormControl" className="FormControl"
oninput={(e: InputEvent) => this.token((e.target as HTMLTextAreaElement).value)} oninput={(e: InputEvent) => this.token((e.target as HTMLTextAreaElement).value)}
rows="6" rows="6"
placeholder={ placeholder={
this.token() === '***' this.token().startsWith('unchanged:')
? extractText(app.translator.trans('flarum-package-manager.admin.auth_config.add_modal.unchanged_token_placeholder')) ? extractText(app.translator.trans('flarum-extension-manager.admin.auth_config.add_modal.unchanged_token_placeholder'))
: '' : ''
} }
> >
{this.token() === '***' ? '' : this.token()} {this.token().startsWith('unchanged:') ? '' : this.token()}
</textarea> </textarea>
</div> </div>
<div className="Form-group"> <div className="Form-group">
<Button className="Button Button--primary" onclick={this.submit.bind(this)}> <Button className="Button Button--primary" onclick={this.submit.bind(this)}>
{app.translator.trans('flarum-package-manager.admin.auth_config.add_modal.submit_button')} {app.translator.trans('flarum-extension-manager.admin.auth_config.add_modal.submit_button')}
</Button> </Button>
</div> </div>
</div> </div>

View File

@@ -9,7 +9,7 @@ export default class ConfigureAuth extends ConfigureJson<IConfigureJson> {
protected type = 'auth'; protected type = 'auth';
title(): Mithril.Children { title(): Mithril.Children {
return app.translator.trans('flarum-package-manager.admin.auth_config.title'); return app.translator.trans('flarum-extension-manager.admin.auth_config.title');
} }
className(): string { className(): string {
@@ -18,16 +18,23 @@ export default class ConfigureAuth extends ConfigureJson<IConfigureJson> {
content(): Mithril.Children { content(): Mithril.Children {
const authSettings = Object.keys(this.settings); const authSettings = Object.keys(this.settings);
const hasAuthSettings =
authSettings.length &&
authSettings.every((type) => {
const data = this.settings[type]();
return Array.isArray(data) ? data.length : Object.keys(data).length;
});
return ( return (
<div className="SettingsGroups-content"> <div className="ExtensionManager-SettingsGroups-content">
{authSettings.length ? ( {hasAuthSettings ? (
authSettings.map((type) => { authSettings.map((type) => {
const hosts = this.settings[type](); const hosts = this.settings[type]();
return ( return (
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans(`flarum-package-manager.admin.auth_config.types.${type}`)}</label> <label>{app.translator.trans(`flarum-extension-manager.admin.auth_config.types.${type}`)}</label>
<div className="ConfigureAuth-hosts"> <div className="ConfigureAuth-hosts">
{Object.keys(hosts).map((host) => { {Object.keys(hosts).map((host) => {
const data = hosts[host] as string | Record<string, string>; const data = hosts[host] as string | Record<string, string>;
@@ -42,7 +49,7 @@ export default class ConfigureAuth extends ConfigureJson<IConfigureJson> {
type, type,
host, host,
token: data, token: data,
onsubmit: this.onchange.bind(this), onsubmit: this.onchange.bind(this, host),
}) })
} }
> >
@@ -51,9 +58,9 @@ export default class ConfigureAuth extends ConfigureJson<IConfigureJson> {
<Button <Button
className="Button Button--icon" className="Button Button--icon"
icon="fas fa-trash" icon="fas fa-trash"
aria-label={app.translator.trans('flarum-package-manager.admin.auth_config.delete_label')} aria-label={app.translator.trans('flarum-extension-manager.admin.auth_config.delete_label')}
onclick={() => { onclick={() => {
if (confirm(extractText(app.translator.trans('flarum-package-manager.admin.auth_config.delete_confirmation')))) { if (confirm(extractText(app.translator.trans('flarum-extension-manager.admin.auth_config.delete_confirmation')))) {
const newType = { ...this.setting(type)() }; const newType = { ...this.setting(type)() };
delete newType[host]; delete newType[host];
@@ -73,7 +80,7 @@ export default class ConfigureAuth extends ConfigureJson<IConfigureJson> {
); );
}) })
) : ( ) : (
<span className="helpText">{app.translator.trans('flarum-package-manager.admin.auth_config.no_auth_methods_configured')}</span> <span className="helpText">{app.translator.trans('flarum-extension-manager.admin.auth_config.no_auth_methods_configured')}</span>
)} )}
</div> </div>
); );
@@ -88,18 +95,26 @@ export default class ConfigureAuth extends ConfigureJson<IConfigureJson> {
loading={this.loading} loading={this.loading}
onclick={() => onclick={() =>
app.modal.show(AuthMethodModal, { app.modal.show(AuthMethodModal, {
onsubmit: this.onchange.bind(this), onsubmit: this.onchange.bind(this, null),
}) })
} }
> >
{app.translator.trans('flarum-package-manager.admin.auth_config.add_label')} {app.translator.trans('flarum-extension-manager.admin.auth_config.add_label')}
</Button> </Button>
); );
return items; return items;
} }
onchange(type: string, host: string, token: string) { onchange(oldHost: string | null, type: string, host: string, token: string) {
this.setting(type)({ ...this.setting(type)(), [host]: token }); const data = { ...this.setting(type)() };
if (oldHost) {
delete data[oldHost];
}
data[host] = token;
this.setting(type)(data);
} }
} }

View File

@@ -14,7 +14,7 @@ export default class ConfigureComposer extends ConfigureJson<IConfigureJson> {
protected type = 'composer'; protected type = 'composer';
title(): Mithril.Children { title(): Mithril.Children {
return app.translator.trans('flarum-package-manager.admin.composer.title'); return app.translator.trans('flarum-extension-manager.admin.composer.title');
} }
className(): string { className(): string {
@@ -23,23 +23,23 @@ export default class ConfigureComposer extends ConfigureJson<IConfigureJson> {
content(): Mithril.Children { content(): Mithril.Children {
return ( return (
<div className="SettingsGroups-content"> <div className="ExtensionManager-SettingsGroups-content">
{this.attrs.buildSettingComponent.call(this, { {this.attrs.buildSettingComponent.call(this, {
setting: 'minimum-stability', setting: 'minimum-stability',
label: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.label'), label: app.translator.trans('flarum-extension-manager.admin.composer.minimum_stability.label'),
help: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.help'), help: app.translator.trans('flarum-extension-manager.admin.composer.minimum_stability.help'),
type: 'select', type: 'select',
options: { options: {
stable: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.options.stable'), stable: app.translator.trans('flarum-extension-manager.admin.composer.minimum_stability.options.stable'),
RC: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.options.rc'), RC: app.translator.trans('flarum-extension-manager.admin.composer.minimum_stability.options.rc'),
beta: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.options.beta'), beta: app.translator.trans('flarum-extension-manager.admin.composer.minimum_stability.options.beta'),
alpha: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.options.alpha'), alpha: app.translator.trans('flarum-extension-manager.admin.composer.minimum_stability.options.alpha'),
dev: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.options.dev'), dev: app.translator.trans('flarum-extension-manager.admin.composer.minimum_stability.options.dev'),
}, },
})} })}
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.composer.repositories.label')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.composer.repositories.label')}</label>
<div className="helpText">{app.translator.trans('flarum-package-manager.admin.composer.repositories.help')}</div> <div className="helpText">{app.translator.trans('flarum-extension-manager.admin.composer.repositories.help')}</div>
<div className="ConfigureComposer-repositories"> <div className="ConfigureComposer-repositories">
{Object.keys(this.setting('repositories')() || {}).map((name) => { {Object.keys(this.setting('repositories')() || {}).map((name) => {
const repository = this.setting('repositories')()[name] as Repository; const repository = this.setting('repositories')()[name] as Repository;
@@ -59,7 +59,14 @@ export default class ConfigureComposer extends ConfigureJson<IConfigureJson> {
app.modal.show(RepositoryModal, { app.modal.show(RepositoryModal, {
name, name,
repository, repository,
onsubmit: this.onchange.bind(this), onsubmit: (repository: Repository, newName: string) => {
const repositories = this.setting('repositories')();
delete repositories[name];
this.setting('repositories')(repositories);
this.onchange(repository, newName);
},
}) })
} }
> >
@@ -68,9 +75,9 @@ export default class ConfigureComposer extends ConfigureJson<IConfigureJson> {
<Button <Button
className="Button Button--icon" className="Button Button--icon"
icon="fas fa-trash" icon="fas fa-trash"
aria-label={app.translator.trans('flarum-package-manager.admin.composer.delete_repository_label')} aria-label={app.translator.trans('flarum-extension-manager.admin.composer.delete_repository_label')}
onclick={() => { onclick={() => {
if (confirm(extractText(app.translator.trans('flarum-package-manager.admin.composer.delete_repository_confirmation')))) { if (confirm(extractText(app.translator.trans('flarum-extension-manager.admin.composer.delete_repository_confirmation')))) {
const repositories = { ...this.setting('repositories')() }; const repositories = { ...this.setting('repositories')() };
delete repositories[name]; delete repositories[name];
@@ -92,7 +99,7 @@ export default class ConfigureComposer extends ConfigureJson<IConfigureJson> {
items.push( items.push(
<Button className="Button" onclick={() => app.modal.show(RepositoryModal, { onsubmit: this.onchange.bind(this) })}> <Button className="Button" onclick={() => app.modal.show(RepositoryModal, { onsubmit: this.onchange.bind(this) })}>
{app.translator.trans('flarum-package-manager.admin.composer.add_repository_label')} {app.translator.trans('flarum-extension-manager.admin.composer.add_repository_label')}
</Button> </Button>
); );

View File

@@ -69,7 +69,7 @@ export default abstract class ConfigureJson<CustomAttrs extends IConfigureJson =
app app
.request({ .request({
method: 'POST', method: 'POST',
url: app.forum.attribute('apiUrl') + '/package-manager/composer', url: app.forum.attribute('apiUrl') + '/extension-manager/composer',
body: { body: {
type: this.type, type: this.type,
data: readOnly ? null : configuration, data: readOnly ? null : configuration,

View File

@@ -14,14 +14,14 @@ export default class ControlSection extends Component<ComponentAttrs> {
view() { view() {
return ( return (
<div className="ExtensionPage-permissions PackageManager-controlSection"> <div className="ExtensionPage-permissions ExtensionManager-controlSection">
<div className="ExtensionPage-permissions-header"> <div className="ExtensionPage-permissions-header">
<div className="container"> <div className="container">
<h2 className="ExtensionTitle">{app.translator.trans('flarum-package-manager.admin.sections.control.title')}</h2> <h2 className="ExtensionTitle">{app.translator.trans('flarum-extension-manager.admin.sections.control.title')}</h2>
</div> </div>
</div> </div>
<div className="container"> <div className="container">
{app.data['flarum-package-manager.writable_dirs'] ? ( {app.data['flarum-extension-manager.writable_dirs'] ? (
<> <>
<Installer /> <Installer />
<Updater /> <Updater />
@@ -29,7 +29,7 @@ export default class ControlSection extends Component<ComponentAttrs> {
) : ( ) : (
<div className="Form-group"> <div className="Form-group">
<Alert type="warning" dismissible={false}> <Alert type="warning" dismissible={false}>
{app.translator.trans('flarum-package-manager.admin.file_permissions')} {app.translator.trans('flarum-extension-manager.admin.file_permissions')}
</Alert> </Alert>
</div> </div>
)} )}

View File

@@ -35,56 +35,56 @@ export default class ExtensionItem<Attrs extends ExtensionItemAttrs = ExtensionI
return ( return (
<div <div
className={classList({ className={classList({
'PackageManager-extension': true, 'ExtensionManager-extension': true,
'PackageManager-extension--core': isCore, 'ExtensionManager-extension--core': isCore,
'PackageManager-extension--danger': isDanger, 'ExtensionManager-extension--danger': isDanger,
})} })}
> >
<div className="PackageManager-extension-icon ExtensionIcon" style={extension.icon}> <div className="ExtensionManager-extension-icon ExtensionIcon" style={extension.icon}>
{extension.icon ? icon(extension.icon.name) : ''} {extension.icon ? icon(extension.icon.name) : ''}
</div> </div>
<div className="PackageManager-extension-info"> <div className="ExtensionManager-extension-info">
<div className="PackageManager-extension-name">{extension.extra['flarum-extension'].title}</div> <div className="ExtensionManager-extension-name">{extension.extra['flarum-extension'].title}</div>
<div className="PackageManager-extension-version"> <div className="ExtensionManager-extension-version">
<span className="PackageManager-extension-version-current">{this.version(updates['version'])}</span> <span className="ExtensionManager-extension-version-current">{this.version(updates['version'])}</span>
{latestVersion ? ( {latestVersion ? (
<Label className="PackageManager-extension-version-latest" type={updates['latest-minor'] ? 'success' : 'warning'}> <Label className="ExtensionManager-extension-version-latest" type={updates['latest-minor'] ? 'success' : 'warning'}>
{this.version(latestVersion)} {this.version(latestVersion)}
</Label> </Label>
) : null} ) : null}
</div> </div>
</div> </div>
<div className="PackageManager-extension-controls"> <div className="ExtensionManager-extension-controls">
{onClickUpdate && typeof onClickUpdate === 'function' ? ( {onClickUpdate && typeof onClickUpdate === 'function' ? (
<Tooltip text={app.translator.trans('flarum-package-manager.admin.extensions.update')}> <Tooltip text={app.translator.trans('flarum-extension-manager.admin.extensions.update')}>
<Button <Button
icon="fas fa-arrow-alt-circle-up" icon="fas fa-arrow-alt-circle-up"
className="Button Button--icon Button--flat" className="Button Button--icon Button--flat"
onclick={onClickUpdate} onclick={onClickUpdate}
aria-label={app.translator.trans('flarum-package-manager.admin.extensions.update')} aria-label={app.translator.trans('flarum-extension-manager.admin.extensions.update')}
/> />
</Tooltip> </Tooltip>
) : onClickUpdate ? ( ) : onClickUpdate ? (
<Dropdown <Dropdown
buttonClassName="Button Button--icon Button--flat" buttonClassName="Button Button--icon Button--flat"
icon="fas fa-arrow-alt-circle-up" icon="fas fa-arrow-alt-circle-up"
label={app.translator.trans('flarum-package-manager.admin.extensions.update')} label={app.translator.trans('flarum-extension-manager.admin.extensions.update')}
> >
<Button icon="fas fa-arrow-alt-circle-up" className="Button" onclick={onClickUpdate.soft}> <Button icon="fas fa-arrow-alt-circle-up" className="Button" onclick={onClickUpdate.soft}>
{app.translator.trans('flarum-package-manager.admin.extensions.update_soft_label')} {app.translator.trans('flarum-extension-manager.admin.extensions.update_soft_label')}
</Button> </Button>
<Button icon="fas fa-arrow-alt-circle-up" className="Button" onclick={onClickUpdate.hard} disabled={!updates['direct-dependency']}> <Button icon="fas fa-arrow-alt-circle-up" className="Button" onclick={onClickUpdate.hard} disabled={!updates['direct-dependency']}>
{app.translator.trans('flarum-package-manager.admin.extensions.update_hard_label')} {app.translator.trans('flarum-extension-manager.admin.extensions.update_hard_label')}
</Button> </Button>
</Dropdown> </Dropdown>
) : null} ) : null}
{whyNotWarning ? ( {whyNotWarning ? (
<Tooltip text={app.translator.trans('flarum-package-manager.admin.extensions.check_why_it_failed_updating')}> <Tooltip text={app.translator.trans('flarum-extension-manager.admin.extensions.check_why_it_failed_updating')}>
<Button <Button
icon="fas fa-exclamation-circle" icon="fas fa-exclamation-circle"
className="Button Button--icon Button--flat Button--danger" className="Button Button--icon Button--flat Button--danger"
onclick={() => app.modal.show(WhyNotModal, { package: extension.name })} onclick={() => app.modal.show(WhyNotModal, { package: extension.name })}
aria-label={app.translator.trans('flarum-package-manager.admin.extensions.check_why_it_failed_updating')} aria-label={app.translator.trans('flarum-extension-manager.admin.extensions.check_why_it_failed_updating')}
/> />
</Tooltip> </Tooltip>
) : null} ) : null}

View File

@@ -19,10 +19,10 @@ export default class Installer extends Component<InstallerAttrs> {
view(): Mithril.Children { view(): Mithril.Children {
return ( return (
<div className="Form-group PackageManager-installer"> <div className="Form-group ExtensionManager-installer">
<label htmlFor="install-extension">{app.translator.trans('flarum-package-manager.admin.extensions.install')}</label> <label htmlFor="install-extension">{app.translator.trans('flarum-extension-manager.admin.extensions.install')}</label>
<p className="helpText"> <p className="helpText">
{app.translator.trans('flarum-package-manager.admin.extensions.install_help', { {app.translator.trans('flarum-extension-manager.admin.extensions.install_help', {
extiverse: <a href="https://extiverse.com">extiverse.com</a>, extiverse: <a href="https://extiverse.com">extiverse.com</a>,
semantic_link: <a href="https://devhints.io/semver" />, semantic_link: <a href="https://devhints.io/semver" />,
code: <code />, code: <code />,
@@ -34,10 +34,10 @@ export default class Installer extends Component<InstallerAttrs> {
className="Button" className="Button"
icon="fas fa-download" icon="fas fa-download"
onclick={this.onsubmit.bind(this)} onclick={this.onsubmit.bind(this)}
loading={app.packageManager.control.isLoading('extension-install')} loading={app.extensionManager.control.isLoading('extension-install')}
disabled={app.packageManager.control.isLoading()} disabled={app.extensionManager.control.hasOperationRunning()}
> >
{app.translator.trans('flarum-package-manager.admin.extensions.proceed')} {app.translator.trans('flarum-extension-manager.admin.extensions.proceed')}
</Button> </Button>
</div> </div>
</div> </div>
@@ -51,6 +51,6 @@ export default class Installer extends Component<InstallerAttrs> {
} }
onsubmit(): void { onsubmit(): void {
app.packageManager.control.requirePackage(this.data()); app.extensionManager.control.requirePackage(this.data());
} }
} }

View File

@@ -30,31 +30,38 @@ export default class MajorUpdater<T extends MajorUpdaterAttrs = MajorUpdaterAttr
// @todo move Form-group--danger class to core for reuse // @todo move Form-group--danger class to core for reuse
return ( return (
<div <div
className={classList('Form-group Form-group--danger PackageManager-majorUpdate', { className={classList('Form-group Form-group--danger ExtensionManager-majorUpdate', {
'PackageManager-majorUpdate--failed': this.updateState.status === 'failure', 'ExtensionManager-majorUpdate--failed': this.updateState.status === 'failure',
'PackageManager-majorUpdate--incompatibleExtensions': this.updateState.incompatibleExtensions.length, 'ExtensionManager-majorUpdate--incompatibleExtensions': this.updateState.incompatibleExtensions.length,
})} })}
> >
<img alt="flarum logo" src={app.forum.attribute('baseUrl') + '/assets/extensions/flarum-package-manager/flarum.svg'} /> <img alt="flarum logo" src={app.forum.attribute('baseUrl') + '/assets/extensions/flarum-extension-manager/flarum.svg'} />
<label>{app.translator.trans('flarum-package-manager.admin.major_updater.title', { version: this.attrs.coreUpdate['latest-major'] })}</label> <label>
<p className="helpText">{app.translator.trans('flarum-package-manager.admin.major_updater.description')}</p> {app.translator.trans('flarum-extension-manager.admin.major_updater.title', { version: this.attrs.coreUpdate['latest-major'] })}
<div className="PackageManager-updaterControls"> </label>
<Tooltip text={app.translator.trans('flarum-package-manager.admin.major_updater.dry_run_help')}> <p className="helpText">{app.translator.trans('flarum-extension-manager.admin.major_updater.description')}</p>
<Button className="Button" icon="fas fa-vial" onclick={this.update.bind(this, true)} disabled={app.packageManager.control.isLoading()}> <div className="ExtensionManager-updaterControls">
{app.translator.trans('flarum-package-manager.admin.major_updater.dry_run')} <Tooltip text={app.translator.trans('flarum-extension-manager.admin.major_updater.dry_run_help')}>
<Button
className="Button"
icon="fas fa-vial"
onclick={this.update.bind(this, true)}
disabled={app.extensionManager.control.hasOperationRunning()}
>
{app.translator.trans('flarum-extension-manager.admin.major_updater.dry_run')}
</Button> </Button>
</Tooltip> </Tooltip>
<Button <Button
className="Button Button--danger" className="Button Button--danger"
icon="fas fa-play" icon="fas fa-play"
onclick={this.update.bind(this, false)} onclick={this.update.bind(this, false)}
disabled={app.packageManager.control.isLoading()} disabled={app.extensionManager.control.hasOperationRunning()}
> >
{app.translator.trans('flarum-package-manager.admin.major_updater.update')} {app.translator.trans('flarum-extension-manager.admin.major_updater.update')}
</Button> </Button>
</div> </div>
{this.updateState.incompatibleExtensions.length ? ( {this.updateState.incompatibleExtensions.length ? (
<div className="PackageManager-majorUpdate-incompatibleExtensions PackageManager-extensions-grid"> <div className="ExtensionManager-majorUpdate-incompatibleExtensions ExtensionManager-extensions-grid">
{this.updateState.incompatibleExtensions.map((extension: string) => ( {this.updateState.incompatibleExtensions.map((extension: string) => (
<ExtensionItem <ExtensionItem
extension={app.data.extensions[extension.replace('flarum-', '').replace('flarum-ext-', '').replace('/', '-')]} extension={app.data.extensions[extension.replace('flarum-', '').replace('flarum-ext-', '').replace('/', '-')]}
@@ -68,20 +75,20 @@ export default class MajorUpdater<T extends MajorUpdaterAttrs = MajorUpdaterAttr
{this.updateState.status === 'failure' ? ( {this.updateState.status === 'failure' ? (
<Alert <Alert
type="error" type="error"
className="PackageManager-majorUpdate-failure" className="ExtensionManager-majorUpdate-failure"
dismissible={false} dismissible={false}
controls={[ controls={[
<Button <Button
className="Button Button--text PackageManager-majorUpdate-failure-details" className="Button Button--text ExtensionManager-majorUpdate-failure-details"
icon="fas fa-question-circle" icon="fas fa-question-circle"
onclick={() => app.modal.show(WhyNotModal, { package: 'flarum/core' })} onclick={() => app.modal.show(WhyNotModal, { package: 'flarum/core' })}
> >
{app.translator.trans('flarum-package-manager.admin.major_updater.failure.why')} {app.translator.trans('flarum-extension-manager.admin.major_updater.failure.why')}
</Button>, </Button>,
]} ]}
> >
<p className="PackageManager-majorUpdate-failure-desc"> <p className="ExtensionManager-majorUpdate-failure-desc">
{app.translator.trans('flarum-package-manager.admin.major_updater.failure.desc')} {app.translator.trans('flarum-extension-manager.admin.major_updater.failure.desc')}
</p> </p>
</Alert> </Alert>
) : null} ) : null}
@@ -90,6 +97,6 @@ export default class MajorUpdater<T extends MajorUpdaterAttrs = MajorUpdaterAttr
} }
update(dryRun: boolean) { update(dryRun: boolean) {
app.packageManager.control.majorUpdate({ dryRun }); app.extensionManager.control.majorUpdate({ dryRun });
} }
} }

View File

@@ -15,7 +15,7 @@ export default class Pagination extends Component<PaginationAttrs> {
return ( return (
<nav className="Pagination UserListPage-gridPagination"> <nav className="Pagination UserListPage-gridPagination">
<Button <Button
disabled={!this.attrs.list.hasPrev()} disabled={!this.attrs.list.hasPrev() || app.extensionManager.control.isLoading()}
title={app.translator.trans('core.admin.users.pagination.back_button')} title={app.translator.trans('core.admin.users.pagination.back_button')}
onclick={() => this.attrs.list.prev()} onclick={() => this.attrs.list.prev()}
icon="fas fa-chevron-left" icon="fas fa-chevron-left"
@@ -28,7 +28,7 @@ export default class Pagination extends Component<PaginationAttrs> {
})} })}
</span> </span>
<Button <Button
disabled={!this.attrs.list.hasNext()} disabled={!this.attrs.list.hasNext() || app.extensionManager.control.isLoading()}
title={app.translator.trans('core.admin.users.pagination.next_button')} title={app.translator.trans('core.admin.users.pagination.next_button')}
onclick={() => this.attrs.list.next()} onclick={() => this.attrs.list.next()}
icon="fas fa-chevron-right" icon="fas fa-chevron-right"

View File

@@ -25,20 +25,21 @@ export default class QueueSection extends Component<{}> {
oninit(vnode: Mithril.Vnode<{}, this>) { oninit(vnode: Mithril.Vnode<{}, this>) {
super.oninit(vnode); super.oninit(vnode);
app.packageManager.queue.load(); app.extensionManager.queue.load();
} }
view() { view() {
return ( return (
<section id="PackageManager-queueSection" className="ExtensionPage-permissions PackageManager-queueSection"> <section id="ExtensionManager-queueSection" className="ExtensionPage-permissions ExtensionManager-queueSection">
<div className="ExtensionPage-permissions-header PackageManager-queueSection-header"> <div className="ExtensionPage-permissions-header ExtensionManager-queueSection-header">
<div className="container"> <div className="container">
<h2 className="ExtensionTitle">{app.translator.trans('flarum-package-manager.admin.sections.queue.title')}</h2> <h2 className="ExtensionTitle">{app.translator.trans('flarum-extension-manager.admin.sections.queue.title')}</h2>
<Button <Button
className="Button Button--icon" className="Button Button--icon"
icon="fas fa-sync-alt" icon="fas fa-sync-alt"
onclick={() => app.packageManager.queue.load()} onclick={() => app.extensionManager.queue.load()}
aria-label={app.translator.trans('flarum-package-manager.admin.sections.queue.refresh')} aria-label={app.translator.trans('flarum-extension-manager.admin.sections.queue.refresh')}
disabled={app.extensionManager.control.isLoading()}
/> />
</div> </div>
</div> </div>
@@ -53,12 +54,12 @@ export default class QueueSection extends Component<{}> {
items.add( items.add(
'operation', 'operation',
{ {
label: extractText(app.translator.trans('flarum-package-manager.admin.sections.queue.columns.operation')), label: extractText(app.translator.trans('flarum-extension-manager.admin.sections.queue.columns.operation')),
content: (task) => ( content: (task) => (
<div className="PackageManager-queueTable-operation"> <div className="ExtensionManager-queueTable-operation">
<span className="PackageManager-queueTable-operation-icon">{this.operationIcon(task.operation())}</span> <span className="ExtensionManager-queueTable-operation-icon">{this.operationIcon(task.operation())}</span>
<span className="PackageManager-queueTable-operation-name"> <span className="ExtensionManager-queueTable-operation-name">
{app.translator.trans(`flarum-package-manager.admin.sections.queue.operations.${task.operation()}`)} {app.translator.trans(`flarum-extension-manager.admin.sections.queue.operations.${task.operation()}`)}
</span> </span>
</div> </div>
), ),
@@ -69,18 +70,18 @@ export default class QueueSection extends Component<{}> {
items.add( items.add(
'package', 'package',
{ {
label: extractText(app.translator.trans('flarum-package-manager.admin.sections.queue.columns.package')), label: extractText(app.translator.trans('flarum-extension-manager.admin.sections.queue.columns.package')),
content: (task) => { content: (task) => {
const extension: Extension | null = app.data.extensions[task.package()?.replace(/(\/flarum-|\/flarum-ext-|\/)/g, '-')]; const extension: Extension | null = app.data.extensions[task.package()?.replace(/(\/flarum-|\/flarum-ext-|\/)/g, '-')];
return extension ? ( return extension ? (
<Link className="PackageManager-queueTable-package" href={app.route('extension', { id: extension.id })}> <Link className="ExtensionManager-queueTable-package" href={app.route('extension', { id: extension.id })}>
<div className="PackageManager-queueTable-package-icon ExtensionIcon" style={extension.icon}> <div className="ExtensionManager-queueTable-package-icon ExtensionIcon" style={extension.icon}>
{!!extension.icon && icon(extension.icon.name)} {!!extension.icon && icon(extension.icon.name)}
</div> </div>
<div className="PackageManager-queueTable-package-details"> <div className="ExtensionManager-queueTable-package-details">
<span className="PackageManager-queueTable-package-title">{extension.extra['flarum-extension'].title}</span> <span className="ExtensionManager-queueTable-package-title">{extension.extra['flarum-extension'].title}</span>
<span className="PackageManager-queueTable-package-name">{task.package()}</span> <span className="ExtensionManager-queueTable-package-name">{task.package()}</span>
</div> </div>
</Link> </Link>
) : ( ) : (
@@ -94,14 +95,14 @@ export default class QueueSection extends Component<{}> {
items.add( items.add(
'status', 'status',
{ {
label: extractText(app.translator.trans('flarum-package-manager.admin.sections.queue.columns.status')), label: extractText(app.translator.trans('flarum-extension-manager.admin.sections.queue.columns.status')),
content: (task) => ( content: (task) => (
<> <>
<Label <Label
className="PackageManager-queueTable-status" className="ExtensionManager-queueTable-status"
type={{ running: 'neutral', failure: 'error', pending: 'warning', success: 'success' }[task.status()]} type={{ running: 'neutral', failure: 'error', pending: 'warning', success: 'success' }[task.status()]}
> >
{app.translator.trans(`flarum-package-manager.admin.sections.queue.statuses.${task.status()}`)} {app.translator.trans(`flarum-extension-manager.admin.sections.queue.statuses.${task.status()}`)}
</Label> </Label>
{['pending', 'running'].includes(task.status()) && <LoadingIndicator size="small" display="inline" />} {['pending', 'running'].includes(task.status()) && <LoadingIndicator size="small" display="inline" />}
</> </>
@@ -113,10 +114,10 @@ export default class QueueSection extends Component<{}> {
items.add( items.add(
'elapsedTime', 'elapsedTime',
{ {
label: extractText(app.translator.trans('flarum-package-manager.admin.sections.queue.columns.elapsed_time')), label: extractText(app.translator.trans('flarum-extension-manager.admin.sections.queue.columns.elapsed_time')),
content: (task) => content: (task) =>
!task.startedAt() || !task.finishedAt() ? ( !task.startedAt() || !task.finishedAt() ? (
app.translator.trans('flarum-package-manager.admin.sections.queue.task_just_started') app.translator.trans('flarum-extension-manager.admin.sections.queue.task_just_started')
) : ( ) : (
<Tooltip text={`${dayjs(task.startedAt()).format('LL LTS')} ${dayjs(task.finishedAt()).format('LL LTS')}`}> <Tooltip text={`${dayjs(task.startedAt()).format('LL LTS')} ${dayjs(task.finishedAt()).format('LL LTS')}`}>
<span>{humanDuration(task.startedAt(), task.finishedAt())}</span> <span>{humanDuration(task.startedAt(), task.finishedAt())}</span>
@@ -129,7 +130,7 @@ export default class QueueSection extends Component<{}> {
items.add( items.add(
'memoryUsed', 'memoryUsed',
{ {
label: extractText(app.translator.trans('flarum-package-manager.admin.sections.queue.columns.peak_memory_used')), label: extractText(app.translator.trans('flarum-extension-manager.admin.sections.queue.columns.peak_memory_used')),
content: (task) => <span>{task.peakMemoryUsed()}</span>, content: (task) => <span>{task.peakMemoryUsed()}</span>,
}, },
60 60
@@ -138,15 +139,16 @@ export default class QueueSection extends Component<{}> {
items.add( items.add(
'details', 'details',
{ {
label: extractText(app.translator.trans('flarum-package-manager.admin.sections.queue.columns.details')), label: extractText(app.translator.trans('flarum-extension-manager.admin.sections.queue.columns.details')),
content: (task) => ( content: (task) => (
<Button <Button
className="Button Button--icon Table-controls-item" className="Button Button--icon Table-controls-item"
icon="fas fa-file-alt" icon="fas fa-file-alt"
aria-label={app.translator.trans('flarum-package-manager.admin.sections.queue.columns.details')} aria-label={app.translator.trans('flarum-extension-manager.admin.sections.queue.columns.details')}
// @todo fix in core // @todo fix in core
// @ts-ignore // @ts-ignore
onclick={() => app.modal.show(TaskOutputModal, { task })} onclick={() => app.modal.show(TaskOutputModal, { task })}
disabled={['pending', 'running'].includes(task.status())}
/> />
), ),
className: 'Table-controls', className: 'Table-controls',
@@ -158,21 +160,21 @@ export default class QueueSection extends Component<{}> {
} }
queueTable() { queueTable() {
const tasks = app.packageManager.queue.getItems(); const tasks = app.extensionManager.queue.getItems();
if (!tasks) { if (!tasks) {
return <LoadingIndicator />; return <LoadingIndicator />;
} }
if (tasks && !tasks.length) { if (tasks && !tasks.length) {
return <h3 className="ExtensionPage-subHeader">{app.translator.trans('flarum-package-manager.admin.sections.queue.none')}</h3>; return <h3 className="ExtensionPage-subHeader">{app.translator.trans('flarum-extension-manager.admin.sections.queue.none')}</h3>;
} }
const columns = this.columns(); const columns = this.columns();
return ( return (
<> <>
<table className="Table PackageManager-queueTable"> <table className="Table ExtensionManager-queueTable">
<thead> <thead>
<tr> <tr>
{columns.toArray().map((item, index) => ( {columns.toArray().map((item, index) => (
@@ -197,7 +199,7 @@ export default class QueueSection extends Component<{}> {
</tbody> </tbody>
</table> </table>
<Pagination list={app.packageManager.queue} /> <Pagination list={app.extensionManager.queue} />
</> </>
); );
} }

View File

@@ -29,24 +29,24 @@ export default class RepositoryModal<CustomAttrs extends IRepositoryModalAttrs =
title(): Mithril.Children { title(): Mithril.Children {
const context = this.attrs.repository ? 'edit' : 'add'; const context = this.attrs.repository ? 'edit' : 'add';
return app.translator.trans(`flarum-package-manager.admin.composer.${context}_repository_label`); return app.translator.trans(`flarum-extension-manager.admin.composer.${context}_repository_label`);
} }
content(): Mithril.Children { content(): Mithril.Children {
const types = { const types = {
composer: app.translator.trans('flarum-package-manager.admin.composer.repositories.types.composer'), composer: app.translator.trans('flarum-extension-manager.admin.composer.repositories.types.composer'),
vcs: app.translator.trans('flarum-package-manager.admin.composer.repositories.types.vcs'), vcs: app.translator.trans('flarum-extension-manager.admin.composer.repositories.types.vcs'),
path: app.translator.trans('flarum-package-manager.admin.composer.repositories.types.path'), path: app.translator.trans('flarum-extension-manager.admin.composer.repositories.types.path'),
}; };
return ( return (
<div className="Modal-body"> <div className="Modal-body">
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.composer.repositories.add_modal.name_label')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.composer.repositories.add_modal.name_label')}</label>
<input className="FormControl" bidi={this.name} /> <input className="FormControl" bidi={this.name} />
</div> </div>
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.composer.repositories.add_modal.type_label')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.composer.repositories.add_modal.type_label')}</label>
<Select <Select
options={types} options={types}
value={this.repository().type} value={this.repository().type}
@@ -54,7 +54,7 @@ export default class RepositoryModal<CustomAttrs extends IRepositoryModalAttrs =
/> />
</div> </div>
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.composer.repositories.add_modal.url')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.composer.repositories.add_modal.url')}</label>
<input <input
className="FormControl" className="FormControl"
onchange={(e: Event) => this.repository({ ...this.repository(), url: (e.target as HTMLInputElement).value })} onchange={(e: Event) => this.repository({ ...this.repository(), url: (e.target as HTMLInputElement).value })}
@@ -63,7 +63,7 @@ export default class RepositoryModal<CustomAttrs extends IRepositoryModalAttrs =
</div> </div>
<div className="Form-group"> <div className="Form-group">
<Button className="Button Button--primary" onclick={this.submit.bind(this)}> <Button className="Button Button--primary" onclick={this.submit.bind(this)}>
{app.translator.trans('flarum-package-manager.admin.composer.repositories.add_modal.submit_button')} {app.translator.trans('flarum-extension-manager.admin.composer.repositories.add_modal.submit_button')}
</Button> </Button>
</div> </div>
</div> </div>

View File

@@ -14,22 +14,22 @@ export default class SettingsPage extends ExtensionPage {
content() { content() {
const settings = app.extensionData.getSettings(this.extension.id); const settings = app.extensionData.getSettings(this.extension.id);
const warnings = [app.translator.trans('flarum-package-manager.admin.settings.access_warning')]; const warnings = [app.translator.trans('flarum-extension-manager.admin.settings.access_warning')];
if (app.data.debugEnabled) warnings.push(app.translator.trans('flarum-package-manager.admin.settings.debug_mode_warning')); if (app.data.debugEnabled) warnings.push(app.translator.trans('flarum-extension-manager.admin.settings.debug_mode_warning'));
return ( return (
<div className="ExtensionPage-settings"> <div className="ExtensionPage-settings">
<div className="container"> <div className="container">
<div className="Form-group"> <div className="Form-group">
<Alert className="PackageManager-primaryWarning" type="warning" dismissible={false}> <Alert className="ExtensionManager-primaryWarning" type="warning" dismissible={false}>
<ul>{listItems(warnings)}</ul> <ul>{listItems(warnings)}</ul>
</Alert> </Alert>
</div> </div>
{settings ? ( {settings ? (
<div className="SettingsGroups"> <div className="ExtensionManager-SettingsGroups">
<div className="Form"> <div className="Form">
<label>{app.translator.trans('flarum-package-manager.admin.settings.title')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.settings.title')}</label>
<div className="SettingsGroups-content">{settings.map(this.buildSettingComponent.bind(this))}</div> <div className="SettingsGroups-content">{settings.map(this.buildSettingComponent.bind(this))}</div>
<div className="Form-group Form--controls">{this.submitButton()}</div> <div className="Form-group Form--controls">{this.submitButton()}</div>
</div> </div>
@@ -51,7 +51,7 @@ export default class SettingsPage extends ExtensionPage {
items.add('control', <ControlSection />, 8); items.add('control', <ControlSection />, 8);
if (app.data.settings['flarum-package-manager.queue_jobs'] !== '0' && app.data.settings['flarum-package-manager.queue_jobs']) { if (app.data.settings['flarum-extension-manager.queue_jobs'] !== '0' && app.data.settings['flarum-extension-manager.queue_jobs']) {
items.add('queue', <QueueSection />, 5); items.add('queue', <QueueSection />, 5);
} }

View File

@@ -12,31 +12,33 @@ export default class TaskOutputModal<CustomAttrs extends TaskOutputModalAttrs =
} }
title() { title() {
return app.translator.trans(`flarum-package-manager.admin.sections.queue.operations.${this.attrs.task.operation()}`); return app.translator.trans(`flarum-extension-manager.admin.sections.queue.operations.${this.attrs.task.operation()}`);
} }
content() { content() {
return ( return (
<div className="Modal-body"> <div className="Modal-body">
<div className="TaskOutputModal-data"> <div className="TaskOutputModal-data">
<div className="Form-group"> {this.attrs.task.status() === 'failure' && (
<label>{app.translator.trans('flarum-package-manager.admin.sections.queue.output_modal.guessed_cause')}</label> <div className="Form-group">
<div className="FormControl TaskOutputModal-data-guessed-cause"> <label>{app.translator.trans('flarum-extension-manager.admin.sections.queue.output_modal.guessed_cause')}</label>
{(this.attrs.task.guessedCause() && <div className="FormControl TaskOutputModal-data-guessed-cause">
app.translator.trans('flarum-package-manager.admin.exceptions.guessed_cause.' + this.attrs.task.guessedCause())) || {(this.attrs.task.guessedCause() &&
app.translator.trans('flarum-package-manager.admin.sections.queue.output_modal.cause_unknown')} app.translator.trans('flarum-extension-manager.admin.exceptions.guessed_cause.' + this.attrs.task.guessedCause())) ||
app.translator.trans('flarum-extension-manager.admin.sections.queue.output_modal.cause_unknown')}
</div>
</div> </div>
</div> )}
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.sections.queue.output_modal.command')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.sections.queue.output_modal.command')}</label>
<div className="FormControl TaskOutputModal-data-command"> <div className="FormControl TaskOutputModal-data-command">
<code>$ composer {this.attrs.task.command()}</code> <code>$ composer {this.attrs.task.command()}</code>
</div> </div>
</div> </div>
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.sections.queue.output_modal.output')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.sections.queue.output_modal.output')}</label>
<div className="FormControl TaskOutputModal-data-output"> <div className="FormControl TaskOutputModal-data-output">
<code> <code>
<pre>{this.attrs.task.output()}</pre> <pre>{this.attrs.task.output()}</pre>

View File

@@ -14,30 +14,30 @@ export type UpdaterLoadingTypes = 'check' | 'minor-update' | 'global-update' | '
export default class Updater extends Component<IUpdaterAttrs> { export default class Updater extends Component<IUpdaterAttrs> {
view() { view() {
const core = app.packageManager.control.coreUpdate; const core = app.extensionManager.control.coreUpdate;
return [ return [
<div className="Form-group"> <div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.updater.updater_title')}</label> <label>{app.translator.trans('flarum-extension-manager.admin.updater.updater_title')}</label>
<p className="helpText">{app.translator.trans('flarum-package-manager.admin.updater.updater_help')}</p> <p className="helpText">{app.translator.trans('flarum-extension-manager.admin.updater.updater_help')}</p>
{this.lastUpdateCheckView()} {this.lastUpdateCheckView()}
<div className="PackageManager-updaterControls">{this.controlItems().toArray()}</div> <div className="ExtensionManager-updaterControls">{this.controlItems().toArray()}</div>
{this.availableUpdatesView()} {this.availableUpdatesView()}
</div>, </div>,
core && core.package['latest-major'] ? ( core && core.package['latest-major'] ? (
<MajorUpdater coreUpdate={core.package} updateState={app.packageManager.control.lastUpdateRun.major} /> <MajorUpdater coreUpdate={core.package} updateState={app.extensionManager.control.lastUpdateRun.major} />
) : null, ) : null,
]; ];
} }
lastUpdateCheckView() { lastUpdateCheckView() {
return ( return (
(app.packageManager.control.lastUpdateCheck?.checkedAt && ( (app.extensionManager.control.lastUpdateCheck?.checkedAt && (
<p className="PackageManager-lastUpdatedAt"> <p className="ExtensionManager-lastUpdatedAt">
<span className="PackageManager-lastUpdatedAt-label"> <span className="ExtensionManager-lastUpdatedAt-label">
{app.translator.trans('flarum-package-manager.admin.updater.last_update_checked_at')} {app.translator.trans('flarum-extension-manager.admin.updater.last_update_checked_at')}
</span> </span>
<span className="PackageManager-lastUpdatedAt-value">{humanTime(app.packageManager.control.lastUpdateCheck.checkedAt)}</span> <span className="ExtensionManager-lastUpdatedAt-value">{humanTime(app.extensionManager.control.lastUpdateCheck.checkedAt)}</span>
</p> </p>
)) || )) ||
null null
@@ -45,11 +45,11 @@ export default class Updater extends Component<IUpdaterAttrs> {
} }
availableUpdatesView() { availableUpdatesView() {
const state = app.packageManager.control; const state = app.extensionManager.control;
if (app.packageManager.control.isLoading('check') || app.packageManager.control.isLoading('global-update')) { if (app.extensionManager.control.isLoading('check') || app.extensionManager.control.isLoading('global-update')) {
return ( return (
<div className="PackageManager-extensions"> <div className="ExtensionManager-extensions">
<LoadingIndicator /> <LoadingIndicator />
</div> </div>
); );
@@ -59,15 +59,15 @@ export default class Updater extends Component<IUpdaterAttrs> {
if (!(state.extensionUpdates.length || hasMinorCoreUpdate)) { if (!(state.extensionUpdates.length || hasMinorCoreUpdate)) {
return ( return (
<div className="PackageManager-extensions"> <div className="ExtensionManager-extensions">
<span className="helpText">{app.translator.trans('flarum-package-manager.admin.updater.up_to_date')}</span> <span className="helpText">{app.translator.trans('flarum-extension-manager.admin.updater.up_to_date')}</span>
</div> </div>
); );
} }
return ( return (
<div className="PackageManager-extensions"> <div className="ExtensionManager-extensions">
<div className="PackageManager-extensions-grid"> <div className="ExtensionManager-extensions-grid">
{hasMinorCoreUpdate ? ( {hasMinorCoreUpdate ? (
<ExtensionItem <ExtensionItem
extension={state.coreUpdate!.extension} extension={state.coreUpdate!.extension}
@@ -101,11 +101,11 @@ export default class Updater extends Component<IUpdaterAttrs> {
<Button <Button
className="Button" className="Button"
icon="fas fa-sync-alt" icon="fas fa-sync-alt"
onclick={() => app.packageManager.control.checkForUpdates()} onclick={() => app.extensionManager.control.checkForUpdates()}
loading={app.packageManager.control.isLoading('check')} loading={app.extensionManager.control.isLoading('check')}
disabled={app.packageManager.control.isLoading()} disabled={app.extensionManager.control.hasOperationRunning()}
> >
{app.translator.trans('flarum-package-manager.admin.updater.check_for_updates')} {app.translator.trans('flarum-extension-manager.admin.updater.check_for_updates')}
</Button>, </Button>,
100 100
); );
@@ -115,11 +115,11 @@ export default class Updater extends Component<IUpdaterAttrs> {
<Button <Button
className="Button" className="Button"
icon="fas fa-play" icon="fas fa-play"
onclick={() => app.packageManager.control.updateGlobally()} onclick={() => app.extensionManager.control.updateGlobally()}
loading={app.packageManager.control.isLoading('global-update')} loading={app.extensionManager.control.isLoading('global-update')}
disabled={app.packageManager.control.isLoading()} disabled={app.extensionManager.control.hasOperationRunning()}
> >
{app.translator.trans('flarum-package-manager.admin.updater.run_global_update')} {app.translator.trans('flarum-extension-manager.admin.updater.run_global_update')}
</Button> </Button>
); );

View File

@@ -24,7 +24,7 @@ export default class WhyNotModal<CustomAttrs extends WhyNotModalAttrs = WhyNotMo
} }
title() { title() {
return app.translator.trans('flarum-package-manager.admin.why_not_modal.title'); return app.translator.trans('flarum-extension-manager.admin.why_not_modal.title');
} }
oncreate(vnode: Mithril.VnodeDOM<CustomAttrs, this>) { oncreate(vnode: Mithril.VnodeDOM<CustomAttrs, this>) {
@@ -41,7 +41,7 @@ export default class WhyNotModal<CustomAttrs extends WhyNotModalAttrs = WhyNotMo
app app
.request<WhyNotResponse>({ .request<WhyNotResponse>({
method: 'POST', method: 'POST',
url: `${app.forum.attribute('apiUrl')}/package-manager/why-not`, url: `${app.forum.attribute('apiUrl')}/extension-manager/why-not`,
body: { body: {
data: { data: {
package: this.attrs.package, package: this.attrs.package,

View File

@@ -4,32 +4,30 @@ import ExtensionPage from 'flarum/admin/components/ExtensionPage';
import Button from 'flarum/common/components/Button'; import Button from 'flarum/common/components/Button';
import LoadingModal from 'flarum/admin/components/LoadingModal'; import LoadingModal from 'flarum/admin/components/LoadingModal';
import isExtensionEnabled from 'flarum/admin/utils/isExtensionEnabled'; import isExtensionEnabled from 'flarum/admin/utils/isExtensionEnabled';
import Alert from 'flarum/common/components/Alert';
import SettingsPage from './components/SettingsPage'; import SettingsPage from './components/SettingsPage';
import Task from './models/Task'; import Task from './models/Task';
import jumpToQueue from './utils/jumpToQueue'; import jumpToQueue from './utils/jumpToQueue';
import extractText from 'flarum/common/utils/extractText'; import extractText from 'flarum/common/utils/extractText';
import { AsyncBackendResponse } from './shims'; import { AsyncBackendResponse } from './shims';
import PackageManagerState from './states/PackageManagerState'; import ExtensionManagerState from './states/ExtensionManagerState';
app.initializers.add('flarum-package-manager', (app) => { app.initializers.add('flarum-extension-manager', (app) => {
app.store.models['package-manager-tasks'] = Task; app.store.models['extension-manager-tasks'] = Task;
app.packageManager = new PackageManagerState(); app.extensionManager = new ExtensionManagerState();
if (app.data['flarum-package-manager.using_sync_queue']) { if (app.data['flarum-extension-manager.using_sync_queue']) {
app.data.settings['flarum-package-manager.queue_jobs'] = '0'; app.data.settings['flarum-extension-manager.queue_jobs'] = '0';
} }
app.extensionData app.extensionData
.for('flarum-package-manager') .for('flarum-extension-manager')
.registerSetting({ .registerSetting({
setting: 'flarum-package-manager.queue_jobs', setting: 'flarum-extension-manager.queue_jobs',
label: app.translator.trans('flarum-package-manager.admin.settings.queue_jobs'), label: app.translator.trans('flarum-extension-manager.admin.settings.queue_jobs'),
help: m.trust( help: m.trust(
extractText( extractText(
app.translator.trans('flarum-package-manager.admin.settings.queue_jobs_help', { app.translator.trans('flarum-extension-manager.admin.settings.queue_jobs_help', {
basic_impl_link: 'https://discuss.flarum.org/d/28151-database-queue-the-simplest-queue-even-for-shared-hosting', basic_impl_link: 'https://discuss.flarum.org/d/28151-database-queue-the-simplest-queue-even-for-shared-hosting',
adv_impl_link: 'https://discuss.flarum.org/d/21873-redis-sessions-cache-queues', adv_impl_link: 'https://discuss.flarum.org/d/21873-redis-sessions-cache-queues',
php_version: `<strong>${app.data.phpVersion}</strong>`, php_version: `<strong>${app.data.phpVersion}</strong>`,
@@ -38,18 +36,18 @@ app.initializers.add('flarum-package-manager', (app) => {
) )
), ),
type: 'boolean', type: 'boolean',
disabled: app.data['flarum-package-manager.using_sync_queue'], disabled: app.data['flarum-extension-manager.using_sync_queue'],
}) })
.registerSetting({ .registerSetting({
setting: 'flarum-package-manager.task_retention_days', setting: 'flarum-extension-manager.task_retention_days',
label: app.translator.trans('flarum-package-manager.admin.settings.task_retention_days'), label: app.translator.trans('flarum-extension-manager.admin.settings.task_retention_days'),
help: app.translator.trans('flarum-package-manager.admin.settings.task_retention_days_help'), help: app.translator.trans('flarum-extension-manager.admin.settings.task_retention_days_help'),
type: 'number', type: 'number',
}) })
.registerPage(SettingsPage); .registerPage(SettingsPage);
extend(ExtensionPage.prototype, 'topItems', function (items) { extend(ExtensionPage.prototype, 'topItems', function (items) {
if (this.extension.id === 'flarum-package-manager' || isExtensionEnabled(this.extension.id)) { if (this.extension.id === 'flarum-extension-manager' || isExtensionEnabled(this.extension.id)) {
return; return;
} }
@@ -63,14 +61,14 @@ app.initializers.add('flarum-package-manager', (app) => {
app app
.request<AsyncBackendResponse | null>({ .request<AsyncBackendResponse | null>({
url: `${app.forum.attribute('apiUrl')}/package-manager/extensions/${this.extension.id}`, url: `${app.forum.attribute('apiUrl')}/extension-manager/extensions/${this.extension.id}`,
method: 'DELETE', method: 'DELETE',
}) })
.then((response) => { .then((response) => {
if (response?.processing) { if (response?.processing) {
jumpToQueue(); jumpToQueue();
} else { } else {
app.alerts.show({ type: 'success' }, app.translator.trans('flarum-package-manager.admin.extensions.successful_remove')); app.alerts.show({ type: 'success' }, app.translator.trans('flarum-extension-manager.admin.extensions.successful_remove'));
window.location = app.forum.attribute('adminUrl'); window.location = app.forum.attribute('adminUrl');
} }
}) })
@@ -79,8 +77,14 @@ app.initializers.add('flarum-package-manager', (app) => {
}); });
}} }}
> >
{app.translator.trans('flarum-package-manager.admin.extensions.remove')} {app.translator.trans('flarum-extension-manager.admin.extensions.remove')}
</Button> </Button>
); );
}); });
}); });
// Expose compat API
import packageManagerCompat from './compat';
import { compat } from '@flarum/core/admin';
Object.assign(compat, packageManagerCompat);

View File

@@ -1,5 +1,5 @@
import 'dayjs/plugin/relativeTime'; import 'dayjs/plugin/relativeTime';
import PackageManagerState from './states/PackageManagerState'; import ExtensionManagerState from './states/ExtensionManagerState';
export interface AsyncBackendResponse { export interface AsyncBackendResponse {
processing: boolean; processing: boolean;
@@ -7,6 +7,6 @@ export interface AsyncBackendResponse {
declare module 'flarum/admin/AdminApplication' { declare module 'flarum/admin/AdminApplication' {
export default interface AdminApplication { export default interface AdminApplication {
packageManager: PackageManagerState; extensionManager: ExtensionManagerState;
} }
} }

View File

@@ -61,7 +61,7 @@ export default class ControlSectionState {
public extensionUpdates!: Extension[]; public extensionUpdates!: Extension[];
public coreUpdate: CoreUpdate | null = null; public coreUpdate: CoreUpdate | null = null;
get lastUpdateRun(): LastUpdateRun { get lastUpdateRun(): LastUpdateRun {
const lastUpdateRun = JSON.parse(app.data.settings['flarum-package-manager.last_update_run']) as LastUpdateRun; const lastUpdateRun = JSON.parse(app.data.settings['flarum-extension-manager.last_update_run']) as LastUpdateRun;
lastUpdateRun.limitedPackages = () => [ lastUpdateRun.limitedPackages = () => [
...lastUpdateRun.major.limitedPackages, ...lastUpdateRun.major.limitedPackages,
@@ -73,7 +73,7 @@ export default class ControlSectionState {
} }
constructor() { constructor() {
this.lastUpdateCheck = JSON.parse(app.data.settings['flarum-package-manager.last_update_check']) as LastUpdateCheck; this.lastUpdateCheck = JSON.parse(app.data.settings['flarum-extension-manager.last_update_check']) as LastUpdateCheck;
this.extensionUpdates = this.formatExtensionUpdates(this.lastUpdateCheck); this.extensionUpdates = this.formatExtensionUpdates(this.lastUpdateCheck);
this.coreUpdate = this.formatCoreUpdate(this.lastUpdateCheck); this.coreUpdate = this.formatCoreUpdate(this.lastUpdateCheck);
} }
@@ -82,18 +82,22 @@ export default class ControlSectionState {
return (name && this.loading === name) || (!name && this.loading !== null); return (name && this.loading === name) || (!name && this.loading !== null);
} }
hasOperationRunning(): boolean {
return this.isLoading() || app.extensionManager.queue.hasPending();
}
setLoading(name: LoadingTypes): void { setLoading(name: LoadingTypes): void {
this.loading = name; this.loading = name;
} }
requirePackage(data: any) { requirePackage(data: any) {
app.packageManager.control.setLoading('extension-install'); app.extensionManager.control.setLoading('extension-install');
app.modal.show(LoadingModal); app.modal.show(LoadingModal);
app app
.request<AsyncBackendResponse & { id: number }>({ .request<AsyncBackendResponse & { id: number }>({
method: 'POST', method: 'POST',
url: `${app.forum.attribute('apiUrl')}/package-manager/extensions`, url: `${app.forum.attribute('apiUrl')}/extension-manager/extensions`,
body: { body: {
data, data,
}, },
@@ -105,7 +109,7 @@ export default class ControlSectionState {
const extensionId = response.id; const extensionId = response.id;
app.alerts.show( app.alerts.show(
{ type: 'success' }, { type: 'success' },
app.translator.trans('flarum-package-manager.admin.extensions.successful_install', { extension: extensionId }) app.translator.trans('flarum-extension-manager.admin.extensions.successful_install', { extension: extensionId })
); );
window.location.href = `${app.forum.attribute('adminUrl')}#/extension/${extensionId}`; window.location.href = `${app.forum.attribute('adminUrl')}#/extension/${extensionId}`;
window.location.reload(); window.location.reload();
@@ -124,7 +128,7 @@ export default class ControlSectionState {
app app
.request<AsyncBackendResponse | LastUpdateCheck>({ .request<AsyncBackendResponse | LastUpdateCheck>({
method: 'POST', method: 'POST',
url: `${app.forum.attribute('apiUrl')}/package-manager/check-for-updates`, url: `${app.forum.attribute('apiUrl')}/extension-manager/check-for-updates`,
}) })
.then((response) => { .then((response) => {
if ((response as AsyncBackendResponse).processing) { if ((response as AsyncBackendResponse).processing) {
@@ -144,20 +148,20 @@ export default class ControlSectionState {
} }
updateCoreMinor() { updateCoreMinor() {
if (confirm(extractText(app.translator.trans('flarum-package-manager.admin.minor_update_confirmation.content')))) { if (confirm(extractText(app.translator.trans('flarum-extension-manager.admin.minor_update_confirmation.content')))) {
app.modal.show(LoadingModal); app.modal.show(LoadingModal);
this.setLoading('minor-update'); this.setLoading('minor-update');
app app
.request<AsyncBackendResponse | null>({ .request<AsyncBackendResponse | null>({
method: 'POST', method: 'POST',
url: `${app.forum.attribute('apiUrl')}/package-manager/minor-update`, url: `${app.forum.attribute('apiUrl')}/extension-manager/minor-update`,
}) })
.then((response) => { .then((response) => {
if (response?.processing) { if (response?.processing) {
jumpToQueue(); jumpToQueue();
} else { } else {
app.alerts.show({ type: 'success' }, app.translator.trans('flarum-package-manager.admin.update_successful')); app.alerts.show({ type: 'success' }, app.translator.trans('flarum-extension-manager.admin.update_successful'));
window.location.reload(); window.location.reload();
} }
}) })
@@ -176,7 +180,7 @@ export default class ControlSectionState {
app app
.request<AsyncBackendResponse | null>({ .request<AsyncBackendResponse | null>({
method: 'PATCH', method: 'PATCH',
url: `${app.forum.attribute('apiUrl')}/package-manager/extensions/${extension.id}`, url: `${app.forum.attribute('apiUrl')}/extension-manager/extensions/${extension.id}`,
body: { body: {
data: { data: {
updateMode, updateMode,
@@ -189,7 +193,7 @@ export default class ControlSectionState {
} else { } else {
app.alerts.show( app.alerts.show(
{ type: 'success' }, { type: 'success' },
app.translator.trans('flarum-package-manager.admin.extensions.successful_update', { app.translator.trans('flarum-extension-manager.admin.extensions.successful_update', {
extension: extension.extra['flarum-extension'].title, extension: extension.extra['flarum-extension'].title,
}) })
); );
@@ -210,13 +214,13 @@ export default class ControlSectionState {
app app
.request<AsyncBackendResponse | null>({ .request<AsyncBackendResponse | null>({
method: 'POST', method: 'POST',
url: `${app.forum.attribute('apiUrl')}/package-manager/global-update`, url: `${app.forum.attribute('apiUrl')}/extension-manager/global-update`,
}) })
.then((response) => { .then((response) => {
if (response?.processing) { if (response?.processing) {
jumpToQueue(); jumpToQueue();
} else { } else {
app.alerts.show({ type: 'success' }, app.translator.trans('flarum-package-manager.admin.updater.global_update_successful')); app.alerts.show({ type: 'success' }, app.translator.trans('flarum-extension-manager.admin.updater.global_update_successful'));
window.location.reload(); window.location.reload();
} }
}) })
@@ -259,11 +263,11 @@ export default class ControlSectionState {
version: app.data.settings.version, version: app.data.settings.version,
icon: { icon: {
// @ts-ignore // @ts-ignore
backgroundImage: `url(${app.data.resources[0]['attributes']['baseUrl']}/assets/extensions/flarum-package-manager/flarum.svg`, backgroundImage: `url(${app.data.resources[0]['attributes']['baseUrl']}/assets/extensions/flarum-extension-manager/flarum.svg`,
}, },
extra: { extra: {
'flarum-extension': { 'flarum-extension': {
title: extractText(app.translator.trans('flarum-package-manager.admin.updater.flarum')), title: extractText(app.translator.trans('flarum-extension-manager.admin.updater.flarum')),
}, },
}, },
}, },
@@ -271,14 +275,14 @@ export default class ControlSectionState {
} }
majorUpdate({ dryRun }: { dryRun: boolean }) { majorUpdate({ dryRun }: { dryRun: boolean }) {
app.packageManager.control.setLoading(dryRun ? 'major-update-dry-run' : 'major-update'); app.extensionManager.control.setLoading(dryRun ? 'major-update-dry-run' : 'major-update');
app.modal.show(LoadingModal); app.modal.show(LoadingModal);
const updateState = this.lastUpdateRun.major; const updateState = this.lastUpdateRun.major;
app app
.request<AsyncBackendResponse | null>({ .request<AsyncBackendResponse | null>({
method: 'POST', method: 'POST',
url: `${app.forum.attribute('apiUrl')}/package-manager/major-update`, url: `${app.forum.attribute('apiUrl')}/extension-manager/major-update`,
body: { body: {
data: { dryRun }, data: { dryRun },
}, },
@@ -287,7 +291,7 @@ export default class ControlSectionState {
if (response?.processing) { if (response?.processing) {
jumpToQueue(); jumpToQueue();
} else { } else {
app.alerts.show({ type: 'success' }, app.translator.trans('flarum-package-manager.admin.update_successful')); app.alerts.show({ type: 'success' }, app.translator.trans('flarum-extension-manager.admin.update_successful'));
window.location.reload(); window.location.reload();
} }
}) })

View File

@@ -1,7 +1,7 @@
import QueueState from './QueueState'; import QueueState from './QueueState';
import ControlSectionState from './ControlSectionState'; import ControlSectionState from './ControlSectionState';
export default class PackageManagerState { export default class ExtensionManagerState {
public queue: QueueState = new QueueState(); public queue: QueueState = new QueueState();
public control: ControlSectionState = new ControlSectionState(); public control: ControlSectionState = new ControlSectionState();
} }

View File

@@ -20,7 +20,7 @@ export default class QueueState {
...params, ...params,
}; };
return app.store.find<Task[]>('package-manager-tasks', params || {}).then((data) => { return app.store.find<Task[]>('extension-manager-tasks', params || {}).then((data) => {
this.tasks = data; this.tasks = data;
this.total = data.payload.meta?.total; this.total = data.payload.meta?.total;
@@ -32,10 +32,12 @@ export default class QueueState {
if (pendingTask) { if (pendingTask) {
this.pollQueue(actionTaken); this.pollQueue(actionTaken);
} else if (actionTaken) { } else if (actionTaken) {
app.packageManager.control.setLoading(null); app.extensionManager.control.setLoading(null);
// Refresh the page // Refresh the page
window.location.reload(); window.location.reload();
} else if (app.extensionManager.control.isLoading()) {
app.extensionManager.control.setLoading(null);
} }
return data; return data;
@@ -85,4 +87,8 @@ export default class QueueState {
this.load({}, actionTaken); this.load({}, actionTaken);
}, 6000); }, 6000);
} }
hasPending() {
return !!this.tasks?.find((task) => task.status() === 'pending' || task.status() === 'running');
}
} }

View File

@@ -1,7 +1,7 @@
import app from 'flarum/admin/app'; import app from 'flarum/admin/app';
export default function (e: any) { export default function (e: any) {
app.packageManager.control.setLoading(null); app.extensionManager.control.setLoading(null);
const error = e.response.errors[0]; const error = e.response.errors[0];
@@ -14,20 +14,20 @@ export default function (e: any) {
switch (error.code) { switch (error.code) {
case 'composer_command_failure': case 'composer_command_failure':
if (error.guessed_cause) { if (error.guessed_cause) {
app.alerts.show({ type: 'error' }, app.translator.trans(`flarum-package-manager.admin.exceptions.guessed_cause.${error.guessed_cause}`)); app.alerts.show({ type: 'error' }, app.translator.trans(`flarum-extension-manager.admin.exceptions.guessed_cause.${error.guessed_cause}`));
app.modal.close(); app.modal.close();
} else { } else {
app.alerts.show({ type: 'error' }, app.translator.trans('flarum-package-manager.admin.exceptions.composer_command_failure')); app.alerts.show({ type: 'error' }, app.translator.trans('flarum-extension-manager.admin.exceptions.composer_command_failure'));
} }
break; break;
case 'extension_already_installed': case 'extension_already_installed':
app.alerts.show({ type: 'error' }, app.translator.trans('flarum-package-manager.admin.exceptions.extension_already_installed')); app.alerts.show({ type: 'error' }, app.translator.trans('flarum-extension-manager.admin.exceptions.extension_already_installed'));
app.modal.close(); app.modal.close();
break; break;
case 'extension_not_installed': case 'extension_not_installed':
app.alerts.show({ type: 'error' }, app.translator.trans('flarum-package-manager.admin.exceptions.extension_not_installed')); app.alerts.show({ type: 'error' }, app.translator.trans('flarum-extension-manager.admin.exceptions.extension_not_installed'));
app.modal.close(); app.modal.close();
} }
} }

View File

@@ -6,11 +6,11 @@ window.jumpToQueue = jumpToQueue;
export default function jumpToQueue(): void { export default function jumpToQueue(): void {
app.modal.close(); app.modal.close();
m.route.set(app.route('extension', { id: 'flarum-package-manager' })); m.route.set(app.route('extension', { id: 'flarum-extension-manager' }));
app.packageManager.queue.load({}, true); app.extensionManager.queue.load({}, true);
setTimeout(() => { setTimeout(() => {
document.getElementById('PackageManager-queueSection')?.scrollIntoView({ block: 'nearest' }); document.getElementById('ExtensionManager-queueSection')?.scrollIntoView({ block: 'nearest' });
}, 200); }, 200);
} }

View File

@@ -10,7 +10,8 @@
// This will output typings to `dist-typings` // This will output typings to `dist-typings`
"declarationDir": "./dist-typings", "declarationDir": "./dist-typings",
"paths": { "paths": {
"flarum/*": ["../../../framework/core/js/dist-typings/*"] "flarum/*": ["../../../framework/core/js/dist-typings/*"],
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
} }
} }
} }

View File

@@ -3,7 +3,7 @@
@import "admin/QueueSection"; @import "admin/QueueSection";
@import "admin/ControlSection"; @import "admin/ControlSection";
.PackageManager-controlSection { .ExtensionManager-controlSection {
> .container { > .container {
padding-bottom: 0; padding-bottom: 0;
} }
@@ -53,6 +53,52 @@
} }
} }
.flarum-package-manager-Page .SettingsGroups .Form { .flarum-extension-manager-Page .SettingsGroups .Form {
max-height: unset; max-height: unset;
} }
.ExtensionManager-SettingsGroups {
display: flex;
column-count: 3;
column-gap: 30px;
flex-wrap: wrap;
.Form {
min-width: 300px;
max-height: 500px;
display: inline-grid;
padding: 10px 20px;
min-height: 20vh;
max-width: 400px;
grid-template-rows: min-content;
border: 1px solid var(--control-bg);
border-radius: var(--border-radius);
flex: 1 1 160px;
>label {
margin-bottom: 10px;
}
@media (max-width: 1209px) {
margin-bottom: 20px;
}
>ol {
>li {
margin-top: 8px;
.Button {
float: right;
visibility: hidden;
margin: -8px -16px -8px 16px;
}
}
}
>label {
float: left;
font-weight: bold;
color: var(--muted-color);
}
}
}

View File

@@ -1,4 +1,4 @@
.PackageManager-lastUpdatedAt { .ExtensionManager-lastUpdatedAt {
color: var(--control-color); color: var(--control-color);
&-label { &-label {
@@ -6,7 +6,7 @@
} }
} }
.PackageManager-updaterControls { .ExtensionManager-updaterControls {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 8px; gap: 8px;
@@ -14,7 +14,7 @@
margin-bottom: 16px; margin-bottom: 16px;
} }
.PackageManager-extensions { .ExtensionManager-extensions {
width: 100%; width: 100%;
&-grid { &-grid {
@@ -25,7 +25,7 @@
} }
} }
.PackageManager-extension { .ExtensionManager-extension {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
@@ -81,7 +81,7 @@
} }
} }
.PackageManager-majorUpdate { .ExtensionManager-majorUpdate {
--space: 16px; --space: 16px;
padding: var(--space); padding: var(--space);
display: grid; display: grid;
@@ -142,7 +142,7 @@
border-top: 1px solid var(--control-bg); border-top: 1px solid var(--control-bg);
} }
.PackageManager-updaterControls { .ExtensionManager-updaterControls {
margin: 0; margin: 0;
} }
} }
@@ -153,7 +153,7 @@
} }
} }
.PackageManager-installer .FormControl-container { .ExtensionManager-installer .FormControl-container {
max-width: 450px; max-width: 450px;
.FormControl { .FormControl {
@@ -161,11 +161,11 @@
} }
} }
.PackageManager-controlSection .container { .ExtensionManager-controlSection .container {
max-width: 1030px; max-width: 1030px;
overflow: visible; overflow: visible;
} }
.PackageManager-primaryWarning ul { .ExtensionManager-primaryWarning ul {
margin: 0; margin: 0;
} }

View File

@@ -1,4 +1,4 @@
.PackageManager-queueSection { .ExtensionManager-queueSection {
&-header > .container { &-header > .container {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@@ -26,7 +26,7 @@
} }
} }
.PackageManager-queueTable { .ExtensionManager-queueTable {
&-package { &-package {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -1,4 +1,4 @@
flarum-package-manager: flarum-extension-manager:
admin: admin:
auth_config: auth_config:
add_label: New authentication method add_label: New authentication method
@@ -81,7 +81,7 @@ flarum-package-manager:
update_hard_label: Hard update update_hard_label: Hard update
file_permissions: > file_permissions: >
The package manager requires read and write permissions on the following files and directories: composer.json, composer.lock, vendor, storage, storage/.composer The extension manager requires read and write permissions on the following files and directories: composer.json, composer.lock, vendor, storage, storage/.composer
major_updater: major_updater:
description: > description: >
@@ -136,8 +136,8 @@ flarum-package-manager:
settings: settings:
title: => core.ref.settings title: => core.ref.settings
access_warning: Please be careful to who you give access to the admin area, the package manager could be misused by bad actors to install packages that can lead to security breaches. access_warning: Please be careful to who you give access to the admin area, the extension manager could be misused by bad actors to install packages that can lead to security breaches.
debug_mode_warning: You are running in debug mode, the package manager cannot properly install and update local development packages. Please use the command line interface instead for such purposes. debug_mode_warning: You are running in debug mode, the extension manager cannot properly install and update local development packages. Please use the command line interface instead for such purposes.
queue_jobs: Run operations in the background queue queue_jobs: Run operations in the background queue
queue_jobs_help: > queue_jobs_help: >
You can read about a <a href='{basic_impl_link}'>basic queue</a> implementation or a <a href='{adv_impl_link}'>more advanced</a> one. You can read about a <a href='{basic_impl_link}'>basic queue</a> implementation or a <a href='{adv_impl_link}'>more advanced</a> one.

View File

@@ -10,7 +10,7 @@
use Flarum\Database\Migration; use Flarum\Database\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
return Migration::createTable( return Migration::createTableIfNotExists(
'package_manager_tasks', 'package_manager_tasks',
function (Blueprint $table) { function (Blueprint $table) {
$table->increments('id'); $table->increments('id');

View File

@@ -7,8 +7,22 @@
* LICENSE file that was distributed with this source code. * LICENSE file that was distributed with this source code.
*/ */
use Flarum\Database\Migration; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
return Migration::addColumns('package_manager_tasks', [ return [
'guessed_cause' => ['type' => 'string', 'length' => 255, 'nullable' => true, 'after' => 'output'], 'up' => function (Builder $schema) {
]); $schema->table('package_manager_tasks', function (Blueprint $table) use ($schema) {
if (! $schema->hasColumn('package_manager_tasks', 'guessed_cause')) {
$table->string('guessed_cause', 255)->nullable()->after('output');
}
});
},
'down' => function (Builder $schema) {
$schema->table('package_manager_tasks', function (Blueprint $table) use ($schema) {
if ($schema->hasColumn('package_manager_tasks', 'guessed_cause')) {
$table->dropColumn('guessed_cause');
}
});
}
];

View File

@@ -0,0 +1,23 @@
<?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.
*/
use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
$schema->rename('package_manager_tasks', 'extension_manager_tasks');
$schema->getConnection()->table('migrations')->where('extension', 'flarum-package-manager')->delete();
},
'down' => function (Builder $schema) {
$schema->rename('extension_manager_tasks', 'package_manager_tasks');
$schema->getConnection()->table('migrations')->where('extension', 'flarum-extension-manager')->update([
'extension' => 'flarum-package-manager',
]);
}
];

View File

@@ -0,0 +1,29 @@
<?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\ExtensionManager;
/**
* @todo: fix in 2.0
*/
trait AllValidatorRules
{
protected function makeValidator(array $attributes)
{
$rules = $this->getRules();
$validator = $this->validator->make($attributes, $rules, $this->getMessages());
foreach ($this->configuration as $callable) {
$callable($this, $validator);
}
return $validator;
}
}

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