Skip to content

Commit 9071d32

Browse files
author
nejc
committed
feat: Add mark as read functionality for whats-new page
- Add PublicWhatsNewController for handling public whats-new page - Add mark as read route and functionality - Update whats-new page to show dynamic content with mark as read button - Fix ShowWhatsNewModal middleware to redirect to home if already read - Update user version when marking as read - Add comprehensive tests for the new functionality
1 parent d07d2be commit 9071d32

File tree

5 files changed

+247
-38
lines changed

5 files changed

+247
-38
lines changed

resources/views/whats-new/page.blade.php

Lines changed: 71 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,79 @@
1212
</div>
1313
<h1 class="text-3xl font-bold text-gray-900 mb-4">🎉 Exciting News: 🎉</h1>
1414
<h2 class="text-xl font-semibold text-gray-800 mb-6">Major Updates to Improve Your Experience!</h2>
15-
<div class="text-left mt-6 space-y-6">
16-
{{-- Example static content, replace with dynamic as needed --}}
17-
<div class="bg-blue-50 border-l-4 border-blue-400 p-4 rounded">
18-
<h3 class="text-lg font-semibold text-blue-900 mb-2">
19-
System Update from Version 1.0.0 to 2.0.0
20-
</h3>
21-
<p class="text-blue-800">We\'ve made significant improvements to enhance your experience!</p>
22-
</div>
23-
<div class="bg-gray-50 p-4 rounded-lg">
24-
<h5 class="text-lg font-semibold text-gray-900 mb-3">🔒 What Does This Mean for You?</h5>
25-
<ul class="space-y-2">
26-
<li class="flex items-start space-x-2">
27-
<span class="text-lg">📝</span>
28-
<div>
29-
<strong class="text-gray-900">New Feature:</strong>
30-
<span class="text-gray-700">You can now enjoy a faster dashboard and improved analytics.</span>
31-
</div>
32-
</li>
33-
<li class="flex items-start space-x-2">
34-
<span class="text-lg">🐞</span>
35-
<div>
36-
<strong class="text-gray-900">Bug Fix:</strong>
37-
<span class="text-gray-700">Resolved login issues for some users.</span>
38-
</div>
39-
</li>
40-
</ul>
15+
16+
@if($latestVersion && $userVersion->isOlderThan($latestVersion->version))
17+
<div class="text-left mt-6 space-y-6">
18+
<!-- System Update Section -->
19+
<div class="bg-blue-50 border-l-4 border-blue-400 p-4 rounded">
20+
<h3 class="text-lg font-semibold text-blue-900 mb-2">
21+
System Update from Version {{ $userVersion->version }} to {{ $latestVersion->version }}
22+
</h3>
23+
<p class="text-blue-800">{{ $latestVersion->description ?? 'We\'ve made significant improvements to enhance your experience!' }}</p>
24+
</div>
25+
26+
<!-- What's New Features -->
27+
@if($whatsNew->count() > 0)
28+
<div class="space-y-4">
29+
@foreach($whatsNew->groupBy('platform_version.version') as $version => $features)
30+
<div class="bg-gray-50 p-4 rounded-lg">
31+
<h5 class="text-lg font-semibold text-gray-900 mb-3">🔒 What Does This Mean for You?</h5>
32+
<ul class="space-y-2">
33+
@foreach($features as $feature)
34+
<li class="flex items-start space-x-2">
35+
<span class="text-lg">{{ $feature->type_icon }}</span>
36+
<div>
37+
<strong class="text-gray-900">{{ $feature->getTitleFromContent() }}:</strong>
38+
<span class="text-gray-700">{{ $feature->getContentWithoutTitle() ?: $feature->content }}</span>
39+
</div>
40+
</li>
41+
@endforeach
42+
</ul>
43+
</div>
44+
@endforeach
45+
</div>
46+
@endif
47+
48+
<!-- Signature Section -->
49+
<div class="bg-green-50 border-l-4 border-green-400 p-4 rounded">
50+
<p class="text-green-800 mb-2">We're excited for you to experience these updates.</p>
51+
<p class="text-green-800">If you have any questions or comments, please don't hesitate to reach out.</p>
52+
<p class="text-green-900 font-semibold mt-3">{!! config('version-platform-manager.whats_new_signature') !!}</p>
53+
</div>
54+
55+
<!-- Mark as Read Button -->
56+
<div class="flex justify-center mt-8">
57+
<form action="{{ route('version-platform-manager.whats-new.mark-read') }}" method="POST" class="inline">
58+
@csrf
59+
<input type="hidden" name="version_id" value="{{ $latestVersion->id }}">
60+
<button type="submit" class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
61+
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
62+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
63+
</svg>
64+
Mark as Read
65+
</button>
66+
</form>
67+
</div>
4168
</div>
42-
<div class="bg-green-50 border-l-4 border-green-400 p-4 rounded">
43-
<p class="text-green-800 mb-2">We\'re excited for you to experience these updates.</p>
44-
<p class="text-green-800">If you have any questions or comments, please don\'t hesitate to reach out.</p>
45-
<p class="text-green-900 font-semibold mt-3">{!! config('version-platform-manager.whats_new_signature') !!}</p>
69+
@else
70+
<div class="text-center mt-6">
71+
<div class="bg-green-50 border-l-4 border-green-400 p-4 rounded">
72+
<h3 class="text-lg font-semibold text-green-900 mb-2">You're up to date!</h3>
73+
<p class="text-green-800">You're currently running the latest version ({{ $userVersion->version }}) of our platform.</p>
74+
</div>
4675
</div>
47-
</div>
76+
@endif
4877
</div>
4978
</div>
79+
80+
@if(session('success'))
81+
<div class="fixed bottom-4 right-4 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg" id="success-message">
82+
{{ session('success') }}
83+
</div>
84+
<script>
85+
setTimeout(() => {
86+
document.getElementById('success-message').style.display = 'none';
87+
}, 3000);
88+
</script>
89+
@endif
5090
@endsection

