Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: move gambits to frontend #3885

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions extensions/lock/js/src/admin/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as default } from '../common/extend';
2 changes: 2 additions & 0 deletions extensions/lock/js/src/admin/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import app from 'flarum/admin/app';

export { default as extend } from './extend';

app.initializers.add('lock', () => {
app.extensionData.for('flarum-lock').registerPermission(
{
Expand Down
7 changes: 7 additions & 0 deletions extensions/lock/js/src/common/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Extend from 'flarum/common/extenders';
import LockedGambit from './query/discussions/LockedGambit';

export default [
new Extend.Search() //
.gambit('discussions', LockedGambit),
];
15 changes: 15 additions & 0 deletions extensions/lock/js/src/common/query/discussions/LockedGambit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import IGambit from 'flarum/common/query/IGambit';

export default class LockedGambit implements IGambit {
pattern(): string {
return 'is:locked';
}

toFilter(_matches: string[], negate: boolean): Record<string, any> {
const key = (negate ? '-' : '') + 'locked';

return {
[key]: true,
};
}
}
4 changes: 4 additions & 0 deletions extensions/lock/js/src/forum/extend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import Extend from 'flarum/common/extenders';
import Discussion from 'flarum/common/models/Discussion';
import DiscussionLockedPost from './components/DiscussionLockedPost';

import commonExtend from '../common/extend';

export default [
...commonExtend,

new Extend.PostTypes() //
.add('discussionLocked', DiscussionLockedPost),

Expand Down
1 change: 1 addition & 0 deletions extensions/sticky/js/src/admin/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as default } from '../common/extend';
2 changes: 2 additions & 0 deletions extensions/sticky/js/src/admin/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import app from 'flarum/admin/app';

export { default as extend } from './extend';

app.initializers.add('flarum-sticky', () => {
app.extensionData.for('flarum-sticky').registerPermission(
{
Expand Down
7 changes: 7 additions & 0 deletions extensions/sticky/js/src/common/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Extend from 'flarum/common/extenders';
import StickyGambit from './query/discussions/StickyGambit';

export default [
new Extend.Search() //
.gambit('discussions', StickyGambit),
];
15 changes: 15 additions & 0 deletions extensions/sticky/js/src/common/query/discussions/StickyGambit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import IGambit from 'flarum/common/query/IGambit';

export default class StickyGambit implements IGambit {
pattern(): string {
return 'is:sticky';
}

toFilter(_matches: string[], negate: boolean): Record<string, any> {
const key = (negate ? '-' : '') + 'sticky';

return {
[key]: true,
};
}
}
4 changes: 4 additions & 0 deletions extensions/sticky/js/src/forum/extend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import Extend from 'flarum/common/extenders';
import Discussion from 'flarum/common/models/Discussion';
import DiscussionStickiedPost from './components/DiscussionStickiedPost';

import commonExtend from '../common/extend';

export default [
...commonExtend,

new Extend.PostTypes() //
.add('discussionStickied', DiscussionStickiedPost),

Expand Down
3 changes: 3 additions & 0 deletions extensions/subscriptions/extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
use Flarum\User\User;

return [
(new Extend\Frontend('admin'))
->js(__DIR__.'/js/dist/admin.js'),

(new Extend\Frontend('forum'))
->js(__DIR__.'/js/dist/forum.js')
->css(__DIR__.'/less/forum.less')
Expand Down
1 change: 1 addition & 0 deletions extensions/subscriptions/js/admin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './src/admin';
1 change: 1 addition & 0 deletions extensions/subscriptions/js/src/admin/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as default } from '../common/extend';
1 change: 1 addition & 0 deletions extensions/subscriptions/js/src/admin/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as extend } from './extend';
7 changes: 7 additions & 0 deletions extensions/subscriptions/js/src/common/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Extend from 'flarum/common/extenders';
import SubscriptionGambit from './query/discussions/SubscriptionGambit';

export default [
new Extend.Search() //
.gambit('discussions', SubscriptionGambit),
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import IGambit from 'flarum/common/query/IGambit';

export default class SubscriptionGambit implements IGambit {
pattern(): string {
return 'is:(follow|ignor)(?:ing|ed)';
}

toFilter(matches: string[], negate: boolean): Record<string, any> {
const type = matches[1] === 'follow' ? 'following' : 'ignoring';

return {
subscription: type,
};
}
}
4 changes: 4 additions & 0 deletions extensions/subscriptions/js/src/forum/extend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import Extend from 'flarum/common/extenders';
import IndexPage from 'flarum/forum/components/IndexPage';
import Discussion from 'flarum/common/models/Discussion';

import commonExtend from '../common/extend';

export default [
...commonExtend,

new Extend.Routes() //
.add('following', '/following', IndexPage),

Expand Down
1 change: 1 addition & 0 deletions extensions/suspend/js/src/admin/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as default } from '../common/extend';
2 changes: 2 additions & 0 deletions extensions/suspend/js/src/admin/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import app from 'flarum/admin/app';

export { default as extend } from './extend';

app.initializers.add('flarum-suspend', () => {
app.extensionData.for('flarum-suspend').registerPermission(
{
Expand Down
7 changes: 7 additions & 0 deletions extensions/suspend/js/src/common/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Extend from 'flarum/common/extenders';
import SuspendedGambit from './query/users/SuspendedGambit';

export default [
new Extend.Search() //
.gambit('users', SuspendedGambit),
];
15 changes: 15 additions & 0 deletions extensions/suspend/js/src/common/query/users/SuspendedGambit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import IGambit from 'flarum/common/query/IGambit';

export default class SuspendedGambit implements IGambit {
pattern(): string {
return 'is:suspended';
}

toFilter(_matches: string[], negate: boolean): Record<string, any> {
const key = (negate ? '-' : '') + 'suspended';

return {
[key]: true,
};
}
}
6 changes: 5 additions & 1 deletion extensions/suspend/js/src/forum/extend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import Extend from 'flarum/common/extenders';
import User from 'flarum/common/models/User';
import Model from 'flarum/common/Model';

import commonExtend from '../common/extend';

export default [
...commonExtend,

new Extend.Model(User)
.attribute<boolean>('canSuspend')
.attribute<Date, string | null | undefined>('suspendedUntil', Model.transformDate)
.attribute<Date | null | undefined, string | null | undefined>('suspendedUntil', Model.transformDate)
.attribute<string | null | undefined>('suspendReason')
.attribute<string | null | undefined>('suspendMessage'),
];
4 changes: 4 additions & 0 deletions extensions/tags/js/src/common/extend.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import Extend from 'flarum/common/extenders';
import Tag from './models/Tag';
import TagGambit from './query/discussions/TagGambit';

export default [
new Extend.Store() //
.add('tags', Tag),

new Extend.Search() //
.gambit('discussions', TagGambit),
];
15 changes: 15 additions & 0 deletions extensions/tags/js/src/common/query/discussions/TagGambit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import IGambit from 'flarum/common/query/IGambit';

export default class TagGambit implements IGambit {
pattern(): string {
return 'tag:(.+)';
}

toFilter(matches: string[], negate: boolean): Record<string, any> {
const key = (negate ? '-' : '') + 'tag';

return {
[key]: matches[1].split(','),
};
}
}
51 changes: 51 additions & 0 deletions framework/core/js/src/common/GambitManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import IGambit from './query/IGambit';
import AuthorGambit from './query/discussions/AuthorGambit';
import CreatedGambit from './query/discussions/CreatedGambit';
import HiddenGambit from './query/discussions/HiddenGambit';
import UnreadGambit from './query/discussions/UnreadGambit';
import EmailGambit from './query/users/EmailGambit';
import GroupGambit from './query/users/GroupGambit';

/**
* The gambit registry. A map of resource types to gambit classes that
* should be used to filter resources of that type. Gambits are automatically
* converted to API filters when requesting resources. Gambits must be applied
* on a filter object that has a `q` property containing the search query.
*/
export default class GambitManager {
gambits: Record<string, Array<new () => IGambit>> = {
discussions: [AuthorGambit, CreatedGambit, HiddenGambit, UnreadGambit],
users: [EmailGambit, GroupGambit],
};

public apply(type: string, filter: Record<string, any>): Record<string, any> {
const gambits = this.gambits[type] || [];

if (gambits.length === 0) return filter;

const bits: string[] = filter.q.split(' ');

for (const gambitClass of gambits) {
const gambit = new gambitClass();

for (const bit of bits) {
const pattern = `^(-?)${gambit.pattern()}$`;
let matches = bit.match(pattern);

if (matches) {
const negate = matches[1] === '-';

matches.splice(1, 1);

Object.assign(filter, gambit.toFilter(matches, negate));

filter.q = filter.q.replace(bit, '');
}
}
}

filter.q = filter.q.trim().replace(/\s+/g, ' ');

return filter;
}
}
13 changes: 12 additions & 1 deletion framework/core/js/src/common/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import app from '../common/app';
import { FlarumRequestOptions } from './Application';
import { fireDeprecationWarning } from './helpers/fireDebugWarning';
import Model, { ModelData, SavedModelData } from './Model';
import GambitManager from './GambitManager';

export interface MetaInformation {
[key: string]: any;
Expand All @@ -21,7 +22,7 @@ export interface ApiQueryParamsPlural {
| {
q: string;
}
| Record<string, string>;
| Record<string, any>;
page?: {
near?: number;
offset?: number;
Expand Down Expand Up @@ -85,6 +86,12 @@ export default class Store {
*/
models: Record<string, { new (): Model }>;

/**
* The gambit manager that will convert search query gambits
* into API filters.
*/
gambits = new GambitManager();

constructor(models: Record<string, { new (): Model }>) {
this.models = models;
}
Expand Down Expand Up @@ -178,6 +185,10 @@ export default class Store {
url += '/' + idOrParams;
}

if ('filter' in params && params?.filter?.q) {
params.filter = this.gambits.apply(type, params.filter);
}

return app
.request<M extends Array<infer _T> ? ApiPayloadPlural : ApiPayloadSingle>({
method: 'GET',
Expand Down
24 changes: 24 additions & 0 deletions framework/core/js/src/common/extenders/Search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type IExtender from './IExtender';
import type { IExtensionModule } from './IExtender';
import type Application from '../Application';
import IGambit from '../query/IGambit';

export default class Search implements IExtender {
protected gambits: Record<string, Array<new () => IGambit>> = {};

public gambit(modelType: string, gambit: new () => IGambit): this {
this.gambits[modelType] = this.gambits[modelType] || [];
this.gambits[modelType].push(gambit);

return this;
}

extend(app: Application, extension: IExtensionModule): void {
for (const [modelType, gambits] of Object.entries(this.gambits)) {
for (const gambit of gambits) {
app.store.gambits.gambits[modelType] = app.store.gambits.gambits[modelType] || [];
app.store.gambits.gambits[modelType].push(gambit);
}
}
}
}
2 changes: 2 additions & 0 deletions framework/core/js/src/common/extenders/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import Model from './Model';
import PostTypes from './PostTypes';
import Routes from './Routes';
import Store from './Store';
import Search from './Search';

const extenders = {
Model,
PostTypes,
Routes,
Store,
Search,
};

export default extenders;
4 changes: 4 additions & 0 deletions framework/core/js/src/common/query/IGambit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default interface IGambit {
pattern(): string;
toFilter(matches: string[], negate: boolean): Record<string, any>;
}
15 changes: 15 additions & 0 deletions framework/core/js/src/common/query/discussions/AuthorGambit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import IGambit from '../IGambit';

export default class AuthorGambit implements IGambit {
public pattern(): string {
return 'author:(.+)';
}

public toFilter(matches: string[], negate: boolean): Record<string, any> {
const key = (negate ? '-' : '') + 'author';

return {
[key]: matches[1].split(','),
};
}
}
20 changes: 20 additions & 0 deletions framework/core/js/src/common/query/discussions/CreatedGambit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import IGambit from '../IGambit';

export default class CreatedGambit implements IGambit {
pattern(): string {
return 'created:(\\d{4}\\-\\d\\d\\-\\d\\d)(?:\\.\\.(\\d{4}\\-\\d\\d\\-\\d\\d))?';
}

toFilter(matches: string[], negate: boolean): Record<string, any> {
const key = (negate ? '-' : '') + 'created';

return {
[key]: matches[2]
? {
from: matches[1],
to: matches[2],
}
: matches[1],
};
}
}
Loading
Loading