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

feat: migrate User Recent Posts to React.js #2664

Merged
merged 20 commits into from
Sep 8, 2024
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
5 changes: 3 additions & 2 deletions app/Community/Components/UserProfileMeta.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use App\Platform\Enums\PlayerStatType;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\View\Component;

Expand Down Expand Up @@ -322,13 +323,13 @@ private function buildRankMetadata(
private function buildSocialStats(User $user): array
{
$userSetRequestInformation = getUserRequestsInformation($user);
$numForumPosts = $user->forumPosts()->count();
$numForumPosts = $user->forumPosts()->authorized()->viewable(Auth::user())->count();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change fixes a bug on the user profile. The current count of forum posts represents all posts made by the user, including the ones that can't be seen due to being unauthorized or locked behind a permissions gate.

The count now reflects the posts that are visible on the /user/[user]/posts page.


// Forum posts
$forumPostsStat = [
'label' => 'Forum posts',
'value' => localized_number($numForumPosts),
'href' => $numForumPosts ? route('user.posts', ['user' => $user]) : null,
'href' => $numForumPosts ? route('user.posts.index', ['user' => $user]) : null,
'isMuted' => $numForumPosts === 0,
];

Expand Down
51 changes: 0 additions & 51 deletions app/Community/Controllers/ForumTopicCommentController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,13 @@
use App\Community\Actions\AddCommentAction;
use App\Community\Actions\GetUrlToCommentDestinationAction;
use App\Community\Requests\ForumTopicCommentRequest;
use App\Community\Services\ForumRecentPostsPageService;
use App\Models\ForumTopic;
use App\Models\ForumTopicComment;
use App\Support\Shortcode\Shortcode;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response as InertiaResponse;

class ForumTopicCommentController extends CommentController
{
public function __construct(
protected ForumRecentPostsPageService $recentPostsPageService
) {
}

/**
* There is no create form for creating a new comment.
* comments have to be created for something -> use sub resource create route, e.g.
Expand Down Expand Up @@ -92,46 +83,4 @@ protected function destroy(ForumTopicComment $comment): RedirectResponse
return redirect($return)
->with('success', $this->resourceActionSuccessMessage('comment', 'delete'));
}

public function showRecentPosts(): InertiaResponse
{
$this->authorize('viewAny', ForumTopicComment::class);

// TODO after POC: thin this out
$pageProps = $this->recentPostsPageService->buildViewData(
request()->user(),
(int) request()->input('offset', 0)
);

// TODO after POC: migrate the query to Eloquent ORM and have it do these mappings automatically
$mappedRecentForumPosts = [];
foreach ($pageProps['recentForumPosts'] as &$recentForumPost) {
$mappedRecentForumPost = [];

$mappedRecentForumPost['forumTopicId'] = (int) $recentForumPost['ForumTopicID'];
$mappedRecentForumPost['forumTopicTitle'] = $recentForumPost['ForumTopicTitle'];
$mappedRecentForumPost['commentId'] = (int) $recentForumPost['CommentID'];
$mappedRecentForumPost['postedAt'] = $recentForumPost['PostedAt'];
$mappedRecentForumPost['authorDisplayName'] = $recentForumPost['Author'];
$mappedRecentForumPost['shortMessage'] = Shortcode::stripAndClamp($recentForumPost['ShortMsg'], 999);
$mappedRecentForumPost['commentIdDay'] = isset($recentForumPost['CommentID_1d']) ? (int) $recentForumPost['CommentID_1d'] : null;
$mappedRecentForumPost['commentCountDay'] = isset($recentForumPost['Count_1d']) ? (int) $recentForumPost['Count_1d'] : null;
$mappedRecentForumPost['commentIdWeek'] = isset($recentForumPost['CommentID_7d']) ? (int) $recentForumPost['CommentID_7d'] : null;
$mappedRecentForumPost['commentCountWeek'] = isset($recentForumPost['Count_7d']) ? (int) $recentForumPost['Count_7d'] : null;

$mappedRecentForumPosts[] = $mappedRecentForumPost;
}
unset($pageProps['recentForumPosts']);
$pageProps['recentForumPosts'] = $mappedRecentForumPosts;

// TODO after POC: remove this code
if (isset($pageProps['previousPageUrl'])) {
$pageProps['previousPageUrl'] = str_replace('recent-posts', 'recent-posts2', $pageProps['previousPageUrl']);
}
if (isset($pageProps['nextPageUrl'])) {
$pageProps['nextPageUrl'] = str_replace('recent-posts', 'recent-posts2', $pageProps['nextPageUrl']);
}

return Inertia::render('forums/recent-posts', $pageProps);
}
}
103 changes: 103 additions & 0 deletions app/Community/Controllers/UserForumTopicCommentController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

declare(strict_types=1);

namespace App\Community\Controllers;

use App\Community\Data\UserRecentPostsPagePropsData;
use App\Data\ForumTopicData;
use App\Data\PaginatedData;
use App\Data\UserData;
use App\Enums\Permissions;
use App\Http\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Inertia\Inertia;
use Inertia\Response as InertiaResponse;

class UserForumTopicCommentController extends Controller
{
public function index(Request $request, User $user): InertiaResponse
{
$this->authorize('view', $user);

$offset = $request->input('page', 1) - 1;
$count = 25;

/** @var User $me */
$me = auth()->user();
$permissions = Permissions::Unregistered;
if ($me) {
$permissions = (int) $me->getAttribute('Permissions');
}

$posts = $this->getUserPosts(
$user,
page: (int) $request->input('page', 1),
permissions: $permissions,
);

$transformedPosts = array_map(
fn ($post) => ForumTopicData::fromUserPost($post)->include('latestComment'),
$posts
);

$paginator = new LengthAwarePaginator(
items: $transformedPosts,
total: $user->forumPosts()->authorized()->viewable($me)->count(),
perPage: $count,
currentPage: $offset + 1,
options: [
'path' => $request->url(),
'query' => $request->query(),
]
);

$paginatedPosts = PaginatedData::fromLengthAwarePaginator($paginator);

$props = new UserRecentPostsPagePropsData(
UserData::fromUser($user),
$paginatedPosts
);

return Inertia::render('user/[user]/posts', $props);
}

private function getUserPosts(User $user, int $page = 1, int $permissions = Permissions::Unregistered): array
{
$count = 25;
$offset = ($page - 1) * $count;

$query = "
SELECT
ft.ID AS ForumTopicID,
ft.Title AS ForumTopicTitle,
f.ID AS ForumID,
f.Title AS ForumTitle,
lftc.ID AS CommentID,
lftc.DateCreated AS PostedAt,
lftc.author_id,
ua.User AS Author,
ua.display_name AS AuthorDisplayName,
LEFT(lftc.Payload, 260) AS ShortMsg,
LENGTH(lftc.Payload) > 260 AS IsTruncated
FROM ForumTopicComment AS lftc
INNER JOIN ForumTopic AS ft ON ft.ID = lftc.ForumTopicID
INNER JOIN Forum AS f ON f.ID = ft.ForumID
LEFT JOIN UserAccounts AS ua ON ua.ID = lftc.author_id
WHERE lftc.author_id = :author_id
AND lftc.Authorised = 1
AND ft.RequiredPermissions <= :permissions
AND ft.deleted_at IS NULL
ORDER BY lftc.DateCreated DESC
LIMIT :offset, :count";

return legacyDbFetchAll($query, [
'author_id' => $user->id,
'offset' => $offset,
'count' => $count,
'permissions' => $permissions,
])->toArray();
}
}
20 changes: 20 additions & 0 deletions app/Community/Data/UserRecentPostsPagePropsData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace App\Community\Data;

use App\Data\PaginatedData;
use App\Data\UserData;
use Spatie\LaravelData\Data;
use Spatie\TypeScriptTransformer\Attributes\TypeScript;

#[TypeScript('UserRecentPostsPageProps<TItems = App.Data.ForumTopic>')]
class UserRecentPostsPagePropsData extends Data
{
public function __construct(
public UserData $targetUser,
public PaginatedData $paginatedTopics,
) {
}
}
3 changes: 3 additions & 0 deletions app/Community/RouteServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use App\Community\Controllers\MessageController;
use App\Community\Controllers\MessageThreadController;
use App\Community\Controllers\UserCommentController;
use App\Community\Controllers\UserForumTopicCommentController;
use App\Community\Controllers\UserSettingsController;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;
Expand Down Expand Up @@ -41,6 +42,8 @@ protected function mapWebRoutes(): void
Route::middleware(['inertia'])->group(function () {
Route::get('forums/recent-posts', [ForumTopicController::class, 'recentPosts'])->name('forum.recent-posts');

Route::get('user/{user}/posts', [UserForumTopicCommentController::class, 'index'])->name('user.posts.index');

Route::get('settings', [UserSettingsController::class, 'show'])->name('settings.show');
});

Expand Down
99 changes: 0 additions & 99 deletions app/Community/Services/ForumRecentPostsPageService.php

This file was deleted.

2 changes: 1 addition & 1 deletion app/Data/ForumTopicCommentData.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function __construct(
public string $body,
public Carbon $createdAt,
public ?Carbon $updatedAt,
public UserData $user,
public ?UserData $user,
public bool $authorized, // TODO migrate to $authorizedAt
public ?int $forumTopicId = null,
) {
Expand Down
33 changes: 29 additions & 4 deletions app/Data/ForumTopicData.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ public function __construct(
public string $title,
public Carbon $createdAt,
public Lazy|ForumTopicCommentData $latestComment,
public Lazy|int $commentCount24h,
public Lazy|int $oldestComment24hId,
public Lazy|int $commentCount7d,
public Lazy|int $oldestComment7dId,
public Lazy|int|null $commentCount24h,
public Lazy|int|null $oldestComment24hId,
public Lazy|int|null $commentCount7d,
public Lazy|int|null $oldestComment7dId,
public ?UserData $user = null,
) {
}
Expand Down Expand Up @@ -54,4 +54,29 @@ public static function fromRecentlyActiveTopic(array $topic): self

);
}

public static function fromUserPost(array $userPost): self
{
return new self(
id: $userPost['ForumTopicID'],
title: $userPost['ForumTopicTitle'],
createdAt: Carbon::parse($userPost['PostedAt']),

user: null,

commentCount24h: null,
oldestComment24hId: null,
commentCount7d: null,
oldestComment7dId: null,

latestComment: Lazy::create(fn () => new ForumTopicCommentData(
id: $userPost['CommentID'],
body: Shortcode::stripAndClamp($userPost['ShortMsg'], 200),
createdAt: Carbon::parse($userPost['PostedAt']),
updatedAt: null,
user: null,
authorized: true
)),
);
}
}
Loading
Loading