routes/web.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use LaravelPlus\VersionPlatformManager\Http\Controllers\UserController;
77
use LaravelPlus\VersionPlatformManager\Http\Controllers\AnalyticsController;
88
use LaravelPlus\VersionPlatformManager\Http\Controllers\DashboardController;
9+
use LaravelPlus\VersionPlatformManager\Http\Controllers\PublicWhatsNewController;
910

1011
Route::middleware(['web', 'auth'])->group(function () {
1112
// Mark version as seen
@@ -60,7 +61,12 @@
6061
});
6162
});
6263

63-
// Standalone public What's New page
64-
Route::get(config('version-platform-manager.public_whats_new.url', 'whats-new'), function () {
65-
return view(config('version-platform-manager.public_whats_new.view', 'version-platform-manager::whats-new.page'));
66-
})->name('version-platform-manager.whats-new.public');
64+
// Standalone public What's New page (requires authentication)
65+
Route::middleware(['web', 'auth'])->group(function () {
66+
Route::get(config('version-platform-manager.public_whats_new.url', 'whats-new'), [PublicWhatsNewController::class, 'index'])
67+
->name('version-platform-manager.whats-new.public');
68+
69+
// Mark as read route for public whats-new page
70+
Route::post('/whats-new/mark-read', [PublicWhatsNewController::class, 'markAsRead'])
71+
->name('version-platform-manager.whats-new.mark-read');
72+
});
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace LaravelPlus\VersionPlatformManager\Http\Controllers;
6+
7+
use Illuminate\Http\Request;
8+
use Illuminate\Http\RedirectResponse;
9+
use Illuminate\View\View;
10+
use LaravelPlus\VersionPlatformManager\Services\VersionService;
11+
use Illuminate\Support\Facades\Route;
12+
13+
class PublicWhatsNewController extends Controller
14+
{
15+
public function __construct(
16+
private VersionService $versionService
17+
) {}
18+
19+
/**
20+
* Display the public whats-new page.
21+
*/
22+
public function index(): View
23+
{
24+
// Check if user is authenticated, if not redirect to login
25+
if (!auth()->check()) {
26+
return redirect()->route('login');
27+
}
28+
29+
$user = auth()->user();
30+
$userVersion = $this->versionService->getUserVersion($user);
31+
$latestVersion = $this->versionService->getLatestPlatformVersion();
32+
$whatsNew = $this->versionService->getWhatsNewForUser($user);
33+
34+
return view('version-platform-manager::whats-new.page', compact(
35+
'userVersion',
36+
'latestVersion',
37+
'whatsNew'
38+
));
39+
}
40+
41+
/**
42+
* Mark the current version as seen by the user.
43+
*/
44+
public function markAsRead(Request $request): RedirectResponse
45+
{
46+
// Check if user is authenticated, if not redirect to login
47+
if (!auth()->check()) {
48+
return redirect()->route('login');
49+
}
50+
51+
$validated = $request->validate([
52+
'version_id' => 'required|integer|exists:platform_versions,id',
53+
]);
54+
55+
$user = auth()->user();
56+
$version = \LaravelPlus\VersionPlatformManager\Models\PlatformVersion::find($validated['version_id']);
57+
58+
if ($version) {
59+
// Update the user's actual version to the latest version
60+
$this->versionService->updateUserVersion($user, $version->version);
61+
62+
// Also mark as seen for tracking
63+
$this->versionService->markVersionAsSeen($user, $version->version);
64+
65+
// Log for debugging
66+
\Log::info('User marked version as read', [
67+
'user_id' => $user->id,
68+
'version' => $version->version,
69+
'version_id' => $version->id
70+
]);
71+
}
72+
73+
// Always redirect to home route after marking as read
74+
return redirect()->route('home')->with('success', 'Marked as read successfully.');
75+
}
76+
}

