Merge remote-tracking branch 'upstream/develop' into impl/mod-listing-page

This commit is contained in:
IsWaffle 2024-08-10 14:15:11 -04:00
commit 651979ccea
7 changed files with 69 additions and 15 deletions

View File

@ -45,7 +45,7 @@ class ModController extends Controller
$this->authorize('view', $mod);
$latestVersion = $mod->versions->sortByDesc('created_at')->first();
$latestVersion = $mod->versions->sortByDesc('version')->first();
return view('mod.show', compact(['mod', 'latestVersion']));
}

View File

@ -80,10 +80,7 @@ class ModResource extends JsonResource
->values()
),
'links' => [
'self' => route('mod.show', [
'mod' => $this->id,
'slug' => $this->slug,
]),
'self' => $this->detailUrl(),
],
];
}

View File

@ -633,7 +633,7 @@ class ImportHubData implements ShouldBeUnique, ShouldQueue
'users' => $modAuthors,
'name' => $modContent?->subject ?? '',
'slug' => Str::slug($modContent?->subject ?? ''),
'teaser' => Str::limit($modContent?->teaser ?? ''),
'teaser' => Str::limit($modContent?->teaser ?? '', 255),
'description' => $this->cleanHubContent($modContent?->message ?? ''),
'thumbnail' => $this->fetchModThumbnail($curl, $mod->fileID, $mod->iconHash, $mod->iconExtension),
'license_id' => License::whereHubId($mod->licenseID)->value('id'),

View File

@ -154,6 +154,14 @@ class Mod extends Model
return $filters->apply($builder);
}
/**
* Build the URL to the mod's detail page.
*/
public function detailUrl(): string
{
return route('mod.show', [$this->id, $this->slug]);
}
/**
* The attributes that should be cast to native types.
*/

View File

@ -2,6 +2,8 @@
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
@foreach ($mods as $mod)
<x-mod-card :mod="$mod" :versionScope="$versionScope"/>
@if ($mod->{$versionScope})
<x-mod-card :mod="$mod" :versionScope="$versionScope"/>
@endif
@endforeach
</div>

View File

@ -43,16 +43,21 @@
</p>
</div>
</div>
{{-- Mod teaser --}}
@if ($mod->teaser)
<p class="mt-6 pt-3 border-t-2 border-gray-200 dark:border-gray-800 text-gray-800 dark:text-gray-200">{{ $mod->teaser }}</p>
@endif
</div>
{{-- Mobile Download Button --}}
<a href="{{ $latestVersion->link }}" class="block lg:hidden">
<button class="text-lg font-extrabold hover:bg-cyan-400 dark:hover:bg-cyan-600 shadow-md dark:shadow-gray-950 drop-shadow-2xl bg-cyan-500 dark:bg-cyan-700 rounded-xl w-full h-20">{{ __('Download Latest Version') }} ({{ $latestVersion->version }})</button>
</a>
{{-- Tabs --}}
<div x-data="{ selectedTab: window.location.hash ? window.location.hash.substring(1) : 'description' }" x-init="$watch('selectedTab', (tab) => {window.location.hash = tab})" class="lg:col-span-2 flex flex-col gap-6">
<div>
{{-- Mobile Download Button --}}
<a href="{{ $latestVersion->link }}" class="block lg:hidden mb-6">
<button class="text-lg font-extrabold hover:bg-cyan-400 dark:hover:bg-cyan-600 shadow-md dark:shadow-gray-950 drop-shadow-2xl bg-cyan-500 dark:bg-cyan-700 rounded-xl w-full h-20">{{ __('Download Latest Version') }} ({{ $latestVersion->version }})</button>
</a>
{{-- Mobile Dropdown --}}
<div class="sm:hidden">
<label for="tabs" class="sr-only">{{ __('Select a tab') }}</label>
@ -84,7 +89,7 @@
{{-- Mod Description --}}
<div x-show="selectedTab === 'description'" class="user-markdown p-4 sm:p-6 bg-white dark:bg-gray-950 rounded-xl shadow-md dark:shadow-gray-950 drop-shadow-2xl">
{{-- The description below is safe to write directly because it has been run though HTMLPurifier during the import process. --}}
{{-- The description below is safe to write directly because it has been run though HTMLPurifier. --}}
{!! Str::markdown($mod->description) !!}
</div>
@ -114,7 +119,7 @@
{{ __('Dependencies:') }}
@foreach ($version->dependencies as $dependency)
@if ($dependency->resolvedVersion?->mod)
<a href="{{ route('mod.show', [$dependency->resolvedVersion->mod->id, $dependency->resolvedVersion->mod->slug]) }}">
<a href="{{ $dependency->resolvedVersion->mod->detailUrl() }}">
{{ $dependency->resolvedVersion->mod->name }}&nbsp;({{ $dependency->resolvedVersion->version }})
</a>@if (!$loop->last), @endif
@endif
@ -184,7 +189,7 @@
<h3>{{ __('Latest Version Dependencies') }}</h3>
<p class="truncate">
@foreach ($latestVersion->dependencies as $dependency)
<a href="{{ route('mod.show', [$dependency->resolvedVersion->mod->id, $dependency->resolvedVersion->mod->slug]) }}">
<a href="{{ $dependency->resolvedVersion->mod->detailUrl() }}">
{{ $dependency->resolvedVersion->mod->name }}&nbsp;({{ $dependency->resolvedVersion->version }})
</a><br />
@endforeach

42
tests/Feature/ModTest.php Normal file
View File

@ -0,0 +1,42 @@
<?php
use App\Models\Mod;
use App\Models\ModVersion;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
it('shows the latest version on the mod detail page', function () {
// Create a mod instance
$mod = Mod::factory()->create();
// Create 5 mod versions with specified versions
$versions = [
'1.0.0',
'1.1.0',
'1.2.0',
'2.0.0',
'2.1.0',
];
// get the highest version in the array
$latestVersion = max($versions);
foreach ($versions as $version) {
ModVersion::factory()->create([
'mod_id' => $mod->id,
'version' => $version,
]);
}
// Make a request to the mod's detail URL
$response = $this->get($mod->detailUrl());
$this->assertEquals('2.1.0', $latestVersion);
// Assert the latest version is next to the mod's name
$response->assertSeeInOrder(explode(' ', "$mod->name $latestVersion"));
// Assert the latest version is in the latest download button
$response->assertSeeText(__('Download Latest Version')." ($latestVersion)");
});