mirror of
https://github.com/sp-tarkov/forge.git
synced 2025-02-13 04:30:41 -05:00
Merge remote-tracking branch 'upstream/develop' into impl/mod-listing-page
This commit is contained in:
commit
651979ccea
@ -45,7 +45,7 @@ class ModController extends Controller
|
|||||||
|
|
||||||
$this->authorize('view', $mod);
|
$this->authorize('view', $mod);
|
||||||
|
|
||||||
$latestVersion = $mod->versions->sortByDesc('created_at')->first();
|
$latestVersion = $mod->versions->sortByDesc('version')->first();
|
||||||
|
|
||||||
return view('mod.show', compact(['mod', 'latestVersion']));
|
return view('mod.show', compact(['mod', 'latestVersion']));
|
||||||
}
|
}
|
||||||
|
@ -80,10 +80,7 @@ class ModResource extends JsonResource
|
|||||||
->values()
|
->values()
|
||||||
),
|
),
|
||||||
'links' => [
|
'links' => [
|
||||||
'self' => route('mod.show', [
|
'self' => $this->detailUrl(),
|
||||||
'mod' => $this->id,
|
|
||||||
'slug' => $this->slug,
|
|
||||||
]),
|
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -633,7 +633,7 @@ class ImportHubData implements ShouldBeUnique, ShouldQueue
|
|||||||
'users' => $modAuthors,
|
'users' => $modAuthors,
|
||||||
'name' => $modContent?->subject ?? '',
|
'name' => $modContent?->subject ?? '',
|
||||||
'slug' => Str::slug($modContent?->subject ?? ''),
|
'slug' => Str::slug($modContent?->subject ?? ''),
|
||||||
'teaser' => Str::limit($modContent?->teaser ?? ''),
|
'teaser' => Str::limit($modContent?->teaser ?? '', 255),
|
||||||
'description' => $this->cleanHubContent($modContent?->message ?? ''),
|
'description' => $this->cleanHubContent($modContent?->message ?? ''),
|
||||||
'thumbnail' => $this->fetchModThumbnail($curl, $mod->fileID, $mod->iconHash, $mod->iconExtension),
|
'thumbnail' => $this->fetchModThumbnail($curl, $mod->fileID, $mod->iconHash, $mod->iconExtension),
|
||||||
'license_id' => License::whereHubId($mod->licenseID)->value('id'),
|
'license_id' => License::whereHubId($mod->licenseID)->value('id'),
|
||||||
|
@ -154,6 +154,14 @@ class Mod extends Model
|
|||||||
return $filters->apply($builder);
|
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.
|
* The attributes that should be cast to native types.
|
||||||
*/
|
*/
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
||||||
@foreach ($mods as $mod)
|
@foreach ($mods as $mod)
|
||||||
<x-mod-card :mod="$mod" :versionScope="$versionScope"/>
|
@if ($mod->{$versionScope})
|
||||||
|
<x-mod-card :mod="$mod" :versionScope="$versionScope"/>
|
||||||
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
@ -43,16 +43,21 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</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 --}}
|
{{-- 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 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>
|
<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 --}}
|
{{-- Mobile Dropdown --}}
|
||||||
<div class="sm:hidden">
|
<div class="sm:hidden">
|
||||||
<label for="tabs" class="sr-only">{{ __('Select a tab') }}</label>
|
<label for="tabs" class="sr-only">{{ __('Select a tab') }}</label>
|
||||||
@ -84,7 +89,7 @@
|
|||||||
|
|
||||||
{{-- Mod Description --}}
|
{{-- 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">
|
<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) !!}
|
{!! Str::markdown($mod->description) !!}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -114,7 +119,7 @@
|
|||||||
{{ __('Dependencies:') }}
|
{{ __('Dependencies:') }}
|
||||||
@foreach ($version->dependencies as $dependency)
|
@foreach ($version->dependencies as $dependency)
|
||||||
@if ($dependency->resolvedVersion?->mod)
|
@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 }} ({{ $dependency->resolvedVersion->version }})
|
{{ $dependency->resolvedVersion->mod->name }} ({{ $dependency->resolvedVersion->version }})
|
||||||
</a>@if (!$loop->last), @endif
|
</a>@if (!$loop->last), @endif
|
||||||
@endif
|
@endif
|
||||||
@ -184,7 +189,7 @@
|
|||||||
<h3>{{ __('Latest Version Dependencies') }}</h3>
|
<h3>{{ __('Latest Version Dependencies') }}</h3>
|
||||||
<p class="truncate">
|
<p class="truncate">
|
||||||
@foreach ($latestVersion->dependencies as $dependency)
|
@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 }} ({{ $dependency->resolvedVersion->version }})
|
{{ $dependency->resolvedVersion->mod->name }} ({{ $dependency->resolvedVersion->version }})
|
||||||
</a><br />
|
</a><br />
|
||||||
@endforeach
|
@endforeach
|
||||||
|
42
tests/Feature/ModTest.php
Normal file
42
tests/Feature/ModTest.php
Normal 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)");
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user