mirror of
https://github.com/flarum/core.git
synced 2025-08-06 08:27:42 +02:00
feat: Code Splitting (#3860)
* feat: configure webpack to allow splitting chunks * feat: `JsDirectoryCompiler` and expose js assets URL * chore: support es2020 dynamic importing * feat: control which URL to fetch chunks from * feat: allow showing async modals & split 'LogInModal' * feat: split `SignUpModal` * feat: allow rendering async pages & split `UserSecurityPage` * fix: module might not be listed in chunk * feat: lazy load user pages * feat: track the chunk containing each module * chore: lightly warn * chore: split `Composer` * feat: add common frontend (for split common chunks) * fix: jsDoc typing imports should be ignored * feat: split `PostStream` `ForgotPasswordModal` and `EditUserModal` * fix: multiple inline async imports not picked up * chore: new `common` frontend assets only needs a jsdir compiler * feat: add revision hash to chunk import URL * fix: nothing to split for `admin` frontend yet * chore: cleanup registry API * chore: throw an error in debug mode if attempting to import a non-loaded module * feat: defer `extend` & `override` until after module registration * fix: plugin not picking up on all module sources * fix: must override default chunk loader function from webpack plugin * feat: split tags `TagDiscussionModal` and `TagSelectionModal` * fix: wrong export name * feat: import chunked modules from external packages * feat: extensions compatibility * feat: Router frontend extender async component * chore: clean JS output path (removes stale chunks) * fix: common chunks also need flushing * chore: flush backend stale chunks * Apply fixes from StyleCI * feat: loading alert when async page component is loading * chore: `yarn format` * chore: typings * chore: remove exception * Apply fixes from StyleCI * chore(infra): bundlewatch * chore(infra): bundlewatch split chunks * feat: split text editor * chore: tag typings * chore: bundlewatch * fix: windows paths * fix: wrong planned ext import format
This commit is contained in:
@@ -4,8 +4,6 @@ import { override, extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import Stream from 'flarum/common/utils/Stream';
|
||||
import ForumApplication from 'flarum/forum/ForumApplication';
|
||||
import Composer from 'flarum/forum/components/Composer';
|
||||
import PostStream from 'flarum/forum/components/PostStream';
|
||||
import ModalManager from 'flarum/common/components/ModalManager';
|
||||
import PostMeta from 'flarum/forum/components/PostMeta';
|
||||
|
||||
@@ -13,7 +11,7 @@ import DiscussionPage from 'flarum/forum/components/DiscussionPage';
|
||||
|
||||
extend(ForumApplication.prototype, 'mount', function () {
|
||||
if (m.route.param('hideFirstPost')) {
|
||||
extend(PostStream.prototype, 'view', (vdom) => {
|
||||
extend('flarum/forum/components/PostStream', 'view', (vdom) => {
|
||||
if (vdom.children[0].attrs['data-number'] === 1) {
|
||||
vdom.children.splice(0, 1);
|
||||
}
|
||||
@@ -42,7 +40,7 @@ const reposition = function () {
|
||||
};
|
||||
|
||||
extend(ModalManager.prototype, 'show', reposition);
|
||||
extend(Composer.prototype, 'show', reposition);
|
||||
extend('flarum/forum/components/Composer', 'show', reposition);
|
||||
|
||||
window.iFrameResizer = {
|
||||
readyCallback: function () {
|
||||
@@ -50,7 +48,7 @@ window.iFrameResizer = {
|
||||
},
|
||||
};
|
||||
|
||||
extend(PostStream.prototype, 'goToNumber', function (promise, number) {
|
||||
extend('flarum/forum/components/PostStream', 'goToNumber', function (promise, number) {
|
||||
if (number === 'reply' && 'parentIFrame' in window && app.composer.isFullScreen()) {
|
||||
const itemTop = this.$('.PostStream-item:last').offset().top;
|
||||
window.parentIFrame.scrollToOffset(0, itemTop);
|
||||
|
@@ -13,7 +13,8 @@ use s9e\TextFormatter\Configurator;
|
||||
return [
|
||||
(new Extend\Frontend('forum'))
|
||||
->js(__DIR__.'/js/dist/forum.js')
|
||||
->css(__DIR__.'/less/forum.less'),
|
||||
->css(__DIR__.'/less/forum.less')
|
||||
->jsDirectory(__DIR__.'/js/dist/forum'),
|
||||
|
||||
(new Extend\Formatter)
|
||||
->configure(function (Configurator $config) {
|
||||
|
@@ -1,7 +1,4 @@
|
||||
import emojiMap from 'simple-emoji-map';
|
||||
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import TextEditor from 'flarum/common/components/TextEditor';
|
||||
import TextEditorButton from 'flarum/common/components/TextEditorButton';
|
||||
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
|
||||
|
||||
@@ -10,11 +7,15 @@ import getEmojiIconCode from './helpers/getEmojiIconCode';
|
||||
import cdn from './cdn';
|
||||
|
||||
export default function addComposerAutocomplete() {
|
||||
const emojiKeys = Object.keys(emojiMap);
|
||||
const $container = $('<div class="ComposerBody-emojiDropdownContainer"></div>');
|
||||
const dropdown = new AutocompleteDropdown();
|
||||
let emojiMap = null;
|
||||
|
||||
extend(TextEditor.prototype, 'oncreate', function () {
|
||||
extend('flarum/common/components/TextEditor', 'oninit', function () {
|
||||
this._loaders.push(async () => await import('./emojiMap').then((m) => (emojiMap = m.default)));
|
||||
});
|
||||
|
||||
extend('flarum/common/components/TextEditor', 'onbuild', function () {
|
||||
const $editor = this.$('.TextEditor-editor').wrap('<div class="ComposerBody-emojiWrapper"></div>');
|
||||
|
||||
this.navigator = new KeyboardNavigatable();
|
||||
@@ -29,7 +30,9 @@ export default function addComposerAutocomplete() {
|
||||
$editor.after($container);
|
||||
});
|
||||
|
||||
extend(TextEditor.prototype, 'buildEditorParams', function (params) {
|
||||
extend('flarum/common/components/TextEditor', 'buildEditorParams', function (params) {
|
||||
const emojiKeys = Object.keys(emojiMap);
|
||||
|
||||
let relEmojiStart;
|
||||
let absEmojiStart;
|
||||
let typed;
|
||||
@@ -166,7 +169,7 @@ export default function addComposerAutocomplete() {
|
||||
});
|
||||
});
|
||||
|
||||
extend(TextEditor.prototype, 'toolbarItems', function (items) {
|
||||
extend('flarum/common/components/TextEditor', 'toolbarItems', function (items) {
|
||||
items.add(
|
||||
'emoji',
|
||||
<TextEditorButton onclick={() => this.attrs.composer.editor.insertAtCursor(' :')} icon="far fa-smile">
|
||||
|
3
extensions/emoji/js/src/forum/emojiMap.ts
Normal file
3
extensions/emoji/js/src/forum/emojiMap.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import emojiMap from 'simple-emoji-map';
|
||||
|
||||
export default emojiMap;
|
@@ -1,6 +1,5 @@
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||
|
||||
import addLikeAction from './addLikeAction';
|
||||
import addLikesList from './addLikesList';
|
||||
@@ -16,7 +15,7 @@ app.initializers.add('flarum-likes', () => {
|
||||
addLikesList();
|
||||
addLikesTabToUserProfile();
|
||||
|
||||
extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
|
||||
extend('flarum/forum/components/NotificationGrid', 'notificationTypes', function (items) {
|
||||
items.add('postLiked', {
|
||||
name: 'postLiked',
|
||||
icon: 'far fa-thumbs-up',
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||
|
||||
import DiscussionLockedNotification from './components/DiscussionLockedNotification';
|
||||
import addLockBadge from './addLockBadge';
|
||||
@@ -14,7 +13,7 @@ app.initializers.add('flarum-lock', () => {
|
||||
addLockBadge();
|
||||
addLockControl();
|
||||
|
||||
extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
|
||||
extend('flarum/forum/components/NotificationGrid', 'notificationTypes', function (items) {
|
||||
items.add('discussionLocked', {
|
||||
name: 'discussionLocked',
|
||||
icon: 'fas fa-lock',
|
||||
|
@@ -9,7 +9,6 @@
|
||||
|
||||
import app from 'flarum/common/app';
|
||||
import { extend, override } from 'flarum/common/extend';
|
||||
import TextEditor from 'flarum/common/components/TextEditor';
|
||||
import BasicEditorDriver from 'flarum/common/utils/BasicEditorDriver';
|
||||
import styleSelectedText from 'flarum/common/utils/styleSelectedText';
|
||||
|
||||
@@ -89,13 +88,9 @@ export function initialize(app) {
|
||||
items.add('italic', makeShortcut('italic', 'i', this));
|
||||
});
|
||||
|
||||
if (TextEditor.prototype.markdownToolbarItems) {
|
||||
override(TextEditor.prototype, 'markdownToolbarItems', markdownToolbarItems);
|
||||
} else {
|
||||
TextEditor.prototype.markdownToolbarItems = markdownToolbarItems;
|
||||
}
|
||||
override('flarum/common/components/TextEditor', 'markdownToolbarItems', markdownToolbarItems);
|
||||
|
||||
extend(TextEditor.prototype, 'toolbarItems', function (items) {
|
||||
extend('flarum/common/components/TextEditor', 'toolbarItems', function (items) {
|
||||
items.add(
|
||||
'markdown',
|
||||
<MarkdownToolbar for={this.textareaId} setShortcutHandler={(handler) => (shortcutHandler = handler)}>
|
||||
|
15
extensions/markdown/js/tsconfig.json
Normal file
15
extensions/markdown/js/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
// Use Flarum's tsconfig as a starting point
|
||||
"extends": "flarum-tsconfig",
|
||||
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||
// and also tells your Typescript server to read core's global typings for
|
||||
// access to `dayjs` and `$` in the global namespace.
|
||||
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||
"compilerOptions": {
|
||||
// This will output typings to `dist-typings`
|
||||
"declarationDir": "./dist-typings",
|
||||
"paths": {
|
||||
"flarum/*": ["../../../framework/core/js/dist-typings/*"]
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,5 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import TextEditor from 'flarum/common/components/TextEditor';
|
||||
import TextEditorButton from 'flarum/common/components/TextEditorButton';
|
||||
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
|
||||
|
||||
@@ -11,7 +10,7 @@ export default function addComposerAutocomplete() {
|
||||
const $container = $('<div class="ComposerBody-mentionsDropdownContainer"></div>');
|
||||
const dropdown = new AutocompleteDropdown();
|
||||
|
||||
extend(TextEditor.prototype, 'oncreate', function () {
|
||||
extend('flarum/common/components/TextEditor', 'onbuild', function () {
|
||||
const $editor = this.$('.TextEditor-editor').wrap('<div class="ComposerBody-mentionsWrapper"></div>');
|
||||
|
||||
this.navigator = new KeyboardNavigatable();
|
||||
@@ -26,7 +25,7 @@ export default function addComposerAutocomplete() {
|
||||
$editor.after($container);
|
||||
});
|
||||
|
||||
extend(TextEditor.prototype, 'buildEditorParams', function (params) {
|
||||
extend('flarum/common/components/TextEditor', 'buildEditorParams', function (params) {
|
||||
let relMentionStart;
|
||||
let absMentionStart;
|
||||
let matchTyped;
|
||||
@@ -128,7 +127,7 @@ export default function addComposerAutocomplete() {
|
||||
params.inputListeners.push(suggestionsInputListener);
|
||||
});
|
||||
|
||||
extend(TextEditor.prototype, 'toolbarItems', function (items) {
|
||||
extend('flarum/common/components/TextEditor', 'toolbarItems', function (items) {
|
||||
items.add(
|
||||
'mention',
|
||||
<TextEditorButton onclick={() => this.attrs.composer.editor.insertAtCursor(' @')} icon="fas fa-at">
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||
import { getPlainContent } from 'flarum/common/utils/string';
|
||||
import textContrastClass from 'flarum/common/helpers/textContrastClass';
|
||||
import Post from 'flarum/forum/components/Post';
|
||||
@@ -46,7 +45,7 @@ app.initializers.add('flarum-mentions', function () {
|
||||
app.notificationComponents.groupMentioned = GroupMentionedNotification;
|
||||
|
||||
// Add notification preferences.
|
||||
extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
|
||||
extend('flarum/forum/components/NotificationGrid', 'notificationTypes', function (items) {
|
||||
items.add('postMentioned', {
|
||||
name: 'postMentioned',
|
||||
icon: 'fas fa-reply',
|
||||
|
@@ -6,8 +6,6 @@ import usernameHelper from 'flarum/common/helpers/username';
|
||||
import avatar from 'flarum/common/helpers/avatar';
|
||||
import highlight from 'flarum/common/helpers/highlight';
|
||||
import { truncate } from 'flarum/common/utils/string';
|
||||
import ReplyComposer from 'flarum/forum/components/ReplyComposer';
|
||||
import EditPostComposer from 'flarum/forum/components/EditPostComposer';
|
||||
import getCleanDisplayName from '../utils/getCleanDisplayName';
|
||||
import type AtMentionFormat from './formats/AtMentionFormat';
|
||||
|
||||
@@ -23,7 +21,10 @@ export default class PostMention extends MentionableModel<Post, AtMentionFormat>
|
||||
* match any username characters that have been typed.
|
||||
*/
|
||||
initialResults(): Post[] {
|
||||
if (!app.composer.bodyMatches(ReplyComposer) && !app.composer.bodyMatches(EditPostComposer)) {
|
||||
const EditPostComposer = flarum.reg.checkModule('core', 'forum/components/EditPostComposer');
|
||||
const ReplyComposer = flarum.reg.checkModule('core', 'forum/components/ReplyComposer');
|
||||
|
||||
if ((!ReplyComposer || !app.composer.bodyMatches(ReplyComposer)) && (!EditPostComposer || !app.composer.bodyMatches(EditPostComposer))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import DiscussionControls from 'flarum/forum/utils/DiscussionControls';
|
||||
import EditPostComposer from 'flarum/forum/components/EditPostComposer';
|
||||
|
||||
export function insertMention(post, composer, quote) {
|
||||
return new Promise((resolve) => {
|
||||
@@ -27,7 +26,9 @@ export function insertMention(post, composer, quote) {
|
||||
}
|
||||
|
||||
export default function reply(post, quote) {
|
||||
if (app.composer.bodyMatches(EditPostComposer) && app.composer.body.attrs.post.discussion() === post.discussion()) {
|
||||
const EditPostComposer = flarum.reg.checkModule('core', 'forum/components/EditPostComposer');
|
||||
|
||||
if (EditPostComposer && app.composer.bodyMatches(EditPostComposer) && app.composer.body.attrs.post.discussion() === post.discussion()) {
|
||||
// If we're already editing a post in the discussion of post we're quoting,
|
||||
// insert the mention directly.
|
||||
return insertMention(post, app.composer, quote);
|
||||
|
@@ -1,9 +1,6 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import Button from 'flarum/common/components/Button';
|
||||
import EditUserModal from 'flarum/common/components/EditUserModal';
|
||||
import SignUpModal from 'flarum/forum/components/SignUpModal';
|
||||
import SettingsPage from 'flarum/forum/components/SettingsPage';
|
||||
import extractText from 'flarum/common/utils/extractText';
|
||||
import Stream from 'flarum/common/utils/Stream';
|
||||
import NickNameModal from './components/NicknameModal';
|
||||
@@ -11,7 +8,7 @@ import NickNameModal from './components/NicknameModal';
|
||||
export { default as extend } from './extend';
|
||||
|
||||
app.initializers.add('flarum/nicknames', () => {
|
||||
extend(SettingsPage.prototype, 'accountItems', function (items) {
|
||||
extend('flarum/forum/components/SettingsPage', 'accountItems', function (items) {
|
||||
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
|
||||
|
||||
if (this.user.canEditNickname()) {
|
||||
@@ -24,11 +21,11 @@ app.initializers.add('flarum/nicknames', () => {
|
||||
}
|
||||
});
|
||||
|
||||
extend(EditUserModal.prototype, 'oninit', function () {
|
||||
extend('flarum/common/components/EditUserModal', 'oninit', function () {
|
||||
this.nickname = Stream(this.attrs.user.displayName());
|
||||
});
|
||||
|
||||
extend(EditUserModal.prototype, 'fields', function (items) {
|
||||
extend('flarum/common/components/EditUserModal', 'fields', function (items) {
|
||||
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
|
||||
|
||||
if (!this.attrs.user.canEditNickname()) return;
|
||||
@@ -47,7 +44,7 @@ app.initializers.add('flarum/nicknames', () => {
|
||||
);
|
||||
});
|
||||
|
||||
extend(EditUserModal.prototype, 'data', function (data) {
|
||||
extend('flarum/common/components/EditUserModal', 'data', function (data) {
|
||||
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
|
||||
|
||||
if (!this.attrs.user.canEditNickname()) return;
|
||||
@@ -57,13 +54,13 @@ app.initializers.add('flarum/nicknames', () => {
|
||||
}
|
||||
});
|
||||
|
||||
extend(SignUpModal.prototype, 'oninit', function () {
|
||||
extend('flarum/forum/components/SignUpModal', 'oninit', function () {
|
||||
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
|
||||
|
||||
this.nickname = Stream(this.attrs.username || '');
|
||||
});
|
||||
|
||||
extend(SignUpModal.prototype, 'onready', function () {
|
||||
extend('flarum/forum/components/SignUpModal', 'onready', function () {
|
||||
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
|
||||
|
||||
if (app.forum.attribute('setNicknameOnRegistration') && app.forum.attribute('randomizeUsernameOnRegistration')) {
|
||||
@@ -71,7 +68,7 @@ app.initializers.add('flarum/nicknames', () => {
|
||||
}
|
||||
});
|
||||
|
||||
extend(SignUpModal.prototype, 'fields', function (items) {
|
||||
extend('flarum/forum/components/SignUpModal', 'fields', function (items) {
|
||||
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
|
||||
|
||||
if (app.forum.attribute('setNicknameOnRegistration')) {
|
||||
@@ -97,7 +94,7 @@ app.initializers.add('flarum/nicknames', () => {
|
||||
}
|
||||
});
|
||||
|
||||
extend(SignUpModal.prototype, 'submitData', function (data) {
|
||||
extend('flarum/forum/components/SignUpModal', 'submitData', function (data) {
|
||||
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
|
||||
|
||||
if (app.forum.attribute('setNicknameOnRegistration')) {
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import SettingsPage from 'flarum/forum/components/SettingsPage';
|
||||
import type SettingsPage from 'flarum/forum/components/SettingsPage';
|
||||
import Switch from 'flarum/common/components/Switch';
|
||||
|
||||
export default function () {
|
||||
extend(SettingsPage.prototype, 'notificationsItems', function (this: SettingsPage, items) {
|
||||
extend('flarum/forum/components/SettingsPage', 'notificationsItems', function (this: SettingsPage, items) {
|
||||
items.add(
|
||||
'followAfterReply',
|
||||
<Switch
|
||||
|
@@ -1,8 +1,5 @@
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import Model from 'flarum/common/Model';
|
||||
import Discussion from 'flarum/common/models/Discussion';
|
||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||
|
||||
import addSubscriptionBadge from './addSubscriptionBadge';
|
||||
import addSubscriptionControls from './addSubscriptionControls';
|
||||
@@ -21,7 +18,7 @@ app.initializers.add('subscriptions', function () {
|
||||
addSubscriptionFilter();
|
||||
addSubscriptionSettings();
|
||||
|
||||
extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
|
||||
extend('flarum/forum/components/NotificationGrid', 'notificationTypes', function (items) {
|
||||
items.add('newPost', {
|
||||
name: 'newPost',
|
||||
icon: 'fas fa-star',
|
||||
|
@@ -10,7 +10,7 @@
|
||||
"declarationDir": "./dist-typings",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"flarum/*": ["../vendor/flarum/core/js/dist-typings/*"]
|
||||
"flarum/*": ["../../../framework/core/js/dist-typings/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -48,10 +48,14 @@ $eagerLoadTagState = function ($query, ?ServerRequestInterface $request, array $
|
||||
return [
|
||||
(new Extend\Frontend('forum'))
|
||||
->js(__DIR__.'/js/dist/forum.js')
|
||||
->jsDirectory(__DIR__.'/js/dist/forum')
|
||||
->css(__DIR__.'/less/forum.less')
|
||||
->route('/t/{slug}', 'tag', Content\Tag::class)
|
||||
->route('/tags', 'tags', Content\Tags::class),
|
||||
|
||||
(new Extend\Frontend('common'))
|
||||
->jsDirectory(__DIR__.'/js/dist/common'),
|
||||
|
||||
(new Extend\Frontend('admin'))
|
||||
->js(__DIR__.'/js/dist/admin.js')
|
||||
->css(__DIR__.'/less/admin.less'),
|
||||
|
@@ -2,7 +2,6 @@ import app from 'flarum/admin/app';
|
||||
import Component from 'flarum/common/Component';
|
||||
import Button from 'flarum/common/components/Button';
|
||||
import LoadingIndicator from 'flarum/common/components/LoadingIndicator';
|
||||
import TagSelectionModal from '../../common/components/TagSelectionModal';
|
||||
import tagsLabel from '../../common/helpers/tagsLabel';
|
||||
|
||||
import type { CommonSettingsItemOptions } from 'flarum/admin/components/AdminPage';
|
||||
@@ -46,7 +45,7 @@ export default class SelectTagsSettingComponent<
|
||||
<Button
|
||||
className="Button Button--text"
|
||||
onclick={() =>
|
||||
app.modal.show(TagSelectionModal, {
|
||||
app.modal.show(() => import('../../common/components/TagSelectionModal'), {
|
||||
selectedTags: this.tags,
|
||||
onsubmit: (tags: Tag[]) => {
|
||||
this.tags = tags;
|
||||
|
@@ -6,6 +6,4 @@ import './helpers/tagsLabel';
|
||||
import './helpers/tagIcon';
|
||||
import './helpers/tagLabel';
|
||||
|
||||
import './components/TagSelectionModal';
|
||||
|
||||
import './states/TagListState';
|
||||
|
@@ -1,13 +1,11 @@
|
||||
import { extend, override } from 'flarum/common/extend';
|
||||
import IndexPage from 'flarum/forum/components/IndexPage';
|
||||
import DiscussionComposer from 'flarum/forum/components/DiscussionComposer';
|
||||
import classList from 'flarum/common/utils/classList';
|
||||
|
||||
import TagDiscussionModal from './components/TagDiscussionModal';
|
||||
import tagsLabel from '../common/helpers/tagsLabel';
|
||||
import getSelectableTags from './utils/getSelectableTags';
|
||||
|
||||
export default function () {
|
||||
export default function addTagComposer() {
|
||||
extend(IndexPage.prototype, 'newDiscussionAction', function (promise) {
|
||||
// From `addTagFilter
|
||||
const tag = this.currentTag();
|
||||
@@ -21,28 +19,28 @@ export default function () {
|
||||
}
|
||||
});
|
||||
|
||||
extend(DiscussionComposer.prototype, 'oninit', function () {
|
||||
extend('flarum/forum/components/DiscussionComposer', 'oninit', function () {
|
||||
app.tagList.load(['parent']).then(() => m.redraw());
|
||||
|
||||
// Add tag-selection abilities to the discussion composer.
|
||||
this.constructor.prototype.chooseTags = function () {
|
||||
const selectableTags = getSelectableTags();
|
||||
|
||||
if (!selectableTags.length) return;
|
||||
|
||||
app.modal.show(() => import('./components/TagDiscussionModal'), {
|
||||
selectedTags: (this.composer.fields.tags || []).slice(0),
|
||||
onsubmit: (tags) => {
|
||||
this.composer.fields.tags = tags;
|
||||
this.$('textarea').focus();
|
||||
},
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
// Add tag-selection abilities to the discussion composer.
|
||||
DiscussionComposer.prototype.chooseTags = function () {
|
||||
const selectableTags = getSelectableTags();
|
||||
|
||||
if (!selectableTags.length) return;
|
||||
|
||||
app.modal.show(TagDiscussionModal, {
|
||||
selectedTags: (this.composer.fields.tags || []).slice(0),
|
||||
onsubmit: (tags) => {
|
||||
this.composer.fields.tags = tags;
|
||||
this.$('textarea').focus();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Add a tag-selection menu to the discussion composer's header, after the
|
||||
// title.
|
||||
extend(DiscussionComposer.prototype, 'headerItems', function (items) {
|
||||
extend('flarum/forum/components/DiscussionComposer', 'headerItems', function (items) {
|
||||
const tags = this.composer.fields.tags || [];
|
||||
const selectableTags = getSelectableTags();
|
||||
|
||||
@@ -59,7 +57,7 @@ export default function () {
|
||||
);
|
||||
});
|
||||
|
||||
override(DiscussionComposer.prototype, 'onsubmit', function (original) {
|
||||
override('flarum/forum/components/DiscussionComposer', 'onsubmit', function (original) {
|
||||
const chosenTags = this.composer.fields.tags || [];
|
||||
const chosenPrimaryTags = chosenTags.filter((tag) => tag.position() !== null && !tag.isChild());
|
||||
const chosenSecondaryTags = chosenTags.filter((tag) => tag.position() === null);
|
||||
@@ -76,7 +74,7 @@ export default function () {
|
||||
chosenSecondaryTags.length < minSecondaryTags) &&
|
||||
selectableTags.length
|
||||
) {
|
||||
app.modal.show(TagDiscussionModal, {
|
||||
app.modal.show(() => import('./components/TagDiscussionModal'), {
|
||||
selectedTags: chosenTags,
|
||||
onsubmit: (tags) => {
|
||||
this.composer.fields.tags = tags;
|
||||
@@ -89,7 +87,7 @@ export default function () {
|
||||
});
|
||||
|
||||
// Add the selected tags as data to submit to the server.
|
||||
extend(DiscussionComposer.prototype, 'data', function (data) {
|
||||
extend('flarum/forum/components/DiscussionComposer', 'data', function (data) {
|
||||
data.relationships = data.relationships || {};
|
||||
data.relationships.tags = this.composer.fields.tags;
|
||||
});
|
||||
|
@@ -2,15 +2,13 @@ import { extend } from 'flarum/common/extend';
|
||||
import DiscussionControls from 'flarum/forum/utils/DiscussionControls';
|
||||
import Button from 'flarum/common/components/Button';
|
||||
|
||||
import TagDiscussionModal from './components/TagDiscussionModal';
|
||||
|
||||
export default function () {
|
||||
export default function addTagControl() {
|
||||
// Add a control allowing the discussion to be moved to another category.
|
||||
extend(DiscussionControls, 'moderationControls', function (items, discussion) {
|
||||
if (discussion.canTag()) {
|
||||
items.add(
|
||||
'tags',
|
||||
<Button icon="fas fa-tag" onclick={() => app.modal.show(TagDiscussionModal, { discussion })}>
|
||||
<Button icon="fas fa-tag" onclick={() => app.modal.show(() => import('./components/TagDiscussionModal'), { discussion })}>
|
||||
{app.translator.trans('flarum-tags.forum.discussion_controls.edit_tags_button')}
|
||||
</Button>
|
||||
);
|
||||
|
@@ -13,7 +13,7 @@ import { ComponentAttrs } from 'flarum/common/Component';
|
||||
|
||||
const findTag = (slug: string) => app.store.all<Tag>('tags').find((tag) => tag.slug().localeCompare(slug, undefined, { sensitivity: 'base' }) === 0);
|
||||
|
||||
export default function () {
|
||||
export default function addTagFilter() {
|
||||
IndexPage.prototype.currentTag = function () {
|
||||
if (this.currentActiveTag) {
|
||||
return this.currentActiveTag;
|
||||
|
@@ -7,7 +7,7 @@ import classList from 'flarum/common/utils/classList';
|
||||
import tagsLabel from '../common/helpers/tagsLabel';
|
||||
import sortTags from '../common/utils/sortTags';
|
||||
|
||||
export default function () {
|
||||
export default function addTagLabels() {
|
||||
// Add tag labels to each discussion in the discussion list.
|
||||
extend(DiscussionListItem.prototype, 'infoItems', function (items) {
|
||||
const tags = this.attrs.discussion.tags();
|
||||
|
@@ -8,7 +8,7 @@ import TagsPage from './components/TagsPage';
|
||||
import app from 'flarum/forum/app';
|
||||
import sortTags from '../common/utils/sortTags';
|
||||
|
||||
export default function () {
|
||||
export default function addTagList() {
|
||||
// Add a link to the tags page, as well as a list of all the tags,
|
||||
// to the index page's sidebar.
|
||||
extend(IndexPage.prototype, 'navItems', function (items) {
|
||||
|
@@ -36,7 +36,7 @@ export default class TagDiscussionModal extends TagSelectionModal<TagDiscussionM
|
||||
},
|
||||
};
|
||||
attrs.requireParentTag = true;
|
||||
attrs.selectableTags = () => getSelectableTags(attrs.discussion);
|
||||
attrs.selectableTags = () => getSelectableTags(attrs.discussion!);
|
||||
attrs.selectedTags ??= (attrs.discussion?.tags() as Tag[]) || [];
|
||||
attrs.canSelect = (tag) => tag.canStartDiscussion();
|
||||
|
||||
|
@@ -3,7 +3,6 @@ import '../common/common';
|
||||
import './utils/getSelectableTags';
|
||||
|
||||
import './components/TagHero';
|
||||
import './components/TagDiscussionModal';
|
||||
import './components/TagsPage';
|
||||
import './components/DiscussionTaggedPost';
|
||||
import './components/TagLinkButton';
|
||||
|
@@ -1,11 +0,0 @@
|
||||
export default function getSelectableTags(discussion) {
|
||||
let tags = app.store.all('tags');
|
||||
|
||||
if (discussion) {
|
||||
tags = tags.filter((tag) => tag.canAddToDiscussion() || discussion.tags().indexOf(tag) !== -1);
|
||||
} else {
|
||||
tags = tags.filter((tag) => tag.canStartDiscussion());
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
15
extensions/tags/js/src/forum/utils/getSelectableTags.ts
Normal file
15
extensions/tags/js/src/forum/utils/getSelectableTags.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type Tag from '../../common/models/Tag';
|
||||
import type Discussion from 'flarum/common/models/Discussion';
|
||||
|
||||
export default function getSelectableTags(discussion: Discussion) {
|
||||
let tags = app.store.all<Tag>('tags');
|
||||
|
||||
if (discussion) {
|
||||
const discussionTags = discussion.tags() || [];
|
||||
tags = tags.filter((tag) => tag.canAddToDiscussion() || discussionTags.includes(tag));
|
||||
} else {
|
||||
tags = tags.filter((tag) => tag.canStartDiscussion());
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
Reference in New Issue
Block a user