src/Http/Middleware/ShowWhatsNewModal.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,20 @@ public function handle(Request $request, Closure $next)
2626

2727
if ($shouldCheck && Auth::check()) {
2828
$versionService = app(VersionService::class);
29-
if ($versionService->userNeedsUpdate(Auth::user())) {
29+
$userNeedsUpdate = $versionService->userNeedsUpdate(Auth::user());
30+
$whatsNewUrl = '/' . ltrim(config('version-platform-manager.public_whats_new.url', 'whats-new'), '/');
31+
$onWhatsNewPage = $request->path() === ltrim($whatsNewUrl, '/');
32+
33+
if ($userNeedsUpdate) {
3034
// Avoid redirect loop
31-
$whatsNewUrl = '/' . ltrim(config('version-platform-manager.public_whats_new.url', 'whats-new'), '/');
32-
if ($request->path() !== ltrim($whatsNewUrl, '/')) {
35+
if (!$onWhatsNewPage) {
3336
return redirect($whatsNewUrl);
3437
}
38+
} else {
39+
// If already read and on whats-new page, redirect to home
40+
if ($onWhatsNewPage) {
41+
return redirect()->route('home');
42+
}
3543
}
3644
}
3745

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
namespace LaravelPlus\VersionPlatformManager\Tests;
4+
5+
use Illuminate\Foundation\Testing\RefreshDatabase;
6+
use Illuminate\Foundation\Testing\WithFaker;
7+
use Tests\TestCase;
8+
use LaravelPlus\VersionPlatformManager\Models\PlatformVersion;
9+
use LaravelPlus\VersionPlatformManager\Models\UserVersion;
10+
use LaravelPlus\VersionPlatformManager\Models\WhatsNew;
11+
use App\Models\User;
12+
13+
class PublicWhatsNewControllerTest extends TestCase
14+
{
15+
use RefreshDatabase, WithFaker;
16+
17+
public function test_guest_redirected_to_login()
18+
{
19+
$response = $this->get('/whats-new');
20+
21+
$response->assertRedirect('/login');
22+
}
23+
24+
public function test_authenticated_user_can_access_whats_new_page()
25+
{
26+
$user = User::factory()->create();
27+
28+
$response = $this->actingAs($user)->get('/whats-new');
29+
30+
$response->assertStatus(200);
31+
$response->assertViewIs('version-platform-manager::whats-new.page');
32+
}
33+
34+
public function test_mark_as_read_requires_authentication()
35+
{
36+
$response = $this->post('/whats-new/mark-read', [
37+
'version_id' => 1
38+
]);
39+
40+
$response->assertRedirect('/login');
41+
}
42+
43+
public function test_authenticated_user_can_mark_version_as_read()
44+
{
45+
$user = User::factory()->create();
46+
$version = PlatformVersion::factory()->create([
47+
'version' => '2.0.0',
48+
'is_active' => true
49+
]);
50+
51+
// Create user version record
52+
UserVersion::create([
53+
'user_id' => $user->id,
54+
'version' => '1.0.0'
55+
]);
56+
57+
$response = $this->actingAs($user)->post('/whats-new/mark-read', [
58+
'version_id' => $version->id
59+
]);
60+
61+
$response->assertRedirect();
62+
$response->assertSessionHas('success', 'Marked as read successfully.');
63+
64+
// Verify the user's last seen version was updated
65+
$userVersion = UserVersion::where('user_id', $user->id)->first();
66+
$this->assertEquals('2.0.0', $userVersion->last_seen_version);
67+
}
68+
69+
public function test_mark_as_read_with_invalid_version_id()
70+
{
71+
$user = User::factory()->create();
72+
73+
$response = $this->actingAs($user)->post('/whats-new/mark-read', [
74+
'version_id' => 999 // Non-existent version
75+
]);
76+
77+
$response->assertSessionHasErrors('version_id');
78+
}
79+
}

0 commit comments

Comments
 (0)