From 3d2d0c7de61a4b8a644e01ba664533f361e9d057 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Tue, 26 Sep 2023 11:52:54 +0100 Subject: [PATCH] refactor: filters to gambits --- .../common/query/discussions/LockedGambit.ts | 8 +++++++ .../common/query/discussions/StickyGambit.ts | 8 +++++++ .../query/discussions/SubscriptionGambit.ts | 8 +++++++ .../src/common/query/users/SuspendedGambit.ts | 8 +++++++ .../src/common/query/discussions/TagGambit.ts | 8 +++++++ framework/core/js/src/common/GambitManager.ts | 21 +++++++++++++++++++ framework/core/js/src/common/query/IGambit.ts | 2 ++ .../common/query/discussions/AuthorGambit.ts | 8 +++++++ .../common/query/discussions/CreatedGambit.ts | 8 +++++++ .../common/query/discussions/HiddenGambit.ts | 8 +++++++ .../common/query/discussions/UnreadGambit.ts | 8 +++++++ .../js/src/common/query/users/EmailGambit.ts | 8 +++++++ .../js/src/common/query/users/GroupGambit.ts | 8 +++++++ .../components/DiscussionsSearchSource.tsx | 7 ++++++- .../js/src/forum/states/GlobalSearchState.ts | 16 ++++++++++---- 15 files changed, 129 insertions(+), 5 deletions(-) diff --git a/extensions/lock/js/src/common/query/discussions/LockedGambit.ts b/extensions/lock/js/src/common/query/discussions/LockedGambit.ts index aa2f8d08ce..b3639fd35d 100644 --- a/extensions/lock/js/src/common/query/discussions/LockedGambit.ts +++ b/extensions/lock/js/src/common/query/discussions/LockedGambit.ts @@ -12,4 +12,12 @@ export default class LockedGambit implements IGambit { [key]: true, }; } + + filterKey(): string { + return 'locked'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}is:locked`; + } } diff --git a/extensions/sticky/js/src/common/query/discussions/StickyGambit.ts b/extensions/sticky/js/src/common/query/discussions/StickyGambit.ts index 1c9ed860ad..d1ab9f688c 100644 --- a/extensions/sticky/js/src/common/query/discussions/StickyGambit.ts +++ b/extensions/sticky/js/src/common/query/discussions/StickyGambit.ts @@ -12,4 +12,12 @@ export default class StickyGambit implements IGambit { [key]: true, }; } + + filterKey(): string { + return 'sticky'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}is:sticky`; + } } diff --git a/extensions/subscriptions/js/src/common/query/discussions/SubscriptionGambit.ts b/extensions/subscriptions/js/src/common/query/discussions/SubscriptionGambit.ts index a702a43eaf..6d1a137078 100644 --- a/extensions/subscriptions/js/src/common/query/discussions/SubscriptionGambit.ts +++ b/extensions/subscriptions/js/src/common/query/discussions/SubscriptionGambit.ts @@ -12,4 +12,12 @@ export default class SubscriptionGambit implements IGambit { subscription: type, }; } + + filterKey(): string { + return 'subscription'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}is:${value}`; + } } diff --git a/extensions/suspend/js/src/common/query/users/SuspendedGambit.ts b/extensions/suspend/js/src/common/query/users/SuspendedGambit.ts index 2ef338f590..f8c2c4c6c0 100644 --- a/extensions/suspend/js/src/common/query/users/SuspendedGambit.ts +++ b/extensions/suspend/js/src/common/query/users/SuspendedGambit.ts @@ -12,4 +12,12 @@ export default class SuspendedGambit implements IGambit { [key]: true, }; } + + filterKey(): string { + return 'suspended'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}is:suspended`; + } } diff --git a/extensions/tags/js/src/common/query/discussions/TagGambit.ts b/extensions/tags/js/src/common/query/discussions/TagGambit.ts index fae0333354..0cae0b17bc 100644 --- a/extensions/tags/js/src/common/query/discussions/TagGambit.ts +++ b/extensions/tags/js/src/common/query/discussions/TagGambit.ts @@ -12,4 +12,12 @@ export default class TagGambit implements IGambit { [key]: matches[1].split(','), }; } + + filterKey(): string { + return 'tag'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}tag:${value}`; + } } diff --git a/framework/core/js/src/common/GambitManager.ts b/framework/core/js/src/common/GambitManager.ts index 11cc0569ec..10774c0920 100644 --- a/framework/core/js/src/common/GambitManager.ts +++ b/framework/core/js/src/common/GambitManager.ts @@ -48,4 +48,25 @@ export default class GambitManager { return filter; } + + public from(type: string, q: string, filter: Record): string { + const gambits = this.gambits[type] || []; + + if (gambits.length === 0) return q; + + Object.keys(filter).forEach((key) => { + for (const gambitClass of gambits) { + const gambit = new gambitClass(); + const negate = key[0] === '-'; + + if (negate) key = key.substring(1); + + if (gambit.filterKey() !== key) continue; + + q += ` ${gambit.fromFilter(filter[key], negate)}`; + } + }); + + return q; + } } diff --git a/framework/core/js/src/common/query/IGambit.ts b/framework/core/js/src/common/query/IGambit.ts index 719c319689..a10e8bdb11 100644 --- a/framework/core/js/src/common/query/IGambit.ts +++ b/framework/core/js/src/common/query/IGambit.ts @@ -1,4 +1,6 @@ export default interface IGambit { pattern(): string; toFilter(matches: string[], negate: boolean): Record; + filterKey(): string; + fromFilter(value: string, negate: boolean): string; } diff --git a/framework/core/js/src/common/query/discussions/AuthorGambit.ts b/framework/core/js/src/common/query/discussions/AuthorGambit.ts index 367686dff2..f38f71cda6 100644 --- a/framework/core/js/src/common/query/discussions/AuthorGambit.ts +++ b/framework/core/js/src/common/query/discussions/AuthorGambit.ts @@ -12,4 +12,12 @@ export default class AuthorGambit implements IGambit { [key]: matches[1].split(','), }; } + + filterKey(): string { + return 'author'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}author:${value}`; + } } diff --git a/framework/core/js/src/common/query/discussions/CreatedGambit.ts b/framework/core/js/src/common/query/discussions/CreatedGambit.ts index 5f2558e068..1b84ed044d 100644 --- a/framework/core/js/src/common/query/discussions/CreatedGambit.ts +++ b/framework/core/js/src/common/query/discussions/CreatedGambit.ts @@ -12,4 +12,12 @@ export default class CreatedGambit implements IGambit { [key]: matches[1], }; } + + filterKey(): string { + return 'created'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}created:${value}`; + } } diff --git a/framework/core/js/src/common/query/discussions/HiddenGambit.ts b/framework/core/js/src/common/query/discussions/HiddenGambit.ts index 2e2157307b..fb0f448df7 100644 --- a/framework/core/js/src/common/query/discussions/HiddenGambit.ts +++ b/framework/core/js/src/common/query/discussions/HiddenGambit.ts @@ -12,4 +12,12 @@ export default class HiddenGambit implements IGambit { [key]: true, }; } + + filterKey(): string { + return 'hidden'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}is:hidden`; + } } diff --git a/framework/core/js/src/common/query/discussions/UnreadGambit.ts b/framework/core/js/src/common/query/discussions/UnreadGambit.ts index ac3fc920e8..9466b76be4 100644 --- a/framework/core/js/src/common/query/discussions/UnreadGambit.ts +++ b/framework/core/js/src/common/query/discussions/UnreadGambit.ts @@ -12,4 +12,12 @@ export default class UnreadGambit implements IGambit { [key]: true, }; } + + filterKey(): string { + return 'unread'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}is:unread`; + } } diff --git a/framework/core/js/src/common/query/users/EmailGambit.ts b/framework/core/js/src/common/query/users/EmailGambit.ts index ad851290f5..5a9d432abd 100644 --- a/framework/core/js/src/common/query/users/EmailGambit.ts +++ b/framework/core/js/src/common/query/users/EmailGambit.ts @@ -12,4 +12,12 @@ export default class EmailGambit implements IGambit { [key]: matches[1], }; } + + filterKey(): string { + return 'email'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}email:${value}`; + } } diff --git a/framework/core/js/src/common/query/users/GroupGambit.ts b/framework/core/js/src/common/query/users/GroupGambit.ts index 279b895bc2..6293367198 100644 --- a/framework/core/js/src/common/query/users/GroupGambit.ts +++ b/framework/core/js/src/common/query/users/GroupGambit.ts @@ -12,4 +12,12 @@ export default class GroupGambit implements IGambit { [key]: matches[1].split(','), }; } + + filterKey(): string { + return 'group'; + } + + fromFilter(value: string, negate: boolean): string { + return `${negate ? '-' : ''}group:${value}`; + } } diff --git a/framework/core/js/src/forum/components/DiscussionsSearchSource.tsx b/framework/core/js/src/forum/components/DiscussionsSearchSource.tsx index 3a42945c65..84de850396 100644 --- a/framework/core/js/src/forum/components/DiscussionsSearchSource.tsx +++ b/framework/core/js/src/forum/components/DiscussionsSearchSource.tsx @@ -48,10 +48,15 @@ export default class DiscussionsSearchSource implements SearchSource { ); }) as Array; + const filter = app.store.gambits.apply('discussions', { q: query }); + const q = filter.q || null; + + delete filter.q; + return [
  • {app.translator.trans('core.forum.search.discussions_heading')}
  • ,
  • - + {app.translator.trans('core.forum.search.all_discussions_button', { query })}
  • , diff --git a/framework/core/js/src/forum/states/GlobalSearchState.ts b/framework/core/js/src/forum/states/GlobalSearchState.ts index f728dfe22b..b4ca4e5c26 100644 --- a/framework/core/js/src/forum/states/GlobalSearchState.ts +++ b/framework/core/js/src/forum/states/GlobalSearchState.ts @@ -36,7 +36,14 @@ export default class GlobalSearchState extends SearchState { * @inheritdoc */ getInitialSearch(): string { - return this.currPageProvidesSearch() ? this.params().q : ''; + return this.currPageProvidesSearch() ? this.searchToQuery() : ''; + } + + private searchToQuery(): string { + const q = this.params().q || ''; + const filter = this.params().filter || {}; + + return app.store.gambits.from('users', app.store.gambits.from('discussions', q, filter), filter).trim(); } /** @@ -57,7 +64,7 @@ export default class GlobalSearchState extends SearchState { * 'x' is clicked in the search box in the header. */ protected clearInitialSearch() { - const { q, ...params } = this.params(); + const { q, filter, ...params } = this.params(); setRouteWithForcedRefresh(app.route(app.current.get('routeName'), params)); } @@ -71,6 +78,9 @@ export default class GlobalSearchState extends SearchState { return { sort: m.route.param('sort'), q: m.route.param('q'), + // Objects must be copied, otherwise they are passed by reference. + // Which could end up undesirably modifying the mithril route params. + filter: Object.assign({}, m.route.param('filter')), }; } @@ -80,8 +90,6 @@ export default class GlobalSearchState extends SearchState { params(): SearchParams { const params = this.stickyParams(); - params.filter = m.route.param('filter'); - return params; }