From 6b7ee14fda8dfd0062464c56a01d4c42026d60b1 Mon Sep 17 00:00:00 2001 From: Tristian Kelly Date: Tue, 21 Nov 2023 17:18:40 -0600 Subject: [PATCH] add pagination to flags list --- .../js/src/forum/components/FlagList.tsx | 69 ++++++++++--------- .../js/src/forum/states/FlagListState.tsx | 32 ++++----- .../Api/Controller/ListFlagsController.php | 43 ++++++++++-- 3 files changed, 89 insertions(+), 55 deletions(-) diff --git a/extensions/flags/js/src/forum/components/FlagList.tsx b/extensions/flags/js/src/forum/components/FlagList.tsx index 74c9c611b7..b1abee82d9 100644 --- a/extensions/flags/js/src/forum/components/FlagList.tsx +++ b/extensions/flags/js/src/forum/components/FlagList.tsx @@ -16,49 +16,54 @@ export interface IFlagListAttrs extends ComponentAttrs { export default class FlagList extends Component { oninit(vnode: Mithril.Vnode) { super.oninit(vnode); - this.state = this.attrs.state; } view() { - const flags = this.state.cache || []; + const state = this.attrs.state; return ( state.hasNext() && !state.isLoadingNext() && state.loadNext()} > -
    - {!this.state.loading && - flags.map((flag) => { - const post = flag.post() as Post; - - return ( -
  • - } - icon="fas fa-flag" - content={app.translator.trans('flarum-flags.forum.flagged_posts.item_text', { - username: username(post.user()), - em: , - discussion: post.discussion().title(), - })} - excerpt={post.contentPlain()} - datetime={flag.createdAt()} - href={app.route.post(post)} - onclick={(e: MouseEvent) => { - app.flags.index = post; - e.redraw = false; - }} - /> -
  • - ); - })} -
+ {this.content(state)}
); } + + content(state) { + if (!state.isLoading() && state.hasItems()) { + return state.getPages().map((page) => { + return page.items.map((flag) => { + const post = flag.post() as Post; + + return ( + } + icon="fas fa-flag" + content={app.translator.trans('flarum-flags.forum.flagged_posts.item_text', { + username: username(post.user()), + em: , + discussion: post.discussion().title(), + })} + excerpt={post.contentPlain()} + datetime={flag.createdAt()} + href={app.route.post(post)} + onclick={(e: MouseEvent) => { + app.flags.index = post; + e.redraw = false; + }} + /> + ); + }); + }); + } + + return null; + } } diff --git a/extensions/flags/js/src/forum/states/FlagListState.tsx b/extensions/flags/js/src/forum/states/FlagListState.tsx index 7afa5543fa..42f3b3b336 100644 --- a/extensions/flags/js/src/forum/states/FlagListState.tsx +++ b/extensions/flags/js/src/forum/states/FlagListState.tsx @@ -1,39 +1,37 @@ import type ForumApplication from 'flarum/forum/ForumApplication'; import type Flag from '../models/Flag'; import type Post from 'flarum/common/models/Post'; +import PaginatedListState from 'flarum/common/states/PaginatedListState'; -export default class FlagListState { +export default class FlagListState extends PaginatedListState { public app: ForumApplication; public loading = false; public cache: Flag[] | null = null; public index: Post | false | null = null; constructor(app: ForumApplication) { + super({}, 1, null); this.app = app; } + get type(): string { + return 'flags'; + } + /** * Load flags into the application's cache if they haven't already * been loaded. */ - load() { - if (this.cache && !this.app.session.user!.attribute('newFlagCount')) { - return; + load(): Promise { + if (this.app.session.user?.attribute('newFlagCount')) { + this.pages = []; + this.location = { page: 1 }; } - this.loading = true; - m.redraw(); + if (this.pages.length > 0) { + return Promise.resolve(); + } - this.app.store - .find('flags') - .then((flags) => { - this.app.session.user!.pushAttributes({ newFlagCount: 0 }); - this.cache = flags.sort((a, b) => b.createdAt()!.getTime() - a.createdAt()!.getTime()); - }) - .catch(() => {}) - .then(() => { - this.loading = false; - m.redraw(); - }); + return super.loadNext(); } } diff --git a/extensions/flags/src/Api/Controller/ListFlagsController.php b/extensions/flags/src/Api/Controller/ListFlagsController.php index 216f61b05a..0a5d362baa 100644 --- a/extensions/flags/src/Api/Controller/ListFlagsController.php +++ b/extensions/flags/src/Api/Controller/ListFlagsController.php @@ -16,6 +16,7 @@ use Flarum\Http\RequestUtil; use Psr\Http\Message\ServerRequestInterface; use Tobscure\JsonApi\Document; +use Flarum\Http\UrlGenerator; class ListFlagsController extends AbstractListController { @@ -28,26 +29,56 @@ class ListFlagsController extends AbstractListController 'post.discussion' ]; + public function __construct( + protected UrlGenerator $url + ) { + } + protected function data(ServerRequestInterface $request, Document $document): iterable { $actor = RequestUtil::getActor($request); - $include = $this->extractInclude($request); $actor->assertRegistered(); $actor->read_flags_at = Carbon::now(); $actor->save(); - $flags = Flag::whereVisibleTo($actor) - ->latest('flags.created_at') - ->groupBy('post_id') - ->get(); + $limit = $this->extractLimit($request); + $offset = $this->extractOffset($request); + $include = $this->extractInclude($request); if (in_array('post.user', $include)) { $include[] = 'post.user.groups'; } - $this->loadRelations($flags, $include); + $primaries = Flag::whereVisibleTo($actor) + ->groupBy('post_id') + ->orderBy('created_at', 'DESC') + ->skip($offset) + ->take($limit + 1); + + $flags = Flag::whereVisibleTo($actor) + ->joinSub($primaries, 'p', 'flags.id', '=', 'p.id') + ->latest() + ->get(); + + $this->loadRelations($flags, $include, $request); + + $flags = $flags->all(); + + $areMoreResults = false; + + if (count($flags) > $limit) { + array_pop($flags); + $areMoreResults = true; + } + + $this->addPaginationData( + $document, + $request, + $this->url->to('api')->route('flags.index'), + $areMoreResults ? null : 0 + ); return $flags; }