From 9d52b9c2d6d3ee205b787ace5aa2264accfdeb7d Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Thu, 28 Jul 2022 01:06:39 -0600 Subject: [PATCH] Improve admin dashboard by moving expensive stats to its page and loading stats and recent data async on the dashboard home page --- app/Http/Controllers/AdminController.php | 66 +++- app/Services/AdminStatsService.php | 29 +- resources/views/admin/home.blade.php | 347 ++++++++++++++---- .../views/admin/partial/sidenav.blade.php | 7 + resources/views/admin/stats.blade.php | 180 +++++++++ routes/web.php | 8 + 6 files changed, 551 insertions(+), 86 deletions(-) create mode 100644 resources/views/admin/stats.blade.php diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 8cacd6fb6..37e3a7c0d 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -6,6 +6,7 @@ use App\{ AccountInterstitial, Contact, Hashtag, + Instance, Newsroom, OauthClient, Profile, @@ -31,6 +32,7 @@ use App\Http\Controllers\Admin\{ }; use Illuminate\Validation\Rule; use App\Services\AdminStatsService; +use App\Services\AccountService; use App\Services\StatusService; use App\Services\StoryService; use App\Models\CustomEmoji; @@ -54,9 +56,71 @@ class AdminController extends Controller } public function home() + { + return view('admin.home'); + } + + public function stats() { $data = AdminStatsService::get(); - return view('admin.home', compact('data')); + return view('admin.stats', compact('data')); + } + + public function getStats() + { + return AdminStatsService::summary(); + } + + public function getAccounts() + { + $users = User::orderByDesc('id')->cursorPaginate(10); + + $res = [ + "next_page_url" => $users->nextPageUrl(), + "data" => $users->map(function($user) { + $account = AccountService::get($user->profile_id, true); + if(!$account) { + return [ + "id" => $user->profile_id, + "username" => $user->username, + "status" => "deleted", + "avatar" => "/storage/avatars/default.jpg", + "created_at" => $user->created_at + ]; + } + $account['user_id'] = $user->id; + return $account; + }) + ->filter(function($user) { + return $user; + }) + ]; + return $res; + } + + public function getPosts() + { + $posts = DB::table('statuses') + ->orderByDesc('id') + ->cursorPaginate(10); + + $res = [ + "next_page_url" => $posts->nextPageUrl(), + "data" => $posts->map(function($post) { + $status = StatusService::get($post->id, false); + if(!$status) { + return ["id" => $post->id, "created_at" => $post->created_at]; + } + return $status; + }) + ]; + + return $res; + } + + public function getInstances() + { + return Instance::orderByDesc('id')->cursorPaginate(10); } public function statuses(Request $request) diff --git a/app/Services/AdminStatsService.php b/app/Services/AdminStatsService.php index dbd52276e..2117207f3 100644 --- a/app/Services/AdminStatsService.php +++ b/app/Services/AdminStatsService.php @@ -26,10 +26,18 @@ class AdminStatsService public static function get() { return array_merge( - self::recentData(), - self::additionalData(), - self::postsGraph() - ); + self::recentData(), + self::additionalData(), + self::postsGraph() + ); + } + + public static function summary() + { + return array_merge( + self::recentData(), + self::additionalDataSummary(), + ); } public static function storage() @@ -102,6 +110,19 @@ class AdminStatsService }); } + protected static function additionalDataSummary() + { + $ttl = now()->addHours(24); + return Cache::remember('admin:dashboard:home:data:v0:24hr', $ttl, function() { + return [ + 'statuses' => PrettyNumber::convert(Status::count()), + 'profiles' => PrettyNumber::convert(Profile::count()), + 'users' => PrettyNumber::convert(User::count()), + 'instances' => PrettyNumber::convert(Instance::count()), + ]; + }); + } + protected static function postsGraph() { $ttl = now()->addHours(12); diff --git a/resources/views/admin/home.blade.php b/resources/views/admin/home.blade.php index 693be5908..6ce8ffcc8 100644 --- a/resources/views/admin/home.blade.php +++ b/resources/views/admin/home.blade.php @@ -2,7 +2,7 @@ @section('section') -
+
@@ -10,14 +10,14 @@

Dashboard

-
+
Total posts
- {{$data['statuses']}} +
@@ -25,10 +25,6 @@
-

- {{$data['statuses_monthly']}} - in last 30 days -

@@ -38,7 +34,7 @@
Total users
- {{$data['users']}} +
@@ -46,10 +42,6 @@
-

- {{$data['users_monthly']}} - in last 30 days -

@@ -59,7 +51,7 @@
Reports
- {{$data['reports']}} +
@@ -67,10 +59,6 @@
-

- {{$data['reports_monthly']}} - in last 30 days -

@@ -80,7 +68,7 @@
Messages
- {{$data['contact']}} +
@@ -88,10 +76,6 @@
-

- {{$data['contact_monthly']}} - in last 30 days -

@@ -102,79 +86,280 @@
-
+
-
Overview
-
Daily Posts
-
-
- +
New
+
Accounts
-
- -
- - -
-
+
+ +
+
+ + +
-
-
-

Failed Jobs (24h)

-

{{$data['failedjobs']}}

-
-
-
-
-

Remote Instances

-

{{$data['instances']}}

-
-
-
-
-

Photos Uploaded

-

{{$data['media']}}

-
-
-
-
-

Storage Used

-

{{$data['storage']}} bytes

-
-
-
+
+
+
+
+
New
+
Instances
+
+
+
+
+ +
+ +
+
@endsection @push('scripts') @endpush + +@push('styles') + +@endpush diff --git a/resources/views/admin/partial/sidenav.blade.php b/resources/views/admin/partial/sidenav.blade.php index e63852e56..31a2a8a05 100644 --- a/resources/views/admin/partial/sidenav.blade.php +++ b/resources/views/admin/partial/sidenav.blade.php @@ -132,6 +132,13 @@ + +
+
+
+
+
+
+

Stats

+
+
+
+
+
+
+
+
+
Total posts
+ {{$data['statuses']}} +
+
+
+ +
+
+
+

+ {{$data['statuses_monthly']}} + in last 30 days +

+
+
+
+
+
+
+
+
+
Total users
+ {{$data['users']}} +
+
+
+ +
+
+
+

+ {{$data['users_monthly']}} + in last 30 days +

+
+
+
+
+
+
+
+
+
Reports
+ {{$data['reports']}} +
+
+
+ +
+
+
+

+ {{$data['reports_monthly']}} + in last 30 days +

+
+
+
+
+
+
+
+
+
Messages
+ {{$data['contact']}} +
+
+
+ +
+
+
+

+ {{$data['contact_monthly']}} + in last 30 days +

+
+
+
+
+
+
+
+
+ +
+ +
+
+
+

Failed Jobs (24h)

+

{{$data['failedjobs']}}

+
+
+
+
+

Remote Instances

+

{{$data['instances']}}

+
+
+
+
+

Photos Uploaded

+

{{$data['media']}}

+
+
+
+
+

Storage Used

+

{{$data['storage']}} bytes

+
+
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/web.php b/routes/web.php index a64fe8c9b..ab9aa03a0 100644 --- a/routes/web.php +++ b/routes/web.php @@ -4,6 +4,7 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio Route::redirect('/', '/dashboard'); Route::redirect('timeline', config('app.url').'/timeline'); Route::get('dashboard', 'AdminController@home')->name('admin.home'); + Route::get('stats', 'AdminController@stats')->name('admin.stats'); Route::get('reports', 'AdminController@reports')->name('admin.reports'); Route::get('reports/show/{id}', 'AdminController@showReport'); Route::post('reports/show/{id}', 'AdminController@updateReport'); @@ -90,6 +91,13 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio Route::post('custom-emoji/new', 'AdminController@customEmojiStore'); Route::post('custom-emoji/delete/{id}', 'AdminController@customEmojiDelete'); Route::get('custom-emoji/duplicates/{id}', 'AdminController@customEmojiShowDuplicates'); + + Route::prefix('api')->group(function() { + Route::get('stats', 'AdminController@getStats'); + Route::get('accounts', 'AdminController@getAccounts'); + Route::get('posts', 'AdminController@getPosts'); + Route::get('instances', 'AdminController@getInstances'); + }); }); Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofactor', 'localization'])->group(function () {