mirror of
https://github.com/flarum/framework.git
synced 2025-04-25 06:04:04 +08:00
feat: introduce frontend extenders (#3645)
* feat: reintroduce frontend extenders * chore: used `Routes` extender in bundled extensions * chore: used `PostTypes` extender in bundled extensions * chore: `yarn format` * chore: naming * chore(review): unnecessary check * chore(review): stay consistent * chore: unused import Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
This commit is contained in:
parent
5fe3cfd837
commit
d7f4975330
4
extensions/flags/js/src/forum/extend.ts
Normal file
4
extensions/flags/js/src/forum/extend.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Extend from 'flarum/common/extenders';
|
||||||
|
import FlagsPage from './components/FlagsPage';
|
||||||
|
|
||||||
|
export default [new Extend.Routes().add('flags', '/flags', FlagsPage)];
|
@ -8,14 +8,14 @@ import addFlagControl from './addFlagControl';
|
|||||||
import addFlagsDropdown from './addFlagsDropdown';
|
import addFlagsDropdown from './addFlagsDropdown';
|
||||||
import addFlagsToPosts from './addFlagsToPosts';
|
import addFlagsToPosts from './addFlagsToPosts';
|
||||||
|
|
||||||
|
export { default as extend } from './extend';
|
||||||
|
|
||||||
app.initializers.add('flarum-flags', () => {
|
app.initializers.add('flarum-flags', () => {
|
||||||
Post.prototype.flags = Model.hasMany<Flag>('flags');
|
Post.prototype.flags = Model.hasMany<Flag>('flags');
|
||||||
Post.prototype.canFlag = Model.attribute<boolean>('canFlag');
|
Post.prototype.canFlag = Model.attribute<boolean>('canFlag');
|
||||||
|
|
||||||
app.store.models.flags = Flag;
|
app.store.models.flags = Flag;
|
||||||
|
|
||||||
app.routes.flags = { path: '/flags', component: FlagsPage };
|
|
||||||
|
|
||||||
app.flags = new FlagListState(app);
|
app.flags = new FlagListState(app);
|
||||||
|
|
||||||
addFlagControl();
|
addFlagControl();
|
||||||
|
@ -2,17 +2,15 @@ import { extend } from 'flarum/common/extend';
|
|||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import UserPage from 'flarum/forum/components/UserPage';
|
import UserPage from 'flarum/forum/components/UserPage';
|
||||||
import LinkButton from 'flarum/common/components/LinkButton';
|
import LinkButton from 'flarum/common/components/LinkButton';
|
||||||
import LikesUserPage from './components/LikesUserPage';
|
|
||||||
import ItemList from 'flarum/common/utils/ItemList';
|
import ItemList from 'flarum/common/utils/ItemList';
|
||||||
import type Mithril from 'mithril';
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
export default function addLikesTabToUserProfile() {
|
export default function addLikesTabToUserProfile() {
|
||||||
app.routes['user.likes'] = { path: '/u/:username/likes', component: LikesUserPage };
|
|
||||||
extend(UserPage.prototype, 'navItems', function (items: ItemList<Mithril.Children>) {
|
extend(UserPage.prototype, 'navItems', function (items: ItemList<Mithril.Children>) {
|
||||||
const user = this.user;
|
const user = this.user;
|
||||||
items.add(
|
items.add(
|
||||||
'likes',
|
'likes',
|
||||||
<LinkButton href={app.route('user.likes', { username: user.slug() })} icon="far fa-thumbs-up">
|
<LinkButton href={app.route('user.likes', { username: user?.slug() })} icon="far fa-thumbs-up">
|
||||||
{app.translator.trans('flarum-likes.forum.user.likes_link')}
|
{app.translator.trans('flarum-likes.forum.user.likes_link')}
|
||||||
</LinkButton>,
|
</LinkButton>,
|
||||||
88
|
88
|
||||||
|
4
extensions/likes/js/src/forum/extend.ts
Normal file
4
extensions/likes/js/src/forum/extend.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Extend from 'flarum/common/extenders';
|
||||||
|
import LikesUserPage from './components/LikesUserPage';
|
||||||
|
|
||||||
|
export default [new Extend.Routes().add('user.likes', '/u/:username/likes', LikesUserPage)];
|
@ -9,6 +9,8 @@ import addLikesList from './addLikesList';
|
|||||||
import PostLikedNotification from './components/PostLikedNotification';
|
import PostLikedNotification from './components/PostLikedNotification';
|
||||||
import addLikesTabToUserProfile from './addLikesTabToUserProfile';
|
import addLikesTabToUserProfile from './addLikesTabToUserProfile';
|
||||||
|
|
||||||
|
export { default as extend } from './extend';
|
||||||
|
|
||||||
app.initializers.add('flarum-likes', () => {
|
app.initializers.add('flarum-likes', () => {
|
||||||
app.notificationComponents.postLiked = PostLikedNotification;
|
app.notificationComponents.postLiked = PostLikedNotification;
|
||||||
|
|
||||||
|
20
extensions/likes/js/tsconfig.json
Normal file
20
extensions/likes/js/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// Use Flarum's tsconfig as a starting point
|
||||||
|
"extends": "flarum-tsconfig",
|
||||||
|
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||||
|
// and also tells your Typescript server to read core's global typings for
|
||||||
|
// access to `dayjs` and `$` in the global namespace.
|
||||||
|
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
// This will output typings to `dist-typings`
|
||||||
|
"declarationDir": "./dist-typings",
|
||||||
|
"paths": {
|
||||||
|
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
// TODO: remove after export registry system implemented
|
||||||
|
// Without this, the old-style `@flarum/core` import is resolved to
|
||||||
|
// source code in flarum/core instead of the dist typings.
|
||||||
|
// This causes an inaccurate "duplicate export" error.
|
||||||
|
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
extensions/lock/js/src/forum/extend.ts
Normal file
4
extensions/lock/js/src/forum/extend.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Extend from 'flarum/common/extenders';
|
||||||
|
import DiscussionLockedPost from './components/DiscussionLockedPost';
|
||||||
|
|
||||||
|
export default [new Extend.PostTypes().add('discussionLocked', DiscussionLockedPost)];
|
@ -4,13 +4,13 @@ import Model from 'flarum/common/Model';
|
|||||||
import Discussion from 'flarum/common/models/Discussion';
|
import Discussion from 'flarum/common/models/Discussion';
|
||||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||||
|
|
||||||
import DiscussionLockedPost from './components/DiscussionLockedPost';
|
|
||||||
import DiscussionLockedNotification from './components/DiscussionLockedNotification';
|
import DiscussionLockedNotification from './components/DiscussionLockedNotification';
|
||||||
import addLockBadge from './addLockBadge';
|
import addLockBadge from './addLockBadge';
|
||||||
import addLockControl from './addLockControl';
|
import addLockControl from './addLockControl';
|
||||||
|
|
||||||
|
export { default as extend } from './extend';
|
||||||
|
|
||||||
app.initializers.add('flarum-lock', () => {
|
app.initializers.add('flarum-lock', () => {
|
||||||
app.postComponents.discussionLocked = DiscussionLockedPost;
|
|
||||||
app.notificationComponents.discussionLocked = DiscussionLockedNotification;
|
app.notificationComponents.discussionLocked = DiscussionLockedNotification;
|
||||||
|
|
||||||
Discussion.prototype.isLocked = Model.attribute('isLocked');
|
Discussion.prototype.isLocked = Model.attribute('isLocked');
|
||||||
|
20
extensions/lock/js/tsconfig.json
Normal file
20
extensions/lock/js/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// Use Flarum's tsconfig as a starting point
|
||||||
|
"extends": "flarum-tsconfig",
|
||||||
|
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||||
|
// and also tells your Typescript server to read core's global typings for
|
||||||
|
// access to `dayjs` and `$` in the global namespace.
|
||||||
|
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
// This will output typings to `dist-typings`
|
||||||
|
"declarationDir": "./dist-typings",
|
||||||
|
"paths": {
|
||||||
|
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
// TODO: remove after export registry system implemented
|
||||||
|
// Without this, the old-style `@flarum/core` import is resolved to
|
||||||
|
// source code in flarum/core instead of the dist typings.
|
||||||
|
// This causes an inaccurate "duplicate export" error.
|
||||||
|
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
extensions/mentions/js/src/forum/extend.ts
Normal file
4
extensions/mentions/js/src/forum/extend.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Extend from 'flarum/common/extenders';
|
||||||
|
import MentionsUserPage from './components/MentionsUserPage';
|
||||||
|
|
||||||
|
export default [new Extend.Routes().add('user.mentions', '/u/:username/mentions', MentionsUserPage)];
|
@ -13,10 +13,11 @@ import UserMentionedNotification from './components/UserMentionedNotification';
|
|||||||
import GroupMentionedNotification from './components/GroupMentionedNotification';
|
import GroupMentionedNotification from './components/GroupMentionedNotification';
|
||||||
import UserPage from 'flarum/forum/components/UserPage';
|
import UserPage from 'flarum/forum/components/UserPage';
|
||||||
import LinkButton from 'flarum/common/components/LinkButton';
|
import LinkButton from 'flarum/common/components/LinkButton';
|
||||||
import MentionsUserPage from './components/MentionsUserPage';
|
|
||||||
import User from 'flarum/common/models/User';
|
import User from 'flarum/common/models/User';
|
||||||
import Model from 'flarum/common/Model';
|
import Model from 'flarum/common/Model';
|
||||||
|
|
||||||
|
export { default as extend } from './extend';
|
||||||
|
|
||||||
app.initializers.add('flarum-mentions', function () {
|
app.initializers.add('flarum-mentions', function () {
|
||||||
User.prototype.canMentionGroups = Model.attribute('canMentionGroups');
|
User.prototype.canMentionGroups = Model.attribute('canMentionGroups');
|
||||||
|
|
||||||
@ -65,7 +66,6 @@ app.initializers.add('flarum-mentions', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add mentions tab in user profile
|
// Add mentions tab in user profile
|
||||||
app.routes['user.mentions'] = { path: '/u/:username/mentions', component: MentionsUserPage };
|
|
||||||
extend(UserPage.prototype, 'navItems', function (items) {
|
extend(UserPage.prototype, 'navItems', function (items) {
|
||||||
const user = this.user;
|
const user = this.user;
|
||||||
items.add(
|
items.add(
|
||||||
|
20
extensions/mentions/js/tsconfig.json
Normal file
20
extensions/mentions/js/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// Use Flarum's tsconfig as a starting point
|
||||||
|
"extends": "flarum-tsconfig",
|
||||||
|
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||||
|
// and also tells your Typescript server to read core's global typings for
|
||||||
|
// access to `dayjs` and `$` in the global namespace.
|
||||||
|
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
// This will output typings to `dist-typings`
|
||||||
|
"declarationDir": "./dist-typings",
|
||||||
|
"paths": {
|
||||||
|
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
// TODO: remove after export registry system implemented
|
||||||
|
// Without this, the old-style `@flarum/core` import is resolved to
|
||||||
|
// source code in flarum/core instead of the dist typings.
|
||||||
|
// This causes an inaccurate "duplicate export" error.
|
||||||
|
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
extensions/sticky/js/src/forum/extend.ts
Normal file
4
extensions/sticky/js/src/forum/extend.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Extend from 'flarum/common/extenders';
|
||||||
|
import DiscussionStickiedPost from './components/DiscussionStickiedPost';
|
||||||
|
|
||||||
|
export default [new Extend.PostTypes().add('discussionStickied', DiscussionStickiedPost)];
|
@ -2,15 +2,14 @@ import app from 'flarum/forum/app';
|
|||||||
import Model from 'flarum/common/Model';
|
import Model from 'flarum/common/Model';
|
||||||
import Discussion from 'flarum/common/models/Discussion';
|
import Discussion from 'flarum/common/models/Discussion';
|
||||||
|
|
||||||
import DiscussionStickiedPost from './components/DiscussionStickiedPost';
|
|
||||||
import addStickyBadge from './addStickyBadge';
|
import addStickyBadge from './addStickyBadge';
|
||||||
import addStickyControl from './addStickyControl';
|
import addStickyControl from './addStickyControl';
|
||||||
import addStickyExcerpt from './addStickyExcerpt';
|
import addStickyExcerpt from './addStickyExcerpt';
|
||||||
import addStickyClass from './addStickyClass';
|
import addStickyClass from './addStickyClass';
|
||||||
|
|
||||||
app.initializers.add('flarum-sticky', () => {
|
export { default as extend } from './extend';
|
||||||
app.postComponents.discussionStickied = DiscussionStickiedPost;
|
|
||||||
|
|
||||||
|
app.initializers.add('flarum-sticky', () => {
|
||||||
Discussion.prototype.isSticky = Model.attribute('isSticky');
|
Discussion.prototype.isSticky = Model.attribute('isSticky');
|
||||||
Discussion.prototype.canSticky = Model.attribute('canSticky');
|
Discussion.prototype.canSticky = Model.attribute('canSticky');
|
||||||
|
|
||||||
|
20
extensions/sticky/js/tsconfig.json
Normal file
20
extensions/sticky/js/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// Use Flarum's tsconfig as a starting point
|
||||||
|
"extends": "flarum-tsconfig",
|
||||||
|
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||||
|
// and also tells your Typescript server to read core's global typings for
|
||||||
|
// access to `dayjs` and `$` in the global namespace.
|
||||||
|
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
// This will output typings to `dist-typings`
|
||||||
|
"declarationDir": "./dist-typings",
|
||||||
|
"paths": {
|
||||||
|
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
// TODO: remove after export registry system implemented
|
||||||
|
// Without this, the old-style `@flarum/core` import is resolved to
|
||||||
|
// source code in flarum/core instead of the dist typings.
|
||||||
|
// This causes an inaccurate "duplicate export" error.
|
||||||
|
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
extensions/subscriptions/js/src/forum/extend.ts
Normal file
4
extensions/subscriptions/js/src/forum/extend.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Extend from 'flarum/common/extenders';
|
||||||
|
import IndexPage from 'flarum/forum/components/IndexPage';
|
||||||
|
|
||||||
|
export default [new Extend.Routes().add('following', '/following', IndexPage)];
|
@ -2,7 +2,6 @@ import { extend } from 'flarum/common/extend';
|
|||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import Model from 'flarum/common/Model';
|
import Model from 'flarum/common/Model';
|
||||||
import Discussion from 'flarum/common/models/Discussion';
|
import Discussion from 'flarum/common/models/Discussion';
|
||||||
import IndexPage from 'flarum/forum/components/IndexPage';
|
|
||||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||||
|
|
||||||
import addSubscriptionBadge from './addSubscriptionBadge';
|
import addSubscriptionBadge from './addSubscriptionBadge';
|
||||||
@ -12,8 +11,9 @@ import addSubscriptionSettings from './addSubscriptionSettings';
|
|||||||
|
|
||||||
import NewPostNotification from './components/NewPostNotification';
|
import NewPostNotification from './components/NewPostNotification';
|
||||||
|
|
||||||
|
export { default as extend } from './extend';
|
||||||
|
|
||||||
app.initializers.add('subscriptions', function () {
|
app.initializers.add('subscriptions', function () {
|
||||||
app.routes.following = { path: '/following', component: IndexPage };
|
|
||||||
app.notificationComponents.newPost = NewPostNotification;
|
app.notificationComponents.newPost = NewPostNotification;
|
||||||
|
|
||||||
Discussion.prototype.subscription = Model.attribute('subscription');
|
Discussion.prototype.subscription = Model.attribute('subscription');
|
||||||
|
14
extensions/tags/js/src/forum/extend.ts
Normal file
14
extensions/tags/js/src/forum/extend.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import app from 'flarum/forum/app';
|
||||||
|
import Extend from 'flarum/common/extenders';
|
||||||
|
import IndexPage from 'flarum/forum/components/IndexPage';
|
||||||
|
import DiscussionTaggedPost from './components/DiscussionTaggedPost';
|
||||||
|
import TagsPage from './components/TagsPage';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
new Extend.Routes()
|
||||||
|
.add('tags', '/tags', TagsPage)
|
||||||
|
.add('tag', '/t/:tags', IndexPage)
|
||||||
|
.helper('tag', (tag) => app.route('tag', { tags: tag.slug() })),
|
||||||
|
|
||||||
|
new Extend.PostTypes().add('discussionTagged', DiscussionTaggedPost),
|
||||||
|
];
|
@ -1,12 +1,9 @@
|
|||||||
import app from 'flarum/forum/app';
|
import app from 'flarum/forum/app';
|
||||||
import Model from 'flarum/common/Model';
|
import Model from 'flarum/common/Model';
|
||||||
import Discussion from 'flarum/common/models/Discussion';
|
import Discussion from 'flarum/common/models/Discussion';
|
||||||
import IndexPage from 'flarum/forum/components/IndexPage';
|
|
||||||
|
|
||||||
import TagListState from '../common/states/TagListState';
|
import TagListState from '../common/states/TagListState';
|
||||||
import Tag from '../common/models/Tag';
|
import Tag from '../common/models/Tag';
|
||||||
import TagsPage from './components/TagsPage';
|
|
||||||
import DiscussionTaggedPost from './components/DiscussionTaggedPost';
|
|
||||||
|
|
||||||
import addTagList from './addTagList';
|
import addTagList from './addTagList';
|
||||||
import addTagFilter from './addTagFilter';
|
import addTagFilter from './addTagFilter';
|
||||||
@ -14,14 +11,9 @@ import addTagLabels from './addTagLabels';
|
|||||||
import addTagControl from './addTagControl';
|
import addTagControl from './addTagControl';
|
||||||
import addTagComposer from './addTagComposer';
|
import addTagComposer from './addTagComposer';
|
||||||
|
|
||||||
|
export { default as extend } from './extend';
|
||||||
|
|
||||||
app.initializers.add('flarum-tags', function () {
|
app.initializers.add('flarum-tags', function () {
|
||||||
app.routes.tags = { path: '/tags', component: TagsPage };
|
|
||||||
app.routes.tag = { path: '/t/:tags', component: IndexPage };
|
|
||||||
|
|
||||||
app.route.tag = (tag: Tag) => app.route('tag', { tags: tag.slug() });
|
|
||||||
|
|
||||||
app.postComponents.discussionTagged = DiscussionTaggedPost;
|
|
||||||
|
|
||||||
app.store.models.tags = Tag;
|
app.store.models.tags = Tag;
|
||||||
|
|
||||||
app.tagList = new TagListState();
|
app.tagList = new TagListState();
|
||||||
|
@ -35,6 +35,7 @@ import type { ComponentAttrs } from './Component';
|
|||||||
import Model, { SavedModelData } from './Model';
|
import Model, { SavedModelData } from './Model';
|
||||||
import fireApplicationError from './helpers/fireApplicationError';
|
import fireApplicationError from './helpers/fireApplicationError';
|
||||||
import IHistory from './IHistory';
|
import IHistory from './IHistory';
|
||||||
|
import IExtender from './extenders/IExtender';
|
||||||
|
|
||||||
export type FlarumScreens = 'phone' | 'tablet' | 'desktop' | 'desktop-hd';
|
export type FlarumScreens = 'phone' | 'tablet' | 'desktop' | 'desktop-hd';
|
||||||
|
|
||||||
@ -300,8 +301,7 @@ export default class Application {
|
|||||||
caughtInitializationErrors.forEach((handler) => handler());
|
caughtInitializationErrors.forEach((handler) => handler());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This entire system needs a do-over for v2
|
public bootExtensions(extensions: Record<string, { extend?: IExtender[] }>) {
|
||||||
public bootExtensions(extensions: Record<string, { extend?: unknown[] }>) {
|
|
||||||
Object.keys(extensions).forEach((name) => {
|
Object.keys(extensions).forEach((name) => {
|
||||||
const extension = extensions[name];
|
const extension = extensions[name];
|
||||||
|
|
||||||
@ -311,7 +311,6 @@ export default class Application {
|
|||||||
const extenders = extension.extend.flat(Infinity);
|
const extenders = extension.extend.flat(Infinity);
|
||||||
|
|
||||||
for (const extender of extenders) {
|
for (const extender of extenders) {
|
||||||
// @ts-expect-error This is beyond saving atm.
|
|
||||||
extender.extend(this, { name, exports: extension });
|
extender.extend(this, { name, exports: extension });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// @ts-expect-error We need to explicitly use the prefix to distinguish between the extend folder.
|
import * as extend from './extend';
|
||||||
import * as extend from './extend.ts';
|
import extenders from './extenders';
|
||||||
import Session from './Session';
|
import Session from './Session';
|
||||||
import Store from './Store';
|
import Store from './Store';
|
||||||
import BasicEditorDriver from './utils/BasicEditorDriver';
|
import BasicEditorDriver from './utils/BasicEditorDriver';
|
||||||
@ -90,6 +90,7 @@ import ModalManagerState from './states/ModalManagerState';
|
|||||||
import PageState from './states/PageState';
|
import PageState from './states/PageState';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
extenders,
|
||||||
extend: extend,
|
extend: extend,
|
||||||
Session: Session,
|
Session: Session,
|
||||||
Store: Store,
|
Store: Store,
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
export default class Model {
|
|
||||||
type;
|
|
||||||
attributes = [];
|
|
||||||
hasOnes = [];
|
|
||||||
hasManys = [];
|
|
||||||
|
|
||||||
constructor(type, model = null) {
|
|
||||||
this.type = type;
|
|
||||||
this.model = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
attribute(name) {
|
|
||||||
this.attributes.push(name);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasOne(type) {
|
|
||||||
this.hasOnes.push(type);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasMany(type) {
|
|
||||||
this.hasManys.push(type);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
extend(app, extension) {
|
|
||||||
if (this.model) {
|
|
||||||
app.store.models[this.type] = this.model;
|
|
||||||
}
|
|
||||||
|
|
||||||
const model = app.store.models[this.type];
|
|
||||||
|
|
||||||
this.attributes.forEach((name) => (model.prototype[name] = model.attribute(name)));
|
|
||||||
this.hasOnes.forEach((name) => (model.prototype[name] = model.hasOne(name)));
|
|
||||||
this.hasManys.forEach((name) => (model.prototype[name] = model.hasMany(name)));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
export default class PostTypes {
|
|
||||||
postComponents = {};
|
|
||||||
|
|
||||||
add(name, component) {
|
|
||||||
this.postComponents[name] = component;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
extend(app, extension) {
|
|
||||||
Object.assign(app.postComponents, this.postComponents);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
export default class Routes {
|
|
||||||
routes = {};
|
|
||||||
|
|
||||||
add(name, path, component) {
|
|
||||||
this.routes[name] = { path, component };
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
extend(app, extension) {
|
|
||||||
Object.assign(app.routes, this.routes);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
export { default as Model } from './Model';
|
|
||||||
export { default as PostTypes } from './PostTypes';
|
|
||||||
export { default as Routes } from './Routes';
|
|
10
framework/core/js/src/common/extenders/IExtender.ts
Normal file
10
framework/core/js/src/common/extenders/IExtender.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import Application from '../Application';
|
||||||
|
|
||||||
|
export interface IExtensionModule {
|
||||||
|
name: string;
|
||||||
|
exports: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default interface IExtender {
|
||||||
|
extend(app: Application, extension: IExtensionModule): void;
|
||||||
|
}
|
24
framework/core/js/src/common/extenders/PostTypes.ts
Normal file
24
framework/core/js/src/common/extenders/PostTypes.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import IExtender, { IExtensionModule } from './IExtender';
|
||||||
|
import Application from '../Application';
|
||||||
|
import ForumApplication from '../../forum/ForumApplication';
|
||||||
|
|
||||||
|
export default class PostTypes implements IExtender {
|
||||||
|
private postComponents: Record<string, any> = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new post component type.
|
||||||
|
* Usually used for event posts.
|
||||||
|
*
|
||||||
|
* @param name The name of the post type.
|
||||||
|
* @param component The component class to render the post.
|
||||||
|
*/
|
||||||
|
add(name: string, component: any): PostTypes {
|
||||||
|
this.postComponents[name] = component;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend(app: Application, extension: IExtensionModule): void {
|
||||||
|
Object.assign((app as unknown as ForumApplication).postComponents, this.postComponents);
|
||||||
|
}
|
||||||
|
}
|
33
framework/core/js/src/common/extenders/Routes.ts
Normal file
33
framework/core/js/src/common/extenders/Routes.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import Application, { FlarumGenericRoute } from '../Application';
|
||||||
|
import IExtender, { IExtensionModule } from './IExtender';
|
||||||
|
|
||||||
|
type HelperRoute = (...args: any) => string;
|
||||||
|
|
||||||
|
export default class Routes implements IExtender {
|
||||||
|
private routes: Record<string, FlarumGenericRoute> = {};
|
||||||
|
private helpers: Record<string, HelperRoute> = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a mithril route to the application.
|
||||||
|
*
|
||||||
|
* @param name The name of the route.
|
||||||
|
* @param path The path of the route.
|
||||||
|
* @param component must extend `Page` component.
|
||||||
|
*/
|
||||||
|
add(name: string, path: `/${string}`, component: any): Routes {
|
||||||
|
this.routes[name] = { path, component };
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
helper(name: string, callback: HelperRoute): Routes {
|
||||||
|
this.helpers[name] = callback;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend(app: Application, extension: IExtensionModule) {
|
||||||
|
Object.assign(app.routes, this.routes);
|
||||||
|
Object.assign(app.route, this.helpers);
|
||||||
|
}
|
||||||
|
}
|
7
framework/core/js/src/common/extenders/index.ts
Normal file
7
framework/core/js/src/common/extenders/index.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import PostTypes from './PostTypes';
|
||||||
|
import Routes from './Routes';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
PostTypes,
|
||||||
|
Routes,
|
||||||
|
};
|
@ -19,10 +19,9 @@ import patchMithril from './utils/patchMithril';
|
|||||||
|
|
||||||
patchMithril(window);
|
patchMithril(window);
|
||||||
|
|
||||||
import * as Extend from './extend/index';
|
|
||||||
import app from './app';
|
import app from './app';
|
||||||
|
|
||||||
export { Extend, app };
|
export { app };
|
||||||
|
|
||||||
import './utils/arrayFlatPolyfill';
|
import './utils/arrayFlatPolyfill';
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user